
Cloud Vulnerability DB
A community-led vulnerabilities database
CVE-2026-104848 is a prototype pollution gadget vulnerability in Tinypool, a minimal Node.js worker thread pool library, that leads to Remote Code Execution (RCE). It affects all versions of tinypool up to and including 2.1.0, and was first published by security researcher ambushneupane on August 30, 2026, with the GitHub Advisory Database entry updated on October 5, 2026. The vulnerability carries a CVSS v4.0 base score of 9.5 (Critical) (Github Advisory, Tinypool Advisory).
The root cause is classified as CWE-1321 (Improperly Controlled Modification of Object Prototype Attributes — Prototype Pollution). In dist/index.js, ThreadPool constructs its options object using a plain object spread ({ ...kDefaultOptions, ...options, filename, maxQueue: 0 } at line 470), which causes properties inherited from a polluted Object.prototype to be copied into own properties. These materialized properties — specifically execArgv and env — are then passed directly to worker_threads.Worker at lines 508–511, bypassing Node.js's built-in protection that ignores prototype-inherited Worker options. Two exploitation vectors exist: polluting Object.prototype.execArgv with ['--require', '/path/to/attacker.js'] causes every spawned worker to preload the attacker's script, and polluting Object.prototype.env with { NODE_OPTIONS: '--require /path/to/attacker.js' } achieves the same via environment injection. A concrete, runnable proof-of-concept with three files (worker.mjs, payload.js, app.js) is publicly available in the security advisory (Tinypool Advisory, Fix Commit).
Successful exploitation results in arbitrary JavaScript code execution inside every worker thread spawned by the pool, running with the full privileges of the host process — achieving total confidentiality, integrity, and availability impact on both the vulnerable and subsequent systems. Because Tinypool is the worker pool backend for Vitest (approximately 42 million downloads per week), the primary blast radius encompasses developer machines and CI/CD runners. An attacker who can introduce a prototype pollution primitive anywhere in the transitive dependency tree (e.g., via lodash, qs, minimist, set-value, or deepmerge) gains a supply-chain foothold enabling theft of CI secrets, signing keys, and build artifacts, as well as the ability to tamper with or inject malware into published packages (Github Advisory, Tinypool Advisory).
A public, high-confidence proof-of-concept exploit is available in the official security advisory, consisting of three complete, runnable files with step-by-step reproduction instructions confirmed on Node.js 20 (Tinypool Advisory). The NVD SSVC assessment classifies exploitation status as "poc" with "total" technical impact. The EPSS score is approximately 0.497% (41st percentile), indicating a moderate near-term exploitation probability. No in-the-wild exploitation or specific threat actor attribution has been reported at this time, and the vulnerability is not currently listed in the CISA KEV catalog (Github Advisory).
Identify a prototype pollution primitive: Locate a dependency in the target application's dependency tree (e.g., lodash, qs, minimist, set-value, or deepmerge) that allows polluting Object.prototype. This can be introduced via a malicious transitive dependency or by exploiting an existing known prototype pollution vulnerability in a direct dependency.
Stage the malicious payload: Place an attacker-controlled JavaScript file (e.g., payload.js) at a path accessible to the Node.js process. This file contains the malicious code to execute, such as exfiltrating secrets or writing a file:
const fs = require('fs')
fs.writeFileSync('/tmp/RCE_PROOF.txt', 'code execution achieved, pid=' + process.pid)Object.prototype.execArgv: Before Tinypool is instantiated, set the polluted property:Object.prototype.execArgv = ['--require', '/path/to/payload.js']Alternatively, use the env vector: Object.prototype.env = { NODE_OPTIONS: '--require /path/to/payload.js' }
Trigger Tinypool instantiation: The target application creates a new Tinypool instance (e.g., new Tinypool({ filename: ..., minThreads: 1, maxThreads: 1 })). Tinypool's ThreadPool constructor spreads options using { ...kDefaultOptions, ...options, filename, maxQueue: 0 }, which copies the polluted execArgv from the prototype chain into own properties.
Worker spawning triggers RCE: When Tinypool spawns a worker thread, it passes this.options.execArgv to new Worker() at lines 508–511 of dist/index.js. Node.js respects the --require flag and loads payload.js, executing arbitrary code in the worker thread with the host process's privileges.
Achieve objectives: The attacker's code runs in every spawned worker, enabling file I/O, credential theft (e.g., reading ~/.npmrc, CI environment variables), artifact tampering, or establishing persistence in the CI pipeline (Tinypool Advisory).
/tmp/ (e.g., RCE_PROOF.txt or similar artifacts) by Node.js worker processes; new or modified scripts in the project directory not matching source control; unexpected .js or .mjs files in temporary directories.strace, auditd, or EDR solutions); Node.js processes with unexpected --require or --import flags in their command-line arguments.*** RCE ***) from test or build steps; Node.js worker thread errors or unexpected module load events in application logs.NODE_OPTIONS environment variable within the process environment; evidence of Object.prototype pollution detectable via runtime instrumentation or security linting tools (Tinypool Advisory).Upgrade tinypool to version 2.1.1 or later, which resolves the vulnerability by replacing the object spread with Object.assign(Object.create(null), kDefaultOptions, options, { filename, maxQueue: 0 }), ensuring worker options are constructed with null-prototype semantics that cannot inherit from a polluted Object.prototype (Tinypool Release, Fix Commit). As a defense-in-depth measure, audit and remediate prototype pollution vulnerabilities in all transitive dependencies (e.g., replace vulnerable versions of lodash, qs, minimist, set-value, or deepmerge), and consider using --frozen-intrinsics or similar Node.js hardening flags in CI environments. Applications that cannot immediately upgrade should avoid using libraries with known prototype pollution vulnerabilities alongside Tinypool (Github Advisory).
The vulnerability was discovered by security researcher ambushneupane, who noted a similar vector had been previously identified in the related library Piscina (GHSA-x9g3-xrwr-cwfg / CVE-2026-55388), highlighting a class-level issue with how Node.js worker pool libraries handle options objects (Tinypool Advisory). The fix was merged promptly by maintainer AriPerkkio on August 23, 2026, and the advisory was published August 30, 2026. The vulnerability attracted downstream attention, with projects such as Expensify's App and sai-foundation/s-code issuing dependency override PRs to adopt the patched version (Fix PR).
Fix availability across major Linux distributions and their releases.
Source: This report was generated using AI
Free Vulnerability Assessment
Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.
Get a personalized demo
"Best User Experience I have ever seen, provides full visibility to cloud workloads."
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
"We know that if Wiz identifies something as critical, it actually is."