Releases: buildcage/docker
Release list
v3.0.3
🎉 Now on GitHub Marketplace
Buildcage for Docker is published to the GitHub Marketplace as of this release.
Nothing changes about how you use the action — this release exists to create the listing. uses: buildcage/docker@<sha> keeps working exactly as before, and there is no reason to upgrade for the changes below. The name, description, and icon shown on the listing shipped in v3.0.2; the two changes here are release plumbing.
CI / Maintenance
- Add
artifact-metadata: writepermission for the image attestation storage record (#272)actions/attestdefaultscreate-storage-recordtotrue, which needs that permission. Without it the attestation itself still succeeded — the image was signed and the Sigstore bundle published normally — but the storage record wasn't created and each publish logged ano artifacts foundwarning.
- Remind the publisher to tick the Marketplace checkbox (#271)
- Publish this Action to the GitHub Marketplace has no field in the release API, so it has to be set by hand on every release. The release workflow's job summary now says so.
Full Changelog: v3.0.2...v3.0.3
v3.0.2
CI / Maintenance
- Name and describe the actions for the Marketplace (#270)
Setup BuilderandReportwere internal working names — too generic to be unique on the Marketplace, and neither said what the action does. They're nowBuildcage for DockerandBuildcage Report, with a Marketplace description and branding. Steps that don't set their ownname:will show the new label in workflow logs.
- Ignore reachability-verified CVEs in the monthly image scan (#268)
- Trivy's binary scan flags CVEs against the Go toolchain and stdlib baked into each vendored binary whether or not the vulnerable path is reachable. Nine were triaged against the threat model in
docs/security.md(and, for the explicit engine, against buildkit v0.32.0's--proxy-networkimplementation), confirmed unreachable, and recorded in.trivyignorewith the reasoning inline.
- Trivy's binary scan flags CVEs against the Go toolchain and stdlib baked into each vendored binary whether or not the vulnerable path is reachable. Nine were triaged against the threat model in
Documentation
- Make the README the usage manual (#259)
docs/reference.mdanddocs/rules.mdare folded into the README, so everything needed to adopt the action — inputs, operation modes, rule syntax, proxy engines, the report action — is on one page instead of split across three. Both files stay behind as stubs pointing at the matching README sections: releaseddist/builds namedocs/reference.mdin a runner-requirement error message, so anyone hitting it on a pinned older version still lands somewhere useful.- The experimental
explicitengine moves to its owndocs/explicit-engine.md, which now also spells out that the TLS interception is BuildKit's own--proxy-networkfeature — Buildcage neither implements nor operates that proxy and never holds the CA key. - What Buildcage is and why it exists moved to the new landing page at buildcage.github.io, leaving the README to cover only how to use it.
Dependencies
- Bump
moby/buildkitDocker tag to v0.32.0 (#266) - Bump
rolldownto v1.2.1 (#262) - Bump
pnpmto v11.19.0 (#267) - Bump
vite-plusto v0.2.7 (#263) - Bump
github/codeql-actionto v4.37.4 (#264) - Bump
docker/login-actionto v4.6.0 (#265) - Bump
actions/attestto v4.2.1 (#260)
Full Changelog: v3.0.1...v3.0.2
v3.0.1
Bug Fixes
- Fail restrict-mode builds with zero outbound traffic despite nothing being blocked (#257)
- The haproxy log's plausibility check couldn't tell "no traffic occurred" apart from a tampered log, so
fail_on_blocked: truefailed builds even withblockedCount: 0. The proxy now always logs a fixed startup line so the check has something to see.
- The haproxy log's plausibility check couldn't tell "no traffic occurred" apart from a tampered log, so
Documentation
- Restore Docker framing to the README after the
runaction split (#255)- Reverts wording and heading levels genericized to cover both
docker buildandrun, and drops the now-orphanedrundiagrams.
- Reverts wording and heading levels genericized to cover both
- Title the README "Buildcage for Docker" to name it within the family (#256)
- Names which
buildcageorg member this repo is, alongsidebuildcage/isolated-run.
- Names which
Dependencies
- Pin
uses:examples in the README and docs to the v3.0.0 release SHA (#254)
Full Changelog: v3.0.0...v3.0.1
v3.0.0
Breaking Changes
-
Repository transferred to
buildcage/docker;setupflattened to the repo root (#245, #253)- This repo moved from
dash14/buildcagetobuildcage/docker. GitHub automatically redirectsuses:references pinned to an existingdash14/buildcageref, so workflows already pinned to v2.x or an older SHA keep working with no action needed. Upgrading to v3.0.0 does require updating theuses:line, though —setupalso moved from asetup/subdirectory to the repo root as part of the same change (mirroring howbuildcage/isolated-runis laid out), so it's no longer just an owner rename. reportis unaffected in shape — only the owner changes, it's still a subdirectory:buildcage/docker/report@v3.
Before (v2.x):
- uses: dash14/buildcage/setup@<sha> # v2.3.0 - uses: dash14/buildcage/report@<sha> # v2.3.0
After (v3.0.0):
- uses: buildcage/docker@<sha> # v3.0.0 - uses: buildcage/docker/report@<sha> # v3.0.0
- This repo moved from
-
runaction removed from this repo — moved tobuildcage/isolated-run(#244)- The experimental
runaction no longer lives here at any version and isn't reachable via the owner-transfer redirect above (it's a removal, not a rename). If your workflow usesdash14/buildcage/runorbuildcage/docker/run, switch tobuildcage/isolated-run, which now versions and releases independently.
- The experimental
CI / Maintenance
- Adopt vitest-style
expect()assertions, powered by chai under QuickJS too (#242) - Finish migrating tests off
node:assertto vitestexpect()(#243)
Dependencies
- Bump
github.com/moby/buildkitmodule to v0.32.0 (#240) - Bump
actions/checkoutto v7.0.1 (#246) - Bump
vite-plusto v0.2.6 (#247) - Bump
github/codeql-actionto v4.37.3 (#248) - Bump
ossf/scorecard-actionto v2.4.4 (#249) - Bump self-referential
dash14/buildcageaction pin to v2.3.0 (#250) - Bump
docker/login-actionto v4.5.1 (#251) - Bump
pnpmto v11.17.0 (#252)
Full Changelog: v2.3.0...v3.0.0
v2.3.0
Features
- Collapse buildcage's own
runaction output into log groups (#220)- Buildcage's own setup/lifecycle logging no longer clutters the step log alongside your
run:command's output — it's now tucked into a collapsed group, matching how a plainrun:step looks.
- Buildcage's own setup/lifecycle logging no longer clutters the step log alongside your
Refactoring
- Centralize the setup ↔ report contract and drop the dash14 label prefix (#224)
⚠️ setupandreportmust be upgraded together — the internal contract they use to hand off report data changed, so pinning them to different versions will break.- Removes duplicated, drift-prone constants shared between the two actions, and drops repo-specific naming from an internal identifier.
- Adopt
@actions/corefor input/state/summary handling (#225)- Replaces hand-rolled input parsing, state handling, and summary writing with the standard GitHub Actions toolkit.
- Resolve lint warnings in shared test helpers (#226)
- Minor internal cleanup.
- Reduce duplicated report logic and test-only parameters (#227)
- Consolidates report pass/fail logic that had drifted into near-duplicate copies, and trims parameters kept only for testing convenience.
- Unify report rendering between
runandreport(#228)- Both actions now share one renderer for their Job Summary output instead of maintaining separate, divergence-prone copies.
- Group sandbox config options by role (#229)
- Reorganizes the
runsandbox's configuration into clearer identity/writable/runtime groupings.
- Reorganizes the
- Fix misplaced utility files and a duplicate helper (#230)
- Removes a redundant reimplementation of an existing helper and relocates a couple of small utilities to better-fitting homes.
- Split report generation into layered concerns (#231)
- Reorganizes report-generation code by concern — shared types, rendering, per-engine data building, and pass/fail outcome — instead of one flat directory.
- Share Docker/Compose helpers between setup and run (#232)
- Splits apart two unrelated Docker helpers that had shared a file, deduplicates an identical rule-logging helper, and lets
setupreuserun's Compose argument builders.
- Splits apart two unrelated Docker helpers that had shared a file, deduplicates an identical rule-logging helper, and lets
- Split run's sandbox pipeline into focused modules (#233)
- Breaks a large, multi-purpose sandbox-execution component into one module per pipeline stage.
- Extract named steps from run's main flow (#234)
- Pulls proxy start/stop and command-execution logic out of one large function into clearly named steps.
- Split log parsing by source, relocate report aggregation (#235)
- Separates a file that mixed several unrelated log-parsing responsibilities, and moves report-row-building logic into the report layer where it belongs.
- Separate pure logic from network I/O in provenance verification (#236)
- Splits testable, pure logic out of the modules that also perform live registry/network calls.
- Relocate misplaced report files and rename a catch-all directory (#237)
- Moves a data-shaping helper out of a directory meant for pass/fail decisions, and renames a vaguely-named shared directory to reflect what it holds.
- Shorten filenames and consolidate trivially small files (#238)
- Drops naming that redundantly repeated its own directory, and merges several small, closely related files that gained little from being split.
- Introduce an import alias for deep relative paths (#239)
- Multi-level
../../imports were hard to read at a glance. Adds a native import alias that works consistently everywhere the code runs, including local/CI flows that execute source directly rather than through the bundled build.
- Multi-level
CI / Maintenance
- Add unified linting, formatting, and commit hooks (#218)
- The project had no formatter, linter, or pre-commit enforcement; adopts a single toolchain covering all three plus type-aware lint.
- Switch unit test runner to vitest (#223)
- Unifies tests onto the same tooling already used for lint/format, replacing the previous runner.
Dependencies
- Bump
google.golang.org/grpcto v1.83.0 inbuildkit-proxy, adding a server-side mitigation for HTTP/2 control-frame flooding and fixing an xDS RBAC engine panic on unsupported fields insideNOTrules (#241) - Bump
rolldown,@types/node,fast-check, and@sigstore/verifyviapnpm audit, and pull inbrace-expansion's ReDoS fix ahead of the usual release-age policy (#222) - Bump
pnpmto v11.15.0 (#221) - Bump
rolldownto v1.2.0 (#216) - Bump
actions/attestto v4.2.0 (#214) - Bump
github.com/moby/buildkitmodule to v0.31.2 (#213) - Bump
moby/buildkitDocker tag to v0.31.2 (#212) - Bump
github/codeql-actionto v4.37.1 (#211) - Bump self-referential
dash14/buildcageaction pin to v2.2.5 (#210)
Full Changelog: v2.2.5...v2.3.0
v2.2.5
Features
- Note '(no communication)' in the report when a build has no outbound traffic (#202)
- Previously a quiet build was indistinguishable from a report that failed to generate — both rendered nothing between the heading and footer. Adds a
_(no communication)_note whenever nothing passed and nothing was blocked.
- Previously a quiet build was indistinguishable from a report that failed to generate — both rendered nothing between the heading and footer. Adds a
- Fail the report when the proxy log shows no trace of a real run (#205)
determineBlockedOutcometreated an empty blocked count as an automatic pass, even when a log had been wiped down to nothing by a tampering or misbehaving step betweensetup/runandreport. Adds a plausibility check requiring some non-decision log content before treating a build as genuinely quiet.
Security
- Harden IPv6 egress blocking and its documentation (#203)
- Neither engine's
init-iptableshad a fallback for kernels without IPv6 support, soip6tablesrunning underset -ecould fail container startup outright instead of degrading gracefully. Now checks/proc/net/if_inet6first and only skipsip6tableswhen the kernel truly lacks IPv6 support.
- Neither engine's
Refactoring
- Consolidate core/lib, core/shared, and core/scripts/lib into core/lib (#192)
- Library code was scattered across four locations with different runtime contracts, and telling which APIs a file could safely use required checking its directory rather than the file itself. Everything now lives in
core/lib, tested under both Node and QuickJS bymake test_core/make test_qjs.
- Library code was scattered across four locations with different runtime contracts, and telling which APIs a file could safely use required checking its directory rather than the file itself. Everything now lives in
- Bake report generation into the image to fix setup/report skew (#199)
setupandreportare independent steps that can be pinned to different refs, so report-building logic could drift from the imagesetupactually built. Each engine's image now bakes in its own report script, whichreportfetches viadocker cpand runs locally.
- Unify Docker-image script build pipeline (#200)
- Merges the separate QuickJS and report-action Rolldown configs and Docker build stages into one, choosing each entry point's build settings by filename suffix instead of a hardcoded target.
- Reorganize Makefile targets and drop the node -e project-name lookup (#201)
- Replaces a per-invocation
node -eshell-out forCOMPOSE_PROJECT_NAMEwith a fixed value pinned via Make pattern-specific variables, and renames every target into a consistent{verb}_{category}_...scheme grouped by Unit Tests / Integration Tests.
- Replaces a per-invocation
- Stream proxy log reads and aggregate them incrementally (#206)
- Reading a proxy's traffic log meant buffering the whole file and re-scanning it up to three times; a build that hit the same host many times (e.g. a dependency-install retry loop) risked exceeding the buffer. Logs are now streamed and aggregated into host/port/rule/reason counts in a single forward pass.
Documentation
- Drop the unused step id and self-hosting cruft from setup examples (#207)
- Removes the never-referenced
id: buildcagestep id, commented-out GHCR login steps, and unexplainedDOCKER_BUILD_SUMMARY/DOCKER_BUILD_RECORD_UPLOADenv vars from the Quick Start and reference examples, since self-hosting already has its own dedicated guide.
- Removes the never-referenced
Dependencies
- Bump
golang.org/x/netto v0.56.0 andgolang.org/x/textto v0.39.0 inbuildkit-proxy, clearing known vulnerabilities in each (GO-2026-5942, GO-2026-5970) (#208) - Bump self-referential
dash14/buildcageaction pin to v2.2.4 (#193) - Bump
@types/nodeto v24.13.3 (#194) - Bump
fast-checkto v4.9.0 (#195) - Bump
github/codeql-actionto v4.37.0 (#196) - Bump
golangDocker tag to v1.26 (#197) - Bump
pnpmto v11.11.0 (#198)
Full Changelog: v2.2.4...v2.2.5
v2.2.4
Features
- Migrate the
runaction's sandbox toruncwith seccomp support (#175)run-isolated.shnow hands the sandboxed command torunc(the OCI reference runtime) instead of hand-rolledunshare/nsenter/setprivnamespace/mount/capability handling. Namespaces, capabilities, mounts, uid/gid, and a seccomp filter derived from Docker's own default profile are all declared in an OCIconfig.jsonand enforced by runc itself — including joining the proxy container's existing network namespace and dropping uid/gid without a user namespace. Resolves the previously-documented "No seccomp profile" Known Limitation.
- Add
known_blocked_rulesto mark expected blocked connections (#181)- In
restrictmode,fail_on_blockedpreviously failed a step on any blocked connection, including ones you already expect and want blocked — a security check confirming a domain stays blocked, or a dependency that phones home to a known-noisy endpoint.known_blocked_rules(same wildcard/~regexsyntax asallowed_*_rules) marks those destinations so they no longer fail the step, while still showing up in the Job Summary's Blocked Hosts table under a new "Expected" column. Available on bothrunandreport.
- In
- Give actionable errors when Docker/sudo is unavailable (e.g.
ubuntu-slim) (#187)setup/run/reportpreviously let rawdocker/sudofailures propagate as a generic "Unexpected error". A newdescribeDockerFailure()classifies Docker failures and names the runner requirement explicitly, calling out container-based hosted runners likeubuntu-slimwhen relevant. A new sudo preflight inrunalso fails fast with its own error instead of misattributing a missing-passwordless-sudo failure to the user's ownrun:command.
Documentation
- Add overview and architecture diagrams for the
runaction (#179)- Matches the diagrams
transparent/explicitalready have in the README anddocs/security.md, illustratingrun's different architecture: arunc-created host process connected to the proxy container by a single dedicated veth pair rather than a shared CNI bridge.
- Matches the diagrams
- Rewrite the README to treat
runas an equal path todocker build(#180)runwas previously an "(Experimental)" bolt-on below thesetup/reportbuild engines; now that it's stable enough to promote, the README presentsdocker buildand a plainrun:step as two equally valid places to apply the same outbound-restriction technology. The fulltransparent/explicitengine breakdown moves out of "How It Works" intodocs/reference.md.
- Use literal block scalars (
|) for multiline rule examples (#182)- Replaces the folded scalar (
>-) previously used inallowed_https_rules/allowed_http_rules/allowed_ip_rulesexamples, matching therun: |style already used elsewhere in the docs. Purely cosmetic — the parser splits rules on any whitespace.
- Replaces the folded scalar (
Refactoring
- Replace the
sandbox0bridge with a direct veth connection to the proxy (#176)- The bridge existed only to give
run-isolated.sha stable, pre-known interface name to attach a veth to —init-iptables's-i sandbox0rule matches on name regardless of when the device appears. Since the sandbox and its proxy are always connected 1:1, the veth's proxy-side end is now renamed directly tosandbox0instead of being attached to a bridge.
- The bridge existed only to give
- Extract a generic markdown table formatter from host-table rendering (#186)
- Splits
core/lib/markdown-table.js's table-building logic (headers, alignment, cell joining) from the host-row-specific rendering added in #181, so the formatter isn't coupled to one fixed Host/Rule/Reason/Count/Expected column set.
- Splits
- Share image provenance verification between
setupandrun(#188)- Both actions independently implemented near-identical
resolveVerifiedImagelogic and their own error class with duplicated provenance codes. A new sharedActionErrorbase class andverifyImageDigestOrThrowconsolidate this into one testable component, giving it unit test coverage for the first time.
- Both actions independently implemented near-identical
- Add a TypeScript build foundation (#189)
- Adds
tsctype-checking (allowJs/checkJs,strict: true) for the existing.jssources acrosscore/lib,setup/src,run/src,report/src, and replaces Rollup with Rolldown for the dist build — laying the groundwork for the migration below without changing any source file's language yet.
- Adds
- Migrate the remaining Node.js sources to TypeScript (#190)
- Converts every
.jsfile undercore/lib,setup/src,run/src,report/srcto.tswith real type annotations, removes all// @ts-nocheckescapes left from #189, and strengthens error codes fromstringto literal unions (ActionError<Code extends string>).
- Converts every
- Migrate the QuickJS-executed scripts to TypeScript (#191)
- Converts the last plain JavaScript in the repo — the scripts run inside containers via QuickJS — completing the migration. Switches the QuickJS runtime from Bellard's original
quickjstoquickjs-ng(what Alpine'squickjspackage actually ships turned out to be the former, not the fork), and bundles each entry point into a single self-contained file with Rolldown instead of shipping raw sources.
- Converts the last plain JavaScript in the repo — the scripts run inside containers via QuickJS — completing the migration. Switches the QuickJS runtime from Bellard's original
CI / Maintenance
- Scope example workflow permissions to job level and make
docker-loginoptional (#183)- The example workflows logged in to GHCR before every run, but
setup's OCI registry client already falls back to anonymous pulls, and the publicdash14/buildcagepackage needs no authentication. Thedocker/login-actionstep and itspackages: readpermission are now commented out (with a note to re-enable for self-hosting under a private package), andpermissionsmoves from workflow level to job level, following least-privilege practice.
- The example workflows logged in to GHCR before every run, but
Dependencies
- Bump
google.golang.org/grpcto v1.82.1, addressing an xDS RBAC authorization bypass and an HTTP/2 Rapid Reset mitigation bypass (GHSA-hrxh-6v49-42gf) (#184) - Bump
golang.org/x/systo v0.45.0 ingen-seccomp-profile, clearing a.trivyignoreentry for a Windows-only CVE that no longer applies (#177) - Bump the
setuptest fixture'sexpressto v5.2.1, clearing qs/path-to-regexp vulnerabilities from itspackage-lock.json(#178) - Bump
pnpmto v11.10.0 (#174) - Bump
golang:1.25-alpineDocker digest to56961d7(#138) - Bump self-referential
dash14/buildcageaction pin to v2.2.3 (#173)
Full Changelog: v2.2.3...v2.2.4
v2.2.3
Breaking Changes
-
Rename the
sandboxaction torun(#166)dash14/buildcage/sandbox@...doesn't describe what the action does — it applies buildcage's network-isolation technology to run an arbitrary command, not "sandbox" it in some more general sense. The action is nowdash14/buildcage/run, matching what a workflow author actually calls it for. No backward-compatible alias is kept.
Before (v2.2.x):
- uses: dash14/buildcage/sandbox@<sha> with: run: npm install
After (v2.2.3):
- uses: dash14/buildcage/run@<sha> with: run: npm install
Features
- Generate a restrict-mode example in the
runaction's audit report (#170)- The
reportaction's audit-mode Job Summary already includes a ready-to-paste restrict-mode YAML example built from the audited hosts, saving a workflow author from hand-copying hostnames out of the table. Therunaction's own report renderer now generates the same kind of example — arun@<ref>step withproxy_mode: restrictand the discovered allowlist rules, plus the originalrun:command preserved so it stays copy-pasteable on its own
- The
Bug Fixes
- Handle read-only remount rejections on Docker-masked
/procmounts (#167)run-isolated.sh's read-only pass walks every mount under/proc/self/mountinfoand fails closed if a remount is rejected. Under Docker Desktop,/proc/scsiand/proc/interruptsare masked before the sandbox re-parents them under a fresh procfs, and the kernel then rejects an otherwise-harmless remount on them, breaking the mac dev loop without indicating any actual isolation gap. Mounts already reported read-only are now skipped, and remaining rejections get one retry re-bound onto themselves
- Fix
run'sactionRef/actionRepofallback for local-path invocations (#171)run/src/main.jsfell through to an empty string instead ofreport/src/main.js's"v2"/"dash14/buildcage"defaults when invoked viauses: ./run, rendering a brokenuses: /run@in the generated audit-mode example
- Fix a trailing blank line in the generated restrict-mode example's
run:block (#172)- GitHub Actions'
run: |block scalar always keeps one trailing newline, whichsplit()turned into a spurious empty line
- GitHub Actions'
- Fix
parseVertexAllowedLogto handlebuildctl's multi-document JSON output (#172)- A single
JSON.parse()on the whole log text threw wheneverbuildctl debug logs --progress=rawjsonflushed more than one newline-separated JSON document, silently dropping theexplicitengine's Audited Hosts table and Communication details section
- A single
Improvements
- Add a
labelinput to therunaction (#172)- Aligns its Job Summary heading (
## Outbound Traffic Report — <label> (mode)) and Audited/Blocked/Allowed Hosts sub-headings with thereportaction's, so multiplerunsteps in the same job can be told apart in the summary
- Aligns its Job Summary heading (
Documentation
- Add
example-explicit.yml, an example workflow for the experimentalexplicitproxy engine (#172) - Add
example-run-audit.yml, an example workflow for therunaction'sauditmode (#172)
CI / Maintenance
- Split
test.ymlintotest-unit.yml,test-integration.yml, andtest-e2e.yml(#157)- Each keeps its own path-filter job and labeled job names (
unit: test,integration: test (...),e2e: test (...)), replacing the singleall-tests-passedrequired check with one aggregator per tier
- Each keeps its own path-filter job and labeled job names (
- Split the
runaction's e2e tests by case and consolidate its integration tests (#171)writable:/privilege-drop/filesystem-default cases and direct concurrent proxy lifecycles don't depend on the action wrapper, so they've moved out oftest-e2e.ymlinto real shell scripts underrun/test/, run via a singlemake test_sandbox_integrationtarget; a newtest_sandbox_audit_modee2e job covers the restrict-mode example added in #170
- Apply the
latestDocker tag on release publish, not draft creation (#169)docker-publish.ymlruns on tag push, which happens while creating the draft release, solatestwas moving onto a new version before anyone reviewed or published it. Tagginglatestis now handled byupdate-major-tag.yml, gated onrelease: published, alongside the existing major/minor floating tags
Refactoring
- Move each action's Docker build context and test fixtures under its own directory (#160)
setup/docker/,sandbox/docker/(nowrun/docker/),setup/test/,sandbox/test/were shared across actions despite belonging to only one of them, making ownership unclear as the actions diverged. Code actually shared across actions (image verification, Sigstore, rule/log parsing) was consolidated into a newcore/
Dependencies
- Bump self-referential
dash14/buildcageaction pin to v2.2.2 (#130) - Bump
github/codeql-actionto v4.36.3 (#158) - Bump
docker/build-push-actionto v7.3.0 (#159) - Bump
docker/login-actionto v4.4.0 (#161) - Bump
docker/setup-buildx-actionto v4.2.0 (#162) - Bump
docker/metadata-actionto v6.2.0 (#163) - Bump
docker/setup-qemu-actionto v4.2.0 (#164) - Bump
google.golang.org/grpcto v1.82.0 (#165)
Full Changelog: v2.2.2...v2.2.3
v2.2.2
Features
- Add an experimental
sandboxaction for network-isolated command execution (#155, #156)- Buildcage previously only isolated Docker
RUNsteps; a compromised dependency could still phone home from a plainrun:step (npm install,pip install, a test suite, a build script). The newsandboxaction wraps anyrun:command in the same outbound-network allowlist (bridge network, iptables redirect, DNS redirect, SNI/Host-based allowlist proxy) thattransparentmode already applies to Docker builds - Unlike a Docker build, the command still runs directly on the runner rather than inside a container — so
actions/setup-node-installed toolchains, credential-provider actions (e.g.aws-actions/configure-aws-credentials), andactions/cache/$HOME-based caches keep working exactly as they do today, with no image or workflow restructuring needed - Also restricts the filesystem to read-only outside
$GITHUB_WORKSPACE,$HOME, and/tmpby default (configurable via a newwritableinput), and is safe to run concurrently across steps via Actions'background/wait/parallelkeywords - Marked experimental: newer and less battle-tested than the
setup/reportbuild-isolation actions — seedocs/security.md#sandbox-actionfor the current threat model and known limitations
- Buildcage previously only isolated Docker
Full Changelog: v2.2.1...v2.2.2
v2.2.1
Security
- Refresh
.trivyignoreagainst currently open Trivy alerts (#143, #147)- Re-triaged newly-flagged and version-fixed CVEs, then restored 6 entries that had been wrongly removed as version-fixed
Improvements
- Reformat the explicit engine's "Communication details" report section (#150)
- Aligned with the rest of the report's conventions (emoji-prefixed heading,
BLOCKEDlist moved ahead of the per-step breakdown), and reformatted each RUN step's request log as a code block
- Aligned with the rest of the report's conventions (emoji-prefixed heading,
Documentation
- Document how to fix npm's CA trust gap under the
explicitengine, including a worked example (#152) - Add
MAINTAINERS.mddocumenting project roles and access (#153) - Add release-verification and dependency-management guidance to
SECURITY.md(#154)
CI / Maintenance
- Cross-compile
buildkit-proxyinstead of emulating the build stage under QEMU (#146)- Pins the build stage to the host's own platform so the Go toolchain always compiles natively, regardless of the image's target platform
- Skip CI test jobs unaffected by a PR's changed paths (#148)
- A new
changesjob classifies a PR's changed paths and skips downstream jobs (Docker test matrix, multiarch check,test_action) whose inputs didn't change
- A new
- Eliminate a flaky SIGPIPE/pipefail race in test assert scripts (#144)
echo "$VAR" | grep -q PATTERNchains underset -o pipefailcould report FAIL even when the pattern matched, ifgrep -qexited early and killedechowith SIGPIPE before it finished writing
- Skip blocked-connection annotations when not running as the
reportaction (#149)report/src/main.js's annotations were gated only onblockedCount, so they leaked into the explicit-modetestCI job (which clearsGITHUB_STEP_SUMMARYto test proxy enforcement directly and was never meant to produce them); annotation output is now gated the same way as the Job Summary write
Dependencies
- Bump self-referential
dash14/buildcageaction pin to v2.2.0 (#145)
Full Changelog: v2.2.0...v2.2.1