Repository navigation
[security][tools] Bash の作業ディレクトリを変えるオプションの検査が、長いオプションの省略形・短いオプションのまとまり・git の全体オプションの後の形で抜ける(#637 のレビューで発見) #645
Description
背景
#637 の merge 前レビュー(H-16、2026-10-09)で見つけた、Bash の閉じ込めの検査の既存の見逃しです。#637 の前の develop にもあり、#637 で緩んだものではありません(2026-10-10、利用者承認で起票)。着手前調査(H-17、2026-10-10)で、develop c98bdc7c の値を確かめ、設計を決めました。判定の関数を tempdir の fixture に対して呼び、結果を見ただけです。
問題
#637 で、オプションで作業ディレクトリを変える形を表にして検査するようになりました。ただし次の書き方の変種では、表のオプションを見つけられず、その後の相対パスが検査されません(R=0)。オプションの書き方を変えるだけで、ワークスペースの中の symlink を通して外のファイルを読めます。入力と値は「根拠」の表にあります。
- 長いオプションの省略形:GNU・bsdtar などは、長いオプションの一意な接頭辞を受け付けます(H-16 で、macOS の bsdtar 3.5.3 と GNU Make 3.81 で効くことを確かめた)。検査は名前を完全一致でだけ照合します。
- 短いオプションのまとまりで、値をとる別のオプションが
Cを値として食う形:検査はまとまりのCをオプションとみなし、次の語を値として読み飛ばすので、その後の本物のオプションを見ません。 gitの値をとる全体のオプションが先にある形:検査は、その値の語を subcommand とみなして走査を止めます。- 表に無いプログラム:
npmの短い名前-C(--prefixと同じ)が表に無い。 - 空の値の理由の path:[tools] Bash で引用した字どおりの括弧のディレクトリへ cd する形(Next.js の [id])が誤って拒否される(#635 の意図した誤拒否、#637 から分離) #643 に移しました(同じ関数を [tools] Bash で引用した字どおりの括弧のディレクトリへ cd する形(Next.js の [id])が誤って拒否される(#635 の意図した誤拒否、#637 から分離) #643 が変えるため)。
設計(H-17 で決定)
- 表のプログラムの長いオプションは、表の長い名前の空でない接頭辞なら、その名前とみなします(
--name=valueと--name valueの両方)。表のプログラムの未知の長いオプションを「決められない」にする案は、参考の記録の 9,198 件(15%)に印が立つため採りません。 - オプションの値として読んだ語が
-で始まるとき(--を除く)は、その語を値として記録したうえで、その語も続けて走査します。値を記録するので、-で始まる名前のディレクトリも今どおり候補になります。プログラムごとに値をとる短いオプションの表を持つ案は、表の保守が要り、漏れが穴になるため採りません。 gitの全体のオプションのうち、値を別の語にとるもの(-c・--git-dir・--work-tree・--namespace・--super-prefix・--config-env・--attr-source)は、値の語ごと読み飛ばして走査を続けます。=でつなぐ形と値をとらないオプションは、今のままです。未知の全体のオプションでは git 自体がエラーで止まるので、今どおり走査を止めます。- 表の
npmに短い名前-Cを足します。ほかのプログラムは足しません:tmux -c(後で動くコマンドの文字列の作業ディレクトリで、検査はその文字列の中を読まない)、docker -w(container の中の path)、unzip -d(展開先、つまり書き込み先の問題で、別の Issue にする)、meson -C・gradle -p(参考の記録に 0 件、後の語は target の名前)。find -execdirは範囲の外です。 - 表は作業ディレクトリのオプションの解析の中だけで変えます。候補を足す側の処理は変えません。
誤拒否の見積り
- 記録(agent の Bash コマンド 436 件):H-17 の試作で値の変化は 0 件。
- 参考(このリポジトリで動いた Claude Code の Bash コマンド 59,358 件):値の変化は 0 件。表の名前の接頭辞の形は 0 件、値をとる全体のオプションで始まる
gitは 151 件、npm -Cは 0 件。 - 候補を足すだけなので、新しく拒否になるのは、足した先に外向き symlink があるか、値が決められない(glob・
$・..など)ときだけです。
受け入れ条件
- 「根拠」の表 1 の形が R=1 になる。
- 「根拠」の表 2 の形(ワークスペースの中の読み書き)を誤って拒否しない。値が変わらない。
- 表 3 の形は今の値のまま(表に足さないプログラムと、git の object の名前の形)。
- 保護 path、秘密情報、bash:verify の自動許可、[security][tools] Bash の書き込み検査の字句解析がバッククオートのコマンド置換を扱わず、中の書き込みを見逃してワークスペース外へ書き込める(#576 の調査で発見) #581・[security][tools] Bash の字句解析が二重引用の中の $(…)・${…} の " を引用の閉じと読み違え、後ろをコメントとして消してワークスペース外へ書き込める(#581 のレビューで発見) #585・[security][tools] Bash の 2 段目の path 検査が、$・glob・動的な値で静的な相対パスや展開先を確かめず、ワークスペース外を読める(#571 を統合) #582・[security][tools] Bash の書き込み先で、引用した閉じ記号と実行される glob・brace が混ざると、外向き symlink の先への書き込みを拒否しない(#582 のレビューで発見) #602・[security][tools] Bash の 2 段目の path 検査が、空白を含む静的パスと = 付きの引数を候補にせず、外を読める(#582 のレビューで発見) #603・[security][tools] Bash の閉じ込めの検査が、引用していない CR を区切りとして扱い、/ を含まない相対の語を候補にしないため、外向き symlink を通して外を読み書きできる(#602・#603 のレビューで発見) #613・[security][tools] Bash の閉じ込めの検査が、.. と ~ だけの語を確かめず、dd の of= を書き込みとして認識しない(#613 の調査で発見) #628・[security][tools] Bash の cd・pushd の行き先が 1 つに一致する glob だと作業ディレクトリが検査されず、外を読み書きできる(#613 のレビューで発見) #635・[security][tools] Bash でオプションにより作業ディレクトリを変える形(tar -C・git -C など)と、- で始まる pushd の行き先が検査されない(#613・#635 のレビューで発見) #637・[security][tools] Bash の閉じ込めの検査が、brace の展開から出てくる ~ を確かめず、home の一覧を読める(#628 のレビューで発見) #641 の印と判定が緩む向きに変わらない(R・A・W・P・S が 1→0、V が 0→1 になる行が 0 件)。
- 誤拒否の見積りをテストのファイルの冒頭に記録する。
- 既存の検証・受入・証跡・リリースゲートを緩めていない(AGENTS.md の honest-failure 方針)。成長上限の baseline を引き上げていない。
対象ファイル
src/tools/bash_write_guard/option_directory.rstests/issue645_bash_option_directory_variants.rs
参照
- [tools] Bash で引用した字どおりの括弧のディレクトリへ cd する形(Next.js の [id])が誤って拒否される(#635 の意図した誤拒否、#637 から分離) #643 と並べて進められます。[tools] Bash で引用した字どおりの括弧のディレクトリへ cd する形(Next.js の [id])が誤って拒否される(#635 の意図した誤拒否、#637 から分離) #643 は作業ディレクトリの検査の本体と字句の解析を変え、既存の issue637 のテストの期待も更新するので、この Issue のテストは新しいファイルに置きます。
- 調査の記録:ローカルの workspace/tmp/1007/wave1/results/H-16/report.md の「抜け道」と「後続の候補」、workspace/tmp/1007/wave1/results/H-17/report.md
- 試作と出力:ローカルの /Volumes/SSD_NX/tmp/wave1-20261007/h17/(proto.diff、out-dev.jsonl、out-proto.jsonl、cc-cmp.txt)
根拠
fixture:ワークスペースの中の sub の中の lf2 は、外のファイルを指す symlink。sub/f と f は普通のファイル。R:2 段目の閉じ込めの判定。値は develop c98bdc7c と H-17 の試作。
表 1(R=0 → R=1 にする)
| 項目 | 入力(例) | develop | 試作 |
|---|---|---|---|
| 1 | tar --dir=sub -cf - lf2、tar --direc sub -cf - lf2、tar --dir sub -cf - lf2、make --dir=sub lf2、env --ch=sub cat lf2、env --chd sub cat lf2、sudo --chd=sub cat lf2、patch --dir=sub -i lf2、just --working-dir sub cat lf2、pnpm --di sub cat lf2、npm --pref sub x lf2 |
R=0 | R=1 |
| 2 | tar -cfC -C sub lf2、tar -cfC --directory=sub lf2、tar -cfC -Csub lf2、tar -fC -Csub lf2、make -fC -C sub lf2、sudo -uD -D sub cat lf2 |
R=0 | R=1 |
| 3 | git -c k=v -C sub log lf2、git --git-dir x -C sub log lf2、git --work-tree sub -C sub log lf2、git --namespace n -C sub log lf2 |
R=0 | R=1 |
| 4 | npm -C sub run x lf2、npm -C sub exec cat lf2 |
R=0 | R=1 |
表 2(許可のまま)
git -C sub status、make -C sub、tar -C sub -cf - f、grep -C 3 x f、git log -C sub、git -c color.ui=never status、git -c k=v -C sub status、git --no-pager log -C、git commit -C HEAD、tar --exclude=x -cf - f、make --no-print-directory -C sub、make -f Makefile test、cargo test --no-fail-fast、cargo --manifest-path x/Cargo.toml test、npm --prefix sub run build、sudo -u root -D sub cat f、env --ignore-environment cat f、tar -xzf a.tar -C sub
表 3(今の値のまま)
| 入力(例) | 値 | 理由 |
|---|---|---|
git -c core.pager=cat -C sub show HEAD:lf2 |
R=0 | HEAD:lf2 は git の中の object の名前で、ファイルの path ではない(元の本文の表から外した) |
meson -C sub lf2、gradle -p sub lf2、tmux -c sub cat lf2、docker -w sub cat lf2、unzip -d sub a.zip lf2 |
R=0 | 設計 4 で表に足さない |
git --no-pager -C sub log lf2、git -P -C sub log lf2、git --git-dir=x -C sub log lf2 |
R=1 | 今も検査される |
コード(develop c98bdc7c)
- 長いオプションの完全一致の照合:
src/tools/bash_write_guard/option_directory.rs:128-147 - まとまりの解析と値の読み飛ばし:同じファイルの
:149-164 gitの全体のオプションで走査を止める:同じファイルの:169-173- 表:同じファイルの
:81-101
関連(参考)
- [security][tools] Bash でオプションにより作業ディレクトリを変える形(tar -C・git -C など)と、- で始まる pushd の行き先が検査されない(#613・#635 のレビューで発見) #637
- [tools] Bash で引用した字どおりの括弧のディレクトリへ cd する形(Next.js の [id])が誤って拒否される(#635 の意図した誤拒否、#637 から分離) #643
- [security][tools] Bash の cd・pushd の行き先が 1 つに一致する glob だと作業ディレクトリが検査されず、外を読み書きできる(#613 のレビューで発見) #635
- [security][tools] Bash の字句検査では、プログラム経由の間接書き込みや検証コマンドの副作用を閉じ込められない #502
Activity
Merge pull request #654 from Kewton/feature/issue-645-security-tools-…
Kewton commentedon Oct 11, 2026
develop に merge 済み(PR #654、merge 後の develop 9047eb3 で CI・acceptance success)。