Skip to content

VNX-673: Control sphere (chroot jail, import or library search path) defined by remote input

Reports Python code where HTTP request or socket data reaches os.chroot(), sys.path, site.addsitedir() or PATH/PYTHONPATH/LD_LIBRARY_PATH/LD_PRELOAD, letting a remote party define what the process trusts.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-673
Severity Low
SARIF level note
Kind sast
Languages Python
CWE CWE-673
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 external-influence-sphere-definition cwe-673 python
Source internal/sast/rules/vnx-673.rego

Overview

VNX-673 maps to CWE-673: External Influence of Sphere Definition. A chroot jail, the module import path and the program and library search paths all define the boundary of what a process trusts. When a remote party chooses that boundary, it can point the jail at /, import its own module, or load its own shared library.

Reported, when the value comes from an HTTP request (Flask, Django, DRF, aiohttp request.args/form/values/json/data/get_json()/GET/POST/query_params/match_info/params/body/cookies/headers, Tornado self.get_argument) or a socket recv, on the sink line or through a variable assigned in the 10 lines above:

  • os.chroot(...)
  • sys.path.insert(...), sys.path.append(...), site.addsitedir(...)
  • os.environ["PATH" | "PYTHONPATH" | "PYTHONHOME" | "LD_LIBRARY_PATH" | "LD_PRELOAD" | "DYLD_*"] = ... and os.putenv of the same.

What Gets Flagged

root = request.args.get("dir")
os.chroot(root)                      # FLAGGED
plugin_dir = request.GET.get("plugin_dir")
sys.path.insert(0, plugin_dir)       # FLAGGED
os.environ["LD_LIBRARY_PATH"] = request.json.get("libdir")   # FLAGGED
env = os.environ.copy()
env["LD_LIBRARY_PATH"] = request.form["libdir"]   # FLAGGED: handed to subprocess.run(env=env)

What Is Not Flagged

  • Constants, settings and configuration values, paths built from __file__ or BASE_DIR.
  • Command-line arguments (sys.argv, argparse): the operator chooses those, not a remote actor.
  • A request value first mapped through an allow-list into a different variable.
  • Other environment variables, comments, string literals and triple-quoted strings.

Remediation

Never let a request name a path the process trusts. Map the request to a fixed set of server-side values:

JAILS = {"a": "/srv/jails/a", "b": "/srv/jails/b"}
os.chroot(JAILS[request.args["name"]])

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

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

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