fix(webdav): require credentials and apply the property permission result - #37179
Open
swicken wants to merge 2 commits into
Open
fix(webdav): require credentials and apply the property permission result#37179swicken wants to merge 2 commits into
swicken wants to merge 2 commits into
Conversation
…rmission answer The WebDAV endpoints are served by a third-party library whose method handlers do not all consult Resource.authorise(). Two consequences, both measured against a running instance: A request carrying no Authorization header was handled by the handlers that run their own sequence rather than the shared one. Anonymous PROPPATCH answered 207, anonymous OPTIONS answered 200 on every /webdav/ mount, and anonymous LOCK on a legacy language path answered 500. WebDavAuthenticationFilter answers those with the RFC 7235 challenge instead, for every method and whatever the body. The status is set rather than raised as a container error, because web.xml maps 401 to an error page that redirects and a WebDAV client cannot act on a 302. Refusals go to the security log alongside comparable events. PROPPATCH's permission check reported one problem per property named in the request, so a body naming none reported an empty list of problems, which the caller reads as no problem: the resource's answer was obtained and then discarded. WebdavPropertyAuthoriser reports the refusal either way, and DotWebdavServlet installs it, which reaches both handlers that check property permissions. Closes dotCMS/private-issues#672
Contributor
|
Claude finished @swicken's task in 2m 52s —— View job Code Review
I reviewed the diff against FindingsNo blocking issues. Verified the parts I could reach in-repo:
🟡 Medium (non-blocking, verification note)
Notes (no action required)
· branch |
The filter decides on one header, so the three bodies were three identical runs of the test above it, and the name pointed the reader at the authoriser's behaviour rather than the filter's. WebdavPropertyAuthoriserTest covers the case a body naming no property actually exercises.
erickgonzalez
approved these changes
Aug 24, 2026
swicken
enabled auto-merge
August 24, 2026 21:49
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The WebDAV endpoints are served by a third-party library whose method handlers do not all
consult
Resource.authorise(...). Two things follow from that, both measured against a runninginstance.
A request carrying no
Authorizationheader is handled by the handlers that run their ownsequence instead of the shared one. Anonymous
PROPPATCHanswered207, anonymousOPTIONSanswered
200on every/webdav/mount point, and anonymousLOCKon a legacy language pathanswered
500. WebDAV in dotCMS resolves every resource against a user, so there is nothing onthese endpoints to serve a caller who has not identified themselves. This adds a filter on
/webdav/*that answers those with the RFC 7235 challenge instead.Separately, the permission check for
PROPPATCHreports one problem per property named in therequest, so a body naming none reports an empty list of problems, which the caller reads as no
problem: the resource's answer is obtained and then discarded.
WebdavPropertyAuthoriserreportsthe refusal either way, and
DotWebdavServletinstalls it through the library's own extensionpoint, which reaches both handlers that check property permissions.
Behaviour
/webdav/*with noAuthorizationheader, or a blank one, gets401withWWW-Authenticate: Basic. Every method, whatever the body.web.xmlmaps401to/html/error/custom-error-page.jsp, which redirects, and a WebDAV client has nothing it can dowith a
302to a login page.OPTIONSis not exempt. Being challenged on the first request is how a WebDAV client learns tosend credentials at all.
without a session.
PROPFINDwith and without a body,OPTIONS,MKCOL,PUT,GET,PROPPATCH,LOCKandDELETEall behave as they did before.PROPPATCHwhose body names no property is now refused for a caller holding no permission onthe resource, instead of answering
207.Merge order with #37167
Both branches add a
<filter>and a<filter-mapping>immediately afterNormalizationFilter,so
web.xmlwill conflict. #37167 should land first. When this branch is rebased, keep bothfilters and map
WebDavAuthenticationFilterbeforeWebDavXmlValidationFilter: there is noreason to buffer and parse a body for a caller who is about to be refused. The
<servlet-class>change here is in a part of the file #37167 does not touch and merges cleanly.
Two filters on the same path is deliberate. One asks whether there is a caller at all, by reading
a single header; the other asks whether the body is shaped the way RFC 4918 says, and has to
buffer and parse to answer. Merging them would put an XML parse behind a credentials check in one
class for no gain.
Testing
11 unit tests.
WebDavAuthenticationFilterTest(6) covers the challenge and its header, everyWebDAV method, a blank
Authorizationheader, non-HTTP pass-through, and pass-through for arequest that does carry credentials.
WebdavPropertyAuthoriserTest(5) covers refusal when noproperty was named, when the name set is null, one refusal per named property, and the allowed
case reporting nothing.
Against a running instance, before and after the change: anonymous
PROPPATCHon three mountpoints with three different no-property bodies went
207→401, anonymousOPTIONS200→401, anonymousLOCKon the legacy language path500→401, and nine functional checkscovering the traffic a real client sends are unchanged. Each guard was also verified by reverting
it and confirming the tests fail.
Not covered: no real desktop client was tested. Finder, Explorer and Office now meet a challenge
on
OPTIONSwhere they previously got a200. That is the standard handshake and every clientimplements it, but it is reasoning rather than a measurement. There is also no CI coverage for
these methods — the
WebDavPostman collection sends Basic auth on every request, so itexercises the authenticated path only.
Closes dotCMS/private-issues#672