The Guest List in /etc/sudoers: Auditing Privilege Without Locking Yourself Out
Photo: Linux server terminal sudo command system administration stock photo, via www.debugpoint.com
Every Linux box you inherit has a guest list. Sometimes it is a tidy /etc/sudoers file. More often it is that file plus a pile of drop-ins under /etc/sudoers.d, each one added by someone who was in a hurry, and each one carrying a little more authority than the last. The result is not usually a dramatic breach. It is something quieter: a service account that can restart anything, a wildcard rule that was meant to cover one script but covers a whole directory, and a NOPASSWD entry that made sense in 2019 and has been riding along ever since.
Auditing sudo privileges is not about distrusting your teammates or your past self. It is about knowing who can do what before an incident, a migration, or a compliance review forces the question. The good news is that you can build a useful inventory with standard tools, and you can remediate it without sawing off the branch you are sitting on.
Snapshot First, Edit Never
The first rule of sudoers work is simple: do not open an editor until you have a copy you can go back to. On a home lab box this feels like overkill. On a machine you reach only through SSH, it is the difference between a five-minute fix and a drive to the office with a rescue USB stick.
Start with a timestamped archive of the current state:
sudo tar -czf ~/sudoers-snapshot-$(date +%F).tgz /etc/sudoers /etc/sudoers.d
sudo visudo -c
That second command validates the current configuration. Run it before you change anything so you know whether the file was already broken. Then keep a root shell open for the rest of the session. Not a shell where you can run sudo; an actual root shell. If you are working remotely, keep a second SSH session open as a non-root user and confirm that you can still authenticate. It sounds paranoid until the first time a drop-in file has a syntax error and sudo stops parsing the whole stack.
Turn the Guest List Into Rows
A sudoers file is readable by humans, but it is not pleasant to audit by eye. You want a machine-readable inventory: user or group, host, run-as target, command, and whether a password is required.
Modern sudo ships with cvtsudoers, which can translate the sudoers format into structured output. Check what your version supports:
cvtsudoers -h | head -40
If JSON or CSV output is available, use it. A command like sudo cvtsudoers -f json /etc/sudoers gives you a parseable view of the main file. Remember that it does not automatically include every drop-in unless you point it at them, so collect /etc/sudoers.d separately or use the include-aware options your version provides.
If your sudo is older, fall back to the account-by-account approach. List real login accounts and service accounts, then ask sudo what each one can do:
getent passwd | awk -F: '$3 >= 1000 {print $1}' | while read -r u; do
echo "### $u"
sudo -l -U "$u" 2>/dev/null
done
That output is not perfect for automation, but it is excellent for spotting outliers. Paste it into a scratch file, sort it, and look for the accounts that show up with more authority than their job description suggests.
Patterns That Should Make You Sit Up
Not every sudoers rule is a problem. The goal is not to remove convenience; it is to remove surprises. A few patterns deserve a second look every time.
The universal NOPASSWD grant. ALL=(ALL) NOPASSWD: ALL is sometimes appropriate for an automation account, but it is rarely appropriate for a human account that also has SSH access. If an account can log in interactively and run anything without a password, that account is now a single credential away from full control.
Wildcard commands with room to grow. A rule like /usr/bin/systemctl * looks narrow because it names systemctl. In practice, it can cover far more than the one service you had in mind. Sudoers wildcards match arguments, and argument matching is not a security boundary in the way people sometimes assume. Write down what the rule was supposed to enable, then test whether the current pattern permits more.
Service accounts with interactive shells. Automation accounts should usually have /usr/sbin/nologin as their shell and a tightly scoped set of commands. If a service account can log in and has broad sudo rights, you have two problems wearing one name badge.
Rules for people who left. This is the classic. The account is disabled in the HR system, but the sudoers entry is still there. Inventory the rules against your current account list, not your memory of the team.
Group grants nobody owns. %wheel ALL=(ALL) ALL is common and often fine, but only if you know who is in wheel. Check group membership separately. A generous group rule is only as safe as its least-reviewed member.
Remediate Like You Expect a Rollback
Once you have the inventory, resist the urge to rewrite everything in one pass. Sudoers changes are high-leverage: a small mistake can remove your own access or break automation that runs at 3 a.m.
Use visudo for every edit. It validates syntax before saving. Prefer numbered drop-in files under /etc/sudoers.d with comments that record the owner and the reason. Something like 10-app-deploy is easier to reason about than a mysterious line at the bottom of the main file.
Make one change at a time. After each change, run sudo visudo -c and then test with sudo -l -U for the affected account. If you are changing your own privileges, keep that root shell open and test from a separate login. When a rule is retired, comment it out in the drop-in first, wait through one normal operating cycle, then remove it.
For remote systems, set a rollback timer before you start. A simple at job that restores the snapshot in 30 minutes is ugly but effective:
sudo at now + 30 minutes <<'EOF'
tar -xzf /root/sudoers-snapshot.tgz -C /
EOF
Cancel the job once you have confirmed everything works. It is not elegant, but neither is a lockout.
Make It a Quarterly Habit
A sudoers audit is not a one-time cleanup. Accounts change, automation grows, and someone will always add a rule during a maintenance window. Put the inventory on a quarterly calendar. Store the sanitized output in version control if you can, and note who owns each broad grant. The goal is not a perfectly minimal sudoers file. The goal is a guest list you can explain, one line at a time, without guessing.