majorcredential-leakunverifiedcollected
読めないDockerフォルダが1つあるだけで、.envの読み取り禁止が黙って外れた(未検証の報告)
ある開発者がLinux上のClaude Codeで、サンドボックスの `denyRead` に `**/.env` を指定した。ところが一つのプロジェクトでは何も効かず、階層の深い `.env` をエージェントが読めてしまった。警告もエラーも出なかった。
原因
筆者によれば、ワイルドカードを具体的なパスに展開するとき、プロジェクト全体を再帰的に一覧する処理が、最初の権限エラーで丸ごと止まっていた。Dockerが作ったデータベース用のフォルダ(権限0700、別ユーザーの所有)がそのエラーを起こし、失敗は握りつぶされ、ルールが守るパスは0件になった。./.env のような固定パスは影響を受けなかった。
結果
設定は正しく見えるのに、深い階層の .env の秘密情報はエージェントのプロセスから読める状態だった。安全装置が「開いたまま」壊れていたことになる。筆者は、リポジトリの中にボリュームを置くDocker Composeの構成では、こうしたフォルダがごく普通にできると指摘している。
対策
上流のサンドボックスは、権限エラーがあっても一覧を続け、読めないフォルダは覆い隠すよう直されたという。ただ、筆者が試したClaude Code(2.1.283)にはまだ入っていなかった。当面の回避策は、ワイルドカードの範囲を絞る(./webapp/**/.env)、固定パスで列挙する、Dockerのボリュームをプロジェクトの外へ出す、複数の書き方を重ねる。禁止ルールは設定を眺めて確かめず、実際に読ませてみて確かめる。
何が起きたか
ある開発者が、Linux上のClaude Code(サンドボックスはbubblewrapで動く)の
プロジェクト設定に sandbox.filesystem.denyRead: ["**/.env"] を書いた。
狙いは単純で、エージェントが何をしても環境変数のファイルだけは読ませない、
というものだった。あるプロジェクトではそのとおりに効いた。ところが
同じ設定の別のプロジェクトでは、深い階層の .env を自由に読めてしまった。
現場の混乱
エラーも警告も、ログに残るものも何もなかった。手がかりは、二つの
プロジェクトの違いだけだった。筆者が比べていくと、効かないほうには、
DockerがPostgreSQLのボリューム用に作ったフォルダがあった。別のユーザーの
所有で、手元のユーザーでは中に入れない権限になっていた。空のフォルダを
1つ作って chmod 000 にするだけで、どこでも同じ現象を再現できた。
原因
サンドボックスは **/.env を具体的なパスに直すため、プロジェクトの下の
ファイルを再帰的に一覧していた。この処理は開けないフォルダを飛ばさず、
最初の権限エラーで止まる。コードはそのエラーを受け止めて空の一覧のまま
先へ進んだので、ルールは何も守らなくなった。固定パスのルールはこの処理を
通らないため、./.env は禁止されたままだった。
対策
筆者によれば、Anthropicが公開しているサンドボックスの実装は、その後、
権限エラーがあっても一覧を続け、読めないフォルダは覆い隠すように直された。
ただ、筆者が試したClaude Codeの版には、まだその修正が入っていなかった。
それまでの回避策として筆者は、ワイルドカードを必要なフォルダに絞る、
大事な .env は固定パスで書く、Dockerのボリュームをプロジェクトの外へ
出す、複数の書き方を重ねる、を挙げている。
もっと広い教訓は、安全装置の確かめ方にある。「開いたまま」壊れる禁止 ルールは、正しく効いているルールと見た目が変わらない。確かなのは、 読めないはずのファイルを実際にエージェントに読ませてみることだけで、 それをプロジェクトごと、変更のたびに行う必要がある。