← 事故一覧へ

majorcredential-leakunverifiedcollected

読めないDockerフォルダが1つあるだけで、.envの読み取り禁止が黙って外れた(未検証の報告)

ある開発者がLinux上のClaude Codeで、サンドボックスの `denyRead` に `**/.env` を指定した。ところが一つのプロジェクトでは何も効かず、階層の深い `.env` をエージェントが読めてしまった。警告もエラーも出なかった。

発生日
深刻度
7/10
影響範囲
data
タグ
#claude-code#sandbox#bubblewrap#deny-read#fail-open#docker#secrets

原因

筆者によれば、ワイルドカードを具体的なパスに展開するとき、プロジェクト全体を再帰的に一覧する処理が、最初の権限エラーで丸ごと止まっていた。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のボリュームをプロジェクトの外へ 出す、複数の書き方を重ねる、を挙げている。

もっと広い教訓は、安全装置の確かめ方にある。「開いたまま」壊れる禁止 ルールは、正しく効いているルールと見た目が変わらない。確かなのは、 読めないはずのファイルを実際にエージェントに読ませてみることだけで、 それをプロジェクトごと、変更のたびに行う必要がある。

出典