Roadmap
Sockguard's shipped v1.7, v2.0, v2.1, and v2.2 work, v2.3 release-candidate status, and later direction.
Sockguard v2.2 is the current stable feature line, with v2.2.11 the latest
release. v2.2.0 closed the volume-mount and read-side gaps that survived
v2.1.0 and added the operator-facing checks that were missing around them;
v2.2.1 is a security patch on that line, closing a raw block-device,
pseudo-filesystem or overlay lower/upper/work-dir mount through the
local volume driver, a literal-* segment slipping past a deny glob,
byte-identical duplicate JSON keys, and a 502 on gzip-compressed bodies
in the visibility and owner-isolation filters. v2.2.2 is a second security
patch, refusing form-encoded request bodies that could replace the query
parameters sockguard had evaluated and closing two owner-isolation gaps on
image push and image retag. v2.2.3 is a third security patch: owner
isolation now checks the image names that commit, build, import, pull and
load assign, so a client can no longer take a name from another owner's
image (an untagged pull such as docker pull -a is refused under owner
isolation), and it closes filter gaps around fromImage beside fromSrc,
Podman's compat /build controls, owner-label stripping on Podman builds,
the distribution endpoint and the registry allowlist, and a spooled request
body left on disk after a later layer denied it. v2.2.4 is a fourth
security patch: Podman build RUN inspection now follows the Containerfile
default and every dockerfile file, refuses remote, absolute and .in
values, symlink and duplicate tar entries and compressed bodies, and Podman
query-parameter ambiguity, libpod container, pod and kube removal, the secret a libpod create replaces under owner isolation, and libpod secret driver
options are gated, while warn and audit profiles forward the body they
refused. v2.2.5 is a fifth security patch: on a Podman upstream, a namespace
joined by path now needs the same allow_host_* gate as host, under owner
isolation a libpod container or pod create is checked against the secrets,
volumes, networks, containers and image volumes it names, and secret_env
and ID-shaped secret references are refused. v2.2.6 is a sixth security
patch: a request body that repeats a key or spells one with U+0130, U+017F
or U+212A is refused, a native Podman container create is held to
allowed_bind_mounts for rootfs, overlays and init_path and refuses
relative bind sources outright, and pod and container creates in a host UTS, cgroup, PID, IPC or
user namespace need their own allow_host_* option. v2.2.7 is a seventh
security patch: on a Podman upstream, a Docker-compatible container create
is held to allowed_bind_mounts for relative, empty, drive-letter and
comma-injected mount fields, and the RUN gate recognises syntax directives
written as // or JSON and RUN instructions that BuildKit assembles across
continuations differently than Sockguard did. v2.2.8 is an eighth security
patch: it rebuilds with Go 1.27.2 and golang.org/x/net 0.60.0 to clear six
Go advisories published on 2026-10-08 in net/http and crypto/tls, with no
change to Sockguard's own behaviour. v2.2.9 is a ninth security patch: with
allow_run_instructions off, a COPY, ADD or ONBUILD heredoc the RUN gate
can't follow now refuses the build, and the gate reads carriage returns,
doubled escapes, the # escape= directive and the JSON syntax directive the way
BuildKit and Podman's builder each do. v2.2.10 is a tenth security patch:
native Podman pod create refuses any nonempty infra_conmon_pid_file,
matching the container-create conmon_pid_file refusal and preventing a
caller-selected host PID-file write. v2.3.0-rc.8
is the current candidate for the next line; v2.3.0 is not stable yet. This roadmap describes direction and priorities, not
promises about dates. A feature is available only after the release notes say
it has shipped.
Shipped in v2.2.11
Native Podman container base_hosts_file and pod hostsFile accept only
empty, image or none. Custom host paths are refused on both routes;
the daemon's configured default and image-based hosts files remain usable.
The guard follows the configured rollout mode and is covered on direct and
versioned requests. The same patch refuses BUILDKIT_SYNTAX overrides on restricted classic and mediated builds, rebuilds with Go 1.27.3 for GO-2026-6809, and refreshes dependencies. Building from source now requires Go 1.27.
Shipped in v2.2.10
Native Podman pod creation refuses infra_conmon_pid_file, matching the
existing container-create refusal of conmon_pid_file. A caller can no
longer select the host file conmon writes the infra container's PID to.
Ordinary pod creation is unchanged. The fix has unit and middleware
regressions on direct and versioned routes. Podman behavior is established
from source and a client-only request capture, not a live-daemon reproduction.
Shipped in v2.2.0
| Track | Delivered |
|---|---|
| Volume-driver bind containment | The local driver's type/o/device options can no longer bind-mount a host path past allowed_bind_mounts, on container create or on a Swarm service mount |
| Volume write inspection | PUT /volumes/{name} is inspected instead of being an unread write, so an allow rule on it no longer forwards a body nothing reads |
| Request-target guard | A request target that is not a rooted path no longer reaches rule evaluation, and a /** catch-all no longer allows one |
| Read-side redaction | Survives gzip encoding, HEAD, 304 revalidation and image inspect, and stops parsing a body the active options cannot rewrite |
| Operator checks | sockguard verify checks a loaded config against the daemon it will actually talk to, server.shutdown_grace replaces the hardcoded 30s drain, and a SOCKGUARD_* variable matching no configuration key warns at startup |
| Rootless rule patterns rejected | A match.path without a leading / now fails config validation instead of loading and matching every rooted path; breaking for any config that used that spelling |
| Per-request allocations | Route metric labels, the /health cache, visibility label injection, owner-label mutation, POST /containers/create decoding and query-string parsing stop repeating work on every request |
Shipped in v2.1.0
| Track | Delivered |
|---|---|
| Native libpod write inspection | Copy-into-container, container-update, restore, checkpoint, mount, and the gated image-write surface are inspected on the same terms as their Docker-compat twins |
| Owner isolation fail-closed | An unresolved target answers 404, a foreign one 403, and an inspect failure 502, forwarding none of them, across the libpod prune family, container commit, and image export/removal |
| Ownership-scoped prune & commit | The libpod prune family is owner-scoped and container commit is owner-checked, with the resulting image labeled so it stays visible to later ownership checks |
| Process-list read acknowledgment | Container and pod process-list reads now require the read-exfiltration acknowledgment |
| Read-side redaction | Reaches libpod container inspect, volume reads, and network topology; showsecret=true no longer hands back a plaintext secret |
Shipped in v2.0.0
| Track | Delivered |
|---|---|
| Signed-policy integrity | Bootstrap trust is selected out of band, cannot share authority with the signed candidate or rotatable signature object, stays pinned across reload, and rejects unsigned compatibility-rule mutation |
| Native Podman builds | /libpod/build constrains primary and additional contexts, host-facing controls, host networking, Dockerfile RUN, and owner labeling on direct and versioned paths |
| BuildKit isolation | Caller identity comes from verified certificates or Unix peer credentials where available, session state is correlated by principal, profile, and session, Solve admission is atomic, and upgrade handshakes are bounded |
| Proxy hardening | Socket cleanup is inode-owned, method-aware resource routing covers keyword names, generated response errors clear stale representation headers, inspected bodies retain deadlines through logging and metrics, and request metric labels have finite cardinality |
| Release surfaces | README, docs, website, Helm metadata, verification assets, and migration guidance agree on v2.0.0; release blobs use sigstore bundles only and published metadata is read back before the release succeeds |
v2.3 release candidate
The general BuildKit gRPC mediation foundation shipped under issue #185. The next feature line extends it with selective raw-LLB and external frontend mediation. Both feature tracks below are implemented in v2.3.0-rc.8; the remaining gate is stable promotion after candidate validation.
| Track | Candidate status |
|---|---|
| BuildKit RUN-instruction coverage | Raw-LLB ExecOps can be individually approved with control.solve.allowed_exec_digests. External frontend gateway Solves are mediated under the root build's policy, and the pinned companion runner executes the compiler outside the daemon. Unknown operations, opaque in-daemon frontends, interactive execution and daemon-resolved nested builds remain denied while RUN is restricted. Build refs and callback session IDs are scoped by client and profile |
| Go module major-version path | The candidate declares github.com/codeswhat/sockguard/v2, with migrated imports, release linker flags and 11 regenerated BuildKit descriptors. After stable v2.3.0 publication, go install github.com/codeswhat/sockguard/v2/app/cmd/sockguard@latest will resolve to the v2 line. Existing v2.2 tags retain their original metadata; Docker, Homebrew, deb and rpm installs are unchanged |
The four-hour soak
and TLS scan
passed on rc.8's exact head, 3d959fe3. The soak used a mock daemon,
completed 257,857,747 requests with zero request errors, and recorded
3,739,648 bytes of RSS growth, below the 64 MiB threshold. This does not
validate real BuildKit workloads. GA is no earlier than 2026-10-23.
Every new candidate needs a fresh four-hour soak and TLS scan; a candidate
containing only fixes already released on the v2.2 line keeps the date,
while a v2.3-only behavior change restarts the 14-day window.
Twelve-month direction
Beyond the next planned line, work remains risk- and demand-driven:
- continue mutation-test hardening of rule evaluation, request-body inspection, response redaction, and configuration validation;
- add release-job egress restrictions without breaking Sigstore, registry, provenance, or SBOM publication;
- expand the CIS Docker Benchmark mapping and audit-ready policy examples;
- consolidate the config-to-filter-to-policy translation layers behind one validated source of truth; and
- evaluate named rule-path aliases and optional policy-extension mechanisms only after their trust boundary and failure mode are concrete.
The project does not plan to become a scheduler, container runtime, secrets manager, or general host firewall. OPA/Rego, WASM, or Go plugin support remains unscheduled because extending the policy engine also extends the trusted computing base.
Shipped in v1.7
Sockguard v1.7.5, the final release in the v1.7 line, shipped on 2026-08-23,
promoting the 1.7.5-rc.1 security candidate to stable: the Swarm
host-network deny now covers TaskTemplate.Networks, three build-time
RUN-instruction gate bypasses are closed, cross-owner attestations access and
two stale identity caches are closed, image-trust verification rejects
cross-repository signature transplants, and Grype scans the published
multi-arch image per platform. Earlier in the line: the v1.7.2 tag's publish
run died signing checksums.txt against cosign v3's new bundle-format
defaults, so it shipped no artifacts, release, or images; v1.7.3 fixed the
signing flags and carried v1.7.2's content, and v1.7.4 added the committed
first-party star chart and the daily main-is-released monitor.
The v1.7 line added:
- BuildKit gRPC mediation: fail-closed policy enforcement over the previously
opaque
/session//grpcBuildKit tunnel across six phases — schema and policy foundation, h2c termination and stream routing, per-message Solve/Status mediation and ref ownership, credential session mediation for Auth/Secrets/SSH, FileSync/FileSend/Upload stream mediation, and fuzzing plus mediated-build presets — replacing the opt-in opaque-tunnel acknowledgment; request_body.network.endpoint_configper-field gates, narrowingallow_endpoint_configfrom one broad switch to independent controls for static addressing, link-local IPs, MAC pinning, gateway priority, and aliases;- four PR-gate gaps closed: Dependency Review, Gitleaks secret scanning, and Actionlint workflow linting all now run and block on every PR, and Grype image scanning moved into the required Docker Build job;
- per-platform release archives now cosign-signed and SLSA build provenance-attested, closing the gap where only the source tarball carried a signature; and
- conformance-matrix and release-tooling fixes: the tri-tool matrix's store-sync poll and current-release resolution, the lockfile-dedupe pre-push hook, and the release-cut workflow's CI gate timeout.
The complete evidence is in the v1.7.0 GitHub milestone, CHANGELOG, and repository release history.
Compatibility boundary
| Workflow | Current status |
|---|---|
| Portwing inventory, inspect, stats, logs, events, and lifecycle calls through Sockguard | Supported by portwing.yaml; exec requires portwing-with-exec.yaml |
| Compose-managed networks and named volumes | Supported by portwing-with-compose.yaml or drydock-with-compose.yaml |
| drydock discovery and container-state sync through Portwing Standard Mode | Supported; the agent handshake and state feed work through Sockguard |
| Portwing Edge dial-out | Stable with drydock 1.6; drydock 1.5 requires DD_EXPERIMENTAL_PORTWING=true |
| drydock-triggered remote updates through Portwing | Not implemented in either mode: Standard trigger routes return 501; the current Edge protocol has no effective watcher/trigger response contract |
Compose --build through a bundled preset | Supported for both transports: classic /build via the *-with-build.yaml presets, and BuildKit's session/gRPC tunnel via the fully-mediated *-with-mediated-build.yaml presets (issue #185's gRPC mediation epic — see Security) |
The compatibility statement is deliberately narrower than “all three tools work together.” Monitoring and authorized container control work. Remote update orchestration does not yet, and Sockguard will not advertise a preset as enabling it until Portwing and drydock implement and test both sides of that contract.
Sockguard will keep supporting documented Docker-compatible clients through versioned presets and explicit policy. It will not claim a compatibility path until the corresponding published images pass the real-daemon conformance matrix. New write transports stay denied when Sockguard cannot inspect them or require a narrowly named operator acknowledgement that makes the limitation visible.
Migration
Upgrade Sockguard through v2.1, including the signed-policy trust split and the v2.0-to-v2.1 TLS-verification deprecation, or migrate from another Docker socket proxy.
Security Model
Sockguard's defense-in-depth model — transport admission, client admission, method/path filtering, request-body inspection, ownership isolation, visibility-controlled reads, and structured access plus audit logging.