1jehuang / 1jehuang/jcode

bash gate: `rm -rf x 2>/dev/null` parses the redirect as delete targets, hits the no-escape protected-path tier

Open
#932 10 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

autonomous: likely bug priority: high recurring-theme triage: reproducible
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:

  1. 2 from the redirect operator is treated as a path operand
  2. /dev/null (the redirect destination) is treated as a delete target
  3. Relative paths resolve against $HOME rather than the command's actual working directory, even with an explicit cd earlier 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.