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

TrackDelivered
Volume-driver bind containmentThe 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 inspectionPUT /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 guardA request target that is not a rooted path no longer reaches rule evaluation, and a /** catch-all no longer allows one
Read-side redactionSurvives gzip encoding, HEAD, 304 revalidation and image inspect, and stops parsing a body the active options cannot rewrite
Operator checkssockguard 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 rejectedA 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 allocationsRoute 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

TrackDelivered
Native libpod write inspectionCopy-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-closedAn 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 & commitThe 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 acknowledgmentContainer and pod process-list reads now require the read-exfiltration acknowledgment
Read-side redactionReaches libpod container inspect, volume reads, and network topology; showsecret=true no longer hands back a plaintext secret

Shipped in v2.0.0

TrackDelivered
Signed-policy integrityBootstrap 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 isolationCaller 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 hardeningSocket 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 surfacesREADME, 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.

TrackCandidate status
BuildKit RUN-instruction coverageRaw-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 pathThe 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//grpc BuildKit 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_config per-field gates, narrowing allow_endpoint_config from 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

WorkflowCurrent status
Portwing inventory, inspect, stats, logs, events, and lifecycle calls through SockguardSupported by portwing.yaml; exec requires portwing-with-exec.yaml
Compose-managed networks and named volumesSupported by portwing-with-compose.yaml or drydock-with-compose.yaml
drydock discovery and container-state sync through Portwing Standard ModeSupported; the agent handshake and state feed work through Sockguard
Portwing Edge dial-outStable with drydock 1.6; drydock 1.5 requires DD_EXPERIMENTAL_PORTWING=true
drydock-triggered remote updates through PortwingNot 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 presetSupported 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.