Buildcage for Docker

August 13, 2026 ยท View on GitHub

Buildcage

GitHub version build test license

Secure your Docker builds against supply chain attacks: restrict outbound network access to only the domains you allow.

When a compromised dependency pulled in by RUN npm install, RUN pip install, or any other build command tries to exfiltrate secrets or phone home, Buildcage blocks it: only the domains you specify are reachable. No Dockerfile changes, no proxy configuration, no certificates to install: works with any language or package manager.

  • Protects docker build: every RUN step, zero Dockerfile changes
  • Self-contained on GitHub: no external service, no telemetry, free and open source

This is not a hypothetical risk: the Shai-Hulud npm worm compromised hundreds of packages whose postinstall scripts exfiltrated CI/CD secrets straight out of the build environment. npm v12 disables install scripts by default, closing off that specific path, but builds still handle secrets and run plenty of other commands that could do the same thing. That's the layer Buildcage protects, regardless of which command triggers it.

Buildcage report showing allowed and blocked connections

A build tries to reach an unexpected domain. Buildcage blocks it and records it in the report. This is what your report looks like after completing the audit โ†’ restrict flow below.

Features

  • ๐Ÿš€ Zero Dockerfile changes: Your Dockerfile and build commands stay exactly as they are
  • ๐Ÿ” Dependency discovery: Discover what your build already talks to before enforcing anything (audit mode)
  • ๐Ÿ›ก๏ธ Allowlist enforcement: Block every destination except the ones you explicitly allow (restrict mode)
  • ๐Ÿ”’ Network isolation: Isolates network access per Dockerfile RUN step, so only explicitly allowed destinations are reachable
  • ๐Ÿ“Š Detailed logging: Every destination your build reaches, reported directly in GitHub's Job Summary

Quick Start

Using Buildcage comes down to three steps: start the Buildcage container, point Docker Buildx at it as a remote builder, then run your build as usual: your Dockerfile and build commands don't change. Steps 2 and 3 use Docker's own setup-buildx-action and build-push-action, so any Buildx-based tool works the same way, including docker/bake-action: just point its driver: remote and endpoint at Buildcage.

Step 1: Discover what domains your build needs (Audit Mode)

- name: Start Buildcage in audit mode
  uses: buildcage/docker@4878a0c897d728304820dc65005ad22bac353be2 # v3.0.0
  with:
    proxy_mode: audit # Log every destination, block nothing

- name: Set up Docker Buildx
  uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
  with:
    driver: remote
    endpoint: docker-container://buildcage

- name: Build Docker image
  uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
  with:
    context: .
    push: false # Set to true to push the built image

- name: Show Buildcage report
  if: always()
  uses: buildcage/docker/report@4878a0c897d728304820dc65005ad22bac353be2 # v3.0.0

See the complete example workflow.

Step 2: Check the report

The report action outputs a Job Summary showing every destination your build contacted:

Outbound Traffic Report - audit mode

Same workflow, run first in audit mode: every destination is logged, nothing is blocked yet.

Copy these domain names into allowed_https_rules or allowed_http_rules for Step 3.

Step 3: Create your allowlist and switch to restrict mode

- name: Start Buildcage in restrict mode
  uses: buildcage/docker@4878a0c897d728304820dc65005ad22bac353be2 # v3.0.0
  with:
    proxy_mode: restrict # Block every destination except the ones you allow
    allowed_https_rules: |
      registry.npmjs.org:443
      fonts.googleapis.com:443

- name: Set up Docker Buildx
  uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
  with:
    driver: remote
    endpoint: docker-container://buildcage

- name: Build Docker image
  uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
  with:
    context: .
    push: false # Set to true to push the built image

- name: Show Buildcage report
  if: always()
  uses: buildcage/docker/report@4878a0c897d728304820dc65005ad22bac353be2 # v3.0.0
  # Build fails if any unexpected connections were blocked

See the complete example workflow.


Your builds are now protected. Any unexpected connections will be blocked and reported.

For the full parameter reference, rule syntax, and operation modes, see the Reference doc.

How It Works

Buildcage runs as a remote driver for Docker Buildx and routes each RUN step's outbound traffic through a proxy that enforces your allowlist, without touching your Dockerfile. No agent installed on the runner is required.

See Reference for the full mechanism, including Docker build's experimental proxy engine switch.

Important

Buildcage controls where your builds can connect, not what code they run. If a malicious package is delivered through a legitimate repository (e.g., a compromised npm package hosted on registry.npmjs.org), Buildcage cannot detect or prevent it: the connection goes to an allowed domain.

Don't make Buildcage your only supply chain security measure. Use it as one layer in a defense-in-depth strategy, a last line of defense. If something slips through your other measures, at least it can't call home.

See Security Considerations for full details.

Comparison

The closest tools in this space are StepSecurity Harden-Runner and Bullfrog, both of which control outbound traffic for an entire GitHub Actions job rather than one build step.

Harden-Runner is a broader security agent, monitoring network, file integrity, and process activity across the whole runner. Buildcage stays narrower on purpose: it only restricts outbound traffic during a Docker build and does nothing else. That focus is also why it stays entirely within your GitHub Actions job: no external dashboard, no account, no tier to unlock for private repos or self-hosted runners.

Bullfrog is free and open source too, but the architecture differs. It allowlists by resolving a domain to an IP address and then permitting that IP, without inspecting the SNI or Host header of the actual connection, so shared infrastructure like a CDN can end up permitting more than the intended domain. Its own documentation also states that jobs running in containers aren't supported, which rules out protecting a Docker build. Buildcage matches on the domain itself and isolates each RUN step individually.

FAQ

  • Does this slow down my builds?

    Minimal impact. Buildcage runs locally, alongside your build, so checking a destination against your allowlist adds no meaningful latency.

  • Can I use this with multi-stage builds?

    Yes. Buildcage doesn't fork or patch BuildKit itself; it only wires up how build traffic is routed, so multi-stage Dockerfiles work exactly as they would without Buildcage.

  • Does this work with private package registries?

    Yes. Just add your private registry's domain to allowed_https_rules (e.g., registry.example.com:443).

  • What happens if I forget to add a required domain?

    In restrict mode, the build will fail with a clear error message. Run in audit mode first to discover all required domains.

  • Can I allow access to an IP address (e.g., http://192.168.1.1)?

    Yes. Add the IP address with a port to allowed_ip_rules (e.g., 192.168.1.1:80). Only IPv4 addresses are supported, and CIDR notation isn't, but a regex rule can match a range (e.g., ~^192\.168\.1\.\d+:80$).

  • Does this protect against malicious code execution?

    No. Buildcage only controls network access. It doesn't prevent malicious code from running; it prevents that code from communicating with external servers.

  • I need to isolate a run: step, not a Docker build โ€” is there something for that?

    Yes: buildcage/isolated-run applies the same network-isolation technology directly to a workflow run: step. It used to live in this repository as an experimental run action; it's now a separate project so it can version and release independently of Docker-build isolation.

  • Can I host Buildcage in my own private repository?

    Yes, see the Self-Hosting Guide. Most projects don't need to, though: pinning the action to a commit SHA (uses: buildcage/docker@<sha> # vX.Y.Z) locks in an exact, Sigstore-verified image for that release, which covers most of the same risk self-hosting is meant to address, without the overhead of maintaining a fork.

Documentation

DocWhat's in it
ReferenceFull parameter reference, operation modes, and how each proxy engine works under the hood
Rule SyntaxWildcard, regex, and IP rule syntax in detail
Security DetailsArchitecture, attack resistance, and known limitations
Self-Hosting GuideHosting your own Buildcage image in a private repository
Development GuideLocal usage, testing, logs, and implementation internals

Why I Built This

Supply chain attacks keep getting more varied and more sophisticated: typosquatted packages, compromised maintainer accounts, malicious postinstall scripts. No single control catches all of it. Defense-in-depth is the baseline now, not an aspiration.

Buildcage is meant to be one of those layers: even if a secret gets stolen, it can't leave the build environment. Layers like that only help if people actually deploy them. Real network isolation for a build usually means someone on a security team configuring egress rules and maintaining them over time. Most projects, especially small ones, don't have that, not because they don't care, but because it's more setup than a side project or a small team has time for.

I wanted adopting this layer to take nothing more than adding an action. The easier it is to adopt, the more systems get that protection, and the more people's personal information stays where it belongs.

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests at github.com/buildcage/docker.

Show Your Support

Knowing that this project is useful to others gives me the motivation to keep working on it. If you find Buildcage helpful, please consider giving it a star โญ on GitHub!

Disclaimer

This software is provided "as is", without warranty of any kind, express or implied. The authors and contributors are not liable for any damages, losses, or security incidents arising from the use of this software. Use at your own risk.

License

The Buildcage source code is licensed under the MIT License. See LICENSE file for details.

The Docker image includes third-party components under their own licenses (GPL, Apache 2.0, ISC, etc.). See THIRD_PARTY_LICENSES for the full list.