HIGH api key exposurenestjssession cookies

Api Key Exposure in Nestjs with Session Cookies

Api Key Exposure in Nestjs with Session Cookies — how this specific combination creates or exposes the vulnerability

Storing API keys in session cookies within a NestJS application can unintentionally expose secrets when session handling is misconfigured. When an API key is placed in a session cookie, it becomes accessible to any code that can read or intercept that cookie. If the cookie is not marked as HttpOnly, a client-side script can read it via JavaScript, enabling cross-site scripting (XSS) attacks to steal the key. If the cookie is not set with Secure and SameSite attributes, it may be transmitted over unencrypted channels or be vulnerable to cross-site request forgery (CSRF) and other injection paths.

Session cookies typically persist for the duration of a browser session or beyond, depending on their TTL. If an API key is stored in such a cookie and the session is long-lived, the exposure window increases. For example, an attacker who gains access to browser storage or network traffic could extract the key and misuse it to call downstream services. Unlike bearer tokens in Authorization headers, session cookies are automatically sent by the browser with each request to the same domain, which can lead to unintended exposure if the application does not enforce strict transport security and scope boundaries.

NestJS applications often use cookie-based sessions via libraries like express-session or NestJS adapters. If these sessions are configured without proper security flags, the API key stored in the cookie may be transmitted in cleartext over HTTP when Secure is not enforced. Additionally, if the application does not validate the origin of requests or enforce strict CORS policies, an attacker may be able to trick a user’s browser into sending session cookies containing the key to a malicious site. This can lead to unauthorized access to backend services that rely on the exposed API key.

Another vector involves server-side logging or error handling. If session data containing API keys is inadvertently included in logs, debugging output, or crash reports, the key can be exposed to unauthorized personnel or exfiltrated through log-injection vulnerabilities. Even when HttpOnly is set, poor key rotation practices combined with long cookie lifetimes increase the risk of prolonged exposure. Therefore, treating session cookies as a potential storage mechanism for highly sensitive secrets like API keys requires careful design around encryption, scope limitation, and lifecycle management.

Session Cookies-Specific Remediation in Nestjs — concrete code fixes

To reduce exposure when using session cookies in NestJS, apply strict cookie attributes and avoid storing highly sensitive values such as raw API keys directly in the cookie. Instead, store a session identifier and keep the API key server-side, tied to that session in a secure store.

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as session from 'express-session';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  app.use(session({
    secret: process.env.SESSION_SECRET || 'change-this-to-a-secure-random-value',
    name: 'sid', // custom session name to obscure default identifiers
    cookie: {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production', // enforce HTTPS in production
      sameSite: 'strict', // or 'lax' if cross-site usage is required
      maxAge: 1000 * 60 * 30, // 30 minutes
      path: '/api', // restrict cookie scope to API routes
    },
    resave: false,
    saveUninitialized: false,
  }));

  await app.listen(3000);
}
bootstrap();

Use server-side session storage to keep API keys out of cookies entirely. For example, store the key in memory, a cache, or a database keyed by the session ID, and only return a non-sensitive reference to the client as part of the cookie.

// Example: storing API key server-side, not in the cookie
app.use(session({
  store: new (require('connect-redis')(session))({
    client: require('redis').createClient({ url: process.env.REDIS_URL }),
  }),
  cookie: {
    httpOnly: true,
    secure: true,
    sameSite: 'strict',
  },
}));

// In a controller or service, associate session ID with API key
const sessionId = req.sessionID;
sessionStore.set(`sess:${sessionId}:apiKey`, process.env.EXTERNAL_API_KEY, 3600);

Rotate API keys regularly and bind them to the session lifecycle so that keys are not long-lived. Implement middleware to validate the origin and integrity of requests that rely on session cookies, and ensure that all API interactions use HTTPS to prevent interception. These practices reduce the likelihood that an exposed session cookie leads to compromise of the underlying API key.

Frequently Asked Questions

Is it safe to store an API key directly in a session cookie in NestJS?
No. Storing an API key directly in a session cookie increases the risk of exposure through XSS, insecure transmission, or logging. Use server-side storage and keep only a session identifier in the cookie.
What cookie settings help protect session cookies in NestJS?
Set httpOnly, secure (in production), sameSite to 'strict' or 'lax', limit the path to '/api', and use short maxAge values to reduce exposure windows.