TensorFlow.js weights-manifest shape DoS PoC
This repository contains a proof-of-concept malicious .tfjs-style weights manifest for a
responsibly-disclosed vulnerability in tensorflow/tfjs
(tested at commit 7f5309fef0a47545e34049903dbdae0f97285f7e), reported via huntr's Model File
Vulnerability program.
What these files are
malicious_manifest.jsonβ a weights manifest declaring a single weight,malicious_weight, ofdtype: "string"andshape: [500000000](500 million).weights.binβ the "backing" weight-data file the manifest points to. It is completely empty (0 bytes) β there is no real weight data behind the declared shape at all.reproduce.jsβ loads the manifest using@tensorflow/tfjs's public, officially-documentedtf.io.weightsLoaderFactoryAPI (the same pattern shown in that function's own JSDoc example for loading weights from disk in Node.js without the nativetfjs-nodeaddon) β no internal or private functions are used.
What happens when you run it
npm install @tensorflow/tfjs
node reproduce.js
The process becomes unresponsive (including a 2-second heartbeat timer in the script itself, which
does not fire while the vulnerable loop is running β the entire Node.js event loop is blocked, not
just the one loading operation) and, after roughly 3.5 minutes, crashes outright with a fatal
V8 out-of-memory error (FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory, heap grown past 4 GB) β not merely a temporary freeze. 500000000
was chosen so the demonstration completes in a few minutes; a real attacker could use an even
larger value (e.g. 999999999999, still just a single JSON integer) for a longer/guaranteed crash
against a victim with more available memory. See the reporter's full write-up submitted via huntr
for the complete timing data and crash log.
This happens because getWeightBytelength() (tfjs-core/src/io/io_utils.ts) computes the
declared string-tensor size (sizeFromShape(shape), unbounded, no validation) and loops that many
times over the weight's binary data β with no check that any real data is actually behind the
declared shape, and no early exit when the (in this case entirely empty) backing buffer is
exhausted.
Scope note
This PoC is provided solely for the purpose of responsible vulnerability disclosure and
reproduction by the tfjs maintainers / huntr triage team. It is not intended for any other use.
Running it will make your own Node.js process unresponsive for the duration of the demo β this is
expected and is exactly the behavior being reported; do not run it against a shared or
production process.