Commit 2abf017
authored
fix(ci): dicht ongeauthenticeerde @claude-trigger (RCE op publieke repo) (#25)
* fix(ci): vereis vertrouwde repo-rol voor Claude-trigger
claude.yml draaide een agent met Bash + een schrijfrechten-token zodra
een issue/comment de tekst "@claude" bevatte, zonder controle op wie de
auteur is. Op deze publieke repo kon daardoor elke GitHub-gebruiker via
een enkele comment code laten uitvoeren in een runner met het
GITHUB_TOKEN en het CLAUDE_CODE_OAUTH_TOKEN.
De job draait nu alleen wanneer de auteur OWNER, MEMBER of COLLABORATOR
is, voor alle vier de triggers (issue_comment, pull_request_review_comment,
pull_request_review, issues).
claude-code-review.yml is defensief gehard: pull_request-velden lopen nu
via env-variabelen in plaats van directe ${{ }}-interpolatie in het
Bash-blok, zodat script-injectie via PR-metadata wordt voorkomen.
* fix(ci): pin claude-code-action naar commit-SHA
@v1 is een mutable tag: GitHub resolvet die bij elke run naar waar v1
op dat moment naar wijst. Een gecompromitteerde upstream-tag zou
daarmee direct in de drie workflows landen die de agent met een
write-scoped token draaien (claude, claude-code-review, api-sync).
Alle drie nu gepind op het commit-SHA waar v1 nu naar wijst
(51ea8ea), met '# v1' als leesbare annotatie. Conform de hardening-
richtlijn van anthropics/claude-code-action zelf.
* fix(ci): verklein aanvalsoppervlak Claude-workflows verder
Twee aanvullende hardeningen bovenop de @claude-auth-gate:
1. id-token: write verwijderd uit claude, claude-code-review en
api-sync. Geen enkele step in deze workflows consumeert een
OIDC-token (geen configure-aws-credentials o.i.d.), dus de
permissie was dood gewicht. Met id-token: write kon een job
een OIDC-token munten met de identiteit van deze repo; relevant
voor claude-code-review omdat die op elke fork-PR draait.
2. claude-code-review draait nu alleen op same-repo PRs
(head.repo.fork == false). Die workflow checkt de PR-head uit
en de review-prompt leest bestanden uit die tree (CLAUDE.md
etc). Op een fork-PR is dat door een aanvaller bestuurde code,
met CLAUDE_CODE_OAUTH_TOKEN in de omgeving en Bash aan: een
klassieke prompt-injection-route. De env-var-hardening dekte
alleen ${{ }}-injectie, niet content-injectie uit de checkout.
api-sync zelf blijft ongewijzigd qua logica: die heeft al een
sanitize-step, gepinde oasdiff en draait niet op untrusted triggers.
* fix(ci): herstel id-token: write voor claude-code-action
Vorige commit verwijderde id-token: write in de aanname dat geen
enkele step het OIDC-token consumeert. Dat was fout: claude-code-action
gebruikt het token intern om te authenticeren tegen de Anthropic
GitHub App. Zonder de permissie faalt elke run met:
Failed to get OIDC token: Unable to get
ACTIONS_ID_TOKEN_REQUEST_URL env variable
id-token: write is hersteld op de drie jobs die de action draaien
(claude, claude-review, api-sync/implement). De daadwerkelijke
hardening tegen ongeauthenticeerd misbruik blijft de auth-gate
(claude.yml) en de fork-gate (claude-code-review.yml): die zorgen
dat het token niet vanuit een untrusted trigger bereikbaar is. De
permissie zelf weghalen was geen mitigatie maar een storing.1 parent a478f2a commit 2abf017
3 files changed
Lines changed: 47 additions & 15 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
180 | 180 | | |
181 | 181 | | |
182 | 182 | | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
183 | 187 | | |
184 | 188 | | |
185 | 189 | | |
| |||
231 | 235 | | |
232 | 236 | | |
233 | 237 | | |
234 | | - | |
| 238 | + | |
235 | 239 | | |
236 | 240 | | |
237 | 241 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
10 | 17 | | |
11 | 18 | | |
12 | 19 | | |
13 | 20 | | |
14 | 21 | | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
15 | 26 | | |
16 | 27 | | |
17 | 28 | | |
| |||
21 | 32 | | |
22 | 33 | | |
23 | 34 | | |
24 | | - | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
25 | 39 | | |
26 | 40 | | |
27 | 41 | | |
| |||
34 | 48 | | |
35 | 49 | | |
36 | 50 | | |
37 | | - | |
| 51 | + | |
38 | 52 | | |
39 | 53 | | |
40 | | - | |
| 54 | + | |
41 | 55 | | |
42 | 56 | | |
43 | 57 | | |
44 | 58 | | |
45 | | - | |
| 59 | + | |
46 | 60 | | |
47 | 61 | | |
48 | | - | |
| 62 | + | |
49 | 63 | | |
50 | 64 | | |
51 | 65 | | |
52 | | - | |
| 66 | + | |
53 | 67 | | |
54 | 68 | | |
55 | | - | |
| 69 | + | |
56 | 70 | | |
57 | 71 | | |
58 | 72 | | |
59 | 73 | | |
60 | 74 | | |
61 | 75 | | |
62 | 76 | | |
63 | | - | |
| 77 | + | |
64 | 78 | | |
65 | 79 | | |
66 | 80 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
15 | 19 | | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
20 | 32 | | |
21 | 33 | | |
22 | 34 | | |
23 | 35 | | |
24 | 36 | | |
| 37 | + | |
| 38 | + | |
25 | 39 | | |
26 | 40 | | |
27 | 41 | | |
| |||
32 | 46 | | |
33 | 47 | | |
34 | 48 | | |
35 | | - | |
| 49 | + | |
36 | 50 | | |
37 | 51 | | |
38 | 52 | | |
| |||
0 commit comments