Skip to content

no-weakened-confinement

cap_add SYS_ADMIN, SYS_MODULE, SYS_RAWIO or DAC_READ_SEARCH, and security_opt seccomp:unconfined, apparmor:unconfined, label:disable or systempaths=unconfined, weaken Compose container isolation. What each setting removes.

On this page

Docker starts a container with a short list of Linux capabilities, a seccomp filter that blocks dangerous syscalls, an AppArmor or SELinux profile, and masked paths under /proc and /sys. Each of those is a layer between a compromised process and the host kernel. cap_add and security_opt are how a Compose file removes them, and they are often added to get past one error and never taken out. This rule reports:

  • cap_add entries for SYS_ADMIN, SYS_MODULE, SYS_RAWIO and DAC_READ_SEARCH, in any case and with or without the CAP_ prefix.
  • security_opt entries seccomp:unconfined, apparmor:unconfined, label:disable and systempaths=unconfined, written with either : or =.

SYS_ADMIN covers mounts and a large part of the kernel's interface. SYS_MODULE loads code into the host kernel. SYS_RAWIO reaches raw I/O ports and memory. DAC_READ_SEARCH bypasses file read checks, and with it a container can open host files by handle. cap_add: [ALL] is reported by no-privileged-service as an error.

NET_ADMIN, NET_RAW and SYS_PTRACE are not reported, because VPN clients and monitoring tools need them.

What the rule catches

compose.yaml — a broad capability and no syscall filter
services:
  agent:
    image: my-agent:1.2.0
    cap_add:
      - SYS_ADMIN
    security_opt:
      - seccomp:unconfined

Scanning this file reports:

⚠ WARN [docker-doctor/no-weakened-confinement]
  Service 'agent' sets cap_add 'SYS_ADMIN', which lets it mount filesystems and reach most of the kernel.

Why it matters

A container shares the host's kernel, so the capabilities, syscall filter and security profile are the only things that limit what a compromised process can ask of it. Removing them widens the kernel surface it can attack and turns an ordinary bug into a host compromise. The runc escapes CVE-2025-31133 and CVE-2025-52565 show how much rides on these defaults. Their advisories say not to run untrusted images, and for containers without user namespaces to avoid root privileges and turn on no new privileges. A service that adds SYS_ADMIN or sets seccomp:unconfined works against that advice.

How to fix it

Remove the capability or the security_opt entry. If the service needs one specific thing, grant that instead, such as a single device in devices.

compose.yaml — one narrow capability, privilege gain blocked
services:
  agent:
    image: my-agent:1.2.0
    cap_add:
      - NET_ADMIN
    security_opt:
      - no-new-privileges:true

Start from no extra access and add only what the error asks for:

  • A device: list it in devices instead of adding a capability.
  • A mount: use a volume, or a tmpfs, instead of SYS_ADMIN.
  • A blocked syscall: write a seccomp profile that allows that syscall and point security_opt at it with seccomp:./profile.json. The rule does not report a custom profile.
  • Privilege gain: add no-new-privileges:true to security_opt.

Some low-level tools, such as profilers and sandboxes that run their own containers, ask for these settings. Set this rule to off in docker-doctor.config.json for a project that exists to run such a tool.

Rule details

  • Rule key — docker-doctor/no-weakened-confinement
  • Category — Compose
  • Default severity — warning
  • Applies to — Docker Compose files

Explain this rule from the CLI:

npx @docker-doctor/cli@latest rules explain docker-doctor/no-weakened-confinement

Change its severity — or turn it off — in your config file:

// docker-doctor.config.ts
export default {
  rules: {
    "docker-doctor/no-weakened-confinement": "off",
  },
};

Severity affects the health score: error findings cost more points than warning, and info costs the least.