Safeguard
Vulnerability Analysis

CVE-2020-5398: Content-type bypass in Spring Framework

CVE-2020-5398 lets attackers bypass Spring Framework RFD protections via Content-Disposition, tricking browsers into downloading malicious files.

Aman Khan
AppSec Engineer
7 min read

CVE-2020-5398 is a reflected file download (RFD) vulnerability in the Spring Framework, caused by a Spring Framework content type bypass in how ContentDisposition.Builder#filename() builds the Content-Disposition response header. When a Spring MVC or Spring WebFlux application derives a filename for that header from unsanitized, user-supplied input, an attacker can craft a URL that tricks a victim's browser into downloading — and in some cases auto-executing — a file with an attacker-chosen name and extension, even though the server never intended to serve that content type. The practical impact is client-side code execution or malicious file delivery riding on the trust of a legitimate domain, which makes RFD a favorite technique for phishing and drive-by malware campaigns that piggyback on real, high-reputation sites.

RFD attacks are less well known than classic reflected XSS, but they follow the same trust-transfer logic: because the malicious download appears to originate from a trusted domain (a bank, an internal tool, a SaaS vendor), users and even some security software are far more willing to open it. Spring Framework had already shipped generic RFD protections years earlier; CVE-2020-5398 is significant because it shows a bypass of the framework's own defensive header-building logic, not a brand-new class of bug.

Affected versions and components

The vulnerability lives in Spring Framework's core HTTP support (org.springframework.http.ContentDisposition) and affects any application — Spring MVC (servlet stack) or Spring WebFlux (reactive stack) — that uses ContentDisposition.Builder#filename() with US_ASCII or the default encoding to build a Content-Disposition header from request-derived data, most commonly to drive a file-download endpoint.

According to Spring's own advisory and mirrored vulnerability databases, the affected branches are:

  • Spring Framework 5.2.0 through 5.2.2
  • Spring Framework 5.1.0 through 5.1.12
  • Spring Framework 5.0.0 through 5.0.15

The issue was fixed in:

  • Spring Framework 5.2.3
  • Spring Framework 5.1.13
  • Spring Framework 5.0.16

Exploitation requires several conditions to line up: the application builds a Content-Disposition filename from attacker-influenced input, it uses the vulnerable encoding path, and the response body can be steered to contain attacker-controlled content. That combination is common in generic "export," "download," or "attachment" endpoints that echo a filename query parameter back into the response headers — a pattern found across a large number of enterprise Java applications built on Spring Boot and Spring MVC.

CVSS, EPSS, and KEV context

CVE-2020-5398 carries a CVSS v3 base score of 7.5 (High), with the vector AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H — network-exploitable and requiring no privileges, but requiring victim interaction and non-trivial attack complexity, since the attacker has to lure a user into clicking a crafted link and the exact bypass payload depends on framework internals. The legacy CVSS v2 score is also 7.5.

What stands out more than the base score is the vulnerability's EPSS (Exploit Prediction Scoring System) signal: current EPSS data places CVE-2020-5398 around the 99.7th percentile for predicted near-term exploitation activity — scored as more likely to see attacker activity than the vast majority of tracked CVEs. That's a notable finding for a vulnerability that is several years old, and a reminder that "old" and "low risk" are not synonyms: RFD-style bugs stay attractive because they're cheap to weaponize and rely on abusing trust in a legitimate domain rather than compromising the server itself. CVE-2020-5398 does not currently appear on CISA's Known Exploited Vulnerabilities (KEV) catalog based on publicly available KEV data, so there's no confirmed record of in-the-wild exploitation tracked by CISA — but the elevated EPSS score suggests defenders shouldn't read that absence as license to deprioritize remediation, especially on internet-facing download endpoints still running unpatched Spring Framework versions.

Timeline

  • Discovery and reporting: The issue was privately reported to the Spring security team by Roman Shalymov of EPAM's research team, who found that the framework's own RFD-mitigation logic in ContentDisposition could be bypassed.
  • January 2020: Spring published its security advisory alongside patched releases, and the issue was assigned CVE-2020-5398 and entered into the NVD.
  • Patched releases: Spring Framework 5.2.3, 5.1.13, and 5.0.16 shipped with the fix, hardening how filenames are encoded when building Content-Disposition headers.
  • Downstream advisories: Because Spring Framework underpins a huge share of the Java ecosystem, downstream distributions and platforms — including Red Hat's middleware products, Oracle's quarterly Critical Patch Updates, Ubuntu's package advisories, and various API gateway and integration products bundling Spring — issued their own follow-on advisories and patches over the following months as vendors worked through their own release cycles.
  • Present day: The CVE remains catalogued in NVD and vulnerability databases, and continues to be surfaced by software composition analysis (SCA) tooling whenever a scan encounters an unpatched Spring Framework dependency in the 5.0.x, 5.1.x, or 5.2.x lines.

Remediation steps

  1. Upgrade Spring Framework. Move to 5.2.3, 5.1.13, 5.0.16, or later within your major/minor line. If you're on Spring Boot, upgrading the parent Boot version to one that pulls in a patched Spring Framework version is the simplest path — check your effective dependency tree rather than trusting the version pinned in your build file, since transitive dependencies can silently reintroduce a vulnerable Spring Framework artifact.
  2. Audit every use of ContentDisposition.Builder. Search your codebase for ContentDisposition.builder(...), .filename(...), and any hand-rolled Content-Disposition header construction. Confirm none of them pass unsanitized request parameters, headers, or path variables directly into the filename.
  3. Avoid the vulnerable encoding path. If you cannot upgrade immediately, review whether your filename-building code uses US_ASCII or default encoding and move to the safer, standards-compliant encoding options Spring provides in the patched versions.
  4. Validate and allowlist filenames server-side. Never trust a filename end-to-end from user input. Strip or reject control characters, path separators, and unexpected extensions before they reach any response header.
  5. Re-scan after patching. Confirm the fix actually landed in your deployed artifact — not just your source repository — since Spring Framework is frequently pulled in transitively by other libraries (data access frameworks, API gateways, admin consoles) that may pin their own, older version.
  6. Treat this as a software composition problem, not just a code review problem. Because the vulnerable code lives inside a widely reused dependency rather than application logic, teams that rely solely on manual code review or SAST scanning of their own code are likely to miss it. This is squarely an SCA and SBOM visibility issue.

How Safeguard Helps

CVE-2020-5398 is a textbook example of why supply chain visibility matters as much as your own application's security posture: the vulnerable logic sits inside Spring Framework itself, several layers below the code your team wrote, and it can be reintroduced silently through a transitive dependency upgrade — or downgrade — that nobody explicitly reviewed.

Safeguard's software supply chain security platform is built to catch exactly this class of risk before it reaches production:

  • Continuous SBOM generation and dependency graph analysis identify every module in your build — direct and transitive — that pulls in an affected Spring Framework version, even when it's buried several layers deep in your dependency tree.
  • Vulnerability correlation against CVE, CVSS, and EPSS data means Safeguard doesn't just flag that a component is "outdated" — it surfaces that CVE-2020-5398 carries an unusually high EPSS percentile, helping your team prioritize the Spring Framework content type bypass fix ahead of lower-signal findings sitting in the same backlog.
  • Policy-driven build gating lets you block CI/CD pipelines from shipping artifacts that resolve to a known-vulnerable Spring Framework version, closing the gap where a routine dependency bump silently reintroduces a patched vulnerability.
  • Drift and provenance monitoring alert your team the moment a build's resolved dependency tree changes from what was last verified, so a transitive downgrade back into the 5.0.x-5.2.2 vulnerable range doesn't slip through unnoticed.
  • Actionable remediation guidance maps each finding to the specific fixed version and flags risky ContentDisposition usage patterns in your own code, cutting the time between "we have a vulnerable dependency" and "we shipped the fix."

For teams running large Spring-based estates, the lesson of CVE-2020-5398 isn't just "patch this one CVE" — it's that continuous, automated dependency visibility is the only reliable way to keep pace with vulnerabilities that live inside the frameworks your applications depend on every day. Safeguard is built to make that visibility continuous, prioritized, and actionable, rather than a once-a-quarter scanning exercise.

Never miss an update

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