← Blog · · df00tech

Piscina Prototype-Pollution Gadget Resurfaces via ThreadPool.options, Enabling RCE (CVE-2026-102992)

breaking ghsa npm CVE-2026-102992

What happened

A new GitHub Security Advisory (GHSA-67c8-pqhq-4rmx, tracked as CVE-2026-102992) discloses that the Node.js worker-thread pool library piscina builds its internal ThreadPool.options as a plain object inheriting from Object.prototype. Any option not given an explicit default in kDefaultOptions — including execArgv, loadBalancer, env, argv, workerData, and several others — is read through the prototype chain. If an attacker can pollute Object.prototype (for example via a separate prototype-pollution bug elsewhere in the application's dependency tree), they can inject values for these options into every Piscina pool in the process.

Per the advisory, this is a regression of an earlier fix: GHSA-x9g3-xrwr-cwfg / CVE-2026-55388 hardened specific filename/name reads in the Piscina constructor and run(), but did not give ThreadPool.options itself a null prototype, leaving the broader class of gadget intact. A public proof-of-concept repository is referenced in the advisory, and the exploit status is listed as PoC-public.

Why it matters for defenders

The most severe gadget is execArgv: polluting Object.prototype.execArgv with a value like ['--require', '/tmp/attacker.js'] causes every subsequently spawned worker thread to preload and execute attacker-controlled code on startup — remote code execution with no direct exploitation of Piscina itself required beyond the prototype-pollution primitive. loadBalancer can similarly be hijacked to execute an attacker-supplied function in the main thread during task scheduling, and env allows injecting arbitrary environment variables into workers. Any application that uses piscina for worker-pool task execution and has any other dependency capable of polluting Object.prototype (a startlingly common bug class in JS merge/clone/JSON-merge utilities) is potentially exposed, even though Piscina is not itself the source of the pollution primitive.

What defenders should watch for

  • Inventory whether piscina is in use (directly or transitively) and check the installed version against the fixed release once published by the maintainers.
  • Audit other dependencies for known or latent prototype-pollution issues — this advisory is a reminder that a pollution bug anywhere in the dependency graph can be weaponized against unrelated libraries that trust Object.prototype-derived option objects.
  • At a high level, hunt for unexpected --require/-r flags or unfamiliar modules being loaded by Node worker threads, and for worker processes spawning with environment variables or CLI arguments that don't match application configuration.
  • As a mitigation pattern, favor libraries and internal code that build options objects with a null prototype (Object.create(null)) or that explicitly validate/allowlist option keys rather than spreading untrusted objects into defaults.
  • Consider runtime hardening such as freezing Object.prototype (Object.freeze(Object.prototype)) where application behavior permits it, as a defense-in-depth measure against this entire bug class.

Developing intel

This is a same-day advisory and the information here reflects only what has been disclosed so far; a fixed version and further remediation guidance may follow. No detection rule accompanies this note. For full technical details and updates, see the original advisory: GHSA-67c8-pqhq-4rmx.

Get new detections in your inbox

New ATT&CK coverage plus CISA KEV / CVE detection rules, roughly weekly. No spam, unsubscribe anytime.