GitHub Advisoryadvisory · npm
GHSA-qjx8-664m-686j JavaScript Cookie: Per-instance prototype hijack in assign() enables cookie-attribute injection
HIGH
Official page ↗
- Aliases
- CVE-2026-46625
- Ecosystem
- npm
- Packages
- js-cookie
- Severity
- High
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N
- Weaknesses
- CWE-1321
- Reviewed
- 2026-05-21
Affected packages
• npm js-cookie: < 3.0.7 → fixed in 3.0.7
Description
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:
```js
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
```js
// src/assign.mjs — full file
export default function (target) {
for (var i = 1; i
Suggested patch
```diff
--- 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:
```js
for (const key of Object.getOwnPropertyNames(source)) {
if (key === '__proto__') continue
target[key] = source[key]
}
```
Related
Alias · CVE (1)
- CVE-2026-46625 JavaScript Cookie is a JavaScript API for handling cookies, client-side. vulnerability
Weakness · CWE (1)
- CWE-1321 Improperly Controlled Modification of Object Prototype Attributes weakness
References
- https://github.com/js-cookie/js-cookie/security/advisories/GHSA-qjx8-664m-686j web
- https://nvd.nist.gov/vuln/detail/CVE-2026-46625 advisory
- https://github.com/js-cookie/js-cookie/commit/eb3c40e89731e99b8970faaf35ddad249c6c0020 web
- https://github.com/js-cookie/js-cookie package
- https://github.com/js-cookie/js-cookie/releases/tag/v3.0.7 web