Skip to content

VNX-426: Untrusted Search Path

Reports Python code that finds modules, libraries or commands through the current working directory: sys.path and site.addsitedir entries that are empty, '.', relative or os.getcwd(); PATH-like variables given an empty or relative element; commands run by a cwd-relative path without cwd=; bare command names run after os.setuid(0); and ctypes loads of relative paths or bare DLL names.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-426
Severity High
SARIF level error
Kind sast
Languages Python
CWE CWE-426
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 untrusted-search-path cwe-426
Source internal/sast/rules/vnx-426.rego

Overview

VNX-426 maps to CWE-426: Untrusted Search Path. When a program looks for code in a place it does not control, whoever controls that place decides what runs. For most programs that place is the current working directory, which is wherever the program happened to be started.

Reported in Python:

  • sys.path.insert/append/extend (and sys.path[:0] =) with "", ".", "..", a relative literal, os.getcwd(), os.curdir, Path.cwd() or os.path.abspath of a relative literal.
  • os.environ[...] =, os.putenv or an env dict item setting PATH, PYTHONPATH, LD_LIBRARY_PATH, LD_PRELOAD, DYLD_LIBRARY_PATH or DYLD_INSERT_LIBRARIES to a value with an empty element (a leading, trailing or doubled separator), "." or a relative directory.
  • subprocess run/call/check_call/check_output/Popen, os.system, os.popen, os.exec* and os.spawn* running ./tool, ../bin/x or bin/x without a cwd= argument.
  • A command run by bare name in a file that makes the process root (os.setuid(0), os.seteuid(0), os.setresuid(0, ...)).
  • ctypes CDLL/WinDLL/OleDLL/PyDLL/LoadLibrary of a relative path or of a bare .dll name that is not a Windows KnownDLL.

What Gets Flagged

sys.path.insert(0, "")                                          # FLAGGED
os.environ["PATH"] = "." + os.pathsep + os.environ["PATH"]      # FLAGGED
subprocess.run(["./bin/deploy", target], check=True)            # FLAGGED
lib = ctypes.CDLL("./libfast.so")                               # FLAGGED

What Is Not Flagged

  • Paths anchored to the program (os.path.dirname(__file__)), sys.prefix or an absolute directory.
  • Commands run by bare name in an unprivileged program (normal PATH use), and calls that pass cwd=.
  • Bare sonames ("libc.so.6"), KnownDLLs ("kernel32") and ctypes.util.find_library.
  • Sphinx docs/conf.py, test files, comments and string literals.

C and C++ search-path elements (LoadLibrary, dlopen, setenv("PATH", ...)) are VNX-427.

Remediation

Anchor every lookup to a location the program controls:

HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
subprocess.run([os.path.join(HERE, "bin", "deploy"), target], check=True)
lib = ctypes.CDLL(os.path.join(HERE, "libfast.so"))

A privileged program should reset PATH to a fixed value and call commands by absolute path.

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

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

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