Repository navigation
#637 [security][tools] Bash でオプションにより作業ディレクトリを変える形と、- で始まる pushd の行き先を検査する - #646
Merged
Kewton merged 3 commits intoOct 10, 2026
Conversation
Read a table program's working-directory option value (tar -C, git -C, make -C, env -C, sudo -D, ninja/go/cargo/pnpm/poetry/yarn/bun/npm/uv/just/ patch, and the tar/gmake aliases) as a working-directory candidate, exactly like a cd destination, through the new leaf module src/tools/bash_write_guard/option_directory.rs. A glob/brace or otherwise unreadable value raises the #635 glob-destination mark so the relative words after it are still refused. Read the word after `pushd --` as a destination even when it starts with `+`/`-`, and name the destination word (option value included) as the undecidable refusal path instead of the following command word. 判断: option values are read from each segment's raw words rather than the resolved program, because env -C / sudo -D never resolve to a Program and a table program can sit behind a prefix (`nice env -C DIR`). 判断: an option value that cannot be read from its spelling (a glob or brace, `$`, a backtick, `~`, a `..` component, or an empty value) raises the #635 mark and adds no candidate, per the issue's design; the mark only ever adds refusals. 本文に無い指摘: `find -execdir` and the options of unlisted programs stay out of scope and keep their existing handling, as the module doc records. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
Add working_directory_caps_an_option_growth_that_skips_the_bound, the option-value analogue of working_directory_caps_a_growth_that_skips_the_bound (#635): forty `git -C sub` values add one candidate each, then a single `git -C r` doubles the set past MAX_CANDIDATES without landing on it, so the inspection must still be undecidable. This catches the `>` → `==` mutation in collect_option_directories' cap check, which would leave the mark clear and allow more. Test-only; no production decision changes. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
…issue-637-security-tools-bash-tar-c-git-c-pushd-613-635
5 tasks
Kewton
deleted the
feature/issue-637-security-tools-bash-tar-c-git-c-pushd-613-635
branch
October 10, 2026 06:36
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.
概要
Bash の閉じ込めの検査に、既存の見逃しが 3 つありました(#613・#635 のレビューと、着手前調査 H-14 で発見)。
tar -C sub -cf - lf2、git -C sub log lf2、env -C sub cat lf2、sudo -D sub cat lf2などは、作業ディレクトリの検査を通らず、その後の/のない相対パスが確かめられていませんでした。値のディレクトリの中に外向きの symlink があると、それを通して外を読めました。-で始まるpushdの行き先:pushd -- -s2 && cat lf7で、--の後の-s2がスタックの番号として読み飛ばされていました。cd 's2*' && cat lf4)の拒否で、理由の path が行き先ではなく、後のコマンドの名前(cat)になっていました。この PR は、Issue 本文の設計 1〜3 どおりに直します。
変更(5 ファイル、+584/−11)
src/tools/bash_write_guard/option_directory.rs(新規、+259)tar・gtar・bsdtar・make・gmake・git(サブコマンドより前だけ)・env・sudo・ninja・go・cargo・pnpm・poetry・yarn・bun・npm・uv・just・patch。-C dir、-Cdir、--directory=dir、--directory dir。--の後は見ない。nice・sudo・envなど)の後にあっても見つかる。src/tools/bash_write_guard/working_directory.rs(+89/−10)cdの行き先と同じ扱いで作業ディレクトリの候補に足す。置き換えはしない([security][tools] Bash の書き込み検査が同じコマンドの cd・pushd の後の cwd を追わず、symlink を通ってワークスペース外へ書き込める(#509 の調査で発見) #568 の設計)。上限の印もcdと同じ。$・`・~・..・空)は、[security][tools] Bash の cd・pushd の行き先が 1 つに一致する glob だと作業ディレクトリが検査されず、外を読み書きできる(#613 のレビューで発見) #635 の glob の行き先の印を立てる。--を含むpushdは、+・-で始まる語も行き先にする。pushd -1・pushd +0(--なし)は今どおり。Inspectionに記録する。src/tools/bash.rs(+8/−1):「決められない」の拒否の理由の path に、記録した行き先の語を使う。src/tools/bash_write_guard.rs(+1):mod option_directory;の 1 行だけ。tests/issue637_bash_option_working_directory.rs(新規、+227)pushd --の読み取りと書き込み、理由の path を確かめる。CARGO_TARGET_TMPDIRの下の一時ディレクトリの中だけ。shell は起動しない。検証
commandmate verifyの 15 ゲート:develop88d5a0dbを取り込んだ HEAD で 15/15 pass(b654b236、scope 5 本、違反 0)。TMPDIR=/tmp cargo test --test issue637_bash_option_working_directory --test issue635_bash_glob_cd_destination --test issue568_bash_cwd_write_targets --test issue582_bash_read_candidates --test issue641_bash_brace_home(CI と同じ条件を作るため):exit 0、7 passed・0 failed、28 passed・0 failed、7 passed・0 failed、6 passed・0 failed、4 passed・0 failed(issue568・issue582・issue635・issue637・issue641 の順)。b506fbdfの src に、この PR のテストを足した)tar -C sub -cf - lf2が拒否されない。pushd -- -s2 && cat lf7が拒否されない。cd 's2*' && cat lf4の理由の path がcatになる。cargo mutants --jobs 1、--in-diff、--libと結合テスト 4 本)>を==にしても通った(候補の数が 64 を踏まずに超えると、上限の印が立たない)。テストを足して直し、2 回目で caught になった。>を>=にする変異:ちょうど 64 で印が立つだけ。-1 文字の語をオプションとして読み進める変異:-Cを余分に拾うだけ。b506fbdf→ HEAD88d5a0db([security][tools] Bash の閉じ込めの検査が、brace の展開から出てくる ~ を確かめず、home の一覧を読める(#628 のレビューで発見) #641 入り)+[security][tools] Bash でオプションにより作業ディレクトリを変える形(tar -C・git -C など)と、- で始まる pushd の行き先が検査されない(#613・#635 のレビューで発見) #637pushd --の 11 変種でも、設計どおり拒否された。意図した誤拒否
cdと同じく後の segment にも残る。git -C sub status; cat lf2は拒否される。root にlf2は無いが、sub/lf2が外向き symlink のため。本文の見積りで、記録の 436 件のうち新しく拒否されるのはこの型だけ。echo tar -C sub; cat lf2も拒否される。どちらも、足した候補の先に外向き symlink があるときだけ起きる。git -C sub status、make -C sub test、tar -C sub -cf - f、tar -C sub -xf a.tar、env -C sub cat f、git commit -C HEAD、npm --prefix sub test、cargo -C sub testは許可のまま。grep -C 3、diff -C 3、git log -C subも変わらない。この PR では直していない既存の穴(どれも #637 の前から R=0 で、この PR で緩んではいない)
tar --dir=sub …、make --dir=sub …、env --ch=sub …。Cを値として食う形:tar -cfC -C sub lf2。gitの値をとる全体のオプションが先にある形:git -c k=v -C sub log lf2、git --git-dir x -C sub …。npm -C、unzip -dなど)とfind -execdir:本文どおり範囲の外。Refs #637
🤖 Generated with Claude Code