Q4 of 24 · Security
What cookie security flags exist and how do you verify they are correctly set?
Short answer
Short answer: HttpOnly prevents JavaScript from reading the cookie (mitigates XSS-based session theft). Secure ensures the cookie is only sent over HTTPS. SameSite=Strict or Lax restricts cross-origin sending (mitigates CSRF). Verify all three via the Set-Cookie response header in browser DevTools, a proxy tool, or an API test assertion.
Detail
HttpOnly: the cookie is not accessible via document.cookie in JavaScript. An XSS attack that injects JavaScript cannot steal an HttpOnly cookie. Session tokens must always be HttpOnly.
Secure: the cookie is only included in HTTPS requests, never in HTTP. Without this flag, a session cookie on an HTTPS site is transmitted in plaintext if the user accidentally visits the HTTP version of a URL — a realistic attack on public networks.
SameSite: controls when the browser sends the cookie with cross-origin requests:
Strict: cookie is never sent with cross-site requests (breaks some SSO flows and external link navigation where you want the user to arrive authenticated)Lax(the modern default in most browsers): cookie is sent with top-level GET navigations (clicking a link) but not with cross-site POST requests — mitigates CSRF for the most common attack vectorNone(+ Secure required): cookie is sent with all cross-site requests — required for third-party cookie scenarios (embedded widgets, cross-origin APIs)
How to verify: intercept the Set-Cookie header in the login response. In Playwright:
const [response] = await Promise.all([
page.waitForResponse(r => r.url().includes('/api/login')),
loginPage.submitCredentials(),
]);
const setCookie = response.headers()['set-cookie'];
expect(setCookie).toContain('HttpOnly');
expect(setCookie).toContain('Secure');
expect(setCookie).toMatch(/SameSite=(Strict|Lax)/i);
// EXAMPLE
cookie-flags.test.ts
test('session cookie has required security flags', async ({ page, request }) => {
const response = await request.post('/api/login', {
data: { email: 'user@example.com', password: 'correct-password' },
});
const setCookie = response.headers()['set-cookie'] ?? '';
expect(setCookie).toContain('HttpOnly');
expect(setCookie).toContain('Secure');
expect(setCookie).toMatch(/SameSite=(Strict|Lax)/i);
});