Skip to content

VNX-913: Request data chooses the file of code the process loads or runs (improper control of dynamically-managed code resources)

Detects HTTP request data naming a script, plugin or native library file that the process loads or executes, in Java, Python, Node.js and Go.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-913
Severity High
SARIF level error
Kind sast
Languages Go, Java, JavaScript / TypeScript, Python
CWE CWE-913
CAPEC CAPEC-66
ATT&CK T1190
CWSS vector CWSS:1.0/TI:H/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:H/DI:H/EX:H/EC:N/P:H
Tags dynamic-code code-loading path-control cwe-913
Source internal/sast/rules/vnx-913.rego

Overview

CWE-913 is improper control of dynamically-managed code resources. This rule reports one slice of it: HTTP request data that chooses the file of code the process loads or runs. A requester who controls the path can point the server at an uploaded script, a world-writable directory or a traversal like ../../tmp/x, and the file runs with the server’s privileges.

The rule follows the request value inline, through string building, or through a variable assigned or destructured from it (and one further assignment) in the 25 lines above the call.

Reported Sinks

Language Sinks
Java ScriptEngine.eval(new FileReader(path)) (also InputStreamReader, FileInputStream, Files.newBufferedReader), GroovyShell evaluate/parse/run with a File, GroovyClassLoader.parseClass, URLClassLoader.newInstance, JNA Native.load/loadLibrary and NativeLibrary.getInstance
Python runpy.run_path/run_module, SourceFileLoader/SourcelessFileLoader/ExtensionFileLoader, imp.load_compiled, execfile, zipimporter, cffi ffi.dlopen
Node.js new Worker(path) from worker_threads, Module._load, new vm.SourceTextModule, vm2 runFile, koffi.load, ffi.Library
Go syscall/windows LoadDLL, NewLazyDLL, LoadLibrary, purego.Dlopen, gopher-lua DoFile, yaegi EvalPath
script = request.args.get("script")
result = runpy.run_path(script)            # reported
String template = request.getParameter("template");
engine.eval(new FileReader("/srv/reports/" + template));   // reported

Not Reported Here

Constant paths, values from configuration or the environment, a path reduced with basename/secure_filename/filepath.Base/getFileName, a value checked against an allowlist or a numeric conversion, a path confined by a prefix check (startsWith, startswith, HasPrefix, commonpath, is_relative_to), and anything in comments or string literals.

Neighbouring CWE-913 shapes belong to other rules, so a line is reported by only one of them:

  • Code strings and file contents passed to eval, exec, Function or vm, including exec(open(path).read()): VNX-94.
  • System.load, Runtime.load, URLClassLoader constructors, plugin.Open, ctypes.CDLL, import_module, require()/import(), process.dlopen, Ruby require/load: VNX-114 and VNX-1027.
  • Reflection that picks a class, module or method: VNX-470.
  • PHP include/require: VNX-98. Mass assignment: VNX-915.

Remediation

Never build a loadable path from request data. Map the request value to a fixed set of files:

SCRIPTS = {"nightly": "/srv/jobs/nightly.py", "weekly": "/srv/jobs/weekly.py"}
path = SCRIPTS.get(request.args.get("job"))
if path is None:
    abort(400)
runpy.run_path(path)

If a file name must come from the client, reduce it to its last element, join it to a fixed directory, resolve the result and check that it is still inside that directory before loading it.

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

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

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