Minimal reproduction of CVE-2026-22732 — Spring Security HTTP response headers silently dropped when controller code writes directly to the servlet response.
Spring Security uses "lazy" header writing by default. When a controller writes to response.getOutputStream(), calls response.flushBuffer(), or sets Content-Length via setIntHeader(), the response is committed before Spring Security can inject its security headers (X-Frame-Options, X-Content-Type-Options, Cache-Control, Strict-Transport-Security, etc.).
CVSS 3.1: 9.1 (Critical) — no authentication or user interaction required.
- Spring Security 5.7.0–5.7.21, 5.8.0–5.8.23, 6.3.0–6.3.14, 6.4.0–6.4.14, 6.5.0–6.5.8, 7.0.0–7.0.3
src/main/java/com/example/vuln/
├── VulnApplication.java # Spring Boot entry point
├── SecurityConfig.java # Configures security headers (X-Frame-Options, CSP, etc.)
└── VulnController.java # 1 safe + 3 vulnerable endpoints
src/test/java/com/example/vuln/
└── HeaderVerificationTest.java # Tests that FAIL on vulnerable versions
| Endpoint | Vulnerable? | Trigger |
|---|---|---|
GET /safe |
No | Normal Spring MVC return |
GET /vuln/stream |
Yes | Writes to response.getOutputStream() |
GET /vuln/flush |
Yes | Calls response.flushBuffer() |
GET /vuln/content-length |
Yes | Sets Content-Length via setIntHeader() |
./mvnw spring-boot:runThen verify with curl:
# Safe — headers present
curl -i http://localhost:8080/safe
# Vulnerable — security headers MISSING
curl -i http://localhost:8080/vuln/stream
curl -i http://localhost:8080/vuln/flush
curl -i http://localhost:8080/vuln/content-length./mvnw testOn a vulnerable version, the vuln* tests will fail (missing headers).
On a patched version (6.5.9+ / 7.0.4+), all tests pass.
Update pom.xml to use a patched Spring Security version:
<spring-security.version>6.5.9</spring-security.version>