Skip to content

chore(deps): update dependency js-cookie to v3.0.7 [security] - #1346

Open
renovate[bot] wants to merge 1 commit into
masterfrom
renovate/npm-js-cookie-vulnerability
Open

chore(deps): update dependency js-cookie to v3.0.7 [security]#1346
renovate[bot] wants to merge 1 commit into
masterfrom
renovate/npm-js-cookie-vulnerability

Conversation

@renovate

@renovaterenovateBot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

PackageChangeAgeConfidence
js-cookie3.0.53.0.7ageconfidence

JavaScript Cookie: Per-instance prototype hijack in assign() enables cookie-attribute injection

CVE-2026-46625 / GHSA-qjx8-664m-686j

More information

Details

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:

constcfg=awaitfetch('/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 fileexportdefaultfunction(target){for(vari=1;i<arguments.length;i++){varsource=arguments[i]for(varkeyinsource){// includes own enumerable '__proto__'target[key]=source[key]// [[Set]] form - fires __proto__ setter}}returntarget}
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$catpoc.mjsletlastSetCookie='';globalThis.document={getcookie(){return'';},setcookie(v){lastSetCookie=v;}};const{default: Cookies}=awaitimport('js-cookie');constattackerAttrs=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:
cls-2026-05-14-01 44 39

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(constkeyofObject.getOwnPropertyNames(source)){if(key==='__proto__')continuetarget[key]=source[key]}

Severity

  • CVSS Score: 7.5 / 10 (High)
  • Vector String: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Release Notes

js-cookie/js-cookie (js-cookie)

v3.0.7

Compare Source

  • Prevent cookie attribute injection: CVE-2026-46625 (eb3c40e)
  • Add Partitioned attribute to readme (b994768)
  • Publish to npm registry via trusted publisher exclusively (4dc71be)
  • Ensure consistent behaviour for get('name') + get() (1953d30)

v3.0.6

Compare Source


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@github-actions

Copy link
Copy Markdown
Contributor

size-limit report 📦

PathSizeLoading time (3g)Running time (snapdragon)Total time
dist/index.js541 B (0%)11 ms (0%)40 ms (+470.53% 🔺)51 ms

@codecov

codecovBot commented Aug 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.00%. Comparing base (7c7be48) to head (1fefe68).

Additional details and impacted files
@@ Coverage Diff @@## master #1346 +/- ##
=======================================
Coverage 90.00% 90.00% =======================================
Files 3 3 Lines 80 80 Branches 20 20 =======================================
Hits 72 72 Misses 6 6 Partials 2 2 

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants