CVE-2026-45281
Description
Nextcloud Server allows authenticated users to access and modify other users' calendars due to improper authorization controls.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Nextcloud Server allows authenticated users to access and modify other users' calendars due to improper authorization controls.
Vulnerability
Nextcloud Server versions 32.0.0 to before 32.0.9 and 33.0.0 to before 33.0.3 are affected by improper authorization controls in the calendar backend. An authenticated attacker with knowledge of another user's principal URL can gain unauthorized access to their calendar [1].
Exploitation
An attacker must first be an authenticated user within Nextcloud. With knowledge of a target user's principal URL, the attacker can send a crafted request to the calendar backend to access and modify the target user's calendar data [1].
Impact
Successful exploitation allows an attacker to gain full access to a target user's calendar, enabling them to view and modify its contents. This compromises the confidentiality and integrity of the calendar data [1].
Mitigation
Nextcloud Server should be upgraded to version 33.0.3 or 32.0.9. For Nextcloud Enterprise Server, specific upgraded versions are recommended, including 33.0.3 and 32.0.9, among others [1]. As a temporary workaround, access to the endpoints remote.php/dav/principals/users//calendar-proxy-read and remote.php/dav/principals/users//calendar-proxy-write can be blocked, and the oc_dav_cal_proxy table can be cleared if data integrity is a concern [1].
AI Insight generated on Jun 1, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1- Range: >=32.0.0,<32.0.9, >=33.0.0,<33.0.3
Patches
160a1e725e0c2Merge pull request #59962 from nextcloud/fix/delegation/add-acls
7 files changed · +116 −15
apps/dav/composer/composer/autoload_classmap.php+2 −0 modified@@ -96,6 +96,8 @@ 'OCA\\DAV\\CalDAV\\Outbox' => $baseDir . '/../lib/CalDAV/Outbox.php', 'OCA\\DAV\\CalDAV\\Plugin' => $baseDir . '/../lib/CalDAV/Plugin.php', 'OCA\\DAV\\CalDAV\\Principal\\Collection' => $baseDir . '/../lib/CalDAV/Principal/Collection.php', + 'OCA\\DAV\\CalDAV\\Principal\\ProxyRead' => $baseDir . '/../lib/CalDAV/Principal/ProxyRead.php', + 'OCA\\DAV\\CalDAV\\Principal\\ProxyWrite' => $baseDir . '/../lib/CalDAV/Principal/ProxyWrite.php', 'OCA\\DAV\\CalDAV\\Principal\\User' => $baseDir . '/../lib/CalDAV/Principal/User.php', 'OCA\\DAV\\CalDAV\\Proxy\\Proxy' => $baseDir . '/../lib/CalDAV/Proxy/Proxy.php', 'OCA\\DAV\\CalDAV\\Proxy\\ProxyMapper' => $baseDir . '/../lib/CalDAV/Proxy/ProxyMapper.php',
apps/dav/composer/composer/autoload_static.php+2 −0 modified@@ -111,6 +111,8 @@ class ComposerStaticInitDAV 'OCA\\DAV\\CalDAV\\Outbox' => __DIR__ . '/..' . '/../lib/CalDAV/Outbox.php', 'OCA\\DAV\\CalDAV\\Plugin' => __DIR__ . '/..' . '/../lib/CalDAV/Plugin.php', 'OCA\\DAV\\CalDAV\\Principal\\Collection' => __DIR__ . '/..' . '/../lib/CalDAV/Principal/Collection.php', + 'OCA\\DAV\\CalDAV\\Principal\\ProxyRead' => __DIR__ . '/..' . '/../lib/CalDAV/Principal/ProxyRead.php', + 'OCA\\DAV\\CalDAV\\Principal\\ProxyWrite' => __DIR__ . '/..' . '/../lib/CalDAV/Principal/ProxyWrite.php', 'OCA\\DAV\\CalDAV\\Principal\\User' => __DIR__ . '/..' . '/../lib/CalDAV/Principal/User.php', 'OCA\\DAV\\CalDAV\\Proxy\\Proxy' => __DIR__ . '/..' . '/../lib/CalDAV/Proxy/Proxy.php', 'OCA\\DAV\\CalDAV\\Proxy\\ProxyMapper' => __DIR__ . '/..' . '/../lib/CalDAV/Proxy/ProxyMapper.php',
apps/dav/lib/CalDAV/Principal/ProxyRead.php+23 −0 added@@ -0,0 +1,23 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\DAV\CalDAV\Principal; + +use Sabre\DAVACL; + +class ProxyRead extends \Sabre\CalDAV\Principal\ProxyRead implements DAVACL\IACL { + use DAVACL\ACLTrait; + + /** + * @inheritDoc + */ + public function getOwner() { + return $this->principalInfo['uri']; + } +}
apps/dav/lib/CalDAV/Principal/ProxyWrite.php+23 −0 added@@ -0,0 +1,23 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\DAV\CalDAV\Principal; + +use Sabre\DAVACL; + +class ProxyWrite extends \Sabre\CalDAV\Principal\ProxyWrite implements DAVACL\IACL { + use DAVACL\ACLTrait; + + /** + * @inheritDoc + */ + public function getOwner() { + return $this->principalInfo['uri']; + } +}
apps/dav/lib/CalDAV/Principal/User.php+40 −0 modified@@ -36,4 +36,44 @@ public function getACL() { ]; return $acl; } + + /** + * Returns a specific child node, referenced by its name. + * + * @param string $name + * + * @return \Sabre\DAV\INode + */ + public function getChild($name) { + $principal = $this->principalBackend->getPrincipalByPath($this->getPrincipalURL() . '/' . $name); + if (!$principal) { + throw new \Sabre\DAV\Exception\NotFound("Node with name $name was not found"); + } + if ($name === 'calendar-proxy-read') { + return new ProxyRead($this->principalBackend, $this->principalProperties); + } + + if ($name === 'calendar-proxy-write') { + return new ProxyWrite($this->principalBackend, $this->principalProperties); + } + + throw new \Sabre\DAV\Exception\NotFound("Node with name $name was not found"); + } + + /** + * Returns an array with all the child nodes. + * + * @return \Sabre\DAV\INode[] + */ + public function getChildren() { + $r = []; + if ($this->principalBackend->getPrincipalByPath($this->getPrincipalURL() . '/calendar-proxy-read')) { + $r[] = new ProxyRead($this->principalBackend, $this->principalProperties); + } + if ($this->principalBackend->getPrincipalByPath($this->getPrincipalURL() . '/calendar-proxy-write')) { + $r[] = new ProxyWrite($this->principalBackend, $this->principalProperties); + } + + return $r; + } }
build/integration/dav_features/caldav-delegation.feature+8 −1 modified@@ -20,4 +20,11 @@ Feature: calendar delegation When "admin" updates property "{DAV:}group-member-set" to href "/remote.php/dav/principals/users/user0" of principal "users/admin/calendar-proxy-write" on the endpoint "/remote.php/dav/principals/" Then The CalDAV response should be multi status And The CalDAV response should contain an href "/remote.php/dav/principals/users/admin/calendar-proxy-write" - And The CalDAV response should contain a property "{DAV:}group-member-set" \ No newline at end of file + And The CalDAV response should contain a property "{DAV:}group-member-set" + + Scenario: Admin cannot grant User1 access to User0's calendar account + Given user "admin" exists + And user "user0" exists + And user "user1" exists + When "admin" updates property "{DAV:}group-member-set" to href "/remote.php/dav/principals/users/user1" of principal "users/user0/calendar-proxy-write" on the endpoint "/remote.php/dav/principals/" + Then The CalDAV HTTP status code should be "404" \ No newline at end of file
build/integration/features/bootstrap/CalDavContext.php+18 −14 modified@@ -408,19 +408,23 @@ public function updatesHrefPropertyOfPrincipal( $xml = new \Sabre\Xml\Service(); $body = $xml->write('{DAV:}propertyupdate', $propPatch, '/'); - $this->response = $this->client->request( - 'PROPPATCH', - $davUrl, - [ - 'headers' => [ - 'Content-Type' => 'application/xml; charset=UTF-8', - ], - 'body' => $body, - 'auth' => [ - $user, - $password, - ], - ] - ); + try { + $this->response = $this->client->request( + 'PROPPATCH', + $davUrl, + [ + 'headers' => [ + 'Content-Type' => 'application/xml; charset=UTF-8', + ], + 'body' => $body, + 'auth' => [ + $user, + $password, + ], + ] + ); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } } }
Vulnerability mechanics
No source-code context for this CVE — mechanics is only generated when we can read the actual fix diff. Without that, the four sections (root cause, attack vector, affected code, fix) would be speculation rather than analysis.
References
3News mentions
0No linked articles in our index yet.