Repository navigation
Conversation
The Bash write-target guard judged relative paths against the workspace root only, so `cd sub && tee link/f` (and readers such as `cd sub && cat link/secret`) traversed a `sub/link` symlink out of the workspace, `pushd`/`popd` were not recognized, and CDPATH could redirect a literal `cd`. Add a working-directory leaf module that builds the union of the directories the command could run in (root plus each determinable cd/pushd destination, appended not replaced), refuses a relative write that escapes from any candidate, refuses relative paths after an undecidable cd (CDPATH, loop, function), matches protected paths against the candidates, judges stage-2 relative reads the same way, and drops CDPATH from the `sh -c` environment. Two-point measurement: on the base tree the four new reject tests fail (e.g. "expected rejection: cd sub && tee link/f"); with the change all five pass. Mutation run (working_directory + wiring, 30-minute cap) was truncated after 10 of 94 mutants; the 10 observed survivors are equivalent under the test set and are explained in the worker report. 読み替え: the issue's problem table lists `cd sub && grep -r x link` as a read that must be rejected, but the referenced H-01 report defers bare words without `/` to #571. To satisfy the issue's 拒否する形 list, stage 2 also joins literal relative words onto every candidate; this only rejects paths that actually escape. 判断: `pushd` with no operand and `pushd ±N` record no working-directory target (they only rotate the stack); `cd` with no operand keeps its existing `~` rejection. 本文に無い指摘: `env cd sub && tee elink/f` is refused by the existing root-relative per-target check (root/elink escapes), not by the new candidate check. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
B1: `DIRSTACK[1]=sub/link` rewrites bash's directory stack, so a later
`popd`, `pushd ±N`, or bare `pushd` can leave the workspace. A word that
contains `DIRSTACK` now marks the working directory undecidable, like
`CDPATH`.
B2: after an undecidable `cd`/`pushd` (CDPATH, DIRSTACK, loop, or function),
a command such as `CDPATH=sub cd link && cat secret` had its relative read
words joined onto the candidates without the undecidable check. Stage two
now refuses when the change is undecidable and at least one relative read
word remains. Read words are taken only from segments that are not a
working-directory change, so a pure `cd d0; cd d1; …` chain stays allowed
while an absolute/home write under an undecidable cd keeps its old reason.
Candidate cap: consecutive distinct `cd` destinations can double the set at
each step. Growth now stops past 64 candidates and the destination becomes
undecidable, and duplicate checks go through a `HashSet` so the check stays
cheap at the cap.
Tests: new reject integration cases for the DIRSTACK forms and for
`CDPATH=sub cd link && {cat,grep} …`, a timed reject for
`cd d0; …; cd d39; tee f` (returns under a second) with its no-write allow,
plus unit tests for the absolute/home undecidable skip, the protected-path
absolute/home skip, `pushd` write targets, and a popd loop.
Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
This was referenced Oct 3, 2026
9 tasks
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.
Closes #568
What changed
src/tools/bash_write_guard/working_directory.rs(new) tracks the working directory a command can reach aftercd,pushdandpopd. It keeps a set of candidates.cdorpushdwith a resolvable target adds that target to every candidate; nothing is ever replaced. Subshells, pipelines and||may or may not restore the directory, and keeping the root covers both cases without emulating them.$, backticks,~, glob,-or...popd,pushd ±Nand a barepushdadd no candidates.pushd -n DIRaddsDIR.CDPATHorDIRSTACKcd,pushdorpopdis combined with a loop or a function definitioncddoubles the set, so this cap prevents exponential work beforeshstarts.src/tools/bash_write_guard.rs:cd/pushdtarget are checked against every candidate.pushdis recorded as aworking directorytarget.protected_path_mutationalso matches relative targets against each candidate.cd tests && cp a.txt spec.rsis now detected.src/tools/bash.rs:cd sub && cat link/secretandCDPATH=sub cd link && cat secret.CDPATHis removed from the environment of thesh -cprocess, so the runtime cannot resolvecddifferently from the static check.src/tools/bash_write_guard/command_prefix.rs:pushdandpopdare added to the write programs that the unresolvable-prefix scan looks for.tests/issue568_bash_cwd_write_targets.rs(new): integration tests that callpath_confinement_rejection.What did not change
shell_tokens,ShellTokenand thecommand_prefixresolution.write_targets.WriteTargets. So write detection and thebash:verifyauto-allow do not change:cd frontend && npm testandcd crates/x && cargo testare still auto-allowed.Verification
175b61da.3581d777, 4 of 5 new integration tests fail. After the review fix, the DIRSTACK/CDPATH test fails onb5bea876, and the candidate-cap test does not return within 15 minutes there. All 7 pass on175b61da.-- working_directory, no--libfilter,--jobs 2):DIRSTACKsentpopdoutside the workspace. A relative read was allowed afterCDPATH. It also found the exponential candidate growth.cd.issue575_*,issue566_*,issue567_*,issue428_*,bash_workspace_confinement.Notes
eval cd …,trap 'cd …' DEBUG,source/alias, and variable names built at runtime (n=CD; export "${n}PATH=sub").CDPATH= cd sub && cargo testis rejected.DIRSTACKmakes the set unresolvable.{ … }の中の書き込みを認識せず、ワークスペース外へ書き込める(#509 の調査で発見) #566 is not needed. Keeping the root candidate already coversenv cd sub.{ … }の中の書き込みを認識せず、ワークスペース外へ書き込める(#509 の調査で発見) #566, [security][tools] Bash の書き込み検査の字句解析が ANSI-C 引用 $'…' を扱わず、program や option を見逃してワークスペース外へ書き込める(#566 の再確認で発見) #575, [security][tools] Bash の書き込み検査が、字句解析で読めないコマンド(heredoc・コメントの中の ')を丸ごと許可し、ワークスペース外へ書き込める(#575 の調査で発見) #576, [security][tools] Bash の 2 段目の読み取りの判定が、引用符のない glob・動的な値・glob を含む絶対パスで抜け、ワークスペース外を読める(#567 の調査で発見) #571, [security][tools] Bash の字句検査では、プログラム経由の間接書き込みや検証コマンドの副作用を閉じ込められない #502.Developed with the CommandMate parallel-dev harness (PM: Claude Code, leader: Claude_Dev, workers: Command Code).
🤖 Generated with Claude Code