Repository navigation
fix(ci): keep the Claude app token out of the on-demand reviewer's reach - #473
Merged
Merged
Conversation
claude-code-action, with no github_token input, swaps the job token for a `claude` GitHub App token minted over OIDC. Its scopes come from the app installation (contents, workflows and actions write), not from the job's `permissions:` block, so `contents: read` was never the boundary. The action then writes that token into the origin remote URL in .git/config after checkout, undoing `persist-credentials: false`, and the model's `Read` plus `gh pr comment` is a path from that file to a public comment. Hand both on-demand workflows the job's own token, drop `id-token: write`, and deny `Read(.git/**)` and `Read(//proc/**)`, the latter because the action also passes its token to the Claude process's environment.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
claude-code-review-on-demand.ymlandclaude-code-focus-on-demand.ymlboth assumed the reviewer's GitHub reach was bounded by the job'spermissions:block and thatpersist-credentials: falsekept tokens out of the tree. Neither held, measured on run 37418782166 and in the action source at the pinned SHA (v1.0.221):github_tokeninput, the action exchanges OIDC for aclaudeGitHub App token (src/github/token.ts). It requests no specific scopes, so the token carries the installation's:contents,workflowsandactionswrite among them.contents: readlimited nothing..git/config. After checkout, the action rewrites the origin URL to embed that token (src/github/operations/git-config.ts; logged as "Updated remote URL with authentication token"), soReadplusgh pr commenthad a path from it to a public comment.--allowedTools, including Glob, Grep,git add/commit/rmand itsgit-push.sh. The run log's "SDK options" shows the real set.Changes
Same three changes in both workflows:
github_token: ${{ github.token }}, so the action skips the OIDC exchange and uses the job token, bounded bycontents: read,pull-requests: write,issues: write.id-token: write, which only served that exchange. Claude authenticates with the OAuth token.--disallowedTools "Read(.git/**),Read(//proc/**)"./procbecause the action also passes its token to the Claude process's environment. Claude Code appliesReaddeny rules to Grep and Glob only best-effort, which is why the token scoping matters on its own.Comments now come from
github-actions[bot]rather thanclaude[bot]. Nothing keys on the login: both verify steps filter on.user.type == "Bot", and incremental mode matches its marker text.Verifying
issue_commentworkflows run frommain, so this can't be exercised before merge. On the first@claude /reviewafter merging, the run log should show "Using provided GITHUB_TOKEN for authentication" rather than "Using GITHUB_TOKEN from OIDC", both deny rules underdisallowedToolsin "SDK options", and a posted review.No changeset: workflow-only, nothing ships in the package.