Skip to content

VNX-NODE-029: Missing HttpOnly flag on cookie

Reports session and credential cookies set from Node.js without HttpOnly: res.cookie()/cookie.serialize() calls lacking httpOnly: true, Set-Cookie header literals without the attribute, and any cookie options with httpOnly: false.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-NODE-029
Severity Medium
SARIF level warning
Kind sast
Languages JavaScript / TypeScript
CWE CWE-1004
CAPEC CAPEC-63
ATT&CK T1059.007
CWSS vector CWSS:1.0/TI:M/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C
Tags cookie httponly session
Source internal/sast/rules/vnx-node-029.rego

Overview

This rule detects calls to cookie() or res.cookie() in JavaScript files where the httpOnly option is absent or explicitly set to false. The HttpOnly flag instructs browsers to deny JavaScript access to a cookie via document.cookie. Without it, any XSS vulnerability in the application, or in a third-party script loaded by the page, can read session and authentication cookies and relay them to an attacker-controlled server, enabling complete session hijacking. This is classified as CWE-1004 (Sensitive Cookie Without ‘HttpOnly’ Flag).

Session tokens are the most valuable target of XSS attacks: a stolen session token provides the attacker with the victim’s authenticated identity without requiring their password. The HttpOnly flag is one of the simplest and most effective mitigations for this attack path. It does not prevent all XSS impacts, but it specifically and reliably removes the ability to steal cookies via document.cookie, significantly raising the cost of a successful XSS exploitation.

Why This Matters

Session hijacking via XSS-based cookie theft is one of the most impactful and easily executed web attacks. Once an attacker has a valid session token, they can impersonate the victim for as long as the session remains active, bypassing MFA, accessing sensitive account data, and performing actions on the victim’s behalf. The attack requires no interaction beyond a successful XSS payload, which can be delivered via a crafted link, an injected ad, or a compromised third-party script.

The HttpOnly flag has been supported by all major browsers since Internet Explorer 6, making it a zero-cost, universally compatible mitigation. Its absence is flagged as a finding in penetration tests, bug bounty programs, and compliance audits (PCI-DSS requirement 6.4). It should be set on all cookies that do not require client-side JavaScript access, which, for session and authentication cookies, is always the case.

What Gets Flagged

// FLAGGED: a token cookie with no options (Express defaults to script-readable)
res.cookie('token', token);

// FLAGGED: options across lines without httpOnly
res.cookie('access_token', accessToken, {
  secure: true,
  sameSite: 'strict',
});

// FLAGGED: the httpOnly: false line, for any cookie
response.cookie('sid', sid, { httpOnly: false, secure: true });

// FLAGGED: Set-Cookie header and cookie.serialize without HttpOnly
res.setHeader('Set-Cookie', `sessionId=${sessionId}; Path=/; Secure`);
cookie.serialize('auth', jwt, { path: '/', secure: true });

Not flagged: options with httpOnly: true (inline or in an options object defined in the file), non-sensitive cookies (theme, lang), CSRF/XSRF token cookies the page must read, Koa ctx.cookies.set() (HttpOnly by default), cookies being cleared, and test files.

Remediation

  1. Add { httpOnly: true } to all res.cookie() calls. This single flag eliminates JavaScript access to the cookie.
  2. Combine httpOnly with secure: true (HTTPS-only transmission) and sameSite: 'strict' or 'lax' (CSRF mitigation) to form a complete cookie security configuration.
  3. Use the cookie-session or express-session middleware with httpOnly: true in the session options object so that all session cookies are consistently secured.
  4. Review whether any cookies genuinely need to be JavaScript-accessible, for most authentication and session cookies, they do not.
// SAFE: session cookie with full security flags
res.cookie('sessionId', token, {
  httpOnly: true,   // not accessible via document.cookie
  secure: true,     // HTTPS only
  sameSite: 'strict', // CSRF protection
  maxAge: 3600000,  // 1 hour in ms
  path: '/',
});

// SAFE: express-session with httpOnly enabled
const session = require('express-session');
app.use(session({
  secret: process.env.SESSION_SECRET,
  cookie: {
    httpOnly: true,
    secure: true,
    sameSite: 'strict',
    maxAge: 3600000,
  },
  resave: false,
  saveUninitialized: false,
}));

References

Suppressing this rule

Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):

# nosec vnx-node-029
// nosec vnx-node-029

Or record an ignore rule: vulnetix ignore add --rule vnx-node-029 --reason "...". See Suppressing findings.

Edit this pageSources: cli/internal/sast/rules/vnx-node-029.rego, cli/internal/sast/docs/vnx-node-029.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.