release: 0.1.2 — a wrapped command no longer escapes the guardrail, and the policy watches itself - #35
Merged
Conversation
Stop your AI coding agent before it touches something it shouldn't. A local guardrail for Claude Code, Cursor, Gemini CLI and more: it blocks out-of-scope writes, .env reads, rm -rf and force pushes, with no API key and zero tokens. It is not a firewall and not a sandbox. It intercepts what an agent DECLARES it is about to do, through that agent's own hook system, and does not sit in the kernel. An adversarial read of the earlier wording found that claim the first thing to attack and the first thing to lose (DECISIONS.md D-095). This is a single-commit history by design. The tool was built over eleven verified phases in a private repository whose commits contain the build machine's absolute paths and internal notes; publishing a rewritten version of that history would leave the original blobs fetchable by SHA. The engineering record it would have carried is published instead as DECISIONS.md and the artifacts under verification/, both of which are checked by scripts/pre-public-scan.sh before every push.
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.
Two security fixes and one new control
If you run 0.1.0 or 0.1.1, the first item is the reason to upgrade.
sh -c 'rm -rf /'was ALLOWED, and it was one of 44The bare command was correctly refused throughout. Wrapping it was enough to turn the rule off:
sh -c,env sh -c,timeout 5 sh -c,nohup,setsid,xargs,find -exec,ssh host '…',perl -e,node -e,eval— 44 of 55 wrapped forms allowed on the published 0.1.1, measuredagainst the tarball downloaded from the registry rather than a local build.
A rule marked
outsideRepoOnlyis skipped when every filesystem-looking argument resolves insideallowed_paths. The tokenizer strips quotes, so-c 'rm -rf /'arrived as one token,rm -rf /,which resolved relative to the repository into
<repo>/rm -rf /— a path inside the allowedscope. Everything looked in-scope, so the recursive-delete rule was never evaluated.
It needs no adversarial agent. Counted against 8,487 real agent shell commands:
python3 -c339,
env182,bash -c89,node -e50,xargs26,timeout17 — 8.1% of everything anagent ran arrives in one of these shapes as ordinary idiom.
Fixed with two independent fences: the effective program is resolved past runner prefixes, and any
argument token containing whitespace is refused classification. 0 of 55 wrapped forms escape
now, with no change to precision or coverage on the frozen 92-block label set. One measured
false positive is named in the changelog rather than left to be found.
usewarden now watches its own policy
Every check watched the agents' hook registrations. None watched the rules those hooks enforce —
so a policy narrowed from the shell was enforced silently while
statussaid PROTECTED anddoctorpassed every row.Preventing that write is not achievable from a hook, and
README.mdhas always said so. Noticingit is. The policy is now sealed at
usewarden init— a verbatim copy, not a hash, because ahash cannot be replayed — and
status,doctor, the status line andusewarden policy --driftreport when the rules in force would catch less than the rules you installed. It compares
verdicts, not text: both rulesets run against a derived probe set and against your own recorded
incidents. A policy made stricter raises nothing, and
usewarden resealaccepts a change youmeant.
Three findings are kept apart: catches lost, protections lost, and protections downgraded from
absolute (
forbidden_paths, everywhere) to conditional (allowed_paths, only where you arestanding). The third is the one a block-count misses.
Also
usewarden resealandusewarden policy --driftare new;usewarden replayshipped and wasnever documented.
SECURITY.mdgains a known issues in published versions table naming both defects against0.1.0 and 0.1.1, so nobody has to read release notes to learn their version does not do what its
page says.
npm testwas broken in four ways that only a checkout of thisrepo could see. Found by building and testing the tree being pushed rather than the tree the
checkout was standing in.
Full detail in
CHANGELOG.md.🤖 Generated with Claude Code
https://claude.ai/code/session_01To6RJknDDPxY3nihw4t64k