This error occurs when Docker's no-new-privileges security option prevents a container process from executing operations that require privilege escalation. The fix involves understanding when no-new-privileges is needed, configuring it correctly, or working around SELinux conflicts on RHEL-based systems.
The "operation not permitted (no-new-privileges)" error indicates that Docker's `no-new-privileges` security option is blocking an operation that would normally require privilege escalation inside the container. The `no-new-privileges` flag is a Linux kernel security feature (added in kernel 3.5) that, once set, prevents a process and all its descendants from gaining additional privileges through mechanisms like: - **setuid/setgid binaries**: Programs like `sudo`, `su`, or `ping` that normally run with elevated privileges - **File capabilities**: Executables with special capability bits that grant specific privileges - **SELinux domain transitions**: Moving from one security context to another with more permissions When Docker runs a container with `--security-opt no-new-privileges:true` (or the daemon default is enabled), the container cannot escalate privileges even if it runs setuid binaries or files with capabilities. This is a security hardening measure recommended by Docker security best practices. The error typically manifests when: 1. You explicitly enable no-new-privileges but your application requires privilege escalation 2. The daemon has no-new-privileges enabled globally in `/etc/docker/daemon.json` 3. SELinux is in enforcing mode and conflicts with the no-new-privileges setting on RHEL/CentOS/Fedora systems
First, confirm that no-new-privileges is the source of the problem by testing with it disabled:
# Test without no-new-privileges
docker run --security-opt no-new-privileges=false your-image
# Or explicitly allow privilege escalation
docker run --security-opt no-new-privileges:false your-imageIf the container works with no-new-privileges=false but fails with it enabled, you've confirmed the issue.
Check if no-new-privileges is enabled daemon-wide:
# Check daemon configuration
cat /etc/docker/daemon.json | grep -i priv
# Check docker info for security options
docker info --format '{{.SecurityOptions}}'If you see "no-new-privileges": true in daemon.json, that's overriding per-container settings.
Docker supports multiple syntax formats for no-new-privileges. Using the wrong format can cause unexpected behavior:
Correct formats:
# Using colon separator (recommended)
docker run --security-opt no-new-privileges:true your-image
docker run --security-opt no-new-privileges:false your-image
# Using equals sign
docker run --security-opt no-new-privileges=true your-image
docker run --security-opt no-new-privileges=false your-image
# Short form (enables it)
docker run --security-opt no-new-privileges your-imageIn Docker Compose:
services:
myapp:
image: your-image
security_opt:
- no-new-privileges:trueNote: Some older Docker versions only accept the colon format. If you get errors, try switching between : and =.
On systems with SELinux in enforcing mode, no-new-privileges can block necessary SELinux domain transitions, causing container startup failures.
Check if SELinux is the cause:
# Check SELinux status
getenforce
# Check for recent SELinux denials
sudo ausearch -m AVC -ts recent | grep docker
# Or check the audit log
sudo grep -i "denied.*docker" /var/log/audit/audit.logSolution 1: Update container-selinux package
The container-selinux package has fixes for no-new-privileges compatibility:
# On RHEL/CentOS 7/8
sudo yum update container-selinux
# On Fedora
sudo dnf update container-selinux
# Restart Docker after update
sudo systemctl restart dockerSolution 2: Temporarily set SELinux to permissive (testing only)
# Temporary - resets on reboot
sudo setenforce 0
# Test the container
docker run --security-opt no-new-privileges:true your-image
# Re-enable enforcing mode
sudo setenforce 1Solution 3: Add SELinux type bounds (advanced)
If updates don't help, you may need to add type bounds for the blocked transition:
# Check what transition is being blocked
sudo ausearch -m AVC -ts recent | grep "type=.*denied"If you want to keep no-new-privileges enabled (recommended for security), modify your application to not require privilege escalation:
For ping/network tools:
Instead of relying on setuid ping, use alternatives:
# Use iputils-ping with capabilities instead of setuid
RUN apt-get update && apt-get install -y iputils-ping \
&& setcap cap_net_raw+ep /bin/pingNote: With no-new-privileges, even file capabilities won't work. Consider using network-based health checks instead.
For sudo requirements:
Run the container as the user that needs access, instead of using sudo:
# Instead of running as root and using sudo
USER appuserOr:
docker run --user 1000:1000 your-imageFor applications that need root:
Run the necessary commands during image build, not at runtime:
# Do privileged operations during build
RUN chown -R appuser:appuser /app
RUN chmod +x /app/scripts/*.sh
# Then run as non-root
USER appuserIf your application genuinely requires privilege escalation and you accept the security trade-off, disable no-new-privileges:
Per-container:
docker run --security-opt no-new-privileges=false your-imageIn Docker Compose:
services:
myapp:
image: your-image
security_opt:
- no-new-privileges=falseDaemon-wide (not recommended):
If no-new-privileges is enabled in the daemon config and causing issues, you can disable it:
# Edit daemon.json
sudo nano /etc/docker/daemon.jsonRemove or set to false:
{
"no-new-privileges": false
}Then restart Docker:
sudo systemctl restart dockerSecurity warning: Disabling no-new-privileges reduces container isolation. Only do this if you understand the security implications and your application truly requires it.
In Kubernetes, no-new-privileges can be enforced via Pod Security Policies, Pod Security Standards, or SecurityContext:
Check if your pod has no-new-privileges set:
# In your pod/deployment spec
spec:
containers:
- name: myapp
securityContext:
allowPrivilegeEscalation: false # This enables no-new-privilegesTo allow privilege escalation:
spec:
containers:
- name: myapp
securityContext:
allowPrivilegeEscalation: trueCheck cluster-wide policies:
# Check for PodSecurityPolicies (deprecated in 1.25)
kubectl get psp
# Check for admission controller configurations
kubectl get validatingwebhookconfigurations
kubectl get mutatingwebhookconfigurationsIf a policy is enforcing allowPrivilegeEscalation: false, you may need to:
1. Request an exception from your cluster admin
2. Modify your application to not require privilege escalation
3. Use a different namespace with less restrictive policies
When containers fail to start due to no-new-privileges, get more details:
Check Docker logs:
# Get container ID from failed start
docker ps -a
# Check logs
docker logs <container_id>
# Inspect the container
docker inspect <container_id> | grep -A 10 "SecurityOpt"Run with verbose logging:
# Run interactively to see startup errors
docker run -it --security-opt no-new-privileges:true your-image /bin/sh
# If that works, try the actual entrypoint
docker run -it --security-opt no-new-privileges:true your-imageCheck what the entrypoint does:
# Inspect the image entrypoint
docker inspect your-image --format='{{.Config.Entrypoint}}'
docker inspect your-image --format='{{.Config.Cmd}}'If the entrypoint runs something like gosu or su-exec to drop privileges, it may conflict with no-new-privileges.
How no-new-privileges works at the kernel level:
The no_new_privs bit is set via prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0). Once set:
- It cannot be unset
- It's inherited by all child processes across fork() and exec()
- execve() will not honor setuid/setgid bits
- File capabilities in the "permitted" set are ignored
SELinux and no-new-privileges interaction:
SELinux type transitions happen during execve(). With no_new_privs, the kernel only allows transitions where the target type is a "subset" of the source type (type bounds). This is why Docker containers with SELinux enabled may fail:
# The transition from docker_t to svirt_lxc_net_t is blocked because
# svirt_lxc_net_t is not a type bound of docker_tDan Walsh's work on container-selinux has added the necessary type bounds for common container types.
Testing no-new-privileges behavior:
# Create a test image with a setuid binary
cat << 'EOF' > Dockerfile
FROM alpine
RUN chmod u+s /bin/ping
CMD ["ping", "-c", "1", "127.0.0.1"]
EOF
docker build -t test-setuid .
# This will work (setuid effective)
docker run --rm test-setuid
# This will fail (setuid ignored)
docker run --rm --security-opt no-new-privileges:true test-setuidDocker Bench Security recommendation:
The CIS Docker Benchmark recommends enabling no-new-privileges. Docker Bench Security check 5.25 verifies this:
# Run Docker Bench Security
docker run -it --net host --pid host --userns host --cap-add audit_control \
-v /var/lib:/var/lib:ro \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
docker/docker-bench-securityRootless Docker considerations:
In rootless Docker, no-new-privileges has additional implications because the Docker daemon itself runs without root. Some setuid operations that work in rootful Docker won't work even without no-new-privileges in rootless mode.
Alternative: Use capabilities instead of setuid:
Instead of relying on setuid binaries:
# Grant specific capabilities to the container
docker run --cap-add NET_RAW --security-opt no-new-privileges:true your-imageThis allows controlled privilege for specific operations while maintaining the no-new-privileges protection.
image operating system "linux" cannot be used on this platform
How to fix 'image operating system linux cannot be used on this platform' in Docker
manifest unknown: manifest unknown
How to fix 'manifest unknown' in Docker
cannot open '/etc/passwd': Permission denied
How to fix 'cannot open: Permission denied' in Docker
Error response from daemon: failed to create the ipvlan port
How to fix 'failed to create the ipvlan port' in Docker
toomanyrequests: Rate exceeded for anonymous users
How to fix 'Rate exceeded for anonymous users' in Docker Hub