CVE-2026-102992
piscina: Prototype-pollution gadget in ThreadPool.options allows RCE via execArgv / loadBalancer / env
piscina is a node.js worker pool implementation. Prior to 4.9.4, 5.3.2, and 6.0.0-rc.5, Piscina stores ThreadPool.options in src/index.ts as a plain object that inherits from Object.prototype. Applications with a separate prototype-pollution primitive can therefore supply inherited values for security-sensitive options that do not have own defaults. An inherited execArgv value is passed to the Node.js Worker constructor and can preload attacker-controlled code in worker threads, an inherited loadBalancer function can execute during task scheduling, and inherited env values can alter worker environments. This issue is fixed in versions 4.9.4, 5.3.2, and 6.0.0-rc.5.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- High
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
9.2
piscina: Prototype-pollution gadget in ThreadPool.options allows RCE via execArgv / loadBalancer / env
piscina is a node.js worker pool implementation. Prior to 4.9.4, 5.3.2, and 6.0.0-rc.5, Piscina stores ThreadPool.options in src/index.ts as a plain object that inherits from Object.prototype. Applications with a separate prototype-pollution primitive can therefore supply inherited values for security-sensitive options that do not have own defaults. An inherited execArgv value is passed to the Node.js Worker constructor and can preload attacker-controlled code in worker threads, an inherited loadBalancer function can execute during task scheduling, and inherited env values can alter worker environments. This issue is fixed in versions 4.9.4, 5.3.2, and 6.0.0-rc.5.
- Record
CVE-2026-102992- CVSS 4.0
- 9.2 Critical
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-1321
- Updated
- 2026-11-02
EUVDEUVD-2026-90364
9.2
piscina is a node.js worker pool implementation. Prior to 4.9.4, 5.3.2, and 6.0.0-rc.5, Piscina stores ThreadPool.options in src/index.ts as a plain object that inherits from Object.prototype. Applications with a separate prototype-pollution primitive can therefore supply inherited values for security-sensitive options that do not have own defaults. An inherited execArgv value is passed to the Node.js Worker constructor and can preload attacker-controlled code in worker threads, an inherited loadBalancer function can execute during task scheduling, and inherited env values can alter worker environments. This issue is fixed in versions 4.9.4, 5.3.2, and 6.0.0-rc.5.
- Record
EUVD-2026-90364- CVSS 4.0
- 9.2 Critical
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-67c8-pqhq-4rmx
9.2
piscina: Prototype-pollution gadget in ThreadPool.options allows RCE via execArgv / loadBalancer / env
Summary
A prototype-pollution gadget in ThreadPool.options allows an attacker who can pollute Object.prototype to execute arbitrary code in Piscina worker threads, invoke arbitrary functions during task scheduling, or inject environment variables into workers. The root cause is that ThreadPool.options is created as a plain object inheriting from Object.prototype, so any option without an explicit default in kDefaultOptions can be supplied via the prototype chain.
Details
In src/index.ts the ThreadPool constructor builds the resolved options object as a plain object:
this.options = { ...kDefaultOptions, ...options, filename, maxQueue: 0 }
Because this object has Object.prototype as its prototype, reads for properties that are not own properties of the object and are not present in kDefaultOptions fall back to Object.prototype. This means a prototype-pollution primitive (e.g. from a vulnerable merge() or JSON.parse merge elsewhere in the application) can inject values for execArgv, env, loadBalancer, argv, workerData, resourceLimits, niceIncrement, closeTimeout, recordTiming, stricterFIFO, workerHistogram, and trackUnmanagedFds.
The most serious gadget is execArgv, which is passed directly to new Worker(..., { execArgv }). An attacker can set Object.prototype.execArgv = ['--require', '/tmp/attacker.js'], causing every worker to preload and execute the attacker-controlled module on startup.
This issue survived the fix for GHSA-x9g3-xrwr-cwfg / CVE-2026-55388 ("Prototype Pollution Gadget → RCE via inherited options.filename"). That advisory hardened the Piscina constructor's filename read and run()'s filename/name reads, but ThreadPool.options itself was not created with a null prototype. The same class of attack is therefore still possible against any option without an explicit default in kDefaultOptions.
PoC
import { resolve } from 'node:path'
import Piscina from 'piscina'
Object.prototype.execArgv = ['--require', '/tmp/attacker.js']
const pool = new Piscina({
filename: resolve(import.meta.dirname, 'worker.js'),
minThreads: 1,
maxThreads: 1,
})
await pool.run(1)
/tmp/attacker.js is executed in the worker on startup. A full reproduction repository with execArgv, loadBalancer, and env vectors is available at https://github.com/Fcmam5/piscina-pp-poc.
Impact
- Remote Code Execution: via
execArgv(arbitrary--requiremodule preloaded in every worker on spawn). - Arbitrary code execution in the main thread: via
loadBalancer, an attacker-supplied function that is called during task scheduling. - Environment/CLI option injection: via
env, which is passed to each worker constructor. - Denial of Service / unexpected behavior: via other reachable options such as
workerData,resourceLimits,niceIncrement,closeTimeout,recordTiming, etc.
Anyone using Piscina in an application where Object.prototype can be polluted (e.g. through a dependency with a prototype-pollution vulnerability) is impacted.
- Record
GHSA-67c8-pqhq-4rmx- CVSS 4.0
- 9.2 Critical
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-1321
- Updated
- 2026-11-02
NVD
9.2
piscina is a node.js worker pool implementation. Prior to 4.9.4, 5.3.2, and 6.0.0-rc.5, Piscina stores ThreadPool.options in src/index.ts as a plain object that inherits from Object.prototype. Applications with a separate prototype-pollution primitive can therefore supply inherited values for security-sensitive options that do not have own defaults. An inherited execArgv value is passed to the Node.js Worker constructor and can preload attacker-controlled code in worker threads, an inherited loadBalancer function can execute during task scheduling, and inherited env values can alter worker environments. This issue is fixed in versions 4.9.4, 5.3.2, and 6.0.0-rc.5.
- Record
CVE-2026-102992- CVSS 4.0
- 9.2 Critical
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Weakness
- CWE-1321
- Updated
- 2026-11-02
OSV
9.2
piscina: Prototype-pollution gadget in ThreadPool.options allows RCE via execArgv / loadBalancer / env
piscina is a node.js worker pool implementation. Prior to 4.9.4, 5.3.2, and 6.0.0-rc.5, Piscina stores ThreadPool.options in src/index.ts as a plain object that inherits from Object.prototype. Applications with a separate prototype-pollution primitive can therefore supply inherited values for security-sensitive options that do not have own defaults. An inherited execArgv value is passed to the Node.js Worker constructor and can preload attacker-controlled code in worker threads, an inherited loadBalancer function can execute during task scheduling, and inherited env values can alter worker environments. This issue is fixed in versions 4.9.4, 5.3.2, and 6.0.0-rc.5.
- Record
CVE-2026-102992- CVSS 4.0
- 9.2 Critical
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-1321
- Updated
- 2026-11-04
OSVGHSA-67c8-pqhq-4rmx
9.2
piscina: Prototype-pollution gadget in ThreadPool.options allows RCE via execArgv / loadBalancer / env
Summary
A prototype-pollution gadget in ThreadPool.options allows an attacker who can pollute Object.prototype to execute arbitrary code in Piscina worker threads, invoke arbitrary functions during task scheduling, or inject environment variables into workers. The root cause is that ThreadPool.options is created as a plain object inheriting from Object.prototype, so any option without an explicit default in kDefaultOptions can be supplied via the prototype chain.
Details
In src/index.ts the ThreadPool constructor builds the resolved options object as a plain object:
this.options = { ...kDefaultOptions, ...options, filename, maxQueue: 0 }
Because this object has Object.prototype as its prototype, reads for properties that are not own properties of the object and are not present in kDefaultOptions fall back to Object.prototype. This means a prototype-pollution primitive (e.g. from a vulnerable merge() or JSON.parse merge elsewhere in the application) can inject values for execArgv, env, loadBalancer, argv, workerData, resourceLimits, niceIncrement, closeTimeout, recordTiming, stricterFIFO, workerHistogram, and trackUnmanagedFds.
The most serious gadget is execArgv, which is passed directly to new Worker(..., { execArgv }). An attacker can set Object.prototype.execArgv = ['--require', '/tmp/attacker.js'], causing every worker to preload and execute the attacker-controlled module on startup.
This issue survived the fix for GHSA-x9g3-xrwr-cwfg / CVE-2026-55388 ("Prototype Pollution Gadget → RCE via inherited options.filename"). That advisory hardened the Piscina constructor's filename read and run()'s filename/name reads, but ThreadPool.options itself was not created with a null prototype. The same class of attack is therefore still possible against any option without an explicit default in kDefaultOptions.
PoC
import { resolve } from 'node:path'
import Piscina from 'piscina'
Object.prototype.execArgv = ['--require', '/tmp/attacker.js']
const pool = new Piscina({
filename: resolve(import.meta.dirname, 'worker.js'),
minThreads: 1,
maxThreads: 1,
})
await pool.run(1)
/tmp/attacker.js is executed in the worker on startup. A full reproduction repository with execArgv, loadBalancer, and env vectors is available at https://github.com/Fcmam5/piscina-pp-poc.
Impact
- Remote Code Execution: via
execArgv(arbitrary--requiremodule preloaded in every worker on spawn). - Arbitrary code execution in the main thread: via
loadBalancer, an attacker-supplied function that is called during task scheduling. - Environment/CLI option injection: via
env, which is passed to each worker constructor. - Denial of Service / unexpected behavior: via other reachable options such as
workerData,resourceLimits,niceIncrement,closeTimeout,recordTiming, etc.
Anyone using Piscina in an application where Object.prototype can be polluted (e.g. through a dependency with a prototype-pollution vulnerability) is impacted.
- Record
GHSA-67c8-pqhq-4rmx- CVSS 4.0
- 9.2 Critical
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-1321
- Updated
- 2026-11-02
Show 7 moreShow less
OSVAZL-105657 No score
CVE-2026-102992 affecting package python-tensorboard 2.16.2-6
piscina is a node.js worker pool implementation. Prior to 4.9.4, 5.3.2, and 6.0.0-rc.5, Piscina stores ThreadPool.options in src/index.ts as a plain object that inherits from Object.prototype. Applications with a separate prototype-pollution primitive can therefore supply inherited values for security-sensitive options that do not have own defaults. An inherited execArgv value is passed to the Node.js Worker constructor and can preload attacker-controlled code in worker threads, an inherited loadBalancer function can execute during task scheduling, and inherited env values can alter worker environments. This issue is fixed in versions 4.9.4, 5.3.2, and 6.0.0-rc.5.
- Record
AZL-105657- Updated
- 2026-11-02
OSVCLSA-2026-1790888307 No score
TuxCare security update for piscina (1 CVE)
TuxCare rebuilt piscina to address 1 CVE. Fixed in 4.8.0-tuxcare.1.
- Record
CLSA-2026-1790888307- Updated
- 2026-11-02
OSVCLSA-2026-1790937670 No score
TuxCare security update for piscina (1 CVE)
TuxCare rebuilt piscina to address 1 CVE. Fixed in 4.6.1-tuxcare.2.
- Record
CLSA-2026-1790937670- Updated
- 2026-11-02
OSVCLSA-2026-1791028065 No score
TuxCare security update for piscina (1 CVE)
TuxCare rebuilt piscina to address 1 CVE. Fixed in 4.4.0-tuxcare.1.
- Record
CLSA-2026-1791028065- Updated
- 2026-11-02
OSVCLSA-2026-1792472733 No score
TuxCare security update for piscina (1 CVE)
TuxCare rebuilt piscina to address 1 CVE. Fixed in 5.2.0-tuxcare.1.
- Record
CLSA-2026-1792472733- Updated
- 2026-11-02
OSVCLSA-2026-1793206864 No score
TuxCare security update for piscina (2 CVEs)
TuxCare rebuilt piscina to address 2 CVEs. Fixed in 3.2.0-tuxcare.1.
- Record
CLSA-2026-1793206864- Updated
- 2026-11-02
OSVROOT-APP-NPM-CVE-2026-102992 No score
CVE-2026-102992 in piscina - Patched by Root
Root has patched CVE-2026-102992 in the piscina package for Root:npm. Multiple fixed versions available.
- Record
ROOT-APP-NPM-CVE-2026-102992- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
piscinanpm |
5.0.0 up to 5.3.2 | 5.3.2 |
piscinanpm |
before 4.9.4 | 4.9.4 |
piscinanpm |
6.0.0-rc.1 up to 6.0.0-rc.5 | 6.0.0-rc.5 |
python-tensorboardAzure Linux:3 |
through 2.16.2-6 | None known |
piscinaTuxCare:npm |
4.8.0-tuxcare.0 up to 4.8.0-tuxcare.1, plus listed versions 4.8.0 |
4.8.0-tuxcare.1 |
piscinaTuxCare:npm |
4.6.1-tuxcare.0 up to 4.6.1-tuxcare.2, plus listed versions 4.6.14.6.1-tuxcare.1 |
4.6.1-tuxcare.2 |
piscinaTuxCare:npm |
4.4.0-tuxcare.0 up to 4.4.0-tuxcare.1, plus listed versions 4.4.0 |
4.4.0-tuxcare.1 |
piscinaTuxCare:npm |
5.2.0-tuxcare.0 up to 5.2.0-tuxcare.1, plus listed versions 5.2.0 |
5.2.0-tuxcare.1 |
piscinaTuxCare:npm From an advisory covering 2 CVEs |
3.2.0-tuxcare.0 up to 3.2.0-tuxcare.1, plus listed versions 3.2.0 |
3.2.0-tuxcare.1 |
piscinaRoot:npm |
before 4.9.3-aikido.1 | 4.9.3-aikido.15.3.1-aikido.1 |
@rootio/piscinaRoot:npm |
before 4.9.3-root.io.1 | 4.9.3-root.io.15.3.1-root.io.1 |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected | ||
| facts | OSV | |
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-102992 is a critical vulnerability (CVSS 9.2) in Piscinajs Piscina, published September 30, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.51%, the 43rd percentile. Fixed in piscina 5.3.2.
References
github.com/piscinajs/piscina/security/advisories/GHSA-67c8-pqhq-4rmx
github.com/piscinajs/piscina/commit/0cb12fca37f526065b072592afe954574dcc656f
github.com/piscinajs/piscina/commit/2f69f67159a0e48b38fd61fa4a91c2fdc19fff72
github.com/piscinajs/piscina/commit/5be7bbb19e3787bb698862cd516121a578d690f7
github.com/piscinajs/piscina/commit/bebbda255c2981cecddd36b171b94be2fd41c9a6
github.com/piscinajs/piscina/releases/tag/v4.9.4