Skip to content

Releases: CodesWhat/sockguard

v1.4.0-rc.1

16 Jun 17:24
a444c2d

Choose a tag to compare

v1.4.0-rc.1 Pre-release
Pre-release
release: v1.4.0-rc.1

v1.3.0

11 Jun 17:38
fe0a643

Choose a tag to compare

v1.3.0 — promotes 1.3.0-rc.3 to stable: swarm identity/privilege rail…

v1.3.0-rc.3

11 Jun 13:39
541345b

Choose a tag to compare

v1.3.0-rc.3 Pre-release
Pre-release
Merge pull request #94 from CodesWhat/release/changelog-rc3

🔧 chore(release): date the 1.3.0-rc.3 changelog entry

v1.3.0-rc.2

10 Jun 19:51
dce6283

Choose a tag to compare

v1.3.0-rc.2 Pre-release
Pre-release
v1.3.0-rc.2: code-review batch (PR #88) + changelog entry (PR #90)

v1.2.0

03 Jun 11:47
7fb8270

Choose a tag to compare

release: v1.2.0

v1.1.0

02 Jun 14:11
b00caee

Choose a tag to compare

sockguard

sockguard is a default-deny Docker socket proxy written in Go. It filters every request by HTTP method, path, and request body — so a compromised API consumer can't escalate through the socket.


🔐 sockguard v1.1.0 — image trust, wired end to end

v1.1.0 makes cosign image-trust verification real — it was policy-only scaffolding in v1.0.0 — and lands a 21-finding security audit across the request-inspection and read-side filters. Everything stays inside the frozen v1.x contract: no breaking config, CLI, env-var, metric, or admin-endpoint changes.

✨ Highlights

  • 🔏 Cosign image-trust verification is now enforced end to end — keyed (PEM) and keyless (Fulcio + Rekor), with registry digest resolution and digest-pinned forwarding. It was a no-op before.
  • 🛡️ 21 HIGH+MEDIUM audit findings closed, each with regression coverage — request-inspection bypasses, read-side isolation gaps, and config/admin hardening.
  • 🧩 Swarm services now enforce container-create policy — capability allowlist, sysctl gate, and image trust all apply to the service ContainerSpec.
  • 🔍 CodeQL actions analysis enabled, and 20 OSSF / Go-vuln-DB advisories cleared via dependency bumps (govulncheck reports zero).

🔏 Image trust (end to end)

  • New internal/imagefetch resolves the image to its registry manifest digest, discovers the cosign signatures attached to it (classic sha256-<digest>.sig tag and OCI 1.1 referrers), reconstructs a Sigstore verification bundle, and binds every signature to the resolved digest before verifying — so a valid signature for one image can't be transplanted onto another.
  • Keyed (PEM) and keyless (Fulcio + Rekor, trust root fetched via TUF at startup) both verify through the existing sigstore-go stack.
  • Verified images are digest-pinned (registry/repo@sha256:…) before the request is forwarded, closing the verify→pull TOCTOU.
  • require_rekor_inclusion now defaults to true for keyless verification.

🔒 Security audit (21 findings)

  • Request inspection — plugin multipart-boundary inspection bypass closed; BuildKit # syntax= external-frontend builds denied; gzip-bomb decompression cap on the build context; new allowed_runtimes allowlist for HostConfig.Runtime (blocks alternate-OCI-runtime profile escapes); empty/whitespace exec User now treated as root.
  • Swarm parityPOST /services/create and /services/*/update now enforce the same capability allowlist, allow_sysctls gate, and image-trust verification as container-create. Swarm is no longer an unfiltered path to privilege.
  • Read-side isolation — visibility now gates container/image sub-resources (logs/stats/top/changes/export/archive/attach, image history/get); image /get export is owner-filtered; the inspect cache no longer memoizes not-found verdicts; response redaction now covers HostConfig.Mounts[].Source and service PreviousSpec.
  • Config / admin — signed-bundle verify-then-load TOCTOU closed and env vars can no longer override signed policy; PID-only unix-peer profile assignment rejected (PIDs are recycled); the dedicated admin TCP listener enforces the same clients.allowed_cidrs backstop as the main listener.
  • Supply chain — CodeQL actions language enabled for workflow static analysis; x/crypto / x/net / x/sys bumped to clear 20 advisories (all unreachable from sockguard's code paths; the post-bump scan is clean).

🧪 Quality

  • Hardened the synthetic benchmark load generator — clean end-of-window shutdown (no more false "proxy error" reports) plus per-error-string counts for anomaly triage.
  • De-flaked the rate-limit and request-ID-generator timing tests against a frozen clock. Test-only — the proxy binary is unaffected.

📥 Install

docker pull ghcr.io/codeswhat/sockguard:1.1.0

Also published to docker.io/codeswhat/sockguard and quay.io/codeswhat/sockguard. Prebuilt binaries for linux/macOS · amd64/arm64 are attached below. Every image and tarball is cosign-signed — see the verification docs.


📦 ghcr.io/codeswhat/sockguard:1.1.0 · 📖 Documentation · 🔎 Full diff

v1.0.0

20 May 18:57
bf59572

Choose a tag to compare

sockguard

sockguard is a default-deny Docker socket proxy written in Go. It filters every request by HTTP method, path, and request body — so a compromised API consumer can't escalate through the socket.


🎉 sockguard v1.0.0 — first stable release

v1.0.0 ships the proxy contract that v1.0.0-rc.2 froze on 2026-05-16. Three small binary deltas land on top of the RC — a pinned Go toolchain, a sealed signature-verification edge case, and a sigstore bump. Everything else is non-binary hardening: new tests, CI workflows, policy presets, compose examples, and docs polish.

✨ Highlights

  • 🏁 First stable release — the v1.x proxy contract is frozen.
  • 🛡️ 12 bundled policy presets — 3 new: CIS Docker Benchmark, GitHub Actions runner, GitLab Runner.
  • 🔐 Go toolchain pinned to 1.26.3 — clears 17 HIGH stdlib CVEs.
  • 🧪 Phase A QA hardening — proxy-vs-daemon differential harness, real-dockerd integration tier, memory/goroutine soak tests, mTLS edge-case suite.
  • 📦 3 ready-to-run Docker Compose stacks under examples/compose/.

🔒 Security

  • Go toolchain pinned to 1.26.3 via the toolchain directive in go.mod; CI now reads go-version-file so the toolchain is a single source of truth. Clears 17 HIGH stdlib CVEs that opened against rc.2's stdlib in the weekly Grype scan.
  • sigverify.VerifyKeyless no longer skips its issuer / SAN re-check on a nil certificate. An absent cert is now treated as a verification failure whenever issuer or SAN expectations are configured — if the cert can't be inspected, the expectation can't be honored, so the only safe answer is to reject.
  • github.com/sigstore/sigstore bumped v1.10.5v1.10.6 — cosmetic upstream OAuth success-page template fix; no behavior change in policy-bundle or image-trust.

🛡️ New presets & examples

Preset For
cis-docker-benchmark.yaml Admission gate for the inspectable subset of CIS Docker Benchmark v1.6.0 Section 5. Non-compliant docker run is rejected with 403 before dockerd ever executes it.
github-actions-runner.yaml Purpose-built for actions/runner self-hosted runners that spawn job + service containers.
gitlab-runner.yaml Purpose-built for gitlab-runner with the Docker executor — rejects Privileged=true even if config.toml asks for it.

Three matching compose stacks ship under examples/compose/ (each with docker-compose.yml, a sockguard.yaml overlay, and a security-tradeoff README.md). Total bundled presets is now 12.

🧪 Quality & testing

  • Proxy-vs-daemon differential harness (app/differential/) — 40+ path-evasion cases, a CL/TE request-smuggling axis, a JSON-decoder differential axis, and a new FuzzPathRoutingDifferential target wired into per-PR / nightly / monthly tiers.
  • End-to-end suite against a real dockerd (app/integration/) — drives sockguard as a process behind a live daemon and checks every shipped preset for allow/deny conformance, wired to a nightly CI job.
  • Memory / goroutine-leak soak (scripts/soak.sh) plus a weekly 4 h CI run; slowloris and concurrent-hijack leak regressions.
  • mTLS / TLS edge-case suiteinternal/sigverify coverage from 0 % to comprehensive; a weekly testssl.sh DAST probe of the TCP listener.
  • Downstream image-signature verification — a verify-published CI job runs the exact cosign verify commands published in the docs against every pushed image tag, catching docs-vs-pipeline drift.

🔧 Tooling & docs

  • gofmt -l CI gate added; govulncheck ./... added to the pre-push pipeline — the tree is vuln-clean.
  • New /docs/cis-docker-benchmark guide; widened /docs/security#known-limitations; /docs/presets now covers all 12 presets.

⬆️ Upgrading from 0.8.x

v1.0.0 carries the breaking YAML / CLI / metrics renames introduced in v1.0.0-rc.1 and the two-flag plaintext-TCP gate from v1.0.0-rc.2. Review those release notes before upgrading.

📥 Install

docker pull ghcr.io/codeswhat/sockguard:1.0.0

Also published to docker.io/codeswhat/sockguard and quay.io/codeswhat/sockguard. Prebuilt binaries for linux/macOS · amd64/arm64 are attached below. Every image and tarball is cosign-signed — see verification docs.


📦 ghcr.io/codeswhat/sockguard:1.0.0 · 📖 Documentation · 🔎 Full diff

v1.0.0-rc.2

17 May 00:55

Choose a tag to compare

v1.0.0-rc.2 Pre-release
Pre-release
sockguard

sockguard is a default-deny Docker socket proxy written in Go. It filters every request by HTTP method, path, and request body — so a compromised API consumer can't escalate through the socket.


sockguard v1.0.0-rc.2 — release candidate 2

⚠️ Pre-release. This is the candidate that froze the v1.0 proxy contract on 2026-05-16. For production use the stable v1.0.0.

⚠️ Breaking change

A non-loopback plaintext TCP listener now requires two insecure acknowledgments instead of one: listen.insecure_allow_plain_tcp (unencrypted transport) and the new listen.insecure_allow_unauthenticated_clients (any host that can reach the port can impersonate a client). One flag without the other is rejected at config validation, so the dangerous mode can't be reached by a single fat-fingered flag. The same applies to admin.listen.*. Existing plaintext non-loopback TCP configs must add insecure_allow_unauthenticated_clients: true (env: SOCKGUARD_LISTEN_INSECURE_ALLOW_UNAUTHENTICATED_CLIENTS).

🔄 Changed

  • request_body.exec.allowed_commands entries are now glob-matched argv templates instead of exact strings. Each token follows the same dialect as path rules (* matches a run of non-slash characters, ** matches any sequence), so an operator can allowlist an exec whose argv carries a variable run ID, timestamp, or generated path — e.g. ["drydock", "finalize", "*"] — without enumerating every literal form. Tokens with no glob metacharacters keep matching exactly as before.
  • A rule whose match.path contains a literal % is now a config-validation error instead of a startup warning — sockguard percent-decodes paths before matching, so such a pattern can never fire, and a silently dead rule is a security-intent gap.

🐛 Fixed

  • Oversized request bodies on the exec, plugin, and swarm inspectors now return 413 Request Entity Too Large instead of 403. All body inspectors now share one size-rejection contract.

🔒 Security

Hardening from the 2026-05-16 branch review:

  • The visibility pattern-filter response buffer (GET /containers/json, /images/json with response.name_patterns / image_patterns) is now capped at 8 MiB — a larger upstream response is rejected with 502 instead of being buffered unbounded, closing an out-of-memory DoS.
  • The visibility middleware now honors rollout mode — an invisible single-resource inspect under mode: warn / audit is forwarded with a would_deny verdict instead of a hard 404, so operators can measure visibility-policy impact before enforcing.
  • The reverse-proxy and side-channel transports now set ResponseHeaderTimeout: 30s — a Docker daemon that accepts a connection but never sends headers can no longer pin a goroutine indefinitely.

📥 Install

docker pull ghcr.io/codeswhat/sockguard:1.0.0-rc.2

📦 ghcr.io/codeswhat/sockguard:1.0.0-rc.2 · 📖 Documentation · 🔎 Full diff

v1.0.0-rc.1

15 May 19:28

Choose a tag to compare

v1.0.0-rc.1 Pre-release
Pre-release
sockguard

sockguard is a default-deny Docker socket proxy written in Go. It filters every request by HTTP method, path, and request body — so a compromised API consumer can't escalate through the socket.


sockguard v1.0.0-rc.1 — release candidate 1

⚠️ Pre-release. First v1.0 release candidate. It carries the breaking renames the v1.x line is built on — read the section below before upgrading. For production use the stable v1.0.0.

⚠️ Breaking changes

YAML schema renames — update configs and env var names before upgrading:

  • listen.tls.allowed_common_nameslisten.tls.common_names (and the matching allowed_dns_names, allowed_ip_addresses, allowed_uri_sans, allowed_public_key_sha256_pins lose their allowed_ prefix — same five renames apply to admin.listen.tls.*).
  • request_body.plugin.allow_ipc_hostallow_host_ipc; allow_pid_hostallow_host_pid.
  • request_body.container_update.allow_devicesallow_all_devices.
  • admin.max_body_bytesadmin.max_request_bytes.
  • reload.debounce_ms / reload.poll_interval_ms (integer ms) → reload.debounce / reload.poll_interval (Go duration strings, e.g. "250ms").

CLI flag rename: --deny-response-verbosity--deny-verbosity.

Prometheus metric renames — update dashboards and alerts:

  • Counter sockguard_throttle_totalsockguard_throttle_requests_total; label reasonreason_code.
  • The rule label is dropped from sockguard_http_denied_requests_total (its value was a zero-based ordinal that shifted on any rule edit). The rule index still appears in the structured audit log (matched_rule) and access log (rule).

🔒 Security

Dependency hardening — bumped eight indirect dependencies to close 11 OSSF Scorecard / OSV-Scanner findings. govulncheck now reports zero reachable and zero unreachable-but-imported vulnerabilities for the proxy binary. Notable: go-tuf/v2 (path-traversal + delegation-threshold + DoS fixes), sigstore/rekor (SSRF + nil-deref fixes), golang.org/x/net (HTTP/2 infinite loop), google.golang.org/grpc (authorization bypass).

Filter inspector hardening:

  • POST /containers/create now always denies HostConfig.VolumesFrom, UTSMode=host, a non-empty CgroupParent, GroupAdd, and ExtraHosts — five namespace-escape / privilege-escalation fields that were previously uninspected. No policy can opt out.
  • POST /containers/{id}/exec and POST /swarm/unlock are now fail-closed when the request body can't be decoded.
  • Filter middleware applies a 30 s read deadline to the request body before inspection, so a slowloris-style stalled body can't pin an inspector worker.

Ownership & client-ACL hardening:

  • The owner-label filter on list endpoints now replaces the entire label filter rather than appending — closing a cross-tenant bypass where a client could OR in label=com.sockguard.owner=victim to widen the visible set.
  • Profile-lookup caches are now bounded (1024 entries, LRU); container-label resolution re-checks the container is still live before caching.

🔄 Changed

  • New RELEASING.md documents the end-to-end release process.
  • serve --help now enumerates configuration precedence; --config help documents the missing-file fallback behavior.

📥 Install

docker pull ghcr.io/codeswhat/sockguard:1.0.0-rc.1

📦 ghcr.io/codeswhat/sockguard:1.0.0-rc.1 · 📖 Documentation · 🔎 Full diff

v0.8.0

14 May 10:56
03dd7a2

Choose a tag to compare

sockguard

sockguard is a default-deny Docker socket proxy written in Go. It filters every request by HTTP method, path, and request body — so a compromised API consumer can't escalate through the socket.


sockguard v0.8.0 — hot reload, signed policy bundles & a control plane

This release turns sockguard's policy from a boot-time artifact into something you can stage, verify, and reload at runtime.

✨ Highlights

  • 🔁 Hot reload of policy at runtime.
  • ✍️ Signed policy bundles — cosign-verify the config before it's trusted.
  • 🎛️ Admin control plane — validate candidate configs and read the running policy version.
  • 🧪 Rollout modes — dry-run a tighter policy with enforce / warn / audit.

🚀 Added

  • Per-profile rollout modes via clients.profiles[*].mode: enforce|warn|audit. warn and audit let an operator stage a tighter policy without breaking callers — every deny gate consults the mode, the request is still served, the audit record carries decision=would_deny, and the deny/throttle counters gain a mode label so dashboards can compare blocked vs. would-have-been-blocked volume side by side. Pre-auth admission gates (CIDR allowlist, identity-lookup failures) stay enforce regardless.
  • Hot reload of policy. With reload.enabled: true, sockguard watches the config file via fsnotify and also reloads on SIGHUP. Events are debounced; the reload pipeline parses, validates, compiles, and atomically swaps the handler chain on success — on any failure the running policy is preserved. Mutating an immutable field (listen.*, upstream.socket, trust material, …) is refused. Two new metrics surface the outcome: sockguard_config_reload_total{result=...} and sockguard_config_reload_last_success_timestamp_seconds.
  • POST /admin/validate — an opt-in admin endpoint that runs a candidate YAML through the same parse/validate/compile pipeline as sockguard validate and returns a structured JSON report. Running policy is never mutated. Useful as a CI gate before promoting a config.
  • Policy versioning. A monotonic generation counter ticks once at startup and once per successful reload, published via GET /admin/policy/version (config SHA-256, rule/profile counts, signer + digest when bundles are enabled) and the sockguard_policy_version gauge.
  • Optional dedicated admin listener. When admin.listen.* is configured, the admin endpoints move to a separate http.Server — the main Docker-API listener never sees admin traffic and admin traffic never traverses the filter chain.
  • Signed policy bundles. With policy_bundle.enabled: true, the on-disk YAML is untrusted until a cosign sigstore bundle confirms it. Keyed (PEM public keys) and keyless (Fulcio issuer + subject) verification, optional Rekor inclusion. Verified at startup and on every hot reload — a signature failure rejects the reload with reject_signature and never touches running policy. Backed by sigstore-go, no new external dependency.

📥 Install

docker pull ghcr.io/codeswhat/sockguard:0.8.0

📦 ghcr.io/codeswhat/sockguard:0.8.0 · 📖 Documentation · 🔎 Full diff