### SockGuard CLI Commands Source: https://getsockguard.com/docs/getting-started A set of command-line examples for managing SockGuard: starting the proxy, validating configuration, testing requests offline, verifying runtime health, and printing the version. Each command uses the `sockguard` binary with specific flags. ```bash # Start the proxy (default command) sockguard serve # Start with a signed policy and separate pinned trust sockguard serve --config /etc/sockguard/sockguard.yaml --policy-bundle-trust-config /etc/sockguard/policy-bundle-trust.yaml # Validate configuration and print the compiled rule table sockguard validate -c /etc/sockguard/sockguard.yaml # Offline dry-run: evaluate a single request against the rules, # show which rule fires and why, without starting the proxy. sockguard match -c /etc/sockguard/sockguard.yaml \ -X GET --path /v1.45/containers/json # Runtime self-check: is the upstream daemon answering, is this # sockguard's own health endpoint up, does the TLS material load sockguard verify -c /etc/sockguard/sockguard.yaml # Print version sockguard version ``` -------------------------------- ### Unix socket endpoints example Source: https://getsockguard.com/docs/multi-host Shows how to reference unix sockets in the endpoints list. A bare path starting with '/' is treated as unix://. TLS fields on unix endpoints are rejected at startup. ```yaml upstream: endpoints: - address: unix:///var/run/docker.sock - address: /var/run/docker-secondary.sock # bare path treated as unix:// ``` -------------------------------- ### Run sockguard binary from GitHub Releases Source: https://getsockguard.com/docs/getting-started Starts the sockguard server with a specified configuration file. Download the binary from GitHub Releases first. ```bash sockguard serve -c /etc/sockguard/sockguard.yaml ``` -------------------------------- ### Install cosign on macOS and Linux Source: https://getsockguard.com/docs/verification Install cosign v3 or later. The release pipeline signs with v3.1.3, pinned in release-from-tag.yml, and the --bundle commands assume the bundle format it emits. ```bash # macOS brew install cosign # Linux (pre-built binary, pin the sha as you see fit) curl -Lo cosign https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64 chmod +x cosign sudo mv cosign /usr/local/bin/ ``` -------------------------------- ### GET /admin/policy/version - Example response body Source: https://getsockguard.com/docs/admin Example response body for GET /admin/policy/version. The version field is a monotonic counter that increments at startup and once per successful hot reload; a stable value across two queries means the policy did not change. The config_sha256 is best-effort and may be empty if the encoder fails. Bundle fields are omitted when policy_bundle.enabled is false. ```json { "version": 4, "loaded_at": "2026-05-13T14:22:01Z", "source": "reload", "rules": 8, "profiles": 3, "compat_active": false, "config_sha256": "a3f2b7c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1", "bundle_source": "operator-signed", "bundle_signer": "keyless:https://token.actions.githubusercontent.com:https://github.com/my-org/my-repo/.github/workflows/release.yml@refs/heads/main", "bundle_digest": "b4c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7" } ``` -------------------------------- ### Homebrew install and version check for sockguard Source: https://getsockguard.com/docs/getting-started Installs the latest stable native binary on macOS or Linux from the CodesWhat tap. The cask installs only the `sockguard` command; it does not create a service or grant Docker socket access. Run `sockguard version` to verify the installation. ```bash brew install --cask codeswhat/tap/sockguard sockguard version ``` -------------------------------- ### POST /admin/validate request example Source: https://getsockguard.com/docs/admin Shows the HTTP request format for the endpoint. The body is a candidate sockguard.yaml file, limited to admin.max_request_bytes (default 512 KiB) via http.MaxBytesReader. ```http POST /admin/validate Content-Type: application/x-yaml ``` -------------------------------- ### GET /admin/policy/version - Retrieve active policy snapshot Source: https://getsockguard.com/docs/admin Returns a snapshot of the currently active policy: version counter, metadata about which config was loaded, bundle verification results when signed bundles are enabled, and the SHA-256 of the effective config. Responds with 200 OK when the snapshot is available, 405 Method Not Allowed for non-GET methods (with an Allow: GET header), and 503 Service Unavailable if the policy snapshot is not initialized yet. ```http GET /admin/policy/version ``` -------------------------------- ### Customize preset with request_body container_create Source: https://getsockguard.com/docs/cis-docker-benchmark Example of how to customize the preset to record an intentional divergence from CIS 5.5: allows mounting /srv/data even though it diverges from the benchmark. Editing the preset file is the canonical place for such notes. ```yaml request_body: container_create: # CIS 5.5: production workload needs /srv/data mounted. Diverges # from the benchmark intentionally — approved 2026-05-20 by # security. allowed_bind_mounts: - "/srv/data" ``` -------------------------------- ### GET /admin/policy/version Source: https://getsockguard.com/docs/admin Returns a snapshot of the currently active policy: version counter, metadata about which config was loaded, bundle verification results when signed bundles are enabled, and the SHA-256 of the effective config. ```APIDOC ## GET /admin/policy/version ### Description Returns a snapshot of the currently active policy: version counter, metadata about which config was loaded, bundle verification results when signed bundles are enabled, and the SHA-256 of the effective config. ### Method GET ### Endpoint /admin/policy/version ### Parameters None ### Request Example ``` GET /admin/policy/version ``` ### Response #### Success Response (200) - **version** (int) - Monotonic counter. Increments at startup and once per successful hot reload. A stable value across two queries means the policy genuinely did not change. - **loaded_at** (RFC3339 string) - Timestamp when this version became active - **source** (string) - `"startup"` or `"reload"` - **rules** (int) - Number of compiled filter rules in the active policy - **profiles** (int) - Number of named client profiles - **compat_active** (bool) - `true` when Tecnativa env-var compat rules are in effect - **config_sha256** (hex string) - SHA-256 of the effective config's JSON encoding. Best-effort; may be empty if the encoder fails. Two snapshots with the same `version` but different hashes indicate a config-drift bug. - **bundle_source** (string) - Omitted when `policy_bundle.enabled: false`. The basename of `policy_bundle.signature_path`, with the directory stripped so the response does not leak the host's filesystem layout to Docker API callers on the main listener. - **bundle_signer** (string) - Omitted when bundles disabled. `keyed:` for keyed verification or `keyless::` for keyless. - **bundle_digest** (hex string) - Omitted when bundles disabled. SHA-256 of the verified YAML bytes. #### Response Example ``` { "version": 4, "loaded_at": "2026-05-13T14:22:01Z", "source": "reload", "rules": 8, "profiles": 3, "compat_active": false, "config_sha256": "a3f2b7c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1", "bundle_source": "operator-signed", "bundle_signer": "keyless:https://token.actions.githubusercontent.com:https://github.com/my-org/my-repo/.github/workflows/release.yml@refs/heads/main", "bundle_digest": "b4c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7" } ``` #### Error Responses - **405 Method Not Allowed** - Non-GET method; `Allow: GET` header is set - **503 Service Unavailable** - Policy snapshot not initialized yet (should not occur after startup) ``` -------------------------------- ### Run sockguard with cis-docker-benchmark.yaml preset Source: https://getsockguard.com/docs/cis-docker-benchmark Starts sockguard with the bundled CIS Docker Benchmark preset. Replace with the numeric group owner of the host socket (stat -c '%g' /var/run/docker.sock on Linux, stat -f '%g' on macOS). The preset is at /etc/sockguard/cis-docker-benchmark.yaml; the --config default is /etc/sockguard/sockguard.yaml with no search path, so a config mounted under another name is ignored. SOCKGUARD_LISTEN_SOCKET puts it on the Unix socket used by the verification steps. ```bash docker run -d \ --name sockguard \ --group-add \ -v /var/run/docker.sock:/var/run/docker.sock \ -v sockguard-socket:/var/run/sockguard \ -e SOCKGUARD_LISTEN_SOCKET=/var/run/sockguard/sockguard.sock \ ghcr.io/codeswhat/sockguard:latest \ serve -c /etc/sockguard/cis-docker-benchmark.yaml ``` -------------------------------- ### Docker Compose setup for Sockguard and consumer app Source: https://getsockguard.com/docs Defines a Sockguard service with a hardened configuration (read-only, dropped capabilities, no-new-privileges) and a consumer app that connects to the filtered socket. Requires setting DOCKER_SOCK_GID to the host socket's group ID before starting. The consumer must run as UID 65532 to access the socket. ```yaml services: sockguard: image: codeswhat/sockguard:latest restart: unless-stopped read_only: true cap_drop: - ALL security_opt: - no-new-privileges:true group_add: - "${DOCKER_SOCK_GID:?set to the GID of /var/run/docker.sock}" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - sockguard-socket:/var/run/sockguard environment: - SOCKGUARD_LISTEN_SOCKET=/var/run/sockguard/sockguard.sock - SOCKGUARD_INSECURE_ALLOW_READ_EXFILTRATION=true - CONTAINERS=1 - IMAGES=1 - EVENTS=1 your-app: depends_on: - sockguard # Sockguard's filtered socket is 0600 and owned by its non-root UID. user: "65532:65532" volumes: - sockguard-socket:/var/run/sockguard:ro environment: - DOCKER_HOST=unix:///var/run/sockguard/sockguard.sock volumes: sockguard-socket: ``` -------------------------------- ### Sockguard config: deny exfiltration-prone GET endpoints and allow reads Source: https://getsockguard.com/docs/migration Sockguard configuration that mirrors 11notes/docker-socket-proxy's read-only policy by denying the seven exfiltration-prone GET endpoints (with wildcard patterns covering inspect and nested image names) and then allowing all other GET requests. Requires insecure_allow_read_exfiltration: true at the top; without it Sockguard exits 1 at startup and lists the additional endpoints (logs, /libpod/** archive/export, /libpod/generate/kube) that the broad GET /** allow would expose. ```yaml insecure_allow_read_exfiltration: true rules: # Deny the seven exfiltration-prone reads 11notes targets # (11notes' own regex only reliably blocks six of these) - match: { method: GET, path: "/containers/*/attach/ws" } action: deny - match: { method: GET, path: "/containers/*/export" } action: deny - match: { method: GET, path: "/containers/*/archive" } action: deny # ** so the inspect endpoints are covered too; a bare /secrets is a literal # match that leaves GET /secrets/{id} to the catch-all allow below - match: { method: GET, path: "/secrets/**" } action: deny - match: { method: GET, path: "/configs/**" } action: deny - match: { method: GET, path: "/swarm/unlockkey" } action: deny # ** covers both single-segment and nested (registry-qualified) image names - match: { method: GET, path: "/images/**/get" } action: deny # Allow everything else read-only, writes fall through to default-deny - match: { method: GET, path: "/**" } action: allow ``` -------------------------------- ### Upgrade and uninstall sockguard cask Source: https://getsockguard.com/docs/getting-started Upgrade or remove the Homebrew cask for sockguard. These commands manage the cask installation. ```bash brew upgrade --cask sockguard brew uninstall --cask sockguard ``` -------------------------------- ### drydock-with-build.yaml: Classic builder support Source: https://getsockguard.com/docs/presets Extends drydock-with-compose.yaml to allow POST /build for the classic builder only. Denies /session, /grpc, and BuildKit method paths. Requires DOCKER_BUILDKIT=0 in the client environment; otherwise builds fail with a /session or /grpc denial. ```yaml # Extends drydock-with-compose.yaml with: # Allows: POST /build — classic builder only, request_body.build left at its # secure defaults (allow_remote_context/allow_host_network/ # allow_run_instructions all false) # Still denies: /session, /grpc, and any moby.buildkit.v1.Control method path # — this preset does not open either endpoint, no insecure_accept_opaque_ # buildkit_tunnels acknowledgment (now deprecated) and no request_body.buildkit # mediation policy. THIS FAILURE IS INTENTIONAL: modern Buildx defaults to # BuildKit, so a default `docker compose build` against this preset still # fails with a /session or /grpc denial. Set DOCKER_BUILDKIT=0 in the client # environment to fall back to the classic builder this preset actually # supports, or use drydock-with-mediated-build.yaml for the fully-mediated # BuildKit alternative. ``` -------------------------------- ### Portwing with Build (portwing-with-build.yaml) Configuration Source: https://getsockguard.com/docs/presets This preset extends portwing-with-compose.yaml to support classic builder operations. It requires the client to set DOCKER_BUILDKIT=0, as modern BuildKit defaults will trigger access denials. ```yaml # Extends portwing-with-compose.yaml with: # Allows: POST /build — classic builder only, request_body.build left at its # secure defaults (allow_remote_context/allow_host_network/ # allow_run_instructions all false) # Still denies: /session, /grpc, and any moby.buildkit.v1.Control method path # — this preset does not open either endpoint, no insecure_accept_opaque_ # buildkit_tunnels acknowledgment (now deprecated) and no request_body.buildkit # mediation policy. THIS FAILURE IS INTENTIONAL: modern Buildx defaults to # BuildKit, so a default `docker compose build` against this preset still # fails with a /session or /grpc denial. Set DOCKER_BUILDKIT=0 in the client # environment to fall back to the classic builder this preset actually # supports, or use portwing-with-mediated-build.yaml for the fully-mediated # BuildKit alternative. # insecure_allow_read_exfiltration=true is inherited from portwing.yaml for the # GET /containers/*/logs rule (see the Portwing section above) ``` -------------------------------- ### GitHub Actions self-hosted runner preset (github-actions-runner.yaml) Source: https://getsockguard.com/docs/presets Preset for self-hosted GitHub Actions runners using the Docker socket to spawn job containers and services. Allows container lifecycle, exec, attach, log streaming, image pull, per-job networks, and named volumes; denies privileged operations, build, swarm, secrets, plugins, and raw tarball export. Requires pairing with client authentication (clients.allowed_cidrs or clients.unix_peer_profiles) and enables body-blind writes and read exfiltration. ```yaml # Allows: container lifecycle, exec, attach, log streaming (GET /containers/*/logs), # image pull, per-job networks, named volumes for cache # Denies: privileged containers, privileged exec, host namespace sharing, bind mounts, # capability additions, build, swarm, secrets, plugins, # raw tarball export (/containers/*/export, /images/*/get) # insecure_allow_body_blind_writes=true — exec argv is not command-pinned (workflow steps are # arbitrary); only privileged exec is denied. insecure_allow_read_exfiltration=true — the runner # streams job output via the logs and attach APIs. Gate the proxy socket to the runner process # via clients.unix_peer_profiles or clients.allowed_cidrs to bound both. ``` -------------------------------- ### Read-Only Configuration (readonly.yaml) Source: https://getsockguard.com/docs/presets Allows GET access to all Docker API endpoints while denying all write operations. Sets insecure_allow_read_exfiltration to true to permit raw archive/export and log/attach stream reads. ```yaml # Allows: GET on containers, images, networks, volumes, system, events, info, ping, version # Denies: all POST, PUT, DELETE ```