Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
rewrite-cve-2026-22732 — OpenRewrite recipe that detects and fixes Spring Security header suppression (CVE-2026-22732) by identifying Content-Length header misuse and generating eager header-writing configuration. | Kitploit
Tools/GitHubGitHub/moderneinc/rewrite-cve-2026-22732
Static AnalysisVulnerability AnalysisCode AnalysisWeb SecurityDevSecOps
GitHubmoderneinc/rewrite-cve-2026-22732

rewrite-cve-2026-22732

OpenRewrite recipe that detects and fixes Spring Security header suppression (CVE-2026-22732) by identifying Content-Length header misuse and generating eager header-writing configuration.

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
View Repository
3611 days agoNot yet reviewed
Share

rewrite-cve-2026-22732

OpenRewrite recipe that detects code susceptible to CVE-2026-22732, a Spring Security defect where setting Content-Length through one of three response methods bypasses Spring Security's OnCommittedResponseWrapper. Because the wrapper never sees the header, onResponseCommitted() never fires, and the lazy-added security headers (X-Frame-Options, X-Content-Type-Options, Cache-Control, etc.) are silently dropped.

What it finds

The actual triggers, confirmed against vulnerable Spring Security 6.4.12 with Spring Boot 3.4.3 / embedded Tomcat:

  1. Servlet Content-Length via the wrapper-bypassing overloads

    response.setHeader("Content-Length", "42");
    response.setIntHeader("Content-Length", 42);
    response.addIntHeader("Content-Length", 42);
    

    These three overloads are not overridden in OnCommittedResponseWrapper. Subsequent body writes complete the declared length and the container commits without firing the lazy header writer.

  2. WebFlux Content-Length via HttpHeaders

    serverHttpResponse.getHeaders().set("Content-Length", "42");
    serverHttpResponse.getHeaders().add("Content-Length", "42");
    serverHttpResponse.getHeaders().setContentLength(42L);
    
  3. WebFlux unconditional response commits

    serverHttpResponse.writeWith(Mono.just(dataBuffer));
    serverHttpResponse.writeAndFlushWith(publisher);
    serverHttpResponse.setComplete();
    

The recipe is gated on Spring Security presence — it emits nothing in files that don't reference any org.springframework.security.* type — and on affected Spring Security version ranges. Per the Spring advisory published 2026-03-19, the affected ranges and fix versions are:

SeriesAffectedFixed
5.7.x5.7.0 – 5.7.215.7.22 (Enterprise)
5.8.x5.8.0 – 5.8.235.8.24 (Enterprise)
6.3.x6.3.0 – 6.3.146.3.15 (Enterprise)
6.4.x6.4.0 – 6.4.146.4.15 (Enterprise)
6.5.x6.5.0 – 6.5.86.5.9 (OSS)
7.0.x7.0.0 – 7.0.37.0.4 (OSS)

Projects resolving a Spring Security version at or above the fix in its series (or on any future series past 7.0 / 6.5) are treated as unaffected and receive no per-sink or per-file markers. Projects where the version can't be resolved fall through to the usual pattern-based detection so a scanner errs toward reporting a finding it can't disprove. The SpringSecurityVersionByProject data table still records the resolved version and flags each project as affected or not, so you can audit what was filtered.

What is intentionally NOT flagged

These look dangerous but are wrapper-tracked, so security headers are written before the response commits:

CodeWhy it's safe
response.setContentLength(int) / setContentLengthLong(long)Overridden — wrapper records the declared length and fires onResponseCommitted() when the body completes.
response.flushBuffer()Overridden — calls doOnResponseCommitted() before super.flushBuffer().
response.getOutputStream().write(..) / flush() / close()Returns SaveContextServletOutputStream; every write/flush/close fires doOnResponseCommitted() before delegating.
response.getWriter().write(..) / print(..) / println(..) / flush() / close()Returns SaveContextPrintWriter; same pattern.
response.addHeader("Content-Length", v)Special-cased in the wrapper — routed through setContentLength(long).

The Semgrep demo's /vuln/flush endpoint claims flushBuffer() is the trigger, but on a vulnerable Spring Security 6.4.12 the response actually returns all six security headers. The real triggers in the demo are the setIntHeader("Content-Length", ...) calls in /vuln/stream and /vuln/content-length.

Finding

Run this one:

RecipePurpose
io.moderne.recipe.cve202622732.FindSpringSecurityHeaderSuppressionRuns every detection and emits the version report table

Building blocks (advanced)

The aggregator above is composed of two smaller recipes. You can invoke them individually if you want only one detection.

RecipePurpose
io.moderne.recipe.cve202622732.FindHttpResponseContentLengthHeaderTaint-flow for "Content-Length" literal reaching setHeader / setIntHeader / addIntHeader (servlet) or HttpHeaders.set / add (WebFlux)
io.moderne.recipe.cve202622732.FindHttpResponseContentLengthOrFlushBufferWebFlux unconditional commits: writeWith, writeAndFlushWith, setComplete, HttpHeaders.setContentLength

Fixing

Run this one:

RecipePurpose
io.moderne.recipe.cve202622732.FixSpringSecurityHeaderSuppressionPicks the cheapest remediation each project can actually take

It runs two steps in order.

1. Bump to the fix on the project's own series. Spring Security published the fix as 6.5.9 and 7.0.4 on Maven Central. Each bump is gated on a FindAffectedSpringSecuritySeries precondition, because UpgradeDependencyVersion only checks that its target is newer — told to go to 7.0.4 it would happily drag a 5.8 project across two major versions.

2. Add an eager header-writing configuration to whatever step 1 could not fix. This generates one @Configuration class per project:

@Bean
public static BeanPostProcessor eagerHeaderWriterFilterBeanPostProcessor() {
    return new BeanPostProcessor() {
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (bean instanceof HeaderWriterFilter) {
                ((HeaderWriterFilter) bean).setShouldWriteHeadersEagerly(true);
            }
            return bean;
        }
    };
}

Writing the headers up front makes it irrelevant whether the wrapper ever observes the commit, so this closes every sink in the project at once — including the ones taint analysis can't reach, like the Map flow under "Known limitations". The BeanPostProcessor sees filters built by the HttpSecurity DSL because AutowireBeanFactoryObjectPostProcessor initialises them through the bean factory. Two independently published fixes for this CVE use exactly this shape (hmcts/idam-web-public, and armory-io's Spinnaker forks via the equivalent ObjectPostProcessor).

Step 2 is what covers the projects step 1 cannot help:

SituationWhy the bump doesn't work
5.7, 5.8, 6.3, 6.4Fix ships to Spring Enterprise subscribers only — not on Maven Central
6.0 - 6.2No fix was ever released on those series
Version managed by an imported BOMNothing is declared locally for the bump to edit

That last row is not a corner case. nla/bamboo resolves 7.0.3 — a series with an open-source fix — entirely from the Spring Boot BOM, so a version check alone would skip it under both steps and leave it vulnerable. AddEagerHeaderWriterConfiguration therefore only defers to the upgrade when the project both has an open-source fix available and declares a version of its own.

The generated class is placed next to an @EnableWebSecurity class where one exists, falling back to @SpringBootApplication and then any @Configuration, so it always lands somewhere component scanning reaches. Projects that already write headers eagerly, or that vendor a patched OnCommittedResponseWrapper (as jogetworkflow/jw-community does), are left alone.

Building blocks (advanced)

Download Tool