fix(ci): strip REVIEW_TOKEN from the review agents' environment #377

Merged
k.renner merged 1 commits from claude-bot/pr-review-strip-review-token into master 2026-07-23 14:18:52 +00:00
Member

Strips REVIEW_TOKEN (write:repository PAT) from the claude triage+review agents' environment via env -u REVIEW_TOKEN.

The step exports the token for its own curl/gitea_post calls, but that also left it in the agents' env — and those agents process attacker-controlled PR content, so a prompt-injected diff could read /proc/self/environ and exfiltrate the write-scoped PAT into the public review comment. The agents never call Gitea themselves (the shell does, via $AUTH), so the token isn't needed in their env.

Defence-in-depth alongside the existing settings.json Read(/proc/**) deny. Caught by the review bot; matches the fix on authentik #3 / HA #180 so all fleet copies stay identical.

Strips `REVIEW_TOKEN` (write:repository PAT) from the `claude` triage+review agents' environment via `env -u REVIEW_TOKEN`. The step exports the token for its own `curl`/`gitea_post` calls, but that also left it in the agents' env — and those agents process attacker-controlled PR content, so a prompt-injected diff could read `/proc/self/environ` and exfiltrate the write-scoped PAT into the public review comment. The agents never call Gitea themselves (the shell does, via `$AUTH`), so the token isn't needed in their env. Defence-in-depth alongside the existing `settings.json` `Read(/proc/**)` deny. Caught by the review bot; matches the fix on authentik #3 / HA #180 so all fleet copies stay identical.
claude-bot added 1 commit 2026-07-23 14:12:44 +00:00
fix(ci): strip REVIEW_TOKEN from the review agents' environment
ci/woodpecker/pr/pr-review Pipeline was successful
a4836879a9
The step exports REVIEW_TOKEN (write:repository PAT) for its own curl/gitea_post
calls, but that also placed it in the environment of the claude triage+review
agents, which process attacker-controlled PR content — a prompt-injected diff
could read /proc/self/environ and exfiltrate it into the public report. The
agents never call Gitea (the shell does, via $AUTH), so run them under
'env -u REVIEW_TOKEN'. Defence in depth alongside the settings.json /proc deny.
Caught by the review bot; matches the fix applied to the other fleet repos.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
review-bot left a comment
Member

🤖 Automated review — model claude-opus-4-8 (complexity: complex), commit a4836879a97e16958b59e834ae31674a51ab9ddc.

Advisory review by the review-bot pipeline. It never approves; a human merges. Push new commits to get a fresh review.


Summary

This PR prepends env -u REVIEW_TOKEN to the two claude agent invocations in
.woodpecker/pr-review.yml, removing the write-scoped Gitea PAT from the
environment of the triage and review agents that process attacker-controlled PR
content. The change is minimal, correct, and closes a real credential-exfil path
as defence-in-depth. No blocking issues.

🔴 Blocking

None.

🟡 Suggestions

  • CLAUDE_CODE_OAUTH_TOKEN still remains in the agents' environment
    (.woodpecker/pr-review.yml:65), since the claude CLI needs it to
    authenticate — it can't be stripped the way REVIEW_TOKEN was. That token is a
    secret too, and the same prompt-injection-reads-/proc/self/environ path
    applies to it. The mitigation is the Read(//proc/**) deny in
    ci/agents/pr-review/settings.json:21, which the PR body correctly cites as
    the other half of the defence. Worth a one-line comment noting that the OAuth
    token is deliberately left in env and relies solely on the Read-sandbox, so a
    future reader doesn't assume env -u covers both. Not required for this merge.

🟢 Nits

None.

Tests

No automated tests accompany this change, which is appropriate — this is a CI
YAML shell edit with no unit-testable surface. The correctness that matters is
behavioural and I verified it by reading the file:

  • env -u REVIEW_TOKEN unsets the variable only for the spawned claude
    process, not the parent shell, so the shell's own AUTH header
    (.woodpecker/pr-review.yml:126) and the gitea_post API calls
    (:148–:156, :241) still have the token. Correct.
  • CLAUDE_CODE_OAUTH_TOKEN is untouched, so the agents can still authenticate to
    Claude. Correct.
  • Both claude invocations (triage :205, review :217) receive the strip, so
    neither agent sees the PAT. Complete.

Recommendation

Looks reasonable — no blocking issues; comments above are optional.

🤖 **Automated review** — model `claude-opus-4-8` (complexity: complex), commit `a4836879a97e16958b59e834ae31674a51ab9ddc`. > Advisory review by the `review-bot` pipeline. It never approves; a human merges. Push new commits to get a fresh review. --- ## Summary This PR prepends `env -u REVIEW_TOKEN` to the two `claude` agent invocations in `.woodpecker/pr-review.yml`, removing the write-scoped Gitea PAT from the environment of the triage and review agents that process attacker-controlled PR content. The change is minimal, correct, and closes a real credential-exfil path as defence-in-depth. No blocking issues. ## 🔴 Blocking None. ## 🟡 Suggestions - `CLAUDE_CODE_OAUTH_TOKEN` still remains in the agents' environment (`.woodpecker/pr-review.yml:65`), since the `claude` CLI needs it to authenticate — it can't be stripped the way `REVIEW_TOKEN` was. That token is a secret too, and the same prompt-injection-reads-`/proc/self/environ` path applies to it. The mitigation is the `Read(//proc/**)` deny in `ci/agents/pr-review/settings.json:21`, which the PR body correctly cites as the other half of the defence. Worth a one-line comment noting that the OAuth token is *deliberately* left in env and relies solely on the Read-sandbox, so a future reader doesn't assume `env -u` covers both. Not required for this merge. ## 🟢 Nits None. ## Tests No automated tests accompany this change, which is appropriate — this is a CI YAML shell edit with no unit-testable surface. The correctness that matters is behavioural and I verified it by reading the file: - `env -u REVIEW_TOKEN` unsets the variable only for the spawned `claude` process, not the parent shell, so the shell's own `AUTH` header (`.woodpecker/pr-review.yml:126`) and the `gitea_post` API calls (`:148`–`:156`, `:241`) still have the token. Correct. - `CLAUDE_CODE_OAUTH_TOKEN` is untouched, so the agents can still authenticate to Claude. Correct. - Both `claude` invocations (triage `:205`, review `:217`) receive the strip, so neither agent sees the PAT. Complete. ## Recommendation Looks reasonable — no blocking issues; comments above are optional. <!-- pr-review:sha=a4836879a97e16958b59e834ae31674a51ab9ddc -->
k.renner merged commit 40a20cb3bd into master 2026-07-23 14:18:52 +00:00
Sign in to join this conversation.