YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
TensorFlow.js PoC β arbitrary local file read at model load (path traversal)
Vulnerability: Loading a TensorFlow.js model.json with @tensorflow/tfjs-node reads files
outside the model directory because weightsManifest[].paths are joined to the model directory
and read with no path-traversal guard. A malicious model.json with ../ in a weight path
performs arbitrary local file read at model-load time. ModelScan does not scan .json, so the
malicious model file is never inspected.
Benign PoC:
model/model.jsonreads../SECRET.txt(a marker that ships in this repo, one level above the model's own folder). This proves the loader escapes the model directory. To read a real sensitive file, set the manifest path to e.g.../../../../../../etc/passwdβ only against files you are authorized to read.
Affected
@tensorflow/tfjs-nodeβtf.loadLayersModel('file://.../model.json')/tf.loadGraphModel(...)/tf.io.fileSystem(...).load().- Sink:
tfjs-node/src/io/file_system.tsβNodeFileSystem.loadWeights:join(dirName, path)thenreadFile(...)with no normalization / no..rejection / no base-dir check.
Layout
tfjs-poc/
model/model.json # weightsManifest paths = ["../SECRET.txt"] (escapes model/)
SECRET.txt # marker "TFJS_LEAK_PROOF1" (16 bytes), sits OUTSIDE model/
reproduce.js # loads model/model.json, prints the bytes read
Reproduce
npm install --ignore-scripts @tensorflow/tfjs-node
node reproduce.js
Expected output:
bytes read from ../SECRET.txt (outside model/): "TFJS_LEAK_PROOF1"
CONFIRMED: arbitrary file read via path traversal at model load
(--ignore-scripts skips the native backend build, which is not needed β the file-read sink is in
the pure-JS dist/io/file_system.js. On Linux the prebuilt native binary installs cleanly without it.)
Verify scanner bypass
modelscan -p model/model.json -r json # -> {"total_scanned": 0, "issues": []}
Impact
- Arbitrary local file read (any file the Node process can access) at model load, default-on.
- The traversed file's bytes are returned as weight data; an app that runs the model / surfaces
outputs can exfiltrate that content. Companion SSRF/same-origin traversal exists in the browser
loader (
tfjs-core/src/io/weights_loader.ts,fetchUrl = filePathPrefix + filepath, unvalidated).
Remediation
Resolve each manifest path and reject any that escapes the model directory:
const base = path.resolve(dirName);
const full = path.resolve(base, p);
if (full !== base && !full.startsWith(base + path.sep)) throw new Error('weight path outside model dir');
Dup note
No prior huntr/NVD/GHSA report for tfjs model-load traversal. GitHub issue #8628 is a different
bug β path traversal in the tfjs converter (write_weights.py, file write during
conversion), not this load-time read in tfjs-node.