Myth: you can give a user sudo on everything except a few dangerous commands. Fact: the sudoers manual says subtracting commands from ALL is generally not effective, and a user with ALL can create their own program that gives a root shell. Use an allow list of specific commands instead.
The myth
It is tempting to write a rule such as:
bill ALL = ALL, !SU, !SHELLS
with SU and SHELLS as aliases for su, bash, sh and similar. It reads like a deny list, and many people assume it works like one.
The fact
The sudoers manual addresses this exact rule in its security notes. It says it is generally not effective to subtract commands from ALL with the ! operator, because a user can copy the desired command to a different name and run that. The same page says that if a user has sudo ALL, nothing prevents them from creating their own program that gives a root shell, or making their own copy of a shell, whatever ! entries say. It concludes that such restrictions are advisory at best and should be reinforced by policy.
So the rule above documents an intention. It does not enforce one.
Related traps in the manual
Shell escapes. Once sudo starts a program, that program can run other programs. The manual says editors, pagers, mail and terminal programs commonly permit shell escapes, which bypass sudo's access control and logging. It lists four approaches. Restricting users to programs without escapes is often unworkable. Intercept mode can validate and log commands run from inside a privileged program, but it has limits, such as not covering shell built-ins and not working with every program.
Negated patterns. Negating a command that uses a wildcard or regular expression in its path can be bypassed, and the manual says using a negated regular expression for the command name is strongly discouraged. Related: the argument wildcard pitfall.
What to do instead
- Write allow lists. List the exact commands a role needs, with fixed arguments.
- Use sudoedit for file edits rather than allowing an editor. See why sudoedit beats sudo vim.
- Treat ALL as root. If someone truly needs everything, say so in the access record and review it, instead of pretending a deny list limits them.
- Log what happens. Keep sudo logs, and send them off the host.
- Add controls outside sudo. File permissions, mandatory access control and session recording catch what sudoers rules cannot.
- Review on a schedule. Remove rules for people who changed roles.
A quick test
Pick one deny rule from your own sudoers files. Log in as that user and try to bypass it by copying the denied binary under another name, or by opening an editor and escaping to a shell. If it works, you have learned something cheaper than an incident.
Safeguard offers compliance evidence automation for access reviews and a free scan at gold.safeguard.sh/scan.
Quick check
Does ALL, !SHELLS stop a user from getting a shell?
No. The manual says they can copy a command under another name or use a shell escape, so the restriction is advisory at best.
What is the safer pattern?
An allow list of specific commands with fixed arguments, plus sudoedit for file edits and logging.
Sources
- sudoers(5) manual page, man7.org, SECURITY NOTES
Last reviewed: 19 October 2026.