v0.14 is out: a mobile auth pack for Swift/iOS and Android, catching insecure token storage, cleartext traffic, and OAuth in embedded WebViews. Read more →
MEDIUM AI PREVALENCE: MEDIUM auth.express.cookie-insecure

An Express session cookie is explicitly configured as insecure.

Why AI tools produce this: AI coding tools produce this regularly, typically when prompted for a shortcut or a quick fix.

Why this matters

Setting secure: false lets the browser send the session cookie over plain HTTP, and httpOnly: false exposes it to document.cookie (any XSS reads it).

Either drop the flag (the framework default may still need hardening) or set secure: true and httpOnly: true for production. If you need insecure cookies in dev, gate the value on NODE_ENV !== 'production' rather than hard-coding false.

VULNERABLE
vulnerable.ts
import session from 'express-session';
import cookieSession from 'cookie-session';

const app = express();

// ruleid: auth.express.cookie-insecure
app.use(
  session({
    secret: process.env.SESSION_SECRET!,
    resave: false,
    saveUninitialized: false,
    cookie: { secure: false },
  }),
);

// ruleid: auth.express.cookie-insecure
app.use(
  session({
    secret: process.env.SESSION_SECRET!,
    cookie: { maxAge: 3600000, httpOnly: false },
  }),
);

// ruleid: auth.express.cookie-insecure
const middleware = expressSession({
  secret: process.env.SESSION_SECRET!,
  cookie: { secure: false, httpOnly: true },
});

// ruleid: auth.express.cookie-insecure
app.use(
  cookieSession({
    name: 'sess',
    keys: [process.env.SESSION_KEY!],
    secure: false,
  }),
);

// ruleid: auth.express.cookie-insecure
app.use(
  cookieSession({
    name: 'sess',
    keys: [process.env.SESSION_KEY!],
    httpOnly: false,
  }),
);
SAFE
safe.ts
import session from 'express-session';
import cookieSession from 'cookie-session';

const app = express();

// ok: auth.express.cookie-insecure -- both flags explicitly hardened
app.use(
  session({
    secret: process.env.SESSION_SECRET!,
    resave: false,
    saveUninitialized: false,
    cookie: { secure: true, httpOnly: true },
  }),
);

// ok: auth.express.cookie-insecure -- no `secure` key at all (undecidable dev vs prod, must NOT fire)
app.use(
  session({
    secret: process.env.SESSION_SECRET!,
    cookie: { maxAge: 3600000 },
  }),
);

// ok: auth.express.cookie-insecure -- gated on environment rather than hard-coded false
app.use(
  cookieSession({
    name: 'sess',
    keys: [process.env.SESSION_KEY!],
    secure: process.env.NODE_ENV === 'production',
  }),
);

// ok: auth.express.cookie-insecure -- res.cookie is covered by auth.cookie.* rules, not this one
app.get('/', (req, res) => {
  res.cookie('sid', 'abc', { secure: false });
  res.send('ok');
});

Suppressing this rule

If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.

// oauthlint-disable-next-line auth.express.cookie-insecure -- <reason>

References

https://github.com/expressjs/session#cookiesecure ↗https://github.com/expressjs/cookie-session#options ↗https://cwe.mitre.org/data/definitions/614.html ↗