Safeguard
Vulnerability Analysis

Spring Security authorization rule bypass (CVE-2023-34035)

CVE-2023-34035 lets Spring Security's requestMatchers() silently mis-evaluate authorization rules in multi-servlet apps. Here's the fix and how to detect exposure.

James
Principal Security Architect
8 min read

In July 2023, the Spring Security team disclosed CVE-2023-34035, an authorization rule bypass affecting one of the most widely deployed access-control frameworks in the Java ecosystem. The flaw doesn't stem from a coding error in Spring Security's cryptography or session handling — it's subtler and arguably more dangerous: applications that mix multiple servlets behind Spring Security, and that define authorization rules using requestMatchers(String) or requestMatchers(HttpMethod, String), can end up with access-control rules that silently don't apply to the requests they were written to protect. An endpoint that a developer believes is locked down to ROLE_ADMIN can, under the right servlet configuration, be reachable by anyone. For teams running Spring Boot applications with any non-trivial servlet topology — actuator endpoints, GraphQL servlets, gRPC bridges, or legacy Struts/JSP handlers alongside Spring MVC's DispatcherServlet — this is exactly the kind of defect that turns a routine dependency bump into an incident-response exercise.

What went wrong

Spring Security's requestMatchers(String) overload is a convenience method: pass it a path pattern like /admin/** and it infers, at configuration time, which RequestMatcher implementation to build based on what's on the classpath. If Spring MVC is present, it assumes the pattern should be interpreted the way Spring MVC's DispatcherServlet would interpret it — using MVC's own path-matching semantics (MvcRequestMatcher), which account for servlet path prefixes, path parameters, and suffix patterns the way the MVC framework does.

That inference breaks down the moment an application registers more than one servlet under Spring Security's protection — for example, mapping DispatcherServlet to /app/* while also running a separate servlet (a metrics endpoint, a custom RPC servlet, a legacy servlet) mapped to a different path. In that scenario, requestMatchers(String) may still build an MvcRequestMatcher that only correctly evaluates requests destined for the MVC servlet. Requests routed to the other servlet — which don't go through DispatcherServlet's handler-mapping logic at all — can be evaluated against a mismatched or overly permissive interpretation of the same path pattern. The net effect: a rule written as "require ROLE_ADMIN for /admin/**" can fail to constrain requests that are technically served by a different servlet but share the same URL space, letting unauthenticated or under-privileged requests reach code paths the developer intended to gate.

This is not a payload-based exploit with a memorable proof-of-concept string — it's a configuration-inference bug. That makes it harder to detect via traditional signature-based scanning and easier to miss in code review, because the vulnerable configuration looks correct. The requestMatchers(String) call reads exactly like the "right" way to write a Spring Security rule, per years of tutorials and Spring's own prior documentation.

Affected versions and components

CVE-2023-34035 affects:

  • Spring Security 5.8.0 through 5.8.4
  • Spring Security 6.0.0 through 6.0.4
  • Spring Security 6.1.0 through 6.1.1

An application is only exploitable when all of the following are true simultaneously:

  1. Spring MVC is present on the application's classpath.
  2. Spring Security is configured to secure more than one servlet in the same application — with at least one of them being Spring MVC's DispatcherServlet.
  3. The application's security configuration uses requestMatchers(String) or requestMatchers(HttpMethod, String) to define authorization rules (rather than explicit matcher types).

Single-servlet Spring Boot applications — the majority of greenfield services — are generally not affected, which is part of why this CVE didn't generate the alarm of, say, a Log4Shell. But "majority of greenfield services" is not the same as "your production estate." Multi-servlet setups are common in older Spring applications migrated forward, in services that expose both REST and legacy SOAP/servlet endpoints, and in platforms bolting on separate servlets for health checks, metrics, or admin tooling. Fixed versions are 5.8.5, 6.0.5, and 6.1.2.

Severity context: CVSS, EPSS, and KEV status

Severity scoring for this CVE is a useful lesson in why single-number risk ratings can mislead. NVD's automated scoring rates it CVSS 5.3 (Medium), reflecting a vector with high attack complexity and required conditions. VMware's CNA (the Spring maintainers' own assessment) scored it 7.3 (High), reflecting the fact that when the precondition is met, the impact is a full authorization bypass on a protected endpoint — a much more serious outcome than the "Medium" label suggests.

On exploit-probability metrics, EPSS places CVE-2023-34035 around 0.6%, roughly the 43rd percentile of scored vulnerabilities — a modest likelihood-of-exploitation score, consistent with a bug that requires a specific application topology rather than a universally exploitable default. It is not currently listed in CISA's Known Exploited Vulnerabilities (KEV) catalog, and there's no confirmed public evidence of in-the-wild exploitation as of this writing. Public discussion and reproduction guidance exist, but this is not (yet) a mass-exploited CVE.

The practical takeaway for security teams: don't triage this purely by its NVD score. A Medium CVSS score with a High CNA assessment, applied to a component that sits directly in your authorization path, deserves reachability analysis rather than a blanket "low priority, patch eventually" label. Context — specifically, whether your application actually meets the three preconditions above — matters far more here than the base score.

Timeline

  • Prior to July 2023 — Mouad Kondah of Kudelski Security identifies and privately reports the authorization inference flaw in requestMatchers(String) to the Spring Security team.
  • July 17, 2023 — Spring officially publishes the advisory and CVE-2023-34035, alongside patched releases 5.8.5, 6.0.5, and 6.1.2, and a companion mitigation guide with example fixes.
  • July 2023 onward — Downstream advisories propagate through GitHub Advisory Database (GHSA-4vpr-xfrp-cj64), NVD, and vendor vulnerability databases; Spring Boot dependency-management BOMs are updated to pull in patched Spring Security versions in subsequent Spring Boot point releases.
  • To date — No confirmed public reports of active exploitation; the CVE remains outside the CISA KEV catalog, but continues to surface in SCA and SBOM scans of applications pinned to pre-patch Spring Security versions.

Remediation

  1. Upgrade Spring Security immediately. Move to 5.8.5, 6.0.5, or 6.1.2 (or later). If you consume Spring Security transitively via Spring Boot, upgrade to a Spring Boot release whose dependency-management BOM pins a patched Spring Security version — check your resolved dependency tree rather than trusting the parent POM version alone.
  2. Audit for the vulnerable precondition. Search your codebase for requestMatchers(String ...) and requestMatchers(HttpMethod, String ...) calls in SecurityFilterChain / HttpSecurity configuration. Cross-reference against your servlet registrations — any application registering more than one servlet (check ServletRegistrationBean, web.xml, or embedded-container servlet mappings) alongside Spring MVC is a candidate for review.
  3. Switch to explicit matchers where multiple servlets exist. For endpoints served by Spring MVC's DispatcherServlet, use requestMatchers(new MvcRequestMatcher(...)) (or the newer PathPatternRequestMatcher builder in later Spring Security releases) explicitly. For endpoints served by other servlets, use requestMatchers(new AntPathRequestMatcher(...)). Don't rely on the string-based inference in mixed-servlet applications, even post-patch — the patched versions largely convert ambiguous configurations into a startup-time error rather than a silent bypass, which is safer but will require you to fix the configuration to get the application running at all.
  4. Add a regression test that asserts denial. Write an integration test that issues an unauthenticated or under-privileged request to every protected endpoint across every registered servlet, and asserts a 401/403. This catches both this class of bug and future authorization drift as the servlet topology evolves.
  5. Re-verify after the fix. Patching alone doesn't guarantee correctness — because the fix in 5.8.5/6.0.5/6.1.2 primarily converts silent misconfiguration into a startup failure, you need to actually resolve the flagged configuration, not just bump the version and assume it compiles cleanly.
  6. Extend the check to indirect consumers. If you maintain internal libraries or platform starter POMs that wrap Spring Security configuration for other teams, push the fix upstream in those shared components, not just in leaf applications — otherwise every consumer inherits the same exposure.

How Safeguard Helps

Manually auditing every SecurityFilterChain and servlet registration across a large Java estate for this exact combination of conditions is exactly the kind of high-noise, low-signal work that security teams don't have time for — which is why reachability matters more than raw dependency matching here. Safeguard's reachability analysis traces whether your application's actual call graph exercises the vulnerable requestMatchers(String) code path in a multi-servlet configuration, so you're not stuck triaging every Spring Security dependency hit as equally urgent. Griffin AI correlates that reachability signal with your SBOM inventory — generated automatically or ingested from existing CycloneDX/SPDX feeds — to flag which services genuinely meet all three exploitability preconditions versus which are theoretically affected but practically safe. For confirmed exposures, Safeguard can open an auto-fix pull request that bumps Spring Security (and, where relevant, the parent Spring Boot BOM) to a patched version and surfaces the flagged configuration lines for review, cutting the time from advisory to remediated code from days to minutes. That combination — precise reachability, AI-driven prioritization, and SBOM-grounded fix automation — is how Safeguard turns a Medium/High-severity configuration bug into a tracked, provably-closed finding instead of a permanent line item on a vulnerability backlog.

Sources:

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.