Skip to content

VNX-SEC-013: Insecure cookie configuration

Detects cookies whose HttpOnly or Secure protection is switched off, and session or authentication cookies issued without HttpOnly, across Node, Python, Go, Java, .NET, PHP and Ruby.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-SEC-013
Severity Medium
SARIF level warning
Kind sast
Languages Any file
CWE CWE-614, CWE-1004
CAPEC CAPEC-31
ATT&CK T1539
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 cookies session web-security
Source internal/sast/rules/vnx-sec-013.rego

Overview

This rule reports a cookie whose HttpOnly or Secure protection is switched off: httpOnly: false / secure: false in cookie or session options (Express, Go http.Cookie and gorilla sessions.Options, ASP.NET CookieOptions, Rails session_store, Spring YAML), Django and Flask SESSION_COOKIE_SECURE / SESSION_COOKIE_HTTPONLY / CSRF_COOKIE_SECURE = False, set_cookie(..., secure=False), Java setHttpOnly(false) / setSecure(false), Spring server.servlet.session.cookie.*=false, CookieSecurePolicy.None, web.config httpOnlyCookies="false", PHP ini_set('session.cookie_httponly', 0) and php.ini, and false as the secure/httponly argument of PHP setcookie() or gin’s c.SetCookie(). It also reports a session, token, auth, JWT, remember-me or user-id cookie issued with no HttpOnly setting at all (res.cookie('session', id), set_cookie('token', t), a Go http.Cookie{} with no HttpOnly field, Java new Cookie("access_token", t) with no setHttpOnly, PHP setcookie('appSession', $v)). It does not report the CSRF/XSRF cookie’s HttpOnly (the page must read it), theme or language cookies, flags read from variables or the environment, options passed as a variable, cookies being cleared, development settings files, tests and documentation. SameSite is not checked. Where a rule for one flag reports the same line, the line is left to it, so a missing flag is one finding: Secure in Java, JavaScript/TypeScript and Python is reported by VNX-614; HttpOnly in Go, PHP, Python and Java and on document.cookie by VNX-1004; HttpOnly on an Express/Fastify res.cookie()/reply.setCookie() and httpOnly: false beside a cookie call by VNX-NODE-029. This rule keeps the rest: Ruby, C#, Kotlin, web.config, php.ini and .htaccess, YAML, gin and fiber cookies, Next.js cookies().set, PHP and Go Secure, setHttpOnly(false) lines, and cookies only its name list counts as sensitive. These settings control three distinct attack surfaces: HttpOnly prevents JavaScript from reading the cookie (blocking XSS-based session theft), Secure ensures the cookie is only sent over HTTPS (blocking cleartext interception), and SameSite restricts cross-origin sending (blocking CSRF).

Why This Matters

Session cookies are the keys to your users’ authenticated sessions. When any of the three security flags are missing or explicitly disabled:

  • No HttpOnly: A single XSS vulnerability anywhere on your site becomes a full account takeover, malicious scripts can run document.cookie to extract the session token and exfiltrate it to an attacker’s server.
  • No Secure: Session tokens are transmitted in cleartext over HTTP connections. On untrusted networks (coffee shops, airports), attackers using network sniffers or tools like Wireshark can capture and replay session tokens.
  • No SameSite (or SameSite=None): Cross-site requests automatically include the cookie, enabling CSRF attacks. An attacker can host a page that makes authenticated requests to your application using the victim’s session.

Many frameworks set these flags to False by default in development for convenience, but production deployments that inherit development configurations become vulnerable.

What Gets Flagged

# FLAGGED: Rails session cookie readable by script
Rails.application.config.session_store :cookie_store, key: "_shop_session", httponly: false
cookies[:auth_token] = { value: user.api_token, expires: 1.day.from_now }
// FLAGGED: ASP.NET cookie options with both flags off
Response.Cookies.Append("auth_token", token, new CookieOptions { HttpOnly = false, Secure = false });
o.Cookie.SecurePolicy = CookieSecurePolicy.None;
# FLAGGED: Spring session cookie flags in application.yml
server:
  servlet:
    session:
      cookie:
        http-only: false
        secure: false
// FLAGGED: no HttpOnly field on a cookie whose name is a parameter
cookie := http.Cookie{
	Name:  name,
	Value: value,
	Path:  "/",
}
// FLAGGED: secure and httponly passed as false
setcookie("auth_token", $token, time() + 3600, "/", "", false, false);

Not flagged: res.cookie('XSRF-TOKEN', req.csrfToken(), { httpOnly: false, secure: true }), res.cookie('theme', 'dark'), secure: process.env.NODE_ENV === 'production'.

Reported by the rule for that flag, not by VNX-SEC-013:

SESSION_COOKIE_SECURE = False                     # VNX-614
SESSION_COOKIE_HTTPONLY = False                   # VNX-1004
response.set_cookie("session_id", token)          # VNX-1004 (HttpOnly) and VNX-614 (Secure)
app.use(session({ cookie: { secure: false } }));  // VNX-614
res.cookie('token', token);                       // VNX-NODE-029 (HttpOnly) and VNX-614 (Secure)
cookie.setSecure(false);                          // VNX-614

Remediation

  1. Enable all three flags for session cookies in production. The goal is Set-Cookie: session=<value>; HttpOnly; Secure; SameSite=Strict.
# SAFE: Django secure cookie settings
SESSION_COOKIE_SECURE = True        # HTTPS only
SESSION_COOKIE_HTTPONLY = True      # not accessible to JavaScript
SESSION_COOKIE_SAMESITE = 'Strict'  # block CSRF
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = True
// SAFE: Express secure cookie configuration
app.use(session({
    secret: process.env.SESSION_SECRET,
    cookie: {
        secure: true,       // HTTPS only
        httpOnly: true,     // no JavaScript access
        sameSite: 'strict', // block CSRF
        maxAge: 3600000,    // 1 hour
    },
    resave: false,
    saveUninitialized: false,
}));
// SAFE: Spring Boot secure cookie configuration
@Configuration
public class SecurityConfig {
    @Bean
    public CookieSameSiteSupplier cookieSameSiteSupplier() {
        return CookieSameSiteSupplier.ofStrict();
    }
    // application.properties:
    // server.servlet.session.cookie.secure=true
    // server.servlet.session.cookie.http-only=true
    // server.servlet.session.cookie.same-site=strict
}
// SAFE: PHP secure session cookie parameters
session_set_cookie_params([
    'lifetime' => 3600,
    'path'     => '/',
    'secure'   => true,
    'httponly' => true,
    'samesite' => 'Strict',
]);
session_start();
  1. Use environment-aware configuration. Set Secure=true in production but allow false in local development only when the local server uses HTTP. Use environment variables to control this:
# SAFE: environment-aware cookie security
import os
SESSION_COOKIE_SECURE = os.environ.get('ENVIRONMENT') == 'production'
  1. Understand the three flag behaviours:

    • HttpOnly: Cookie is inaccessible to JavaScript, use for all session cookies
    • Secure: Cookie is only sent over HTTPS, required in production
    • SameSite=Strict: Cookie not sent on cross-site requests, strongest CSRF protection; use Lax if you need cookies sent on top-level navigation (e.g., OAuth redirects)
  2. Set SameSite=Lax as a minimum for session cookies if Strict breaks your login flow. None requires Secure to be set as well (browsers enforce this).

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-sec-013
// nosec vnx-sec-013

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

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