PERMISSION/PROTOCOL
Back to incident tracker

2026-06-01

HighPrimary

Flatt Security: Claude Code GitHub Action checkWritePermissions Bypass — Any GitHub App Hijacks CI/CD Pipelines; Cline npm Token Stolen in Wild Exploitation

Flatt Security disclosed a checkWritePermissions bypass in the Claude Code GitHub Action: any GitHub App passed the trust gate regardless of actual permissions. Exploited in the wild — Cline's npm publish token stolen February 2026. CVSS 7.8, $3,800 bounty.

Claude Code GitHub ActionCredential exposureAuthorization bypass in GitHub Action permission gate — CI/CD credential theft and supply chain compromiseAny public GitHub repository with the Claude Code GitHub Action installed — the bypass allowed untrusted GitHub Apps to trigger Claude Code workflow runs with write-level repository privileges

What happened

Attacker creates a GitHub App, installs it on their own repository to obtain an installation token, then uses that token to open an issue or PR on any target public repository that has the Claude Code GitHub Action installed. The App's actor name ends in [bot], passing the checkWritePermissions gate unconditionally. The attacker embeds prompt injection in the issue body; Claude Code processes it with write-level workflow privileges, reads /proc/self/environ, and exfiltrates OIDC tokens and CI/CD secrets to an attacker-controlled endpoint.

Why it matters

CI/CD secret and OIDC token theft from any public repository using the Claude Code GitHub Action. With stolen OIDC tokens, attackers can impersonate the workflow and access any downstream resource the workflow had permissions to reach — cloud provider APIs, npm publish tokens, package registry credentials, deployment targets. In the confirmed Cline exploitation: attacker stole the npm publish token and pushed an unauthorized [email protected] release, installing attacker-controlled code on approximately 4,000 developer machines before the package was pulled.

Missing authorization check

The permission gate must verify cryptographically confirmed write scope, not actor name suffix. GitHub App installation tokens do not carry implicit write grants — permission level must be checked against the app's actual installation grants for the target repository, not inferred from the actor identity string. A PP-style authority receipt would require the calling entity to demonstrate its permission scope via an independent channel before any workflow run proceeds.

Would PP block it?

The Flatt attack has two stages: (1) trigger the Claude Code workflow via the checkWritePermissions bypass, and (2) exfiltrate secrets via /proc/self/environ and use them to impersonate the workflow downstream. PP addresses stage 2 directly: stolen OIDC tokens cannot generate PP receipts, so actions taken with those tokens — including npm publishes and cloud API calls — would fail PP's authority check. Stage 1 (workflow trigger) is outside PP's current scope; the fix there is in the permission gate itself (verify actual write scope, not actor suffix). A complete defense requires both: the gate fix to prevent unauthorized triggers, and PP's Credential Gate to block unauthorized use of any credentials that leak during an unauthorized run.

Incident analysis

Timeline and technical read

Timeline

  1. 2026-01-12

    RyotaK (GMO Flatt Security) reports checkWritePermissions bypass to Anthropic. The vulnerability allows any GitHub App to pass the permission gate by meeting the [bot] actor suffix check, regardless of actual repository write permissions.

  2. 2026-01-16

    Anthropic fixes the permission bypass in claude-code-action. Additional misconfiguration issues reported January 17 and addressed in subsequent releases. Final fix confirmed in v1.0.94.

  3. 2026-02-17

    Wild exploitation confirmed: Cline's GitHub Actions workflow is compromised using a variant of the misconfiguration. Attacker steals the npm publish token and pushes unauthorized [email protected] to the npm registry, silently delivering attacker-controlled code to approximately 4,000 developer machines before the package is pulled. (Tracked separately as clinejection-cline-230-npm-supply-chain.)

  4. 2026-06-01

    Flatt Security publicly discloses the checkWritePermissions bypass. Anthropic confirms a $3,800 bug bounty plus $1,000 bypass documentation bonus. CVSS v4.0 score: 7.8. Full technical writeup published at flatt.tech/research/posts/poisoning-claude-code-one-github-issue-to-break-the-supply-chain/.

  5. 2026-06-01

    The Hacker News, CybersecurityNews, eSecurity Planet, and letsdatascience.com cover the public disclosure. Supply chain risk framing emphasizes that a single malicious GitHub issue could have compromised the Claude Code action's own source repository, propagating attacker code to every downstream repository using the action.

Technical breakdown

  • The checkWritePermissions function checked whether the triggering actor's name ended in [bot] as a proxy for 'this is a trusted GitHub App.' GitHub Apps use the naming convention <app-name>[bot] for their actor identity, but this suffix is not access-controlled — any GitHub App installation creates an actor with this naming pattern regardless of what permissions the app was granted.
  • GitHub Apps can create issues and PRs on public repositories using only a free installation token (public read access). This means the entire population of GitHub App actors — including completely untrusted, attacker-controlled apps — could pass the checkWritePermissions gate and trigger Claude Code workflow runs with write-level privileges in the target repository.
  • Once Claude Code processes an issue or PR from a bypassed actor, it runs with the workflow's full permission set. Claude Code's existing /proc/self/environ access pattern then becomes the exfiltration vector: ACTIONS_ID_TOKEN_REQUEST_TOKEN and ACTIONS_ID_TOKEN_REQUEST_URL from the process environment can be exchanged for privileged GitHub App installation tokens, escalating from issue-open access to full repository compromise.
  • The worst-case scenario identified by Flatt: if the Claude Code action's own source repository (anthropics/claude-code-action) were targeted, compromising it would propagate malicious changes to every repository using the action — a first-order supply chain attack with a blast radius proportional to Claude Code's adoption.
  • The Cline exploitation (February 2026) confirmed that the attack class was operationally viable before public disclosure. The attacker obtained the npm publish token and pushed an unauthorized [email protected] release, demonstrating that CI/CD secrets reachable from the workflow environment could be turned into real-world supply chain impact within the disclosure window.

Authorization boundary

Where the authorization boundary should have been

This incident is categorized as Credential exposure. The relevant Permission Protocol gate is Credential Gate. The read is conditional: the block only applies where the real action boundary is routed through a gate.

If enforced at
Credential Gate — any action requiring CI/CD secrets, publish tokens, or OIDC-derived credentials must carry a PP receipt signed by an authority channel that the bypassed workflow trigger cannot access
Still needs
Workflow trigger authorization (verifying that the actor that opened an issue/PR has actual write permissions before allowing Claude Code to process it); GitHub App permission scope verification at the gate layer
Receipt required for
All CI/CD credential uses downstream of a Claude Code workflow run — npm publish tokens, OIDC exchanges, cloud provider API calls, and any package registry push — must carry receipts signed before the workflow begins processing untrusted input

PP's Credential Gate prevents CI/CD secrets from flowing to unverified callers. Stolen OIDC tokens and workflow credentials cannot produce PP-signed authority receipts — the signing authority is separate from the credential chain. However, PP does not currently prevent the initial workflow trigger via a bypassed permission gate; it would block the downstream secret exfiltration and unauthorized publish action, but not the trigger itself.

Start small

Put the relevant gate at this action boundary.

This incident maps to Credential Gate. Start with the boundary that controls the actual action, then require a signed receipt before execution.

Replay this incident with a signer in the loop