Skip to content

Webdav public dir writable behavior - #285

Open
tchapi wants to merge 3 commits into
mainfrom
cc/webdav
Open

tchapi wants to merge 3 commits into
mainfrom
cc/webdav

Conversation

@tchapi

@tchapi tchapi commented Sep 8, 2026 •

Copy link
Copy Markdown
Owner

WebDAV: enforce ACL on the public directory and on temporary files

Security fix

sabre's TemporaryFileFilterPlugin stores the junk files desktop clients write next to real ones (.DS_Store, Thumbs.db, ._*, *.swp, …) outside the DAV tree. Because those files never exist in the tree, the ACL plugin never checked anything for them: anybody, authenticated or not, could PUT, GET and
DELETE such files under any path.

DavisTemporaryFileFilterPlugin now applies the privileges of the directory the file would live in (bind for PUT, unbind for DELETE, read otherwise), exactly like a real file. Anonymous requests get a 401, unprivileged users a 403, and no temporary file is written.

Behaviour change: who can write to /dav/public

The public directory is now mounted as \Sabre\DAVACL\FS\Collection with an explicit ACL:

  • every authenticated user can read it;
  • only admins (as flagged in the dashboard) can create, modify or delete files in it, unless the new WEBDAV_PUBLIC_DIR_WRITABLE=true opens it to every authenticated user.

Important

Up to 5.4 the public directory fell under sabre's default ACL, which granted every authenticated user {DAV:}all. Deployments that use it as a shared drop folder must set WEBDAV_PUBLIC_DIR_WRITABLE=true when upgrading, otherwise regular users get a 403 when saving. The Diagnostics page shows which policy is
active.

Stricter directory checks

WEBDAV_TMP_DIR, WEBDAV_PUBLIC_DIR and WEBDAV_HOMES_DIR must:

  • be absolute paths (a relative one resolves against the PHP process' cwd);
  • exist and be directories;
  • not live inside the web root, where the web server would serve them without any permission check;
  • not be nested in one another: the tmp dir holds the locks database and the temporary files, the homes dir holds other users' files.

Davis refuses to start the DAV server otherwise, with a message naming the variable.

Other changes

  • The sabre response is rebuilt from $server->httpResponse (status, headers, body) instead of only patching Content-Type. Plugins that short-circuit a request from beforeMethod (the temporary file filter does) never reach Sapi::sendResponse, so their status and headers were previously lost.
  • \Sabre\DAVACL\FS\Collection extends FSExt\Directory: the public dir gains fast MOVE, inode-based ETags, PATCH partial updates, and rejects . / .. children.
  • Diagnostics page: new "WebDAV public directory" line (en, fr, de).
  • README, .env and docker/.env document the new variable and the upgrade path.

Tests

New tests/Functional/WebDavTest.php (enables WebDAV with throw-away directories):

  • anonymous PUT / GET / DELETE of temporary files are refused and nothing is written;
  • authenticated users can use temporary files, and they follow the parent directory ACL;
  • regular users can read but not write the public dir; admins can do everything; WEBDAV_PUBLIC_DIR_WRITABLE=true opens it;
  • the public dir is never readable anonymously;
  • relative paths, directories inside the web root and nested tmp/homes/public directories are refused;
  • sabre headers (Content-Type, WWW-Authenticate) survive the conversion to a Symfony response.

requestDav() moved to a shared DavRequestTrait.

@tchapi tchapi self-assigned this Sep 8, 2026
@tchapi tchapi added the enhancement New feature or request label Sep 8, 2026
@tchapi tchapi added the ai-generated Mostly generated by AI label Sep 23, 2026
@tchapi
tchapi added this pull request to stack #301 September 23, 2026 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-generated Mostly generated by AI enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant