Skip to content

VNX-269: Improper Privilege Management

Privileges are dropped in the wrong order: the user ID is changed to a non-root user before the group ID or the supplementary groups, so the later call fails and the process keeps root's groups.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-269
Severity High
SARIF level error
Kind sast
Languages C, C++, Python
CWE CWE-269
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-mgmt privilege-drop cwe-269
Source internal/sast/rules/vnx-269.rego

Overview

VNX-269 maps to CWE-269: Improper Privilege Management. It reports a group change (setgid, setegid, setregid, setresgid, setgroups, initgroups) that comes after the user ID was already dropped to a non-root user in the same function.

Why This Matters

Changing the group ID and the supplementary group list requires root. A daemon that calls setuid(pw->pw_uid) first has already given root up, so its following setgid() or setgroups() fails with EPERM. If the result is not checked, or is checked by a branch that carries on, the process runs as the intended user but still in group 0 and in every supplementary group root had, which often means read access to /etc/shadow-adjacent files, log directories and sockets meant only for administrators.

What Gets Flagged

if (setuid(pw->pw_uid) != 0) exit(1);
if (setgid(pw->pw_gid) != 0) exit(1);      /* flagged: too late */

setresuid(uid, uid, uid);
setgroups(0, NULL);                         /* flagged */
if (::seteuid(uid) == -1) throw std::runtime_error("seteuid");
if (::setegid(gid) == -1) throw std::runtime_error("setegid");   // flagged
os.setuid(pw.pw_uid)
os.setgid(pw.pw_gid)    # flagged
os.setgroups([])        # flagged

Not flagged: the correct order (setgroups/initgroups, then setgid, then setuid); a regain of root (seteuid(0)) between the two calls; setgid(0) after the drop, which is the check that root cannot be regained; calls in different functions; and the names in comments or string literals.

Remediation

  1. Drop in this order: clear or set the supplementary groups (setgroups(0, NULL) or initgroups), then setgid(gid), then setuid(uid).
  2. Check every return value and stop on failure.
  3. After the drop, verify it: setuid(0) and setgid(0) must now fail.

References

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-269
// nosec vnx-269

Or record an ignore rule: vulnetix ignore add --rule vnx-269 --reason "...". See Suppressing findings.

Edit this pageSources: cli/internal/sast/rules/vnx-269.rego, cli/internal/sast/docs/vnx-269.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.