Securing CI/CD in an agentic world: Claude Code Github action case
Microsoft discovers prompt injection vulnerability in Claude Code GitHub Action allowing CI/CD workflow secret access.
Summary
Microsoft Threat Intelligence identified a prompt injection vulnerability in Anthropic's Claude Code GitHub Action that could expose CI/CD workflow secrets when AI agents process untrusted GitHub content (issue bodies, PRs, comments). The vulnerability allowed the Read tool to access /proc/self/environ, exposing the ANTHROPIC_API_KEY and other credentials. Anthropic mitigated the issue in version 2.1.128 by blocking access to sensitive /proc files, and Microsoft provides guidance for securing AI-powered CI/CD workflows against similar attacks.
Full text
Share Link copied to clipboard! Tags CI/CDFrontier AI modelsVulnerability Content types Research Products and services Microsoft Defender Topics Actionable threat insightsAI and agentsDefending against advanced tactics Microsoft Threat Intelligence discovered that Anthropic’s Claude Code GitHub Action could expose CI/CD workflow secrets when AI agents process untrusted GitHub content, including issue bodies, pull request descriptions, and comments. We found that while Claude Code Action supported environment scrubbing for subprocess execution paths such as Bash, the Read tool was not subject to the same sandboxing model. It was eventually authorized to access /proc/self/environ, reading the workflow’s ANTHROPIC_API_KEY and potentially other credentials available to the runner. Following our responsible disclosure, Anthropic mitigated this issue in Claude Code version 2.1.128 by blocking access to sensitive /proc files. Defenders should treat AI workflows that process untrusted GitHub content as high-risk when they also have access to secrets, file-read tools, or external communication channels. We began this research after observing prompt injection attempts in public repositories using AI-assisted GitHub workflows across multiple vendors, where attacker-controlled issue or PR content is processed by the AI agent and could influence its tool use. For example: Prompt injection hidden as HTML comment The injection payload was placed inside an HTML comment (<!– –>), making it invisible when the issue is rendered in the browser but still visible to the AI model which reads the raw markdown: Figure 1. HTML comment hidden inside an issue opened by the actor. XSS Injection via issue triage workflow The target repository – fork of a major open-source documentation project – used a highly permissive GitHub Actions workflow to automate issue resolution. We believe the actor is using a fork to test which payloads work before disclosing or exploiting them. Whenever a user opened a new issue, an AI bot interpreted the request and was granted robust operational tools to resolve it: search_local_git_repo read_local_git_repo_file_content create_pull_request_from_changes This tool chain, operating without external oversight, provided an unauthorized user with the exact high-level primitives needed to plant malware without directly possessing write access. Disguising the attack as a legitimate feature request for “diagnostic telemetry”, the payload provided the AI with a precise sequence of commands rather than a standard conversational prompt. It instructed the bot to search for a specific markdown heading, read the target file’s contents, append an exact block of malicious HTML, and immediately invoke the pull request tool to commit the newly poisoned file, effectively steering the AI step-by-step through a supply-chain compromise. The attack vector successfully coerced the bot into locating the target documentation file and appending an invisible XSS image tag: Had this PR been merged by a maintainer or by automated CI/CD automation, rendering the documentation site would execute JavaScript on visitors’ machines to silently exfiltrate their session tokens to the attacker’s endpoint. This same trust boundary is what makes the Read tool vulnerability exploitable: once an attacker can influence the agent, they might be able to steer it toward sensitive files available inside the CI runner environment. To understand the vulnerability described in this blog, it helps to first understand the environment in which they operate. GitHub Actions workflows were designed for deterministic automation—running tests, deploying builds, and enforcing policy. But as AI-powered tools like Claude Code Action have entered that environment, they’ve brought up a fundamentally different execution model: one where natural language can be treated as instruction. The sections below walk through how that model works, where the security boundaries are drawn, and critically, why those boundaries fail. GitHub workflows: What they are and how they execute code GitHub Actions is GitHub’s native automation and CI/CD platform. A workflow is a YAML configuration file that defines jobs to run when repository events occur, such as pull_request, issue_comment, scheduled runs, or manual dispatch. When a workflow is triggered, GitHub executes its jobs on a runner: an ephemeral virtual machine, or in some cases a self-hosted environment. That runner is not just executing code in isolation. Depending on the workflow configuration, it may receive repository contents, issue and pull request metadata, environment variables, the GITHUB_TOKEN, cloud credentials, package publishing tokens, and third-party API keys. Where AI enters GitHub workflows GitHub workflows were built for deterministic automation: run tests, build artifacts, deploy code, label issues, or enforce repository policy. AI-powered workflows change that model. Instead of only executing predefined logic, they ingest repository context, interpret natural-language input, and decide which actions to take next. A common example is AI-based pull request review. Tools such as Anthropic’s Claude Code GitHub Action can trigger on pull requests, read the diff, title, description, and comments, then post review feedback or security findings. In more advanced configurations, the same agent can modify files, create commits, or open follow-up pull requests from inside the CI runner. Despite differences between vendors and implementations, the security pattern is consistent: GitHub events provide workflow context. Some of that context is untrusted user-controlled content. The content is embedded into an LLM prompt. The model’s output is treated as actionable. The agent runs inside a CI environment with access to secrets, repository data, and tools such as Bash, file access, or GitHub APIs. These integrations are not necessarily careless. Most include system prompts, filters, and policy logic intended to separate user content from control instructions. But when those boundaries fail, the workflow is no longer just automation. It becomes an AI agent embedded inside the repository, and its prompt construction, tool permissions, and runtime isolation become part of the security perimeter. Claude Code action Claude Code Action is a GitHub action that runs Claude inside your CI runner. Under the hood, it’s a wrapper around the Claude Agent SDK (software development kit). The Claude Code Action handles GitHub-specific concerns (parsing the event, fetching issue/PR context, building the prompt, wiring up MCP (Model Context Protocol) servers, managing tracking comments) and then calls the SDK’s query function to drive Claude. Tool permissions, model selection, and most other runtime behavior are SDK options that the action is responsible for setting. Vulnerability details Figure 2: Attack flow. When Anthropic designed Claude Code Actions, they knew the risks. For the Bash tool, they support Bubblewrap (namespace-based Linux sandbox) with a scrubbed environment (enforced by CLAUDE_CODE_SUBPROCESS_ENV_SCRUB , auto enabled for actions that can be triggered by non-write users). This is a solid defense. However, a gap exists: the Read tool is not subject to the same isolation. Rather than routing Read operations through the same secure isolation boundary as Bash, these operations represent direct, in-process calls. They inherently bypass the Bubblewrap sandbox, operating with full access to the process’s environment variables. To confirm the exploitability of this gap, we constructed a prompt injection payload. We tested this in a lab environment, specifically a non-write user enabled, which forces the CLAUDE_CODE_SUBPROCESS_ENV_SCRUB mitigation active. We then injected this malicious prompt, the kind that naturally flows through issue bodies, PR comments, or other input: Figure 3: The malicious prompt. This prompt defeats two distinct layers of defense: Claude’s safety / s
Indicators of Compromise
- mitre_attack — T1005 - Data from Local System
- mitre_attack — T1059 - Command and Scripting Interpreter
- mitre_attack — T1570 - Lateral Tool Transfer