VNX-266: Incorrect Privilege Assignment
Root is assigned as a process's whole identity (setuid(0), setresuid(0, 0, 0), os.setuid(0)) in a function that never drops it, or a file is given the set-user-ID or set-group-ID bit.
| Field | Value |
|---|---|
| Rule ID | VNX-266 |
| Severity | High |
| SARIF level | error |
| Kind | sast |
| Languages | C, C++, Python |
| CWE | CWE-266 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:H/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:H/DI:H/EX:H/EC:N/P:H |
| Tags | privilege setuid cwe-266 |
| Source | internal/sast/rules/vnx-266.rego |
Overview
VNX-266 maps to CWE-266: Incorrect Privilege Assignment. It reports two ways code hands out root: making root the process’s permanent identity, and marking a file set-user-ID or set-group-ID so that anyone who runs it gets its owner’s privileges.
Why This Matters
setuid(0) in a process whose effective user is root sets the real, effective and saved user IDs to root at once. From then on there is no unprivileged identity left to return to, and every file the process opens, every command it runs and every child it starts runs as root. A set-user-ID bit does the same for a file: every user who can execute it runs it as the owner, so any flaw in it (an environment variable it trusts, a path it builds) becomes a local privilege escalation.
What Gets Flagged
if (setuid(0) != 0) { perror("setuid"); return 1; }
::setresuid(0, 0, 0);
chmod(dst, 04755);
fchmod(fd, S_ISUID | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
os.setuid(0)
os.chmod(path, 0o4755)
os.chmod(path, st.st_mode | stat.S_ISUID)
Not flagged: a temporary seteuid(0) (whether it is lowered again is VNX-272); a function that also drops to a non-root user, including the if (setuid(0) != -1) check that confirms a drop cannot be undone; testing or clearing the bits (st.st_mode & S_ISUID, mode & ~S_ISUID); ordinary modes such as 0755; wrappers like my_setuid(0); and the calls in comments or string literals.
Remediation
- Do the privileged step with a temporary
seteuid(0), then drop permanently withsetgroups,setgidandsetuidto an unprivileged user. - Instead of a set-user-ID binary, grant the one capability the program needs (
setcap cap_net_bind_service+ep) or move the privileged operation into a small helper behind a fixed, validated interface (polkit, a systemd service, a socket-activated daemon).
References
- CWE-266: Incorrect Privilege Assignment
- SEI CERT POS36-C: Observe correct revocation order while relinquishing privileges
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-266
// nosec vnx-266
Or record an ignore rule: vulnetix ignore add --rule vnx-266 --reason "...". See Suppressing findings.