“Audit SUID executables” is a CIS benchmark item asking you to review every SUID (set-user-ID) file, because each runs with its owner’s privileges, usually root. Fix it by listing them with find / -xdev -type f -perm -4000, confirming each belongs to a package you need, and clearing the bit with chmod u-s where it does not.
What the scanner is actually detecting
This finding comes from Tenable’s CIS Linux audit files, run as a credentialed compliance scan in Nessus. It is a review item, not a vulnerability check: Nessus runs a file search on the host, returns the list of SUID (and in some benchmarks SGID) files as output, and leaves the judgment to you. Tenable’s item text notes that Nessus “has provided the target output to assist in reviewing”, and manual items like this normally appear with a WARNING status instead of PASSED or FAILED.
The wording and numbering change between benchmarks:
| Tenable audit file | Item title |
|---|---|
| CIS SUSE Linux Enterprise Server 11 L1 v2.1.1 | 6.1.11 Audit SUID executables |
| CIS Red Hat Enterprise Linux 7 STIG v2.0.0 L1 Server | 6.1.13 Audit SUID executables |
| CIS Ubuntu Linux 14.04 LTS Server v2.0.0 L1 | 6.1.14 Audit SGID executables |
| CIS Amazon Linux 2023 v1.0.0 L1 Server | 6.1.13 Ensure SUID and SGID files are reviewed |
The remediation text is essentially the same in each: make sure no rogue SUID or SGID programs have been introduced, and confirm the integrity of the binaries that are listed. Some versions add a concrete hint: compare system binaries against the checksum recorded by the package, because a mismatch suggests the file was replaced.
Real-world risk
A SUID root program runs as root no matter which user starts it. That design is what lets passwd update /etc/shadow for an ordinary user, and it is also why a bug in any SUID root binary becomes a local privilege escalation. CVE-2021-4034 (PwnKit) is the standard example: pkexec from polkit is a setuid tool, and a flaw in how it handled its arguments let any local user become root.
There are two separate risks behind this item:
- Unneeded attack surface. Every SUID binary that nobody on the host uses is code running as root for no benefit. Removing the bit or the package shrinks what a local attacker can target.
- Persistence and tampering. An attacker who gained root once can leave a SUID copy of a shell or interpreter behind as a backdoor. A SUID file that no package owns, or a package file whose checksum no longer matches, is a real compromise indicator.
Stated honestly: SUID bits on standard package files are normal, so this finding alone does not mean anything is wrong. The risk is also local only: an attacker needs code execution on the host first.
How to confirm it on the host
The classic one-liner find / -perm -4000 works, but it also walks network mounts and pseudo filesystems. With -xdev, find stays on one filesystem, so run it once per local mount point. The -perm -4000 test matches files with the SUID bit set; -perm -2000 matches SGID. Run as root so no directory is skipped:
# SUID and SGID files on every local filesystem, with mode, owner and group
df --local -P | awk 'NR>1 {print $6}' |
xargs -I '{}' find '{}' -xdev -type f ( -perm -4000 -o -perm -2000 )
-printf '%m %u %g %pn' 2>/dev/null | sort -u | tee /root/suid-sgid-$(date +%F).txt
A mode starting with 4 (for example 4755) is SUID, 2 is SGID, and 6 is both. Next, find out which files no package owns:
awk '{print $4}' /root/suid-sgid-$(date +%F).txt > /tmp/suid-paths.txt
# RHEL, Fedora, SUSE (RPM)
while read -r f; do rpm -qf "$f" >/dev/null 2>&1 || echo "UNOWNED: $f"; done < /tmp/suid-paths.txt
# Debian, Ubuntu
while read -r f; do dpkg -S "$f" >/dev/null 2>&1 || echo "UNOWNED: $f"; done < /tmp/suid-paths.txt
Then check integrity for the package-owned files:
# RPM: compares size, digest, permissions, owner and group; no output means no difference
rpm -Vf /usr/bin/passwd
# Debian, Ubuntu: compares file contents (md5) only, not permissions
dpkg --verify passwd
In rpm -V output, a 5 means the digest differs and an M means the mode differs. A changed digest on a SUID binary deserves immediate attention.
How to fix it
Decide what each file is
- Package-owned, used by ordinary users (for example
passwd,su,sudo): keep it and add it to your approved baseline. - Package-owned, but the feature is not used on this host: uninstall the package if nothing depends on it, or clear the bit.
- Package-owned, but only root ever runs it: clear the bit. Root does not need SUID to run a program as root.
- Not owned by any package, or failing verification: investigate before changing anything (see below).
Clear the bit (any distribution)
Record the current state first so you can restore it exactly:
stat -c '%a %U %G %n' /usr/bin/chfn | tee -a /root/suid-changes.log
sudo chmod u-s /usr/bin/chfn # remove SUID
sudo chmod g-s /path/to/file # remove SGID
Replace /usr/bin/chfn with the files your review marked as unneeded.
Debian and Ubuntu: make it survive package updates
A plain chmod is undone when the package is upgraded or reinstalled. dpkg-statoverride tells dpkg to use a different owner and mode whenever it installs that path, and its man page names removing the setuid flag as a use case. Keep the current owner and group, and give the mode in octal:
sudo dpkg-statoverride --update --add root root 0755 /usr/bin/chfn
dpkg-statoverride --list
--update applies the new mode immediately if the file exists.
RHEL, Fedora and SUSE: remove the package or re-apply
On RPM systems, a package update writes the file again with the mode recorded in the package, so a chmod u-s can quietly come back. Where the whole package is unneeded, removing it is the durable fix:
rpm -qf /path/to/file # which package
sudo dnf remove <package> # RHEL, Fedora
sudo zypper remove <package> # SUSE
Review the dependency list before confirming. If the package must stay, enforce the mode with your configuration management tool, or re-run the chmod after each patch cycle.
Unowned or modified SUID files: treat it as an incident
Do not just delete a SUID file you cannot explain. Record ls -l, stat and sha256sum output, and check whether it belongs to vendor software installed outside the package manager (agents under /opt are common). If there is no legitimate origin, follow your incident response process, since whoever planted it already had root.
Limit where SUID can work
The nosuid mount option makes the kernel ignore SUID and SGID bits on a filesystem. CIS benchmarks recommend it separately for locations such as /tmp, /dev/shm and /home. Add it to the options field in /etc/fstab, then apply it without a reboot:
sudo mount -o remount,nosuid /dev/shm
How to verify the fix and rescan
- Check each changed file:
stat -c '%A %n' /usr/bin/chfnshould show-rwxr-xr-xinstead of-rwsr-xr-x. - Re-run the listing command and compare it with your approved baseline:
diff /root/suid-sgid-approved.txt /root/suid-sgid-$(date +%F).txt. - On Debian and Ubuntu, confirm the override is stored with
dpkg-statoverride --list. - Rerun the credentialed compliance scan. Because this is a manual review item, expect it to stay a WARNING even on a clean host. Close it by attaching the reviewed list, not by waiting for PASSED. The search needs root to read every directory, so see our guide to SSH credentials for Linux authenticated scans if the output looks incomplete.
What can break and how to roll back
Removing SUID from the wrong file breaks things for non-root users immediately:
- sudo refuses to run at all and reports that it must be owned by uid 0 and have the setuid bit set. Never clear it on a host administered through sudo.
- passwd and su: users can no longer change their own password or switch user.
- mount, umount and fusermount: user mounts and FUSE filesystems stop working for non-root users.
- pkexec and unix_chkpwd: polkit actions and some password checks done by unprivileged programs, such as screen lockers, can fail.
- rpm -V will report
Mfor files whose mode you changed. That is expected, but note it for anyone auditing package integrity.
Keep a root session open while you work. To roll back, restore the mode from your log:
sudo chmod 4755 /usr/bin/chfn # value recorded by stat earlier
# Debian, Ubuntu: drop the override (it leaves the file unchanged), then restore
sudo dpkg-statoverride --remove /usr/bin/chfn
sudo chmod 4755 /usr/bin/chfn
# RPM: reset file metadata to the packaged values
sudo rpm --restore <package>
Common false positive reasons
- The finding is informational by design. A WARNING listing only standard package binaries is not a defect; it is the evidence the auditor asked for.
- Container and image storage. Image layers under directories such as
/var/lib/dockeror/var/lib/containerscontain the SUID binaries of each image’s own packages. - Chroots, build roots and backups. A restored system image or a build chroot carries its own copies of
passwdandsu. - Merged /usr on Debian. dpkg may record a file under
/binwhile the scan reports/usr/bin. Ifdpkg -Sfinds nothing, try the other path before calling a file unowned.
FAQ
Is having SUID binaries a vulnerability?
No. Linux depends on a small set of them. The risk comes from ones you do not need, ones with known bugs, and ones no package accounts for.
Which SUID binaries are safe to keep on Linux?
Package-owned files that ordinary users need, which pass rpm -V or dpkg --verify. The exact list depends on the distribution and installed packages, so build a baseline per server role.
Will the SUID bit come back after updates?
It can. On Debian and Ubuntu, use dpkg-statoverride. On RPM systems, remove the package or enforce the mode after each update.
How do I audit SGID executables?
Use the same process with -perm -2000 and chmod g-s. SGID grants the file’s group instead of its owner.
Tracking this finding across many hosts
The work that scales is keeping one approved SUID and SGID baseline per server role and chasing only the differences. SITEY, a self-hosted vulnerability management platform, imports findings from 16 scanners, including Nessus results uploaded as a .nessus export. Its AI can draft host-specific remediation scripts, such as a dpkg-statoverride change, that run only after human approval, are deployed by its agents on Linux endpoints, and are followed by a re-test to verify closure.