Imagine every door in your building can be jammed shut with a single envelope stuffed with too many pages
CVE-2025-48976 is a resource-exhaustion denial-of-service in Apache Commons FileUpload, the de-facto multipart/form-data parsing library for the Java ecosystem. The flaw is dead simple: the library hard-coded a 10 KB ceiling on per-part header sizes but imposed no limit on the number of parts or the number of headers per part. An attacker sends a single HTTP POST with thousands of parts, each carrying dozens of custom headers, and the server allocates memory for all of them until the JVM stalls. Affected versions span commons-fileupload 1.0 through 1.5.x and commons-fileupload2-core 2.0.0-M1 through 2.0.0-M3. Because Apache Tomcat bundles its own copy of this code, Tomcat 9.0.0.M1–9.0.105, 10.1.0.M1–10.1.41, and 11.0.0.M1–11.0.7 are independently affected under the sibling CVE-2025-48988.
The vendor's HIGH / 7.5 rating is honest and well-calibrated. This is unauthenticated, low-complexity, no-interaction DoS over the network — all the attack-path knobs are turned to maximum ease. What keeps it from CRITICAL is the impact ceiling: availability loss only, with no path to code execution, data exfiltration, or privilege escalation. A restart plus a WAF rule restores service. Given the 142,000+ Maven Central dependents on commons-fileupload 1.x alone, plus Tomcat's installed base, the exposure population is enormous — but the consequence per hit is bounded at service disruption.
4 steps from start to impact.
Identify multipart upload endpoint
multipart/form-data — file uploads, form submissions, API calls. No authentication or special knowledge is needed; a simple Content-Type probe or directory brute-force suffices. The endpoint only needs to invoke FileUpload.parseRequest() or Tomcat's built-in multipart parsing.- Target application exposes at least one multipart-capable endpoint
- Target is reachable over the network
- Endpoint may sit behind a CDN or WAF that enforces body-size or part-count limits
- Internal-only apps are unreachable from the internet
Craft malicious multipart payload
requests is required. The payload is deterministic — no brute-forcing, no race conditions, no heap grooming.- Attacker has network connectivity to the endpoint
- Payload is large (~tens of MB); bandwidth-constrained attackers may struggle at scale
- PoC defaults target Tomcat specifically; adaptation to other servlet containers is trivial but requires awareness
Send parallelized requests
- Target JVM has default or generous heap settings
- No reverse-proxy rate limiting in front of the application
- Enterprise load balancers (F5, HAProxy, Envoy) with connection-rate limits will throttle the flood
- Kubernetes pods with memory limits will OOMKill and restart, limiting sustained impact
- Tomcat
maxParameterCountormaxPartCount(if set) can cap part processing
Service denial achieved
- Steps 1–3 succeeded
- Auto-scaling or container restarts limit downtime window
- Geographic rate limiting or IP reputation blocking can cut off the attacker
The supporting signals.
| In-the-Wild Status | No confirmed active campaigns. Not on CISA KEV. However, EPSS 62.6% (99th percentile) signals extremely high exploitation probability — the statistical model expects widespread opportunistic scanning. |
|---|---|
| Proof of Concept | Public PoC by Samb102 on GitHub — Python script, weaponized with Docker lab. Fires 1,000 parallel multipart requests × 1,000 parts × 50 headers from 50 workers. Trivially adaptable. |
| EPSS | 0.62646 — 99th percentile. Among the highest-probability CVEs in the current window. |
| KEV Status | Not listed as of 2026-09-14. |
| CVSS Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H — Network attack, no auth, no interaction, availability-only impact. GHSA independently scored CVSS 4.0 at 8.7. |
| Affected Versions | commons-fileupload 1.0 – 1.5.x; commons-fileupload2-core 2.0.0-M1 – 2.0.0-M3. Also Tomcat 9.0.x ≤ 9.0.105, 10.1.x ≤ 10.1.41, 11.0.x ≤ 11.0.7 (via CVE-2025-48988). |
| Fixed Versions | commons-fileupload 1.6.0, commons-fileupload2-core 2.0.0-M4. Tomcat 9.0.106, 10.1.42, 11.0.8. |
| Exposure Data | Maven Central shows 142,000+ dependents on commons-fileupload 1.x. Tomcat is the world's most-deployed Java servlet container. Combined exposure is massive but the vulnerable parsing path requires an active multipart endpoint. |
| Disclosure Date | 2025-06-16, coordinated by the Apache Software Foundation. |
| Reporter | Not individually credited in the ASF advisory. Discovered during internal code review / community contribution. |
noisgate verdict.
The single most decisive factor is the availability-only impact ceiling — this is a pure DoS with no path to code execution, data access, or lateral movement, which caps the severity below CRITICAL despite trivial unauthenticated exploitation. The enormous installed base (142K+ Maven dependents, all supported Tomcat branches) and a weaponized public PoC at the 99th EPSS percentile justify maintaining — not downgrading — the vendor's HIGH rating.
Why this verdict
- Unauthenticated, zero-interaction, low-complexity network attack — every multipart endpoint in every affected Java app is a target. No friction on the attacker's side of the equation.
- Massive exposure population — commons-fileupload 1.x has 142K+ Maven Central dependents; Tomcat is independently affected across three major branches. This is not a niche library.
- Weaponized public PoC — Samb102's exploit is copy-paste ready with a Docker lab, and EPSS at the 99th percentile reflects the statistical expectation of mass scanning.
- Role multiplier: Commons FileUpload and Tomcat are used across every deployment role — workstations (dev), line-of-business apps, identity providers (Keycloak on Tomcat), CI/CD (Jenkins), and monitoring dashboards. A DoS against an IdP or CI server causes cascading outages, but the blast radius remains service unavailability, not compromise. Even in the worst high-value role scenario (IdP down → auth outage across the fleet), recovery is a restart, not a forensic investigation. This keeps the floor at HIGH, not CRITICAL.
- Impact ceiling is availability-only — CVSS C:N/I:N/A:H. No memory corruption, no arbitrary write, no deserialization chain. The vulnerability cannot be upgraded to RCE by chaining with other primitives.
Why not higher?
CRITICAL requires a path to confidentiality or integrity impact, or an availability impact so catastrophic it threatens safety (OT/ICS). This CVE is pure resource exhaustion — the JVM runs out of heap and the process stalls or crashes. Recovery is a restart. Even against high-value targets like an IdP running on Tomcat, the outcome is a temporary outage, not domain takeover or data breach. There is no chain to RCE.
Why not lower?
Downgrading below HIGH would ignore the combination of zero-authentication exploitation, a weaponized public PoC, 99th-percentile EPSS, and the broadest possible Java library exposure. Any internet-facing Java application that accepts file uploads is a sitting target with no attacker prerequisites. The statistical model strongly predicts mass exploitation attempts, and the library's ubiquity means your fleet almost certainly includes affected instances.
What to do — in priority order.
- Deploy WAF rules to limit multipart part count and header count — Configure your WAF (ModSecurity, AWS WAF, Cloudflare, F5 ASM) to reject requests with more than 100 parts or more than 20 headers per part. This directly blocks the attack vector. Deploy within 30 days per the noisgate mitigation SLA for HIGH.
- Set Tomcat maxPartCount parameter — In Tomcat's
server.xmlorweb.xml, set<multipart-config><max-file-size>and themaxParameterCountconnector attribute. Tomcat 10.1.42+ adds explicitmaxPartCount; on older versions,maxParameterCountprovides partial coverage. Apply to all Tomcat instances. - Configure JVM heap limits and container memory ceilings — Ensure
-Xmxis set conservatively and Kubernetesresources.limits.memoryis enforced. This converts a hang into an OOMKill + automatic restart, limiting the blast radius to seconds of downtime rather than sustained outage. - Rate-limit POST requests to upload endpoints — At the reverse proxy or API gateway layer, enforce per-IP rate limits (e.g., 10 multipart POSTs/minute) on known upload paths. This blunts parallelized attacks even if the payload structure isn't inspected.
- Network-level DDoS protection (Cloudflare L3/L4, AWS Shield) — this is an application-layer (L7) attack using valid HTTP. Volumetric DDoS mitigation won't inspect multipart structure.
- Authentication requirements alone — if the upload endpoint already requires auth, it helps narrow attackers to credential holders, but authenticated users can still trigger the DoS. The fix must be at the parsing layer.
- Java Security Manager — deprecated since Java 17 and doesn't restrict heap allocation patterns. It cannot prevent this class of resource exhaustion.
Crowdsourced verification payload.
Run this on any host where you need to check for vulnerable commons-fileupload JARs or Tomcat versions. Execute as any user with read access to the application's lib directories. Example: bash check_cve_2025_48976.sh /opt/tomcat /opt/myapp/WEB-INF/lib
#!/usr/bin/env bash
# check_cve_2025_48976.sh — Detect CVE-2025-48976 / CVE-2025-48988
# Usage: bash check_cve_2025_48976.sh <dir1> [dir2] ...
# Exit codes: 0 = PATCHED/UNKNOWN, 1 = VULNERABLE
set -euo pipefail
VULNERABLE=0
if [ $# -eq 0 ]; then
echo "Usage: $0 <directory> [directory ...]"
echo "Scans for vulnerable commons-fileupload JARs and Tomcat versions."
exit 2
fi
for DIR in "$@"; do
if [ ! -d "$DIR" ]; then
echo "[SKIP] Not a directory: $DIR"
continue
fi
# Check commons-fileupload 1.x (vulnerable: 1.0–1.5.x)
find "$DIR" -name 'commons-fileupload-*.jar' 2>/dev/null | while read -r JAR; do
VER=$(basename "$JAR" | sed -E 's/commons-fileupload-([0-9][0-9.]*).*/\1/')
MAJOR=$(echo "$VER" | cut -d. -f1)
MINOR=$(echo "$VER" | cut -d. -f2)
if [ "$MAJOR" -eq 1 ] && [ "$MINOR" -lt 6 ]; then
echo "[VULNERABLE] $JAR (version $VER < 1.6.0)"
VULNERABLE=1
else
echo "[PATCHED] $JAR (version $VER)"
fi
done
# Check commons-fileupload2-core (vulnerable: 2.0.0-M1 through 2.0.0-M3)
find "$DIR" -name 'commons-fileupload2-core-*.jar' 2>/dev/null | while read -r JAR; do
BASENAME=$(basename "$JAR")
if echo "$BASENAME" | grep -qE '2\.0\.0-M[123][^0-9]'; then
echo "[VULNERABLE] $JAR (pre-2.0.0-M4)"
VULNERABLE=1
else
echo "[PATCHED] $JAR"
fi
done
# Check Tomcat version via catalina.jar MANIFEST or version.sh
CATALINA_JAR=$(find "$DIR" -name 'catalina.jar' -path '*/lib/*' 2>/dev/null | head -1)
if [ -n "${CATALINA_JAR:-}" ]; then
TC_VER=$(unzip -p "$CATALINA_JAR" org/apache/catalina/util/ServerInfo.properties 2>/dev/null | grep 'server.number' | cut -d= -f2 | tr -d '[:space:]')
if [ -n "$TC_VER" ]; then
TC_MAJOR=$(echo "$TC_VER" | cut -d. -f1)
TC_MINOR=$(echo "$TC_VER" | cut -d. -f2)
TC_PATCH=$(echo "$TC_VER" | cut -d. -f3)
VULN_TC=0
if [ "$TC_MAJOR" -eq 9 ] && [ "$TC_MINOR" -eq 0 ] && [ "$TC_PATCH" -le 105 ]; then VULN_TC=1; fi
if [ "$TC_MAJOR" -eq 10 ] && [ "$TC_MINOR" -eq 1 ] && [ "$TC_PATCH" -le 41 ]; then VULN_TC=1; fi
if [ "$TC_MAJOR" -eq 11 ] && [ "$TC_MINOR" -eq 0 ] && [ "$TC_PATCH" -le 7 ]; then VULN_TC=1; fi
if [ "$VULN_TC" -eq 1 ]; then
echo "[VULNERABLE] Tomcat $TC_VER at $(dirname "$CATALINA_JAR") (CVE-2025-48988)"
VULNERABLE=1
else
echo "[PATCHED] Tomcat $TC_VER at $(dirname "$CATALINA_JAR")"
fi
fi
fi
done
if [ "$VULNERABLE" -eq 1 ]; then
echo ""
echo "RESULT: VULNERABLE"
exit 1
else
echo ""
echo "RESULT: PATCHED (or no matching JARs found — verify manually)"
exit 0
fiIf you remember one thing.
maxPartCount configuration within 30 days. Per the noisgate remediation SLA, complete library upgrades and Tomcat patching across all environments within 180 days. Given the 99th-percentile EPSS and weaponized PoC, front-load internet-facing systems into the first mitigation wave. This is DoS-only — no emergency weekend patching — but the attack surface is too broad and the tooling too accessible to let it slide past the 30-day mitigation window.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.