Skip to content

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

Description

@amudhansowrirajan

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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:permissionsbugSomething isn't workingp2Non-showstopper bug or popular feature request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions