PoC Archive PoC Archive
Critical CVE-2026-22732 unpatched

Spring Security Lazy Header Writing Security Header Bypass (CVE-2026-22732)

by Drew Dennison / semgrep (GitHub: semgrep) · 2026-07-05

CVSS 9.1/10
Severity
Critical
CVE
CVE-2026-22732
Category
web
Affected product
Spring Security (Spring Boot applications)
Affected versions
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
Disclosed
2026-07-05
Patch status
unpatched

Metadata

FieldValue
Date Added2026-07-05
Last Updated2026-04
Author / ResearcherDrew Dennison / semgrep (GitHub: semgrep)
CVE / AdvisoryCVE-2026-22732
Categoryweb
SeverityCritical
CVSS Score9.1 (CVSSv3.1, per source README)
StatusPoC
Tagsspring-security, spring-boot, security-headers, response-splitting, x-frame-options, hsts, java, junit
RelatedN/A

Affected Target

FieldValue
Software / SystemSpring Security (Spring Boot applications)
Versions Affected5.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
Language / PlatformJava (Spring Boot / Spring Security)
Authentication RequiredNo
Network Access RequiredYes

Summary

CVE-2026-22732 affects Spring Security’s default “lazy” header-writing mechanism, which normally injects security-related response headers (X-Frame-Options, X-Content-Type-Options, Cache-Control, Strict-Transport-Security, etc.) just before the HTTP response is committed. If controller code writes directly to response.getOutputStream(), calls response.flushBuffer(), or sets Content-Length via setIntHeader(), the response is committed before Spring Security’s header writer runs, so all of these protective headers are silently dropped. The included demo Spring Boot application defines one safe endpoint (/safe) and three vulnerable endpoints (/vuln/stream, /vuln/flush, /vuln/content-length) that each trigger the early-commit condition, plus a JUnit test suite that fails on vulnerable versions (headers missing) and passes once Spring Security is upgraded to a patched release. No authentication or user interaction is required to observe or exploit the missing-header condition on any endpoint that streams data or sets response headers early — this is a common pattern for file downloads, streaming APIs, and manual JSON responses.


Vulnerability Details

Root Cause

Spring Security’s HeaderWriterFilter writes security headers lazily, immediately before the response commits; certain servlet API calls made directly by application code (getOutputStream() writes, flushBuffer(), setIntHeader("Content-Length", ...)) commit the response earlier than expected, causing the header writer to be skipped entirely for that response.

Attack Vector

  1. Identify a Spring Boot endpoint backed by vulnerable Spring Security versions that streams a file, flushes the response manually, or sets Content-Length directly (common in download/streaming/manual-JSON endpoints).
  2. Send a normal HTTP request to that endpoint.
  3. Observe that expected security headers (X-Frame-Options, X-Content-Type-Options, Cache-Control, HSTS, etc.) are absent from the response, even though SecurityConfig explicitly configures them.
  4. Chain the missing headers with a separate client-side vector appropriate to the dropped protection — e.g., clickjacking via missing X-Frame-Options, MIME-sniffing attacks via missing X-Content-Type-Options, or downgrade/cookie theft via missing HSTS.

Impact

Silent removal of critical defense-in-depth response headers on affected endpoints, increasing exposure to clickjacking, MIME-sniffing, caching of sensitive responses, and transport-downgrade attacks, without any indication in the response that protections are missing.


Environment / Lab Setup

Target:   Spring Boot application using an affected Spring Security version
Attacker: curl / any HTTP client; Java 17+ and Maven (via ./mvnw) to run the demo locally

Proof of Concept

PoC Script

See src/main/java/com/example/vuln/VulnController.java, SecurityConfig.java, and the test in src/test/java/com/example/vuln/HeaderVerificationTest.java in this folder.

1
2
3
4
5
./mvnw spring-boot:run
curl -i http://localhost:8080/safe             # headers present
curl -i http://localhost:8080/vuln/stream      # security headers MISSING
curl -i http://localhost:8080/vuln/flush       # security headers MISSING
curl -i http://localhost:8080/vuln/content-length  # security headers MISSING

Running the app and diffing curl -i output between /safe and the three /vuln/* endpoints shows the configured security headers present on /safe but absent on all three vulnerable endpoints; ./mvnw test runs HeaderVerificationTest, which fails on vulnerable Spring Security versions and passes once upgraded to 6.5.9+ / 7.0.4+.


Detection & Indicators of Compromise

Signs of compromise:

  • Automated header-scanning (e.g., securityheaders.com-style checks) reporting inconsistent header presence across endpoints of the same Spring Boot application
  • Application code review revealing direct response.getOutputStream(), flushBuffer(), or setIntHeader("Content-Length", ...) calls in controller methods
  • Reports of clickjacking or MIME-sniffing issues limited to specific streaming/download endpoints while other endpoints are unaffected

Remediation

ActionDetail
Primary fixUpgrade Spring Security to 6.5.9+ or 7.0.4+ (or the corresponding patched release for your branch)
Interim mitigationForce eager header writing by setting HeaderWriterFilter.setShouldWriteHeadersEagerly(true) via an ObjectPostProcessor, as shown (commented out) in SecurityConfig.java

References


Notes

Mirrored from https://github.com/semgrep/cve-2026-22732-demo on 2026-07-05.