F-2025-0001·authentication
JWT cookie set without security flags (token theft and CSRF risk)
TL;DR
The session JWT was set in a cookie without HttpOnly, Secure, or SameSite attributes, leaving the token readable by client-side JavaScript and vulnerable to CSRF and theft via XSS.
Severity
HIGH
Impact
HIGH
Likelihood
HIGH
Method
MManual review
CAT.
Complexity
LOW
Exploitability
HIGH
02Section · Description
Description
The application issued a session JWT and stored it in a cookie using cookies().set("jwt", jwt) without specifying any security attributes. Because the cookie lacked HttpOnly, Secure, SameSite, Path, and expiration controls:
- HttpOnly missing: The token was trivially accessible to any JavaScript executing in the origin. A single XSS or compromised third-party script equals full session theft.
- Secure missing: If the site is ever served over HTTP (misconfiguration or staging), the cookie could be intercepted.
- SameSite missing: Cross-site requests could carry the JWT, enabling CSRF state-changing actions.
typescript
// src/actions/auth.ts (excerpt)const jwt = await thirdwebAuth.generateJWT({ payload: verifiedPayload.payload });const cookieStore = await cookies();cookieStore.set("jwt", jwt); // <-- no httpOnly/secure/sameSite/maxAge/path
03Section · Impact
Impact
- Account takeover: an attacker with the JWT can call protected APIs and act as the user.
- Privilege escalation: if tokens encode roles or claims, the attacker may reach privileged functionality.
- Data exfiltration and financial loss: any actions available to the stolen session (viewing or moving funds, changing settings) become possible.
04Section · Recommendation
Recommendation
Set the cookie with secure attributes (server-side only):
typescript
cookies().set({name: "jwt",value: jwt,httpOnly: true,secure: process.env.NODE_ENV === "production",sameSite: "lax",path: "/",maxAge: 60 * 60 * 24 * 7,});
Use matching attributes on logout/delete. Issue short-lived JWTs (exp) and pair them with refresh tokens stored with stricter storage and rotation (refresh token HttpOnly, refresh endpoint protected).
Ipal Network: Confirmed. Zealynx: Fixed.
Status
Fixed