Skip to content

fix(claude): credentials の deny 誤爆と mktemp の失敗を直す - #80

Merged
tunepolo merged 1 commit into
mainfrom
fix/claude-credentials-glob
Aug 20, 2026
Merged

fix(claude): credentials の deny 誤爆と mktemp の失敗を直す#80
tunepolo merged 1 commit into
mainfrom
fix/claude-credentials-glob

Conversation

@tunepolo

Copy link
Copy Markdown
Owner

概要

#78 で入れた設定を Claude Code 再起動後に実機で確認したところ、2つの問題が残っていた。どちらも #78 と同じ「名前だけのグロブが、秘密ではなくソースを掴んでいる」型。

1. **/credentials の deny が node_modules を巻き込む

~/Repos 配下で **/credentials に該当するパスを数えたところ、10件すべてが node_modules 内のディレクトリだった。

financial-doc-parser/eval/node_modules/@anthropic-ai/sdk/lib/credentials
financial-doc-parser/eval/node_modules/@azure/identity/dist/esm/credentials
financial-doc-parser/eval/node_modules/@azure/storage-common/dist/commonjs/credentials
...

本物の認証情報は0件、誤爆率100%。これにより tree-walk するツールが途中で止まる。実測では以下のとおり。

$ gofmt -l .
open eval/node_modules/@anthropic-ai/sdk/lib/credentials: operation not permitted
$ echo $?
2

終了コード 2 が返るため、フォーマット違反の検出と権限エラーの区別がつかない。

対応: 拡張子つきの実在パターンに絞る。

before after
**/credentials **/credentials.json **/credentials.yml **/credentials.yaml **/credentials.db

拡張子なしの credentials ファイルは読めるようになるが、~/.aws/~/.config/gcloud/ はディレクトリ単位で別途 deny してあるため、実際に守りたい対象は落ちない。

2. mktemp -d がサンドボックスで失敗する

$ mktemp -d
mktemp: mkdtemp failed on /var/folders/xk/.../T/tmp.apjUlAZLnz: Operation not permitted
$ echo $TMPDIR
/tmp/claude-502

macOS の mktemp は引数なしの場合 $TMPDIR を無視して confstr(_CS_DARWIN_USER_TEMP_DIR)/var/folders/*/*/T)を使う。ここが allowWrite に無いため落ちる。

対応: allowWrite/var/folders/*/*/T を追加。OS のユーザ一時ディレクトリなので、すでに許可している $TMPDIR と同等のリスク。

自分で書くスクリプトは $TMPDIR を明示するため履歴上の発生はほぼ無いが、このリポジトリの tests/pre-commit-hook.test.shmktemp -d を使っており、ローカルでは TMP_BASE が空になって失敗する(CI では通る)。

$ bash tests/pre-commit-hook.test.sh
install: /leak/.git/hooks/INS@mscxOD: No such file or directory
結果: 1 pass / 1 fail

手を入れなかったもの

  • **/secrets/**: dot_git-templates/secrets/ を塞いでいると疑ったが、実測では読めた。誤爆していない
  • **/*.pem: certifi の公開CAバンドル(cacert.pem)が拒否されることは確認したが、実際に壊れた履歴が無い。絞ると server.pem のように鍵を含む命名を取りこぼすため、保護を下げるトレードオフを取らない判断にした

#78 の効果確認(参考)

再起動後、以下は意図どおりになっていた。

  • golangci-lint run のキャッシュ警告が消えた(従来58回失敗していた箇所)
  • go vet ./... が承認プロンプトなしで終了コード 0
  • .env.example / .envrc.example / .envrc_example は読める
  • .env / .env_prod / .env_stg / .envrc は拒否
  • ~/.ssh/known_hosts / ~/.config/gh/hosts.yml は拒否

検証状況

サンドボックス設定はセッション開始時に読まれるため、この PR の2点は次回の Claude Code 再起動後でないと実機確認できない。現時点で確認済みなのは JSON として valid であることと、意図したキーに入っていることだけ。/var/folders/*/*/T のグロブが allowWrite で解釈されるかも未確認。

🤖 Generated with Claude Code

#78 の設定を再起動後に実機で確認したところ、2つの問題が残っていた。

**credentials の deny が node_modules を巻き込む**

~/Repos 配下で `**/credentials` に該当する10件は、すべて node_modules 内の
ディレクトリだった(@anthropic-ai/sdk, @azure/identity, @azure/storage-common
のソース構成)。本物の認証情報は0件で、誤爆率100%。

これにより tree-walk するツールが途中で止まる。実測では
`gofmt -l .` が終了コード 2 を返すため、フォーマット違反の検出と
権限エラーの区別がつかない状態だった。

拡張子つきの実在パターンに絞る。拡張子なしの `credentials` ファイルは
読めるようになるが、~/.aws や ~/.config/gcloud はディレクトリ単位で
別途 deny してあるため、実際に守りたい対象は落ちない。

**mktemp -d がサンドボックスで失敗する**

macOS の mktemp は引数なしの場合 $TMPDIR を無視して
confstr(_CS_DARWIN_USER_TEMP_DIR) すなわち /var/folders/*/*/T を使う。
ここが allowWrite に無いため mkdtemp が Operation not permitted になる。

自分で書くスクリプトは $TMPDIR を明示するので履歴上の発生はほぼ無いが、
このリポジトリの tests/pre-commit-hook.test.sh が mktemp -d を使っており
ローカルでは TMP_BASE が空になって失敗する(CI では通る)。
OS のユーザ一時ディレクトリなので、$TMPDIR を許可しているのと同等のリスク。

**なお `**/secrets/**` は誤爆していなかった**

dot_git-templates/secrets/ を塞いでいると疑ったが、実測では読めた。
`**/*.pem` が certifi の公開CAバンドルを塞ぐ件は確認したが、実際に
壊れた履歴が無く、絞ると server.pem のような命名を取りこぼすため
今回は手を入れない。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@tunepolo
tunepolo merged commit bfbb72c into main Aug 20, 2026
7 checks passed
@tunepolo
tunepolo deleted the fix/claude-credentials-glob branch August 20, 2026 06:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant