RedScore.ai

Fixes

Cookie & Privacy Hygiene · Updated 2026-05-02

Secure Flag Audit

Set Secure on every cookie. Session cookies missing Secure fail; non-session missing warns. Fix in your framework's session config.

The Secure flag on a cookie tells the browser to only send that cookie over HTTPS connections. Without it, a cookie set on https://yourdomain.tld is also sent over plain http://, where any network observer can read it. For session cookies (auth tokens, login state), this is the difference between safe transport and account takeover via passive sniffing on a hotel wifi or an ISP-level adversary.

RedScore parses every cookie set in first-response Set-Cookie headers across primary hosts and audits the Secure flag. Session cookies missing Secure are scored harder than other cookies, because they directly carry authentication.

How the check works

Per primary host, the check tallies cookies missing Secure and splits them by whether the cookie name looks like a session cookie (heuristic match against common patterns: "session", "sessid", "sess", "auth", "jwt", "token", framework-specific names like "connect.sid", "_csrf", etc.). The host score:

  • 1.0 (full credit): every cookie has Secure.
  • 0.5 (partial): no session cookies missing Secure, but at least one non-session cookie missing it. Reason: COOKIE_SECURE_NONSESSION_MISSING.
  • 0.0 (zero): at least one session cookie missing Secure. Reason: COOKIE_SECURE_SESSION_MISSING.

Per-host scores are weighted (apex highest) and averaged across all primary hosts to produce the category score (34 pts possible).

How the verdict maps to evidence

  • Pass: all cookies on every primary host have Secure.
  • Warn: at least one non-session cookie missing Secure on at least one host.
  • Fail: at least one session cookie missing Secure on at least one host.

Evidence shows host_rows with each host's parsed cookies, the Secure flag state, and which cookies (if any) tripped which reason code.

Fix: set Secure on every cookie

There is no downside to setting Secure on every cookie when your site is HTTPS-only (which it should be; see HTTPS Consistency). The fix is per-framework configuration, usually a one-line setting.

Per-framework snippets

Express / Node.js (express-session)

import session from "express-session";

app.use(session({
  secret: process.env.SESSION_SECRET,
  cookie: {
    secure: true,        // Secure flag
    httpOnly: true,      // (covered in HttpOnly Audit)
    sameSite: "lax",     // (covered in SameSite Audit)
    maxAge: 1000 * 60 * 60 * 8,
  },
}));

// In dev (HTTP), set secure: false or use 'auto' if you have proxy trust set up.

Django

# settings.py
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

# Both default to False in Django; flip explicitly for production.

Rails

# config/environments/production.rb
Rails.application.config.session_store :cookie_store,
  key: "_yourapp_session",
  secure: true,
  httponly: true,
  same_site: :lax

# Or globally enforce HTTPS (sets Secure on session, CSRF, and cookies):
config.force_ssl = true

ASP.NET Core

// Program.cs (or Startup.ConfigureServices)
services.Configure<CookiePolicyOptions>(options => {
    options.Secure = CookieSecurePolicy.Always;
});

services.AddSession(options => {
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});

Spring Boot

# application.properties
server.servlet.session.cookie.secure=true
server.servlet.session.cookie.http-only=true
server.servlet.session.cookie.same-site=lax

Laravel

// config/session.php
'secure' => env('SESSION_SECURE_COOKIE', true),
'http_only' => true,
'same_site' => 'lax',

Plain Set-Cookie header

Set-Cookie: session_id=abc123; Path=/; Secure; HttpOnly; SameSite=Lax

__Secure- prefix for higher assurance

Cookies whose name starts with __Secure- are required by browsers to be sent only with the Secure attribute set; setting one without Secure causes the browser to reject the Set-Cookie outright. Use this prefix as a self-policing safety net for any high-sensitivity cookie:

Self-policing session cookie

Set-Cookie: __Secure-session=abc123; Path=/; Secure; HttpOnly; SameSite=Lax

Verify the fix

  • curl -sI -c /dev/null https://yourdomain.tld | grep -iE 'set-cookie' shows the Set-Cookie headers your server returns. Confirm every cookie has the Secure attribute.
  • Open the page in a browser, open DevTools → Application → Cookies → yourdomain.tld. Check the "Secure" column for every cookie.
  • Try loading the same page over HTTP (curl http://yourdomain.tld even if it redirects). Confirm no cookies are sent in the redirect's Set-Cookie that your HTTPS site sets with Secure.
  • Re-run the RedScore lookup. Pass requires Secure on every cookie across every primary host.

Common pitfalls

  • Dev mode override that ships to prod. Many frameworks use Secure=true conditionally based on environment. If the production env var is wrong (NODE_ENV=development by accident), Secure stays off in production. Verify with curl in production after every deploy.
  • Behind a TLS-terminating proxy. If your origin sees plain HTTP from the proxy, the framework may refuse to set Secure (because "connection isn't secure from origin's view"). Configure proxy trust and the X-Forwarded-Proto header so the framework knows the original request was HTTPS. Express: app.set("trust proxy", 1). Django: SECURE_PROXY_SSL_HEADER. Rails: config.force_ssl = true.
  • Third-party scripts setting cookies without Secure. Analytics, ads, embedded widgets all set their own cookies via JavaScript or via their own Set-Cookie. If they ride on your domain (first-party), they show up in this audit. Either configure the third-party to set Secure, or accept the warn.
  • Cookie set on HTTP page, then carried to HTTPS. Some legacy auth flows set a cookie on a non-HTTPS step (typo, redirect chain). The cookie is never marked Secure. Audit redirect chains: every Set-Cookie should occur on the HTTPS leg.
  • Manually-coded Set-Cookie in app code. A custom Set-Cookie header that bypasses your framework's session middleware can miss Secure. Grep your codebase for direct Set-Cookie writes and add the attribute.
  • Cookies without Domain attribute. Host-only cookies do not have the same exposure as parent-domain cookies, but Secure is still required to keep them off HTTP requests. There is no "safe to skip Secure" case on an HTTPS site.

What to do next

See how these recommendations apply to your site's current scan results.

Scan domain