Hardening Linux Namespaces and POSIX Capabilities
Prevent privilege escalation by stripping unused POSIX capabilities, disabling unprivileged user namespaces, and enforcing Ambient Capabilities.
Netbay Developer Relations
Netbay Engineering
On this page
Historically, Linux partitioned security privileges into a crude binary model: either a process ran as an unprivileged user (UID > 0) with restricted permissions, or as the all-powerful superuser (root, UID 0). If a web server needed to bind to low-numbered privileged port 80 or 443, administrators had to launch the entire binary as root, creating immense blast radius if the application suffered a memory safety bug.
POSIX capabilities decompose monolithic superuser privileges into 41 distinct permissions, such as CAP_NET_BIND_SERVICE (bind privileged ports), CAP_NET_ADMIN (configure network interfaces), and CAP_SYS_PTRACE (trace processes). Combining capability dropping with Linux namespace restrictions prevents attackers who compromise container runtimes or web applications from escalating to host-level root control.
Inspecting and Granting File Capabilities
Instead of running services via setuid root binaries (like chmod u+s), attach targeted capabilities directly to executable file headers using libcap2-bin:
# Inspect existing capabilities on binaries
getcap /usr/sbin/tcpdump
getcap /usr/bin/ping
# Grant a custom Golang binary permission to bind ports 80/443 without root
sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/custom-proxy
# Verify that the capability is attached
getcap /usr/local/bin/custom-proxy
# Output: /usr/local/bin/custom-proxy cap_net_bind_service=epNow unprivileged user www-data can execute /usr/local/bin/custom-proxy and listen on port 443 without requiring sudo or root ownership.
Enforcing Capability Hardening in systemd
For modern service daemons, manage capabilities declaratively within systemd service unit files rather than attaching them to filesystem metadata:
# /etc/systemd/system/secure-api.service
[Unit]
Description=Hardened Secure API
After=network.target
[Service]
Type=simple
User=apiuser
Group=apiuser
ExecStart=/usr/local/bin/api-server
# Drop all capabilities except port binding
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
# Sandboxing directives
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
RestrictNamespaces=yesSetting NoNewPrivileges=yes ensures that the process and any child processes it spawns cannot gain new privileges via setuid or setgid binaries.
Privilege Escalation Video
Inspect common privilege escalation techniques and kernel boundary defenses in this technical walkthrough:
Disabling Unprivileged User Namespaces
Unprivileged user namespaces allow non-root users to create arbitrary namespaces. While useful for rootless containers, they have historically accounted for dozens of local privilege escalation vulnerabilities in the Linux kernel. If you run standard Docker or systemd daemons, disable unprivileged user namespaces via sysctl:
# Disable unprivileged user namespace creation
echo "kernel.unprivileged_userns_clone = 0" | sudo tee /etc/sysctl.d/99-disable-userns.conf
sudo sysctl -p /etc/sysctl.d/99-disable-userns.confDeploy hardened microservices on secure cloud instances at netbayhosts.in.
Keep reading
Follow along on a real VPS
Deploy Linux in under 60 seconds
These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.
Deploy an instance