CVE-2026-46625
JavaScript Cookie: Per-instance prototype hijack in assign() enables cookie-attribute injection
JavaScript Cookie is a JavaScript API for handling cookies, client-side. Prior to version 3.0.7, js-cookie's internal assign() helper copies properties with for...in + plain assignment. When the source object is produced by JSON.parse, the JSON object's "proto" member is an own enumerable property, so the for…in enumerates it and the target[key] = source[key] write triggers the Object.prototype.proto setter on the fresh target ({}). The result is a per-instance prototype hijack: Object.prototype itself is untouched, but the merged attributes object now inherits attacker-controlled keys. Because the consuming set() function then enumerates the merged object with another for...in, every key the attacker placed on the polluted prototype lands in the resulting Set-Cookie string as an attribute pair. The attacker can set domain=, secure=, samesite=, expires=, and path= on cookies whose attributes the developer thought were locked down. This issue has been patched in version 3.0.7.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- None
- Integrity
- High
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
7.5
JavaScript Cookie: Per-instance prototype hijack in assign() enables cookie-attribute injection
JavaScript Cookie is a JavaScript API for handling cookies, client-side. Prior to version 3.0.7, js-cookie's internal assign() helper copies properties with for...in + plain assignment. When the source object is produced by JSON.parse, the JSON object's "proto" member is an own enumerable property, so the for…in enumerates it and the target[key] = source[key] write triggers the Object.prototype.proto setter on the fresh target ({}). The result is a per-instance prototype hijack: Object.prototype itself is untouched, but the merged attributes object now inherits attacker-controlled keys. Because the consuming set() function then enumerates the merged object with another for...in, every key the attacker placed on the polluted prototype lands in the resulting Set-Cookie string as an attribute pair. The attacker can set domain=, secure=, samesite=, expires=, and path= on cookies whose attributes the developer thought were locked down. This issue has been patched in version 3.0.7.
- Record
CVE-2026-46625- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N - Weakness
- CWE-1321, CWE-915
- Updated
- 2026-11-02
EUVDEUVD-2026-36154
7.5
JavaScript Cookie is a JavaScript API for handling cookies, client-side. Prior to version 3.0.7, js-cookie's internal assign() helper copies properties with for...in + plain assignment. When the source object is produced by JSON.parse, the JSON object's "proto" member is an own enumerable property, so the for…in enumerates it and the target[key] = source[key] write triggers the Object.prototype.proto setter on the fresh target ({}). The result is a per-instance prototype hijack: Object.prototype itself is untouched, but the merged attributes object now inherits attacker-controlled keys. Because the consuming set() function then enumerates the merged object with another for...in, every key the attacker placed on the polluted prototype lands in the resulting Set-Cookie string as an attribute pair. The attacker can set domain=, secure=, samesite=, expires=, and path= on cookies whose attributes the developer thought were locked down. This issue has been patched in version 3.0.7.
- Record
EUVD-2026-36154- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-qjx8-664m-686j
7.5
JavaScript Cookie: Per-instance prototype hijack in assign() enables cookie-attribute injection
Summary
js-cookie's internal assign() helper copies properties with for...in + plain assignment. When the source object is produced by JSON.parse, the JSON object's "__proto__" member is an own enumerable property, so the for…in enumerates it and the target[key] = source[key] write triggers the Object.prototype.__proto__ setter on the fresh target ({}). The result is a per-instance prototype hijack: Object.prototype itself is untouched, but the merged attributes object now inherits attacker-controlled keys.
Because the consuming set() function then enumerates the merged object with another for...in, every key the attacker placed on the polluted prototype lands in the resulting Set-Cookie string as an attribute pair. The attacker can set domain=, secure=, samesite=, expires=, and path= on cookies whose attributes the developer thought were locked down.
Impact
Any application that forwards a JSON-derived object as the attributes argument to Cookies.set, Cookies.remove, Cookies.withAttributes, or Cookies.withConverter is vulnerable. This is the standard pattern when cookie configuration comes from a backend:
const cfg = await fetch('/config').then(r => r.json());
Cookies.set('session', token, cfg.cookieAttrs); // cfg.cookieAttrs influenced by attacker
A payload of {"__proto__":{"domain":"evil.example","secure":"false","samesite":"None"}} causes js-cookie to emit:
Set-Cookie: session=TOKEN; path=/; domain=evil.example; secure=false; samesite=None
Affected code
// src/assign.mjs — full file
export default function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i]
for (var key in source) { // includes own enumerable '__proto__'
target[key] = source[key] // [[Set]] form - fires __proto__ setter
}
}
return target
}
Proof of concept
Node 22.11.0, no third-party deps:
Environment setup
mkdir -p /tmp/jscookie-poc && cd /tmp/jscookie-poc
npm init -y
npm i js-cookie
PoC
ubuntu@kuber:/tmp/jscookie-poc$ cat poc.mjs
let lastSetCookie = '';
globalThis.document = {
get cookie() { return ''; },
set cookie(v) { lastSetCookie = v; }
};
const { default: Cookies } = await import('js-cookie');
const attackerAttrs = JSON.parse(
'{"__proto__":{"secure":"false","domain":"evil.com","samesite":"None","expires":-1}}'
);
Cookies.set('session', 'TOKEN', attackerAttrs);
console.log('Set-Cookie that js-cookie wrote to document.cookie:');
console.log(lastSetCookie);
Execution: <img width="2614" height="1174" alt="cls-2026-05-14-01 44 39" src="https://github.com/user-attachments/assets/120df1fe-7e97-4ca3-904e-ab80d71ecf62" />
Suggested patch
--- a/src/assign.mjs
+++ b/src/assign.mjs
@@
export default function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i]
- for (var key in source) {
- target[key] = source[key]
- }
+ for (var key in source) {
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue
+ Object.defineProperty(target, key, {
+ value: source[key],
+ writable: true,
+ enumerable: true,
+ configurable: true,
+ })
+ }
}
return target
}
Equivalent one-liner alternative - iterate own names only and filter:
for (const key of Object.getOwnPropertyNames(source)) {
if (key === '__proto__') continue
target[key] = source[key]
}
- Record
GHSA-qjx8-664m-686j- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N - Weakness
- CWE-1321
- Updated
- 2026-11-02
NVD
7.5
JavaScript Cookie is a JavaScript API for handling cookies, client-side. Prior to version 3.0.7, js-cookie's internal assign() helper copies properties with for...in + plain assignment. When the source object is produced by JSON.parse, the JSON object's "proto" member is an own enumerable property, so the for…in enumerates it and the target[key] = source[key] write triggers the Object.prototype.proto setter on the fresh target ({}). The result is a per-instance prototype hijack: Object.prototype itself is untouched, but the merged attributes object now inherits attacker-controlled keys. Because the consuming set() function then enumerates the merged object with another for...in, every key the attacker placed on the polluted prototype lands in the resulting Set-Cookie string as an attribute pair. The attacker can set domain=, secure=, samesite=, expires=, and path= on cookies whose attributes the developer thought were locked down. This issue has been patched in version 3.0.7.
- Record
CVE-2026-46625- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N - Weakness
- CWE-1321, CWE-915
- Updated
- 2026-11-02
OSV
7.5
JavaScript Cookie: Per-instance prototype hijack in assign() enables cookie-attribute injection
JavaScript Cookie is a JavaScript API for handling cookies, client-side. Prior to version 3.0.7, js-cookie's internal assign() helper copies properties with for...in + plain assignment. When the source object is produced by JSON.parse, the JSON object's "proto" member is an own enumerable property, so the for…in enumerates it and the target[key] = source[key] write triggers the Object.prototype.proto setter on the fresh target ({}). The result is a per-instance prototype hijack: Object.prototype itself is untouched, but the merged attributes object now inherits attacker-controlled keys. Because the consuming set() function then enumerates the merged object with another for...in, every key the attacker placed on the polluted prototype lands in the resulting Set-Cookie string as an attribute pair. The attacker can set domain=, secure=, samesite=, expires=, and path= on cookies whose attributes the developer thought were locked down. This issue has been patched in version 3.0.7.
- Record
CVE-2026-46625- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N - Weakness
- CWE-1321
- Updated
- 2026-11-02
OSVDEBIAN-CVE-2026-46625
7.5
JavaScript Cookie is a JavaScript API for handling cookies, client-side. Prior to version 3.0.7, js-cookie's internal assign() helper copies properties with for...in + plain assignment. When the source object is produced by JSON.parse, the JSON object's "proto" member is an own enumerable property, so the for…in enumerates it and the target[key] = source[key] write triggers the Object.prototype.proto setter on the fresh target ({}). The result is a per-instance prototype hijack: Object.prototype itself is untouched, but the merged attributes object now inherits attacker-controlled keys. Because the consuming set() function then enumerates the merged object with another for...in, every key the attacker placed on the polluted prototype lands in the resulting Set-Cookie string as an attribute pair. The attacker can set domain=, secure=, samesite=, expires=, and path= on cookies whose attributes the developer thought were locked down. This issue has been patched in version 3.0.7.
- Record
DEBIAN-CVE-2026-46625- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N - Updated
- 2026-11-02
Show 4 moreShow less
OSVGHSA-qjx8-664m-686j
7.5
JavaScript Cookie: Per-instance prototype hijack in assign() enables cookie-attribute injection
Summary
js-cookie's internal assign() helper copies properties with for...in + plain assignment. When the source object is produced by JSON.parse, the JSON object's "__proto__" member is an own enumerable property, so the for…in enumerates it and the target[key] = source[key] write triggers the Object.prototype.__proto__ setter on the fresh target ({}). The result is a per-instance prototype hijack: Object.prototype itself is untouched, but the merged attributes object now inherits attacker-controlled keys.
Because the consuming set() function then enumerates the merged object with another for...in, every key the attacker placed on the polluted prototype lands in the resulting Set-Cookie string as an attribute pair. The attacker can set domain=, secure=, samesite=, expires=, and path= on cookies whose attributes the developer thought were locked down.
Impact
Any application that forwards a JSON-derived object as the attributes argument to Cookies.set, Cookies.remove, Cookies.withAttributes, or Cookies.withConverter is vulnerable. This is the standard pattern when cookie configuration comes from a backend:
const cfg = await fetch('/config').then(r => r.json());
Cookies.set('session', token, cfg.cookieAttrs); // cfg.cookieAttrs influenced by attacker
A payload of {"__proto__":{"domain":"evil.example","secure":"false","samesite":"None"}} causes js-cookie to emit:
Set-Cookie: session=TOKEN; path=/; domain=evil.example; secure=false; samesite=None
Affected code
// src/assign.mjs — full file
export default function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i]
for (var key in source) { // includes own enumerable '__proto__'
target[key] = source[key] // [[Set]] form - fires __proto__ setter
}
}
return target
}
Proof of concept
Node 22.11.0, no third-party deps:
Environment setup
mkdir -p /tmp/jscookie-poc && cd /tmp/jscookie-poc
npm init -y
npm i js-cookie
PoC
ubuntu@kuber:/tmp/jscookie-poc$ cat poc.mjs
let lastSetCookie = '';
globalThis.document = {
get cookie() { return ''; },
set cookie(v) { lastSetCookie = v; }
};
const { default: Cookies } = await import('js-cookie');
const attackerAttrs = JSON.parse(
'{"__proto__":{"secure":"false","domain":"evil.com","samesite":"None","expires":-1}}'
);
Cookies.set('session', 'TOKEN', attackerAttrs);
console.log('Set-Cookie that js-cookie wrote to document.cookie:');
console.log(lastSetCookie);
Execution: <img width="2614" height="1174" alt="cls-2026-05-14-01 44 39" src="https://github.com/user-attachments/assets/120df1fe-7e97-4ca3-904e-ab80d71ecf62" />
Suggested patch
--- a/src/assign.mjs
+++ b/src/assign.mjs
@@
export default function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i]
- for (var key in source) {
- target[key] = source[key]
- }
+ for (var key in source) {
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue
+ Object.defineProperty(target, key, {
+ value: source[key],
+ writable: true,
+ enumerable: true,
+ configurable: true,
+ })
+ }
}
return target
}
Equivalent one-liner alternative - iterate own names only and filter:
for (const key of Object.getOwnPropertyNames(source)) {
if (key === '__proto__') continue
target[key] = source[key]
}
- Record
GHSA-qjx8-664m-686j- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N - Weakness
- CWE-1321
- Updated
- 2026-11-02
OSVROOT-APP-NPM-CVE-2026-46625
7.5
CVE-2026-46625 in @rootio/js-cookie - Patched by Root
Root has patched CVE-2026-46625 in the @rootio/js-cookie package for Root:npm. Multiple fixed versions available.
- Record
ROOT-APP-NPM-CVE-2026-46625- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N - Updated
- 2026-11-02
OSVUBUNTU-CVE-2026-46625
7.5
JavaScript Cookie is a JavaScript API for handling cookies, client-side. Prior to version 3.0.7, js-cookie's internal assign() helper copies properties with for...in + plain assignment. When the source object is produced by JSON.parse, the JSON object's "proto" member is an own enumerable property, so the for…in enumerates it and the target[key] = source[key] write triggers the Object.prototype.proto setter on the fresh target ({}). The result is a per-instance prototype hijack: Object.prototype itself is untouched, but the merged attributes object now inherits attacker-controlled keys. Because the consuming set() function then enumerates the merged object with another for...in, every key the attacker placed on the polluted prototype lands in the resulting Set-Cookie string as an attribute pair. The attacker can set domain=, secure=, samesite=, expires=, and path= on cookies whose attributes the developer thought were locked down. This issue has been patched in version 3.0.7.
- Record
UBUNTU-CVE-2026-46625- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N - Updated
- 2026-11-02
OSVCLSA-2026-1782089812 No score
TuxCare security update for js-cookie (1 CVE)
TuxCare rebuilt js-cookie to address 1 CVE. Fixed in 2.2.1-tuxcare.1.
- Record
CLSA-2026-1782089812- Updated
- 2026-11-02
Affected products
- js-cookie javascript cookie
- js-cookie
- red hat cryostat 4 on rhel 9
- red hat openshift lightspeed
- red hat 3scale api management platform 2
- red hat advanced cluster security for kubernetes 4.10
- red hat ansible automation platform 2
- red hat ansible automation platform 2.1
- red hat ansible automation platform 2.2
- red hat ansible automation platform 2.7
- red hat developer hub 1.10
- red hat developer hub 1.9
Show 16 moreShow less
- red hat discovery 2
- red hat enterprise linux 10
- red hat enterprise linux 8
- red hat enterprise linux 9
- red hat jboss enterprise application platform 7
- red hat jboss enterprise application platform 8
- red hat jboss enterprise application platform expansion pack
- red hat openshift ai (rhoai)
- red hat openshift ai 3.4
- red hat openshift container platform 4
- red hat openshift service mesh 3.3
- redhat 3scale api management
- redhat ansible automation platform
- redhat enterprise linux
- redhat openshift ai
- redhat openshift lightspeed
Affected packages
| Package | Affected | Fixed |
|---|---|---|
js-cookienpm |
through 3.0.5 | 3.0.7 |
js-cookieTuxCare:npm |
2.2.1-tuxcare.0 up to 2.2.1-tuxcare.1, plus listed versions 2.2.1 |
2.2.1-tuxcare.1 |
node-js-cookieDebian:12 |
All versions, plus listed versions 3.0.1+~3.0.0-33.0.7+~3.0.6-13.0.7+~3.0.6-23.0.8+~3.0.6-1 |
None known |
node-js-cookieDebian:13 |
All versions, plus listed versions 3.0.1+~3.0.0-33.0.7+~3.0.6-13.0.7+~3.0.6-23.0.8+~3.0.6-1 |
None known |
node-js-cookieDebian:14 |
before 3.0.7+~3.0.6-1, plus listed versions 3.0.1+~3.0.0-3 |
3.0.7+~3.0.6-1 |
js-cookienpm |
before 3.0.7 | 3.0.7 |
@rootio/js-cookieRoot:npm |
before 2.2.1-root.io.1 | 2.2.1-root.io.13.0.5-root.io.13.0.5-root.io.22.2.1-root.io.2 |
js-cookieRoot:npm |
before 3.0.5-aikido.2 | 3.0.5-aikido.22.2.1-aikido.2 |
node-js-cookieUbuntu:18.04:LTS |
All versions, plus listed versions 2.2.0-1 |
None known |
node-js-cookieUbuntu:20.04:LTS |
All versions, plus listed versions 2.2.0-22.2.1-1 |
None known |
Show 5 moreShow less
| Package | Affected | Fixed |
|---|---|---|
node-js-cookieUbuntu:22.04:LTS |
All versions, plus listed versions 2.2.1-12.2.1-23.0.1+~3.0.0-2 |
None known |
node-js-cookieUbuntu:24.04:LTS |
All versions, plus listed versions 3.0.1+~3.0.0-3 |
None known |
node-js-cookieUbuntu:25.10 |
All versions, plus listed versions 3.0.1+~3.0.0-3 |
None known |
node-js-cookieUbuntu:26.10 |
All versions, plus listed versions 3.0.1+~3.0.0-33.0.7+~3.0.6-23.0.8+~3.0.6-1 |
None known |
node-js-cookieUbuntu:26.04:LTS |
All versions, plus listed versions 3.0.1+~3.0.0-3 |
None known |
History
| Recorded | Changed | Sources |
|---|---|---|
| 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-46625 is a high vulnerability (CVSS 7.5) in Js-cookie Javascript Cookie, published May 21, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.92%, the 60th percentile. Fixed in js-cookie 3.0.7.
References
github.com/js-cookie/js-cookie/security/advisories/GHSA-qjx8-664m-686j
github.com/js-cookie/js-cookie/commit/eb3c40e89731e99b8970faaf35ddad249c6c0020
github.com/js-cookie/js-cookie/releases/tag/v3.0.7
access.redhat.com/security/cve/CVE-2026-46625
bugzilla.redhat.com/show_bug.cgi?id=2487740
security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-46625.json
Show 17 moreShow less
access.redhat.com/errata/RHSA-2026:48151
access.redhat.com/errata/RHSA-2026:36625
access.redhat.com/errata/RHSA-2026:56338
access.redhat.com/errata/RHSA-2026:56357
access.redhat.com/errata/RHSA-2026:59153
access.redhat.com/errata/RHSA-2026:48126
access.redhat.com/errata/RHSA-2026:49642
access.redhat.com/errata/RHSA-2026:52768
access.redhat.com/errata/RHSA-2026:60520
access.redhat.com/errata/RHSA-2026:33183
nvd.nist.gov/vuln/detail/CVE-2026-46625
github.com/advisories/GHSA-qjx8-664m-686j
github.com/CVEProject/cvelistV5/tree/main/cves/2026/46xxx/CVE-2026-46625.json
security-tracker.debian.org/tracker/CVE-2026-46625
github.com/js-cookie/js-cookie
ubuntu.com/security/CVE-2026-46625
cve.org/CVERecord?id=CVE-2026-46625