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.
| 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_*"] = ...andos.putenvof 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__orBASE_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.