anthropics / anthropics/claude-code-action

AGENTS.md is not in SENSITIVE_PATHS — the documented @AGENTS.md import loads the PR head's instructions despite the CLAUDE.md restore

Đang mở
#1,696 1 bình luận 0 reaction 0 người được giao Xem trên GitHub
area:permissions bug p2
Ngôn ngữ chính
TypeScript
Star
8.9k
Fork
2.1k
Chỉ số merge pull request
Chỉ số pull request đang chờ

Mô tả

## Summary

`SENSITIVE_PATHS` (src/github/operations/restore-config.ts, ~line 26 at v1.0.195 / `d40ddef`) restores `CLAUDE.md`, `CLAUDE.local.md`, `.claude`, `.mcp.json`, `.claude.json`, `.gitmodules`, `.ripgreprc`, and `.husky` from the base branch on PR contexts, described in-file as "Paths that are both PR-controllable and read from cwd at CLI startup" — so a PR cannot inject instructions into the run.

`AGENTS.md` is not on that list. But the Claude Code memory docs explicitly recommend keeping shared instructions in `AGENTS.md` and importing them from `CLAUDE.md` via `@AGENTS.md` (https://code.claude.com/docs/en/memory, "AGENTS.md" section). In a repo using that documented pattern, the restored base-branch `CLAUDE.md` still contains the `@AGENTS.md` import — and the import resolves against the working tree, which is the **PR head** checkout (src/github/operations/branch.ts checks out `pull/N/head`, including fork PRs). The import therefore loads the PR author's `AGENTS.md` into the run's instructions, reopening the injection path the CLAUDE.md restore was built to close.

## Impact

Bounded by the trigger gate (write access required by default, `allowed_non_write_users` empty), so exploitation requires a maintainer commenting `@claude` on a PR whose head modifies or adds `AGENTS.md`. That is precisely the scenario `SENSITIVE_PATHS` exists to defend — a maintainer invoking the action on an untrusted contribution — and the file it misses is the one the product's own docs tell users to put their instructions in. Nested `AGENTS.md` files in subdirectories (also part of the agents.md convention) have the same property when imported.

## Reproduction sketch

1. Repo with `CLAUDE.md` containing `@AGENTS.md` (the documented pattern) and both files on the default branch.
2. External PR modifies `AGENTS.md` to include adversarial instructions.
3. Maintainer comments `@claude` on the PR.
4. The action restores `CLAUDE.md` from base (correct), but the `@AGENTS.md` import inside it resolves to the PR head's file — the modified instructions load.

## Suggested fix

Add `AGENTS.md` (and arguably `AGENTS.local.md` / nested `**/AGENTS.md`, matching whatever the import + native-discovery surface grows to) to `SENSITIVE_PATHS`. More generally: any file reachable from a restored `CLAUDE.md` via `@` imports inherits CLAUDE.md's trust requirements — a recursive restore of the import closure would close the class rather than the instance, but the single filename covers the documented pattern today.

Found while auditing our own repo's adoption of the `@AGENTS.md` import pattern (action pinned at v1 → v1.0.195, installing Claude Code 2.1.235; confirmed 2.1.235 does not natively discover AGENTS.md, so the import is the sole loader — which is exactly why it escapes the restore).

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.