Repository navigation
guard: what it cannot see and what the shell can still remove; alarm: a transient failure that keeps happening - #27
Merged
Conversation
…not removed or relinked from the shell, and Logs Insights is a read Measured against this gate with the commands a second deployment running copies of these files now denies its unattended agent. A pipe into a shell (curl ... | sh, | sudo bash, |bash) and a fetched script handed to one (bash -c "$(curl ...)", sh <(curl ...), source/. <(...), eval "$(...)") passed in both postures: the guard read sh, and every verb in the script stayed out of reach. They are refused under every posture now, before the mode branch, with the way through said: fetch it, read it, run what it holds. rm results/x.json, rm -f CLAUDE.md, find results -delete and ln -sf /tmp/x .claude/skills/x passed while cp and mv into the same paths were refused: the case files the next run reads could be deleted, and a skill planted whose content lives wherever the run can write. rm, rmdir, unlink, shred, ln, touch and find with -delete or an -exec that removes or writes now name their targets like cp does. aws logs start-query (and CloudTrail Lake's) is a read in the readonly posture, named exactly so Athena's start-query-execution stays refused. Each rule's test fails with the rule removed.
…per six hours, and a landing says so Rate limits and 5xx are retried and, when they fail again, filed as one investigation's bad luck; none of them is a node-wide shape, so none paged. A second deployment running copies of these files lost three days of rounds to a rate limit exactly that way. The third consecutive failure of one transient kind now pages through the alarm channel, at most once per kind per six hours, and the next run the engine finishes says the node is landing again. Kinds are named (a 429 and 'rate limit exceeded' are one kind), node-wide failures are not counted twice, and one investigation's own failure is not counted at all. The streak lives in memory. The alarm setting's comment, and so the generated reference, now lists everything that pages.
…can no longer do; the decision note The containment row now lists removing and linking among the shell's refused writes, the unseen-code rule under every posture, and a script saved to a file and then run among what it does not stop. The README's guard item says the same. The decision note records what was measured and the consequences: an installer's curl | sh is refused even on a writing node, ln -s to a protected file over-blocks, the streak restarts with the process, and nothing persisted changes shape.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three lessons from a second deployment running copies of these files, by Claude (claude-opus-5-5) at the repository owner's request. Each was measured against this repository's own gate or failure path before it was changed, and each fix has a test that fails without it.
1. A script the guard never sees is refused, under every posture. A pipe into a shell (
curl … | sh,| sudo bash,|bash) and a fetched script handed to one (bash -c "$(curl …)",sh <(curl …),source <(…),eval "$(…)") passed in both postures: the guard readsh, and every verb in the script stayed out of reach of every rule. The work stack's egress allowlist includes raw.githubusercontent.com, where anyone can host a script. Refused now before the mode branch, with the way through said: fetch it, read it, run what it holds. Pipes intosha256sum,jq,python3 -m json.toolorshellcheckare untouched.2. Removing or relinking a protected path from the shell is a write.
rm results/x.json,rm -f CLAUDE.md,find results -deleteandln -sf /tmp/x .claude/skills/xpassed whilecpandmvinto the same paths were refused: the case files the next run reads could be deleted, and a skill planted whose content lives wherever the run can write.rm,rmdir,unlink,shred,ln,touch, andfindwith-deleteor an-execthat removes or writes now name their targets the waycpdoes, in both postures.3. A transient failure that keeps happening pages. Rate limits and 5xx are retried and, failing again, filed as one investigation's bad luck; none is a node-wide shape, so none paged. The other deployment lost three days of rounds to a rate limit that way. The third consecutive failure of one transient kind now pages once per kind per six hours, and the next run that lands says so. Node-wide failures are not counted twice; one investigation's own failure is not counted.
Also:
aws logs start-query(and CloudTrail Lake's) is a read in the readonly posture, named exactly so Athena'sstart-query-execution, which writes to a bucket, stays refused.Not ported: an emergency-stop file, and the other deployment's deny list for its writing agent — this repository's writing posture allows writes by design and its readonly guard already refuses those verbs.
Decision note:
.agents/notes/implemented/2026-10-27-what-the-guard-cannot-see-and-a-failure-that-keeps-happening.md.Gate: STACK GATE GREEN locally; CI read back before merging.