bash gate: `rm -rf x 2>/dev/null` parses the redirect as delete targets, hits the no-escape protected-path tier
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 19.9k
- Forks
- 2.3k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 30
Description
Summary
rm -rf <path> 2>/dev/null is parsed such that the stderr redirect becomes two additional delete targets, one of which is /dev/null. That last one trips the "protected system path" rule, which is hard-blocked with no justification escape, so the command cannot be run at all.
Three distinct parser bugs stack here:
2from the redirect operator is treated as a path operand/dev/null(the redirect destination) is treated as a delete target- Relative paths resolve against
$HOMErather than the command's actual working directory, even with an explicitcdearlier in the same command
Steps to reproduce
Baseline, works fine:
cd /tmp && rm -rf nonexistent-test-dir-xyz 2>&1; echo "exit=$?"
→ runs, exit=0
Add only 2>/dev/null:
cd /tmp && rm -rf nonexistent-test-dir-xyz 2>/dev/null; echo "exit=$?"
Actual
Error: This command is blocked and cannot be confirmed.
- recursive delete inside the working directory (target: /home/user/nonexistent-test-dir-xyz)
- recursive delete inside the working directory (target: /home/user/2)
- targets a protected system or home path that must never be destroyed (target: /dev/null)
If the user genuinely wants this, they must run it themselves outside the agent.
The two runs differ only in 2>&1 vs 2>/dev/null.
Expected
One delete target: /tmp/nonexistent-test-dir-xyz. 2 and /dev/null are redirect syntax, not operands. Nothing is ever deleted at /dev/null; it is a write destination.
Why this one is worse than the sibling issues
/dev/null lands in the protected-path tier, which is a hard block. The message says "the user must run it themselves outside the agent", and there is no justification retry. So a wholly ordinary line like:
rm -rf build-dir 2>/dev/null
is permanently unrunnable. 2>/dev/null on a cleanup command is about as common as bash gets.
Bug 3 deserves separate attention
Note the resolved paths. The command was cd /tmp && rm -rf nonexistent-test-dir-xyz, but the gate reported the target under $HOME.
The cd /tmp was ignored and the relative path was resolved against $HOME. That is a safety-relevant misresolution in its own right, independent of the redirect parsing. It means the tier decision ("inside the working directory") is computed against the wrong directory. It could equally cause a false negative, where a genuinely dangerous relative delete gets classified against the wrong base and looks safe.
Suggested fix
Parse redirects out before extracting operands. N>target, N>>target, &>target, N>&M, and <target are all redirect syntax; their operands are never command arguments. A shell-aware tokenizer gets this for free; a regex over the raw string will keep producing this class of bug.
Separately, track cd within the command when resolving relative paths, or decline to classify relative paths by absolute location at all.
Context
Hit while cloning a git repo into a temp dir: cd /tmp && rm -rf <repo>; git clone .... The workaround was generating a unique directory name so no rm was needed, which is strictly worse since it leaves stale directories behind.
Related: #922 (heredoc bodies scanned as code), #751, #709, #738. Same underlying theme, risk classification running over text that is not a command operand. This report adds the redirect-operand and cwd-resolution cases, and notes that the protected-path tier has no escape hatch.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the bash gate's command parsing and relative-path resolution entry points, then reproduce the two commands from the report. Done means redirect syntax is excluded from delete targets and cd /tmp is honored, so the example reports only /tmp/nonexistent-test-dir-xyz without treating /dev/null as a protected delete target.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bash, rust
- Domain
- cli, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 65/100