Skip to content

✨ feat(filter): swarm ContainerSpec User/Privileges enforcement parity - #92

Merged
scttbnsn merged 1 commit into
mainfrom
feat/swarm-user-privileges-parity
Jun 11, 2026
Merged

✨ feat(filter): swarm ContainerSpec User/Privileges enforcement parity#92
scttbnsn merged 1 commit into
mainfrom
feat/swarm-user-privileges-parity

Conversation

@scttbnsn

Copy link
Copy Markdown
Contributor

What

Service create/update now enforces the same identity/privilege hardening rails the container-create inspector already enforces, mirrored onto the swarm ContainerSpec. This closes a bypass where a swarm service could request a workload posture that POST /containers/create would have denied.

Four new opt-in request_body.service knobs (all default off):

Knob ContainerSpec field Mirrors
require_non_root_user User container-create require_non_root_user
require_no_new_privileges Privileges.NoNewPrivileges (bool) container-create require_no_new_privileges
require_readonly_rootfs ReadOnly container-create require_readonly_rootfs
require_drop_all_capabilities CapabilityDrop ⊇ "ALL" container-create require_drop_all_capabilities

The root-user check reuses container-create's numeric-UID parse, so zero-padded "00" / "0:0" forms are rejected, not just the literal "0". NoNewPrivileges is a direct Privileges boolean here (a nil Privileges block = unset = denied), unlike the container-create HostConfig.SecurityOpt string encoding.

Scope rationale

Swarm has no privileged mode, no per-service namespace sharing (PidMode/IpcMode/UsernsMode), and no runtime/device selection in ContainerSpec, so those container-create rails have no service equivalent and are intentionally not mirrored. Seccomp/AppArmor map only to a narrow enum (unconfined/disabled) rather than container-create's named-profile allowlist — deferred to a follow-up to avoid shipping divergent semantics under the same config names (tracked in the README roadmap).

Tests

  • Rail-by-rail deny/allow for all four knobs
  • Zero-padded/root/0:0 UID rejection
  • NoNewPrivileges nil-block vs explicit-false vs true
  • All-rails-satisfied compose on the /services/*/update path
  • Env-var registration guard (Viper only unmarshals registered keys)
  • Config → ServiceOptions field-mapping coverage

gofmt, go vet, golangci-lint, and full go test ./... all clean locally; pre-push suite passed.

Docs

CHANGELOG Added, README roadmap (item moved to done; seccomp/apparmor remainder noted), and configuration.mdx (prose, options table, example YAML, four env-var rows) updated atomically.

Service create/update now mirrors four container-create hardening knobs
onto the swarm ContainerSpec, closing a bypass where a service could
request a workload posture /containers/create would have denied:

- 🔒 require_non_root_user → ContainerSpec.User (reuses the numeric-UID
  parse, so zero-padded "00"/"0:0" forms are rejected, not just "0")
- 🔒 require_no_new_privileges → ContainerSpec.Privileges.NoNewPrivileges
  (a direct bool, unlike the container-create SecurityOpt string)
- 🔒 require_readonly_rootfs → ContainerSpec.ReadOnly
- 🔒 require_drop_all_capabilities → ContainerSpec.CapabilityDrop ⊇ "ALL"

All default off. Swarm has no privileged mode, per-service namespace
sharing, or runtime/device selection, so those container-create rails
have no service equivalent and are intentionally not mirrored. Seccomp/
AppArmor map only to a narrow enum (unconfined/disabled) rather than the
named-profile allowlist, deferred to avoid divergent semantics.

- ✨ feat(config): add the four require_* service knobs + Viper defaults
- 🧪 test: rail-by-rail deny/allow, zero-padded UID, update path, env-var
  registration guard, and options-mapping coverage
- 📝 docs(changelog/readme/config): document the new rails and env vars
@vercel

vercel Bot commented Jun 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
sockguard-website Ready Ready Preview, Comment Jun 11, 2026 2:46am

@biggest-littlest biggest-littlest left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving: swarm ContainerSpec User/Privileges parity. CI fully green (36/36), scope cleanly mirrors the container-create rails with no phantom swarm fields, tests cover every rail + zero-padded UID + env-var registration.

@scttbnsn
scttbnsn merged commit c4160de into main Jun 11, 2026
37 checks passed
@scttbnsn
scttbnsn deleted the feat/swarm-user-privileges-parity branch June 11, 2026 10:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants