logo

Database

Insecurely generated cookies - Secure

Need

Transmission of session cookies over encrypted connections only

Context

• Usage of Kotlin 1.9+ on the JVM for building web applications

• Usage of the javax.servlet API for cookies

Description

1. Non compliant code

import javax.servlet.http.Cookie
import javax.servlet.http.HttpServletResponse

fun addSessionCookie(response: HttpServletResponse, sessionId: String) {
    // Without Secure, the cookie is also sent over plain HTTP
    val cookie = Cookie("SESSIONID", sessionId).apply {
        isHttpOnly = true
        path = "/"...

The `addSessionCookie` function below creates the session cookie as `HttpOnly`, but without the `Secure` attribute. Without `Secure`, the browser also sends the cookie over plain HTTP. An attacker on the same network, such as a public Wi-Fi hotspot, can make the browser send a request to `http://` for the same domain, for example with an image tag on any page, and read the session cookie from the unencrypted traffic. With it, the attacker takes over the session. Setting `secure = false` explicitly, often done to make local development work over HTTP, has the same effect when it reaches production.

2. Steps

• Set `secure = true` on every `Cookie` that carries a session or authentication token before calling `addCookie`.

• Remove explicit `secure = false` assignments from code that reaches production.

• Configure container-managed session cookies with `server.servlet.session.cookie.secure=true`.

• Serve the application only over HTTPS and send a `Strict-Transport-Security` header.

3. Secure code example

import javax.servlet.http.Cookie
import javax.servlet.http.HttpServletResponse

fun addSessionCookie(response: HttpServletResponse, sessionId: String) {
    val cookie = Cookie("SESSIONID", sessionId).apply {
        isHttpOnly = true
        secure = true
        path = "/"...

The corrected function sets `secure = true`, so the browser only sends the cookie over HTTPS and it never travels in clear text. The cookie remains `HttpOnly`, so scripts cannot read it either. `Secure` protects the cookie, but the site should also be served only over HTTPS and send a `Strict-Transport-Security` header, so browsers do not make the first request in clear text. For local development over HTTP, a local TLS setup is safer than disabling the attribute in code that can be deployed. For container-managed sessions, the equivalent setting in Spring Boot is `server.servlet.session.cookie.secure=true`.