Reference

August 15, 2026 · View on GitHub

Setup Action (buildcage/docker)

Starts the Buildcage builder container.

- name: Start Buildcage builder
  uses: buildcage/docker@567c77b193bcb93d3a534e3bf1481e2543bb9811 # v3.0.1
  with:
    proxy_mode: restrict
    allowed_https_rules: |
      registry.npmjs.org:443
      github.com:443

Parameters

ParameterRequiredDefaultDescription
builder_nameNobuildcageName of the builder container
proxy_modeNorestrictOperation mode (audit / restrict)
proxy_engineNotransparentNetwork enforcement engine (transparent / explicit, see Proxy Engines)
allowed_https_rulesNoemptyHTTPS allow rules (wildcard or regex, port required)
allowed_http_rulesNoemptyHTTP allow rules (wildcard or regex, port required)
allowed_ip_rulesNoemptyIP address allow rules (wildcard or regex, port required)
known_blocked_rulesNoemptyDomains expected to be blocked intentionally (wildcard or regex, port required); blocked connections matching these don't fail the report step even when fail_on_blocked is true — see Report Action below

Rule Syntax

PatternExampleMatches
Exact domainexample.com:443example.com on port 443 only
Single-level wildcard*.example.com:443sub.example.com on port 443 (not deep.sub.example.com)
Multi-level wildcard**.example.com:443sub.example.com and deep.sub.example.com on port 443
Single-char wildcardexampl?.com:443example.com, examplx.com on port 443
Wildcard portexample.com:*example.com on any port
Regex~^custom\.pattern:\d+$Matched against domain:port

IP address rules (e.g., 192.168.1.1:443) use the same syntax but go in allowed_ip_rules.

For detailed syntax, see Rule Syntax.

Connecting Buildx

Pass the container name to docker/setup-buildx-action to use Buildcage as a remote builder. The endpoint must match the builder_name parameter (default: buildcage):

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

Operation Modes

Set the proxy_mode parameter to control how Buildcage handles outbound connections:

proxy_modeWhen to useBehavior
audit First-time setup, adding new dependencies, or investigating issues
  • Allows all connections the active engine can observe — each engine still rejects what it can't classify, on its own terms (see Proxy Engines below)
  • Logs every domain accessed during the build
restrict Production builds, CI/CD pipelines, security-critical environments
  • Allows connections only to domains in allowed_http_rules / allowed_https_rules
  • Blocks all other connections
  • Logs allowed and blocked attempts

See the audit mode and restrict mode example workflows for each in full.

Proxy Engines

proxy_engine selects how Buildcage intercepts and enforces traffic. Two engines are available:

  • transparent (default): a transparent proxy — traffic is intercepted at the network level, with no proxy configuration or CA trust needed inside the build
  • explicit: BuildKit's native --proxy-network — injects HTTP_PROXY/HTTPS_PROXY and a CA certificate, then MITMs the traffic to inspect requests directly

It's independent of proxy_mode (audit/restrict): either engine works with either mode, and both use identical allowed_https_rules / allowed_http_rules / allowed_ip_rules syntax.

transparent (default)explicit
Isolation mechanismCNI network + DNS redirectionBuildKit native --proxy-network (point-to-point network namespace)
TLS handlingNot terminated — SNI (HTTPS) / Host header (HTTP) inspected onlyTerminated (MITM) via an injected CA — full host and path visible
Dockerfile / tool changesNone requiredNone for tools that already respect HTTP_PROXY/HTTPS_PROXY and trust the system CA store (most OpenSSL-based tools); a tool that bundles its own CA store (e.g. npm) needs an env var or flag pointing it at the system CA store — see CA Trust for Tools with Their Own CA Store below
Enforcement granularityDomain (and port)Domain (and port) — same as transparent; the decrypted path is visible for logging but isn't matched by allowed_*_rules
allowed_ip_rules enforcementRaw TCP passthrough — no protocol inspection once ip:port matchesSame as domain rules — matched and MITM'd via the BuildKit source policy, not a special-cased passthrough
Non-cooperative tools (ignore proxy env vars, or open raw sockets)Still observed, blocked, and logged — network-level enforcement, no opt-outBlocked with "network unreachable" — invisible, no trace anywhere in the report
Report detailAllowed / blocked hostsAllowed / blocked hosts (with full path), plus a per-step "Communication details" breakdown
BuildKit provenance / SLSA integrationNot integratedIntegrated into BuildKit's own build output and SLSA provenance
Best forDefault choice — works with any tool regardless of proxy-awarenessCooperative tools, when path-level visibility or provenance integration matters more than catching non-cooperative traffic

transparent enforces at the network layer regardless of whether a tool cooperates, so every connection attempt is observed and recorded — this is why it's the default. Use explicit if you need full URL/path-level visibility integrated into BuildKit's own build output and SLSA provenance, and your build's tools are known to respect HTTP_PROXY/HTTPS_PROXY. See Explicit Proxy Engine for the full technical detail. See the complete example workflow for a working explicit engine setup, including the CA trust workaround below.

CA Trust for Tools with Their Own CA Store

Under proxy_engine: explicit, BuildKit injects its generated CA directly into the container's own system CA bundle file, so tools that consult that file the normal way (most tools built on OpenSSL — curl, git, Go binaries, etc.) already trust it with no configuration. A tool that instead bundles its own separate CA store ignores that file entirely and still fails with a TLS/certificate error, even though HTTP_PROXY/HTTPS_PROXY are set correctly.

npm is the common case — point it at the system CA store BuildKit already patched, either inline on the command that needs it:

RUN NODE_USE_SYSTEM_CA=1 npm install

or once per stage if it runs npm more than once:

FROM node:22-alpine
ARG NODE_USE_SYSTEM_CA=1
RUN npm install
RUN npm run build

If a different tool fails the same way — a RUN step that works under transparent (or without Buildcage at all) but fails with a TLS/certificate error under explicit — check that tool's own documentation for an equivalent setting; this is specific to tools that maintain their own CA store rather than consulting the system one.

Usage Notes

  • Start with audit mode to discover required domains, then switch to restrict mode.

  • Separate HTTP and HTTPS domains — some services use different hosts for each protocol.

  • Common package registries often use multiple domains (e.g., PyPI uses both pypi.org and files.pythonhosted.org).

  • Some package managers download over plain HTTP (e.g., certain Debian mirrors). Add those domains to allowed_http_rules separately:

    allowed_http_rules: deb.debian.org:80
    allowed_https_rules: registry.npmjs.org:443
    

Note

The Docker image is always pulled from ghcr.io/<action-owner>/<action-repo> and its build provenance is cryptographically verified (keyless signature) before the image is pulled. External image overrides are not supported to preserve this guarantee. For best security, pin the action to a commit SHA: uses: buildcage/docker@<40-char-sha> # vX.Y.Z

Self-hosting with a custom image requires forking the repository. See the Self-Hosting Guide. If the action package is private (self-hosted in a private repository), run docker/login-action with packages: read before this action — credentials stored by Docker are picked up automatically.


Report Action (buildcage/docker/report)

Displays communication logs after builds and optionally fails if any BLOCKED connections are found.

- name: Show proxy report
  if: always()
  uses: buildcage/docker/report@567c77b193bcb93d3a534e3bf1481e2543bb9811 # v3.0.1

Job Summary

Audit mode:

Outbound Traffic Report - audit mode

Use the domain names shown in the report to create your allowlist for restrict mode.

Restrict mode:

Outbound Traffic Report - restrict mode

In restrict mode, the report step fails if blocked connections are detected, causing the workflow to fail. You can disable this by setting fail_on_blocked: false. In audit mode, blocked connections (e.g., protocol errors) are reported but never cause the step to fail.

If some blocked connections are expected — a known-noisy dependency, a domain you're deliberately keeping off the allowlist to confirm it stays blocked — list them in setup's known_blocked_rules input (same syntax as allowed_https_rules, see Rule Syntax). When every blocked connection matches known_blocked_rules, the step no longer fails even with fail_on_blocked: true, and a ::notice:: is emitted instead of ::error::; any other, unmatched blocked connection still fails the step as before. Once known_blocked_rules is set, the Job Summary's Blocked Hosts table gains an extra Expected column (✅) marking the matched rows.

Parameters

ParameterRequiredDefaultDescription
builder_nameNobuildcageName of the builder container
fail_on_blockedNotrueFail the step if blocked connections are detected (restrict mode only; ignored in audit mode)