Linux capabilities break the monolithic privilege of root into individual, grantable units. Instead of running a whole program as root to do one privileged thing, you grant just the capability it needs. This reference lists the capability constants with the exact power each confers and a risk rating.
How it works
Each capability is a named bit (e.g. CAP_NET_BIND_SERVICE) that authorizes a
specific class of privileged operations. A process carries several capability
sets — permitted, effective, inheritable, bounding and ambient — that together
decide which privileges are active. Executables can also carry file
capabilities, granted on exec, which replace the old setuid-root pattern.
The risk rating here is practical guidance: some capabilities are narrow and safe
(CAP_NET_BIND_SERVICE), while others — CAP_SYS_ADMIN, CAP_SYS_MODULE,
CAP_BPF, CAP_DAC_OVERRIDE — are powerful enough to be treated as equivalent
to full root.
Key capabilities at a glance
| Capability | What it grants | Risk |
|---|---|---|
CAP_NET_BIND_SERVICE | Bind ports below 1024 | Low |
CAP_NET_RAW | Use raw and packet sockets | Medium |
CAP_DAC_OVERRIDE | Bypass file read/write/exec DAC checks | High |
CAP_SYS_PTRACE | Trace any process, read its memory | High |
CAP_SYS_ADMIN | ~30 unrelated operations; near-root | High |
CAP_SYS_MODULE | Load and unload kernel modules | High |
CAP_BPF | Load BPF programs (kernel 5.8+) | Medium–High |
CAP_CHECKPOINT_RESTORE | Checkpoint/restore operations (kernel 5.9+) | Medium |
Example
To let a service bind port 443 without root, drop all capabilities and grant only the one it needs:
setcap cap_net_bind_service=+ep /usr/local/bin/myserver
getcap /usr/local/bin/myserver
# /usr/local/bin/myserver cap_net_bind_service=ep
The binary can now bind privileged ports while running as an unprivileged user.
Practical workflow: drop all, add only what you need
The safest approach for containers and system services is to start with no capabilities and add back only what the code actually calls. For Docker:
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE myimage
For systemd services, use AmbientCapabilities=CAP_NET_BIND_SERVICE in the unit file with User=myservice to gain the same effect without touching the binary.
Inspecting capability state
To see what capabilities a running process holds, read its /proc entry and decode the hex bitmask:
cat /proc/$(pgrep myservice)/status | grep Cap
# CapInh: 0000000000000000
# CapPrm: 0000000000000400
# CapEff: 0000000000000400
# CapBnd: 000001ffffffffff
capsh --decode=0000000000000400
# 0x0000000000000400=cap_net_bind_service
The effective set (CapEff) is what is actually active right now; the bounding set (CapBnd) caps what the process can ever gain.
Notes
CAP_SYS_PTRACElets a process read any other process’s memory — keep it out of multi-tenant environments and never grant it in shared containers.- Kernel 5.8 split
CAP_BPFandCAP_PERFMONout ofCAP_SYS_ADMIN, so modern profilers and eBPF tools can run narrowly privileged. - Capabilities pair with seccomp profiles, user namespaces, and cgroups; alone they are not a full sandbox — treat them as one layer in a defense-in-depth stack.