The security problem with autonomous agents in CI/CD

Agentic workflows promise to scale software engineering by letting AI agents handle everything from documentation fixes to unit tests and refactoring. But that automation introduces a fundamental challenge: agents are non-deterministic. They consume untrusted inputs—web pages, issue reports, pull request comments—and reason over repository state to make decisions at runtime. That makes them radically different from the deterministic scripts that have traditionally run in CI/CD pipelines.

GitHub Agentic Workflows run on GitHub Actions, where everything in a job shares a single trust domain. That permissive model is fine for predictable automation with broad access and composability. But a buggy or prompt-injected agent with unrestricted access to that environment can interfere with MCP servers, exfiltrate authentication secrets, and make arbitrary network requests. The security architecture therefore treats agent execution as an extension of the CI/CD model, not a separate runtime. The design separates open-ended authoring from governed execution, then compiles a workflow into a GitHub Action with explicit constraints on permissions, outputs, auditability, and network access.

Threat model: assume the agent is hostile

Two properties of agentic workflows fundamentally change the threat model. First, agents reason over repository state and act autonomously, which means they cannot be trusted by default. Second, the permissive nature of GitHub Actions means a single trust domain creates a large blast radius when an untrusted agent is introduced. The architecture assumes an agent will attempt to read and write state it shouldn't, communicate over unintended channels, and abuse legitimate channels to perform unwanted actions. Agentic Workflows therefore default to a strict security mode guided by four principles: defense in depth, no secrets for agents, staged and vetted writes, and comprehensive logging.

Layered defense

The security model is built from three layers, each enforcing distinct properties that limit the impact of failures above it.

Diagram of a three-layer system architecture with labeled sections Planning layer, Configuration layer, and Substrate layer. Each layer contains three blue tiles:

Planning: Safe Outputs MCP (GitHub write operations), Call filtering (call availability, volume), Output sanitization (secret removal, moderation).
Configuration: Compiler (GH AW extension), Firewall policies (allowlist), MCP config (Docker image, auth token).
Substrate: Action runner VM (OS, hypervisor), Docker containers (Docker daemon, network), Trusted containers (firewall, MCP gateway, API proxy).

Substrate layer

At the base is a GitHub Actions runner VM with several trusted containers that constrain what an agent can access. The substrate provides isolation between components, mediation of privileged operations and system calls, and kernel-enforced communication boundaries. These protections hold even if a user-level component is compromised and executes arbitrary code within its container boundary.

Configuration layer

Above the substrate, declarative artifacts and their toolchains instantiate the secure system structure. The configuration layer determines which components load, how they connect, what communication channels are permitted, and what privileges are assigned. Externally minted tokens—agent API keys and GitHub access tokens—are the critical inputs that bound a component's external effects, and configuration controls which tokens reach which containers.

Planning layer

The top layer stages the workflow over time. While the configuration layer defines which components exist and how they communicate, the planning layer determines which are active and when, creating explicit data exchanges between stages. The safe outputs subsystem is the primary instance of this secure planning.

Zero secrets for agents

The core requirement from the start was that agentic workflow agents should have zero access to secrets. In a standard GitHub Actions execution, sensitive material like agent authentication tokens and MCP server API keys live in environment variables and configuration files that every process in the VM can read. That is dangerous because agents are susceptible to prompt injection: a malicious web page or repository issue can trick an agent into leaking credentials through shell commands, configuration files, /proc state, or workflow logs—then exfiltrate them over the internet or encode them in public GitHub objects.

The first mitigation is to isolate the agent in a dedicated container with tightly controlled egress. The agent gets firewalled internet access through a private network, MCP communication through a trusted MCP gateway, and LLM API calls through an isolated API proxy. The MCP gateway runs in its own trusted container and has exclusive access to MCP authentication material. LLM tokens stay in the proxy rather than the agent container, so agents like Claude, Codex, and Copilot route model traffic through it without ever seeing their own credentials.

Architecture diagram showing several connected Docker containers. A Codex token connects to an api-proxy container, which connects to an OpenAI service icon. A separate flow shows an agent container (linked to chroot/host) communicating over http to a gh-aw-firewall container, then over http to a gh-aw-mcpg container (linked to Host Docker Socket), then over stdio to a GitHub MCP container (linked to a GitHub PAT). A GitHub icon appears above the GitHub MCP container.

Zero-secret agents require a trade-off with utility. Coding workloads need access to compilers, interpreters, scripts, and repository state, but provisioning all of that inside the agent container would duplicate existing Actions provisioning logic and expand the firewall allowlist. Instead, the agent runs in a chroot jail rooted at /host, with the entire host file system mounted read-only. Selected writable paths are then overlaid with empty tmpfs layers. This keeps the host-side setup intact while constraining the agent's writable and discoverable surface to exactly what the job requires.

Staged and vetted writes

Even without secrets, a rogue agent can cause harm: spamming issues and pull requests, adding objectionable URLs or content to repository objects, or overwhelming maintainers. To prevent this, the agentic workflows compiler decomposes a workflow into explicit stages, each defining the active components and permissions (read versus write), the data artifacts that stage emits, and the admissible downstream consumers of those artifacts.

While running, the agent reads GitHub state through the GitHub MCP server and stages updates only through the safe outputs MCP server. When the agent exits, a suite of analyses processes the buffered write operations.

Diagram showing a GitHub-centric workflow with green arrows and two rows of components. At the top, a GitHub icon points down into three boxes: Agent (Untrusted), GitHub MCP (Read-only), and MCP config (Write-buffered). Below are three processing steps labeled Filter operations, Moderate content, and Remove secrets, each marked 'Deterministic analysis.' Green arrows indicate data flow from GitHub into the system, down through configuration to 'Remove secrets,' then left through 'Moderate content' and 'Filter operations,' looping back toward the agent.

Safe outputs enforce three things. First, workflow authors specify which GitHub operations an agent may perform—for instance, limiting it to issues, comments, or pull requests. Second, the system caps the number of updates, such as restricting a run to three pull requests. Third, content analysis removes unwanted patterns like embedded URLs. Only artifacts that pass the entire pipeline move downstream, so every stage's side effects are explicit and vetted.

Comprehensive observability

No amount of prevention guarantees that an agent will not attempt to transform repository data, invoke tools in unintended ways, or try to escape its constraints. Post-incident analysis requires a complete execution trail, and agentic workflows log extensively at every trust boundary. The firewall records network and destination-level activity; the API proxy captures model request and response metadata; the MCP gateway logs tool invocations. The agent container is instrumented to audit sensitive actions such as environment variable accesses.

These logs support end-to-end forensic reconstruction, policy validation, and anomaly detection. They also lay the foundation for future information-flow controls: every location where communication can be observed is a location where it can be mediated. Agentic Workflows already support lockdown mode on the GitHub MCP server, and additional safety controls are planned that will enforce policies based on repository object visibility (public versus private) and author role.