Insecure Cookie Flags Allow Session Hijacking and CSRF
What Is This Vulnerability?
Session cookies and authentication tokens stored in cookies must be configured with the Secure, HttpOnly, and SameSite flags. Without Secure, cookies are sent over unencrypted HTTP connections. Without HttpOnly, JavaScript can read them via document.cookie. Without SameSite, they are attached to cross-site requests, enabling CSRF attacks.
Why It Happens
Many cookie-setting libraries and frameworks default to permissive cookie flags for backward compatibility. Developers set the cookie value without explicitly configuring security attributes, and the defaults (no Secure, no HttpOnly, SameSite=None or Lax depending on browser) leave the cookie exposed.
Example Code
import { NextResponse } from "next/server";
export async function POST(request: Request) {
const { email, password } = await request.json();
const session = await authenticate(email, password);
const response = NextResponse.json({ success: true });
// Cookie set without security flags
response.cookies.set("session_id", session.id);
return response;
}import { NextResponse } from "next/server";
export async function POST(request: Request) {
const { email, password } = await request.json();
const session = await authenticate(email, password);
const response = NextResponse.json({ success: true });
response.cookies.set("session_id", session.id, {
httpOnly: true,
secure: true,
sameSite: "strict",
maxAge: 60 * 60 * 24,
path: "/",
});
return response;
}How Hackers Exploit It
Without HttpOnly, an XSS attack can steal the session cookie with document.cookie and send it to the attacker's server. Without Secure, an attacker on the same network can intercept the cookie over an HTTP connection. Without SameSite, a malicious site can trigger authenticated requests to your app using the victim's cookies.
How to Fix It
Always set httpOnly: true to prevent JavaScript access, secure: true to restrict the cookie to HTTPS connections, and sameSite: 'strict' or 'lax' to control cross-site sending behavior. Set a reasonable maxAge and scope the cookie to the narrowest path needed. Audit all places in your codebase where cookies are set.