Files
homelab/ci/agents/issue-fix/settings.json
T
claude-botandClaude Opus 4.8 ab105233d9 security(ci): add Read sandbox to alert-monitor and issue-fix agents
Both agent steps hold Gitea write credentials in their environment
(issue-fix holds a push token too), but neither passed --settings, so
their Read tool was unrestricted — unlike update-audit, which got a
Read sandbox for exactly this reason (gitea issue #197).

That left a complete exfil path: Read /proc/self/environ yields the
token, Write puts it in the agent's output file, and the pipeline posts
that output verbatim as a Gitea issue body / PR body on a PUBLIC repo.

Add the same deny-list used by update-audit (/proc, /root, /home, /etc,
.git) to both agents and wire --settings into each invocation. The repo
checkout, .ci-alert-monitor/ and /tmp/alert-fix/ stay readable, which is
all either agent needs.

This is defense-in-depth only. The root cause — CI pipelines holding an
admin-owned token at all — is tracked separately.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 16:55:23 +02:00

29 lines
1.5 KiB
JSON

{
"//": "Read sandbox for the issue-fix agent. This step's environment holds BOTH",
"//2": "a Gitea issue-write token and a repo push token, so the agent's Read tool",
"//3": "is denied access to anything that could hold credentials: the container's",
"//4": "/proc (env var dumps via /proc/self/environ), /root and /home (SSH keys,",
"//5": ".netrc, git-credential stores), /etc, and the repo's own .git/ (which can",
"//6": "carry an embedded clone token). The repo checkout itself stays readable",
"//7": "and writable — this agent's job is to edit ansible/, opentofu/,",
"//8": "kubernetes/ and ci/images/ — as does /tmp/alert-fix/ (the issue body it",
"//9": "is asked to fix).",
"//10": "Matters here because the agent's edits are pushed to a branch and its",
"//11": "summary is posted as a PR body / issue comment on a PUBLIC repo, so an",
"//12": "unsandboxed Read gives a prompt-injected instruction a read-then-publish",
"//13": "exfil path. Denying .git/ also keeps the agent away from the push",
"//14": "credential the pipeline's own git commands use.",
"//15": "Mirrors ci/agents/update-audit/settings.json; see gitea issue #197.",
"//16": "Verified empirically against Claude Code 2.1.207: relative deny globs",
"//17": "anchor to the pipeline's cwd (repo root), not this file's directory.",
"permissions": {
"deny": [
"Read(//proc/**)",
"Read(//root/**)",
"Read(//home/**)",
"Read(//etc/**)",
"Read(.git/**)"
]
}
}