hacnho's picture
Upload folder using huggingface_hub
32810b6 verified
|
Raw
History Blame Contribute Delete
1.96 kB

TensorFlow.js string weight metadata DoS PoC

This repository contains a minimal TensorFlow.js model-file-format PoC for a CPU denial-of-service in @tensorflow/tfjs 4.22.0.

The malicious model is a valid one-layer Dense LayersModel plus one extra unused weight manifest entry:

{
  "name": "unused_extra_string",
  "shape": [50000000],
  "dtype": "string"
}

The weights file is only 8 bytes. Loading the model with tf.loadLayersModel() decodes every weight spec before strict model-weight matching rejects extras. For dtype: "string", tf.io.decodeWeights() loops over sizeFromShape(spec.shape) while trying to read per-string length headers. With a large shape and truncated/empty string data, the Node.js event loop is tied up until an external watchdog kills the process.

Reproduce

npm ci
npm run repro

Expected result:

  • control_valid_model: loads and predicts 7 in about 10 ms.
  • numeric_extra_float32_control: rejects the extra large numeric weight in about 15 ms.
  • malicious_extra_string_dos: does not return before the 3 second watchdog and is killed with ETIMEDOUT / SIGKILL.

For a shorter local demo:

npm run repro:small

Files

  • repro_tfjs_string_weight_dos.js - standalone reproducer and watchdog.
  • models/ - control, numeric-control, and malicious TF.js model.json / weights.bin files.
  • evidence/tfjs-string-weight-dos-repro-2026-06-23-132907011.json - recorded reproduce run.
  • evidence/tfjs-string-weight-timing-2026-06-23-132953595.json - timing curve showing string weights scale linearly while numeric weights reject immediately.
  • source/ - local source excerpts from the installed 4.22.0 package.
  • duplicate-check.md - local, dashboard, and public Huntr duplicate gate notes.
  • report.md - Huntr report body.
  • SHA256SUMS - hashes for all package files.

Environment

  • Node.js v20.20.2
  • npm 10.8.2
  • @tensorflow/tfjs 4.22.0