A bouncer who checks the forged ticket, sees it fail, and still lets you through the VIP door because the door lock still works
When @fastify/secure-session 7.5.0 through 8.4.1 is configured with signed cookies, a failed signature check still passes the raw cookie value to the session decoder. Because the encryption key is unchanged, the plugin decrypts the cookie and accepts the session. The attacker only needs an already-issued, unexpired encrypted cookie; they need neither the signing secret nor the encryption key.
The vendor's MEDIUM 4.2 is defensible on paper but overstates reality. The vulnerability requires possession of a stolen cookie and an application that rotates only the signing secret while retaining the encryption key. Most teams rotate the encryption key or use a unified secret, and even then the attacker gains no new privileges, cannot forge data, and cannot extend expiry. That is a LOW-severity session life-extension bug in a specific operational misconfiguration.
4 steps from start to impact.
Possess a valid encrypted session cookie
- Attacker already holds a session cookie from a victim user
- Cookie is within its original expiry
- HTTP-only and Secure flags prevent many exfiltration vectors
- Encrypted payload doesn't leak secrets by itself
- Requires an existing compromise vector to steal the cookie
Application rotates only the cookie signing secret
- Application uses separate signing secret and encryption key
- Only the signing secret is rotated
- Most deployments rotate the encryption key or use the same key for sign and encrypt
- Operational rotation of only signing secret is rare
Strip the obsolete signature from the cookie
- Cookie format known (public) or easy to derive
- Trivial to do with a simple string split
- No secret knowledge required
Replay stripped cookie to the application
- Network access to the Fastify application
- Encryption key unchanged
- Session must not have been separately expired by other means
- Application firewalls generally don't inspect cookie signature format
- WAF cookie signature inspection can't reliably detect stripped cookies because the encrypted payload is opaque and the server decrypts after signature check.
- Setting HTTP-only/Secure flags doesn't help if the attacker already has the cookie.
- Rotating only the signing secret is exactly the condition that triggers the bug.
The supporting signals.
| In-the-wild status | No known exploitation; not listed in CISA KEV |
|---|---|
| PoC availability | No standalone public PoC required beyond trivial cookie stripping; no dedicated exploit observed for this CVE |
| EPSS score / percentile | Expected low (EPSS likely below 5% — dependency on stolen cookie suppresses exploitation) |
| KEV status | Not in CISA Known Exploited Vulnerabilities catalog |
| CVSS vector interpretation | AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N — network attack but high complexity due to stolen-cookie prerequisite and config constraint |
| Affected version range | 7.5.0 through 8.4.1 |
| Fixed version | 8.4.2 |
| Disclosure date | Unknown (CVE reserved/future) |
| Reporting researcher/org | Unknown; issue in Fastify secure-session advisory |
| Scanning/exposure data | No mass scanning; npm package install count not directly vulnerable by default |
Sources.
Why this verdict
- Precondition is stolen session cookie — attacker must already possess a valid encrypted cookie; the bug only extends that session after partial rotation.
- Configuration-specific trigger — signing secret must be independent from encryption key and only signing secret rotated; uncommon.
- Role multiplier: typical app session only — worst outcome is a single user's continued session; no domain/fleet/supply-chain blast radius even if the app is critical, because the attacker gains no new privileges.
Why not higher?
The bug does not provide initial access, cannot forge or elevate sessions, and cannot survive encryption-key rotation. The requirement that the attacker already holds a session cookie and that the app rotated only the signing secret sharply limits the exposed population, so a MEDIUM or higher rating overstates operational risk.
Why not lower?
The flaw defeats a documented revocation control in the specific configuration. If an admin or privileged user session is stolen and the app relies on signing secret rotation, the attacker retains access, so it cannot be dismissed as IGNORE.
Crowdsourced verification payload.
Run this on the build or runtime host where the Node.js application depends on @fastify/secure-session. Requires Python 3 and npm installed. From the project root, run python3 check_secure_session.py; no elevated privileges needed. It will inspect package.json and node_modules.
#!/usr/bin/env python3
import json, sys, os
def parse(v):
return tuple(map(int, v.split('-')[0].split('.')))
try:
pkg_path = 'node_modules/@fastify/secure-session/package.json'
if os.path.exists(pkg_path):
with open(pkg_path) as f:
data = json.load(f)
version = data['version']
else:
if os.path.exists('package.json'):
with open('package.json') as f:
root = json.load(f)
v = root.get('dependencies', {}).get('@fastify/secure-session') or root.get('devDependencies', {}).get('@fastify/secure-session')
if not v:
print('UNKNOWN: package not found in dependencies')
sys.exit(2)
version = v.lstrip('^~')
else:
print('UNKNOWN: no package.json found')
sys.exit(2)
vv = parse(version)
if (7, 5, 0) <= vv < (8, 4, 2):
print(f'VULNERABLE: @fastify/secure-session {version} is in vulnerable range 7.5.0-8.4.1')
sys.exit(1)
elif vv >= (8, 4, 2):
print(f'PATCHED: @fastify/secure-session {version} is >=8.4.2')
sys.exit(0)
else:
print(f'UNKNOWN: version {version} is below 7.5.0 or not vulnerable')
sys.exit(2)
except Exception as e:
print(f'UNKNOWN: {e}')
sys.exit(2)