← Back to Feed CACHED · 2026-09-10 12:34:05 · CACHE_KEY CVE-2026-88038
CVE-2026-88038 · CWE-74 · Disclosed 2026-09-10

cookies vulnerable to Set-Cookie attribute injection via unvalidated domain and path options

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

Like worrying about a lock that can be re-keyed — but only if someone already left the key blank

CVE-2026-88038 affects the npm cookies package (pillarjs/cookies) in all versions before 0.9.2. The library constructs Set-Cookie response headers by concatenating domain and path option values directly into the header string. While cookie *names* and *values* are validated against character sets that reject semicolons, the domain and path parameters only pass through permissive RFC 7230 validation that allows semicolons. An attacker who can influence the value passed to domain or path — for example via domain: '.' + req.headers.host — can inject additional cookie attributes (SameSite, Secure, HttpOnly, Domain) into the response header. The package has ~1.9 million weekly npm downloads and is a core dependency of the Koa framework and various Express middleware stacks.

The vendor's MEDIUM 4.8 score is honest but arguably still generous. The CVSS vector correctly sets AC:H because exploitation requires the application to pass *untrusted, request-derived input* into the domain or path cookie options — a pattern most production codebases simply don't use. Developers overwhelmingly hardcode these values or pull them from server-side configuration. Even when the chain succeeds, the impact ceiling is limited to weakening cookie security flags (stripping HttpOnly, overriding SameSite), which is a *precondition* for further attacks like CSRF or session fixation — not a direct compromise. There is no RCE, no authentication bypass, and no availability impact. noisgate downgrades to LOW 3.5.

"Cookie attribute injection needs an app anti-pattern most codebases dont have"
02 · The Attack Path

3 steps from start to impact.

STEP 01

Identify application passing untrusted input to cookie options

The attacker must find a Node.js application using pillarjs/cookies (directly or via Koa) where domain or path options are derived from request-controlled input. The canonical anti-pattern is domain: '.' + req.headers.host or similar constructs that reflect a user-supplied hostname into the cookie's domain attribute. Without this application-level coding pattern, the vulnerability is unreachable.
Conditions required:
  • Application uses pillarjs/cookies < 0.9.2
  • Application passes attacker-influenced input to domain or path cookie options
Where this breaks in practice:
  • Most applications hardcode domain/path in config or environment variables
  • Code review and linting rules commonly flag request-derived cookie parameters
  • This anti-pattern is not present in Koa's default session middleware
Detection/coverage: npm audit and Snyk will flag cookies < 0.9.2. Static analysis tools (Semgrep, CodeQL) can detect req.headers flowing into cookie option objects.
STEP 02

Inject semicolon-delimited attributes via Host header

The attacker sends a request with a crafted Host header (or other reflected input) containing a semicolon followed by cookie attribute key-value pairs, e.g., evil.com; SameSite=None; Secure. The cookies library concatenates this into the Set-Cookie header without sanitization, causing the browser to parse the injected attributes as part of the cookie directive.
Conditions required:
  • Attacker can send arbitrary Host headers to the application
  • No upstream reverse proxy normalizes or rejects malformed Host headers
Where this breaks in practice:
  • Most production deployments sit behind nginx, Cloudflare, or an ALB that normalizes Host headers
  • WAF rules commonly block semicolons in Host headers
  • Koa's app.proxy setting and X-Forwarded-Host handling add additional layers
Detection/coverage: WAF logs for anomalous Host header characters (;, \r, \n). Server-side logging of Set-Cookie response headers can catch injected attributes.
STEP 03

Weaken victim's session cookie protections

If the injection succeeds, the attacker can strip HttpOnly (exposing the cookie to XSS), override SameSite=Lax to SameSite=None (enabling cross-site request attachment), or broaden Domain scope (sharing the cookie with sibling subdomains). These changes weaken the security posture of the victim's session cookie but do not directly steal it. A separate attack (XSS, CSRF) must still be chained to exploit the weakened cookie.
Conditions required:
  • Successful attribute injection from step 2
  • A second vulnerability (XSS or CSRF vector) to exploit the weakened cookie protections
Where this breaks in practice:
  • Modern browsers default SameSite=Lax when not specified, limiting the CSRF window
  • CSP headers and other defense-in-depth measures reduce XSS exploitability independently
  • The attacker must chain a second, separate vulnerability to gain any meaningful impact
Detection/coverage: Browser developer tools and response header inspection reveal injected attributes. Security scanners like Burp Suite flag unusual Set-Cookie structures.
03 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNone observed. No reports from any threat intelligence feed, no CISA KEV listing, no vendor acknowledgment of active exploitation.
Proof-of-conceptNone public. The advisory describes the injection mechanism conceptually but no weaponized PoC repository or researcher demo has been published as of 2026-09-10.
EPSS scoreNot yet scored. Advisory was published 2026-09-10 (today); EPSS lag means no score is available yet. Expected to land in the low single-digit percentile given AC:H and no known exploitation.
KEV statusNot listed. Not on the CISA Known Exploited Vulnerabilities catalog.
CVSS vectorCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N — Network-reachable but high attack complexity, no privileges or user interaction needed, unchanged scope, low confidentiality and integrity impact, no availability impact.
Affected versionspillarjs/cookies < 0.9.2 (all prior releases)
Fixed version0.9.2 — adds semicolon, CR, and LF rejection to domain and path option validation.
Scanning / exposure~1.9M weekly npm downloads; top 1% of npm packages. Core dependency of Koa (~8M downloads/week) and egg.js. However, vulnerable *application pattern* (untrusted input → cookie options) is a small subset of that install base.
Disclosure date2026-09-10 (GHSA-x44v-5gxf-r6hf published today)
Reporter / creditsRemediation by UlisesGascon, reviewed by blakeembrey (pillarjs maintainer).
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to LOW (3.5/10)

The single most decisive factor is that exploitation requires the application to pass attacker-controlled input into the domain or path cookie options — an uncommon coding anti-pattern that the vast majority of the 1.9M-download install base does not exhibit. Even successful exploitation only weakens cookie security flags rather than directly compromising authentication, data, or availability, making the *effective* blast radius negligible without a chained second vulnerability.

HIGH Vulnerability mechanics and affected version range
MEDIUM Prevalence of the vulnerable application pattern in production
LOW EPSS and future exploitation likelihood (advisory is hours old)

Why this verdict

  • Attack complexity is genuinely high (AC:H is accurate): The vulnerability is only reachable when the consuming application passes untrusted, request-derived input into cookie domain or path options. This is a specific anti-pattern, not a default behavior of the library or its framework consumers (Koa, egg.js).
  • Impact ceiling is a stepping stone, not a destination: Successful injection weakens cookie attributes (SameSite, HttpOnly, Secure) but does not directly yield credential theft, RCE, or data exfiltration. A second, independent vulnerability must be chained for meaningful impact. The CVSS C:L/I:L/A:N accurately reflects this.
  • Reverse-proxy friction eliminates most real-world paths: Production Node.js deployments almost universally sit behind nginx, Cloudflare, AWS ALB, or similar reverse proxies that normalize or reject malformed Host headers containing semicolons, cutting off the primary injection vector before it reaches application code.
  • Role multiplier: pillarjs/cookies is a web-application-tier library. In high-value roles (IdP built on Koa, CI/CD dashboard), the chain could weaken session cookie protections — but the outcome is still 'weakened cookie flags requiring a chained attack,' not 'domain takeover / fleet compromise / mass data egress.' The blast radius is tenant-scoped at most and conditional on a second vuln. Floor does not trigger.
  • No exploitation evidence or tooling: Zero in-the-wild activity, no public PoC, no KEV listing, advisory published today. The absence of any attacker interest further supports a lower severity.

Why not higher?

A MEDIUM rating would require either a realistic path to direct compromise without chaining or evidence that the vulnerable coding pattern is common in production. Neither condition is met. The AC:H constraint is not theoretical — it requires a specific, uncommon application anti-pattern. Even the 1.9M weekly downloads represent *library* adoption, not *vulnerable-pattern* adoption; the actual exploitable population is a small fraction of that base.

Why not lower?

An IGNORE rating would be inappropriate because the library is extremely widely deployed and a non-trivial number of applications *could* exhibit the vulnerable pattern, especially multi-tenant SaaS platforms that dynamically scope cookies to tenant-supplied domains. The fix is a single npm update and the risk, while low, is non-zero. Tracking and patching within a backlog cycle is warranted.

05 · Compensating Control

What to do — in priority order.

  1. Audit application code for untrusted input flowing into cookie options — Search your codebase for calls to cookies.set() or Koa's ctx.cookies.set() where the domain or path option is derived from req.headers, query parameters, or any user-controlled source. If no such pattern exists, your application is not exploitable regardless of library version. This is a one-time audit — no ongoing SLA since verdict is LOW.
  2. Ensure reverse proxy normalizes Host headers — Verify that your upstream reverse proxy (nginx, Cloudflare, ALB, Envoy) rejects or strips semicolons, carriage returns, and newlines from the Host header before forwarding to Node.js. This blocks the primary injection vector at the network edge.
  3. Upgrade to cookies 0.9.2 — Run npm update cookies or pin >=0.9.2 in package.json. This is the definitive fix — the new version rejects semicolons, CR, and LF in domain and path options. Per the LOW verdict, treat this as backlog hygiene with no hard SLA.
What doesn't work
  • CSP headers — Content Security Policy governs script execution and resource loading, not Set-Cookie header construction. CSP does not prevent cookie attribute injection.
  • HttpOnly flag on other cookies — Setting HttpOnly on your session cookie is good practice but does not prevent *this vulnerability from overriding it*. The injection can strip HttpOnly from the affected cookie.
  • Cookie signing (Keygrip) — pillarjs/cookies supports signed cookies, but signing validates cookie *values*, not *attributes*. The injected SameSite=None or Domain=.evil.com attributes are not covered by the signature.
06 · Verification

Crowdsourced verification payload.

Run this on any machine with Node.js and npm/npx available. It checks the installed version of the cookies package in the current project directory. No special privileges required. Example: bash check_cve_2026_88038.sh /path/to/your/node/project

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2026_88038.sh — Detect CVE-2026-88038 in pillarjs/cookies
# Usage: bash check_cve_2026_88038.sh [project_dir]
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN

set -euo pipefail

PROJECT_DIR="${1:-.}"
PKG_JSON="$PROJECT_DIR/node_modules/cookies/package.json"

if [ ! -f "$PKG_JSON" ]; then
  echo "UNKNOWN — cookies package not found in $PROJECT_DIR/node_modules/"
  exit 2
fi

VERSION=$(node -e "console.log(require('$PKG_JSON').version)" 2>/dev/null)
if [ -z "$VERSION" ]; then
  echo "UNKNOWN — could not parse version from $PKG_JSON"
  exit 2
fi

# Compare version against fixed version 0.9.2
RESULT=$(node -e "
  const v = '$VERSION'.split('.').map(Number);
  const fix = [0, 9, 2];
  for (let i = 0; i < 3; i++) {
    if ((v[i]||0) < fix[i]) { console.log('VULNERABLE'); process.exit(0); }
    if ((v[i]||0) > fix[i]) { console.log('PATCHED'); process.exit(0); }
  }
  console.log('PATCHED');
")

echo "$RESULT — cookies version $VERSION (fixed in 0.9.2)"
if [ "$RESULT" = "VULNERABLE" ]; then
  exit 1
elif [ "$RESULT" = "PATCHED" ]; then
  exit 0
else
  exit 2
fi
07 · Bottom Line

If you remember one thing.

TL;DR
CVE-2026-88038 is a cookie attribute injection flaw in pillarjs/cookies < 0.9.2 that is only exploitable when your application passes attacker-controlled input into cookie domain or path options — an uncommon pattern. noisgate reassesses this as LOW (3.5), downgraded from the vendor's MEDIUM 4.8. There is no noisgate mitigation SLA for LOW — treat this as backlog hygiene. First, run a quick codebase grep for cookies.set calls where domain or path derives from request headers; if you find none, you are not exploitable and can deprioritize freely. If you *do* find the pattern, bump cookies to 0.9.2 (npm update cookies) and harden your reverse proxy to strip semicolons from Host headers. No hard remediation deadline applies, but folding the upgrade into your next dependency refresh cycle is good housekeeping.

Sources

  1. GitHub Advisory GHSA-x44v-5gxf-r6hf
  2. pillarjs/cookies GitHub repository
  3. npm cookies package
  4. Related: Hono cookie injection CVE-2026-29086
  5. Related: undici cookie injection CVE-2026-16729
  6. CISA KEV Catalog
  7. CWE-74: Improper Neutralization of Special Elements
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.