Scope Marvin App token to each job's declared permissions (#4834)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
nate nowack 2026-08-18 11:42:17 -05:00 committed by GitHub
commit bfcdfa59ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 19 additions and 2 deletions

View file

@ -36,6 +36,12 @@ jobs:
with:
app-id: ${{ secrets.MARVIN_APP_ID }}
private-key: ${{ secrets.MARVIN_APP_PRIVATE_KEY }}
# Match the job's `permissions:` block above. Unscoped, the token
# inherits the App installation's full set — which includes
# contents: write and actions: write, neither of which this job
# declares and both of which end up in the model's shell as GH_TOKEN.
permission-contents: read
permission-issues: write
- name: Set dedupe prompt
id: dedupe-prompt
@ -114,8 +120,12 @@ jobs:
prompt: ${{ steps.dedupe-prompt.outputs.PROMPT }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY_FOR_CI }}
allowed_non_write_users: "*"
# No `Bash(gh api:*)`: it reaches every endpoint the token can, which
# is the reason marvin-label-triage routes its one write through
# .github/scripts/triage-label.sh instead. Dedupe searches, reads and
# comments — the four verbs below cover that.
claude_args: |
--allowedTools "Bash(gh issue view:*)","Bash(gh search:*)","Bash(gh issue list:*)","Bash(gh api:*)","Bash(gh issue comment:*)",Task
--allowedTools "Bash(gh issue view:*)","Bash(gh search:*)","Bash(gh issue list:*)","Bash(gh issue comment:*)",Task
settings: |
{
"model": "claude-sonnet-5",

View file

@ -56,7 +56,14 @@ jobs:
with:
app-id: ${{ secrets.MARVIN_APP_ID }}
private-key: ${{ secrets.MARVIN_APP_PRIVATE_KEY }}
owner: PrefectHQ
# No `owner:` — with it set and `repositories:` empty the token is
# scoped to every repo in the PrefectHQ installation. Triage only
# ever touches this one. The permissions below match the job's
# `permissions:` block; unscoped the token would also carry
# contents: write and actions: write from the App installation.
permission-contents: read
permission-issues: write
permission-pull-requests: write
- name: Set triage prompt
id: triage-prompt