Apache Tomcat WebDAV — one low-severity finding, written up honestly
This is a short writeup of a small finding. CVE-2026-41284 — an
unbounded-resource issue in Apache Tomcat’s WebdavServlet —
rated Low by the Apache Tomcat security team and published
2026-05-12 in the May release advisory. We sent the original disclosure on
2026-04-11. One of our two reported findings was correctly rejected; the other was
re-tested with stronger evidence and accepted.
We are not going to oversell the work. The bug is real but narrow, the disclosure cycle taught us more about our own methodology than the bug itself did, and we got lucky on the second finding — the version we first wrote up was sloppy and would have been rejected too if Apache hadn’t come back with a clean rejection of the first one that gave us a reason to re-examine the second.
The Finding
WebdavServlet — the optional WebDAV implementation that ships with
every supported Tomcat branch — handles PROPFIND and
LOCK in a way that lets a single unauthenticated request consume far
more heap than the wire payload, with no internal cap. A moderate request body is
amplified twice along the path:
- Body read into an unbounded
ByteArrayOutputStream.WebdavServlet.doPropfindcallsIOTools.flow(is, os)with no size cap. The connector-levelmaxPostSizedoes not apply becausePROPFINDis not a form-parsed method — we accepted a 50 MBPROPFINDbody whilemaxPostSizeretained its default 2 MB. - Property nodes accumulated into an
ArrayList. The parsed DOM is walked and every child of<prop>is added to a plainArrayListwith no length check. N trivial<getcontentlength/>elements become Norg.w3c.dom.Nodeinstances plus NArrayListentries. - Response serialised into a single
StringBuilder.XMLWriter.writeElementappends one response element per requested property to a single internalStringBuilderthat is never flushed until the response is complete. The per-element response token is longer than the per-element request token, so this stage dominates.
One ~95 MB PROPFIND against a default Tomcat instance (default
heap, no special headers, no Depth: infinity) drives RSS from ~132 MB
baseline to >1 GB and produces a java.lang.OutOfMemoryError
entirely in product code. Two fault lines show up across branches, which is the
useful confirmation that this isn’t one specific implementation detail:
Tomcat 11.0.21 — stage 2 (ArrayList) fires first:
java.lang.OutOfMemoryError: Java heap space at java.base/java.util.ArrayList.grow(ArrayList.java:237) at java.base/java.util.ArrayList.add(ArrayList.java:454) at org.apache.catalina.servlets.WebdavServlet.doPropfind(WebdavServlet.java:875)
Tomcat 9.0.117 and 10.1.54 — stage 3 (StringBuilder) fires first:
java.lang.OutOfMemoryError: Java heap space at java.base/java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:582) at java.base/java.lang.StringBuilder.append(StringBuilder.java:179) at org.apache.catalina.util.XMLWriter.writeElement(XMLWriter.java:163) at org.apache.catalina.servlets.WebdavServlet.propfindResource(WebdavServlet.java:2651) at org.apache.catalina.servlets.WebdavServlet.doPropfind(WebdavServlet.java:940)
Preconditions are minimal: WebdavServlet mapped into a context
(the bundled webapps/webdav/ sample app is enough), no authentication,
no readonly=false requirement — that constraint applies to
PROPPATCH but not to PROPFIND or LOCK.
The amplification is structural (element count), not parser-driven; the XML
contains no entities, no DTD, no namespace tricks.
CVE-2026-41284 — the outcome
Apache Tomcat security accepted the report for PROPFIND and
LOCK, classified as “Allocation of Resources Without Limits or
Throttling.” Severity: Low. Published 2026-05-12 alongside
the May releases:
seclists.org/oss-sec/2026/q2/499.
Affected branches per the advisory: 11.0.0-M1 → 11.0.21, 10.1.0-M1 → 10.1.54, 10.0.0-M1 → 10.0.27, 9.0.0-M1 → 9.0.117, 8.5.0 → 8.5.100, and 4.0 → 7.0.109. The pattern is therefore long-standing, not a regression in 11.x.
The PROPPATCH portion of our original report was rejected, correctly:
“The report is accepted for PROPFIND and LOCK but rejected for PROPPATCH since PROPPATCH requires write access and a user with write access already has a variety of ways they can cause harm.”
PROPPATCH is gated by readonly=false, which already
grants PUT, DELETE, MOVE, and
MKCOL. The unbounded-body pattern in doProppatch is
still real code but it doesn’t cross a new privilege boundary, so it
doesn’t warrant its own CVE.
What this isn’t
Worth saying plainly so the rating isn’t mis-read:
- Low severity. A single-request heap exhaustion is a real DoS
primitive, but the affected component (
WebdavServlet) is rarely mapped into a production Tomcat context. Most public-facing Tomcat deployments do not ship WebDAV at all, or only behind authentication for a single internal-tooling endpoint. - Not RCE, not auth bypass, not data exposure. The bug exhausts memory in the serving thread; the JVM may or may not recover depending on heap settings and concurrent load. There is no path to code execution or to reading anything sensitive.
- No exploit-shape novelty. Unbounded body-read into an unbounded accumulator is the most ordinary resource-exhaustion pattern a code reviewer ever finds in Java. The only mildly interesting thing here is the three-stage compounding, which is why the OOM lands so cheaply.
What actually happened in the process
We reported two findings on 2026-04-11. Two days later Apache rejected the first with a clean technical disproof: our root-cause analysis on the alleged AJP path-traversal was wrong — the lengths involved were within Tomcat’s documented behaviour and an alternative explanation we hadn’t considered accounted for everything we observed. Withdrew it the same day.
That rejection prompted us to actually re-test the second finding properly. Until then our WebDAV writeup had described it as a “cumulative, concurrency-dependent DoS” based on heap growth observations across many requests — vague enough that a reviewer would have had to do real work to decide whether to take it seriously. On re-test we produced a single-request OOM with stack traces in product code. That is the version of the finding that got accepted.
We were lucky here. The original WebDAV writeup would probably have been rejected on the same kind of reasoning that got the first finding rejected — insufficient evidence, alternative explanations not addressed, characterisation that didn’t match the actual defect. The clean rejection of the AJP finding was the warning we needed to look harder at the one finding we did have. Without it we would have gone zero for two.
Lessons for next time
Concrete things we are changing in our process, none of them flattering:
- Single-request reproducer or no submission. If a finding can only be characterised across many requests under unspecified concurrency, we don’t actually understand it yet. The reviewer’s first question is going to be “is this just normal heap growth?” and the answer has to be one curl command and a stack trace, not a paragraph.
- Disprove your own report before sending it. The Apache response to FND-001 was a short list of alternative explanations we should have ruled out ourselves. We now keep an explicit disproof section in every disclosure email — what alternative explanations exist, how we ruled each one out. Adding that to the FND-004 resend cut the acceptance round-trip to one cycle.
- Stack traces in product code or it doesn’t count.
An OOM in
java.util.ArrayList.growisn’t evidence of a product bug on its own. An OOM whose stack frames pass throughWebdavServlet.doPropfindwith no user-supplied JSP / filter in the chain is. - The methodology is not the story. Earlier drafts of this page led with the volume of fuzzing and LLM review we’d done. None of that mattered to the outcome — the accepted finding came from manual code reading. We removed that section. If a future writeup has a methodology story worth telling, we will tell that one; this isn’t it.
Disclosure timeline
| Date | Event |
|---|---|
| 2026-04-11 | Two findings reported to [email protected]. |
| 2026-04-13 | Apache rejects FND-001 (AJP) with technical disproof. We withdraw it. |
| 2026-04-13 | FND-004 (WebDAV) re-tested, single-request OOM reproduced, resent with inline disproof section. |
| 2026-04-13 | Apache Tomcat security accepts FND-004 for PROPFIND and LOCK; rejects the PROPPATCH portion. CVE-2026-41284 assigned. Severity: Low. |
| 2026-05-12 | Public advisory: seclists.org/oss-sec/2026/q2/499. |