Skip to content

VNX-274: Improper Handling of Insufficient Privileges

Detects privilege changes whose failure is noticed and then ignored: an if on a failed setuid/setgid/setresuid/setgroups/chroot or impersonation call that only logs (C, C++), an except OSError/PermissionError that passes or logs around os.setuid/os.chroot (Python), an err != nil after syscall/unix Setuid that only logs (Go), and an if on a failed posix_setuid/posix_setgid that only logs (PHP).

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-274
Severity Low
SARIF level note
Kind sast
Languages C, C++, Python, Go, PHP
CWE CWE-274
CAPEC CAPEC-66
ATT&CK T1190
CWSS vector CWSS:1.0/TI:L/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:L/DI:H/EX:L/EC:N/P:L
Tags insufficient-privileges privilege-drop error-handling cwe-274
Source internal/sast/rules/vnx-274.rego

Overview

VNX-274 maps to CWE-274: Improper Handling of Insufficient Privileges. When the process lacks the privilege to change identity or enter a jail, the call fails. Detecting the failure is not enough: if the failure branch only prints a warning and falls through, the program carries on as root, or outside the jail, exactly as if the check were missing. VNX-273 covers the call that is not checked at all; this rule covers the check that does not stop.

Reported:

  • C and C++: an if on the failure of setuid, setgid, seteuid, setegid, setreuid, setregid, setresuid, setresgid, setgroups, initgroups or chroot (!= 0, < 0, == -1, or the bare call), directly or through a result variable assigned just above, and on the failure of ImpersonateNamedPipeClient, ImpersonateLoggedOnUser, ImpersonateSelf, ImpersonateAnonymousToken or SetThreadToken, whose branch has no return, exit, abort, std::terminate(), fatal raise(SIGKILL), goto, err()/errx(), glibc error() with a nonzero status, break, continue or fatal()/die()-style call. Words inside the log message (“return code”, “will exit”) do not count as stopping.
  • Python: os.setuid, os.setgid, os.seteuid, os.setegid, os.setreuid, os.setresuid, os.setresgid, os.setgroups, os.initgroups or os.chroot (also called bare after from os import setuid) in a try whose except OSError/PermissionError/Exception/bare except neither raises, returns nor exits, or inside contextlib.suppress(OSError).
  • Go: if err != nil after syscall/unix Setuid, Setgid, Setresuid, Setgroups, Chroot and similar, whose body neither returns, panics, calls os.Exit, syscall.Exit nor log.Fatal.
  • PHP: an if on the failure of posix_setuid, posix_setgid, posix_seteuid, posix_setegid or posix_initgroups (!posix_setuid(...), !@posix_setuid(...), === false, or Yoda false === posix_setuid(...)) whose body neither throws, returns, exits nor dies.

What Gets Flagged

// FLAGGED: the failure is printed, then serve_clients() runs as root
if (setuid(pw->pw_uid) != 0) {
    perror("setuid");
}
serve_clients();
# FLAGGED: a failed drop is swallowed
try:
    os.setuid(uid)
except PermissionError as exc:
    logger.warning("could not drop to uid %s: %s", uid, exc)
serve()
// FLAGGED
if err := syscall.Setuid(uid); err != nil {
    log.Printf("setuid: %v", err)
}
serve()
// FLAGGED: the worker keeps running as root
if (!posix_setgid($gid) || !posix_initgroups($user, $gid) || !posix_setuid($uid)) {
    $this->log("Warning: change gid or uid failed.");
}

What Is Not Flagged

  • A failure branch that stops: return -1, exit(1), err(1, "setgid"), error(EXIT_FAILURE, errno, ...), abort(), goto fail, raise, sys.exit(...), return False, log.Fatalf(...), panic(err), throw new RuntimeException(...), die(...).
  • A check on success (if (setuid(uid) == 0) { run_unprivileged(); }).
  • An unchecked call, which is VNX-273, and a raise back to root (if (seteuid(0) != 0) perror(...)): failing to gain root leaves the program less privileged.
  • An except for an unrelated exception (except KeyError:).

Remediation

Treat a failed privilege change as fatal:

if (setuid(pw->pw_uid) != 0) {
    perror("setuid");
    exit(EXIT_FAILURE);
}
try:
    os.setuid(uid)
except OSError:
    log.exception("cannot drop privileges")
    raise

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

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

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