From 5ed02235035fb1cc4e865c44bf430e5ccc5a903d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 14 Oct 2025 10:50:02 +0200 Subject: [PATCH 1/4] fix(dav): Restrict properties allowed object classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- apps/dav/lib/DAV/CustomPropertiesBackend.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/apps/dav/lib/DAV/CustomPropertiesBackend.php b/apps/dav/lib/DAV/CustomPropertiesBackend.php index a1da75e9ec190..9840c95c38dd2 100644 --- a/apps/dav/lib/DAV/CustomPropertiesBackend.php +++ b/apps/dav/lib/DAV/CustomPropertiesBackend.php @@ -426,6 +426,19 @@ private function encodeValueForDatabase($value): array { $valueType = self::PROPERTY_TYPE_XML; $value = $value->getXml(); } else { + if (!is_object($value)) { + throw new DavException( + "Property \"$name\" has an invalid value of type " . gettype($value), + ); + } + if (!str_starts_with($value::class, 'Sabre\\DAV\\Xml\\Property\\') + && !str_starts_with($value::class, 'Sabre\\CalDAV\\Xml\\Property\\') + && !str_starts_with($value::class, 'Sabre\\CardDAV\\Xml\\Property\\') + && !str_starts_with($value::class, 'OCA\\DAV\\')) { + throw new DavException( + "Property \"$name\" has an invalid value of class " . $value::class, + ); + } $valueType = self::PROPERTY_TYPE_OBJECT; $value = serialize($value); } @@ -435,7 +448,7 @@ private function encodeValueForDatabase($value): array { /** * @return mixed|Complex|string */ - private function decodeValueFromDatabase(string $value, int $valueType) { + private function decodeValueFromDatabase(string $value, int $valueType): mixed { switch ($valueType) { case self::PROPERTY_TYPE_XML: return new Complex($value); @@ -444,7 +457,7 @@ private function decodeValueFromDatabase(string $value, int $valueType) { case self::PROPERTY_TYPE_STRING: default: return $value; - } + }; } private function createDeleteQuery(): IQueryBuilder { From 24f0ee0e3fa1c68b996aa8fb752d73bd3f81615c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 14 Oct 2025 17:50:53 +0200 Subject: [PATCH 2/4] fix(dav): Allow arrays (of scalars) in property values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- apps/dav/lib/DAV/CustomPropertiesBackend.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/dav/lib/DAV/CustomPropertiesBackend.php b/apps/dav/lib/DAV/CustomPropertiesBackend.php index 9840c95c38dd2..f29a161738f96 100644 --- a/apps/dav/lib/DAV/CustomPropertiesBackend.php +++ b/apps/dav/lib/DAV/CustomPropertiesBackend.php @@ -426,7 +426,16 @@ private function encodeValueForDatabase($value): array { $valueType = self::PROPERTY_TYPE_XML; $value = $value->getXml(); } else { - if (!is_object($value)) { + if (is_array($value)) { + // For array only allow scalar values + foreach ($value as $item) { + if (!is_scalar($item)) { + throw new DavException( + "Property \"$name\" has an invalid value of array containing " . gettype($value), + ); + } + } + } elseif (!is_object($value)) { throw new DavException( "Property \"$name\" has an invalid value of type " . gettype($value), ); From d2bafb529f8dabb60772d01ca0b4dc76e3b4d297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 16 Oct 2025 09:32:23 +0200 Subject: [PATCH 3/4] fix(dav): Allow array of array of scalars, and fix error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet [skip ci] --- apps/dav/lib/DAV/CustomPropertiesBackend.php | 37 ++++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/apps/dav/lib/DAV/CustomPropertiesBackend.php b/apps/dav/lib/DAV/CustomPropertiesBackend.php index f29a161738f96..b9c446d703669 100644 --- a/apps/dav/lib/DAV/CustomPropertiesBackend.php +++ b/apps/dav/lib/DAV/CustomPropertiesBackend.php @@ -415,6 +415,18 @@ private function formatPath(string $path): string { return $path; } + private static function checkIsArrayOfScalar(string $name, array $array): void { + foreach ($array as $item) { + if (is_array($item)) { + self::checkIsArrayOfScalar($name, $item); + } elseif ($item !== null && !is_scalar($item)) { + throw new DavException( + "Property \"$name\" has an invalid value of array containing " . gettype($item), + ); + } + } + } + /** * @param mixed $value * @return array @@ -428,25 +440,20 @@ private function encodeValueForDatabase($value): array { } else { if (is_array($value)) { // For array only allow scalar values - foreach ($value as $item) { - if (!is_scalar($item)) { - throw new DavException( - "Property \"$name\" has an invalid value of array containing " . gettype($value), - ); - } - } + self::checkIsArrayOfScalar($name, $value); } elseif (!is_object($value)) { throw new DavException( "Property \"$name\" has an invalid value of type " . gettype($value), ); - } - if (!str_starts_with($value::class, 'Sabre\\DAV\\Xml\\Property\\') - && !str_starts_with($value::class, 'Sabre\\CalDAV\\Xml\\Property\\') - && !str_starts_with($value::class, 'Sabre\\CardDAV\\Xml\\Property\\') - && !str_starts_with($value::class, 'OCA\\DAV\\')) { - throw new DavException( - "Property \"$name\" has an invalid value of class " . $value::class, - ); + } else { + if (!str_starts_with($value::class, 'Sabre\\DAV\\Xml\\Property\\') + && !str_starts_with($value::class, 'Sabre\\CalDAV\\Xml\\Property\\') + && !str_starts_with($value::class, 'Sabre\\CardDAV\\Xml\\Property\\') + && !str_starts_with($value::class, 'OCA\\DAV\\')) { + throw new DavException( + "Property \"$name\" has an invalid value of class " . $value::class, + ); + } } $valueType = self::PROPERTY_TYPE_OBJECT; $value = serialize($value); From 2d652c5555b97be0765d8843f43f871738c6076c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Mon, 20 Oct 2025 11:50:44 +0200 Subject: [PATCH 4/4] fix(dav): Adapt changes to stable28 code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- apps/dav/lib/DAV/CustomPropertiesBackend.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/dav/lib/DAV/CustomPropertiesBackend.php b/apps/dav/lib/DAV/CustomPropertiesBackend.php index b9c446d703669..7c9d861018d86 100644 --- a/apps/dav/lib/DAV/CustomPropertiesBackend.php +++ b/apps/dav/lib/DAV/CustomPropertiesBackend.php @@ -30,6 +30,7 @@ use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; use OCP\IUser; +use Sabre\DAV\Exception as DavException; use Sabre\DAV\PropertyStorage\Backend\BackendInterface; use Sabre\DAV\PropFind; use Sabre\DAV\PropPatch; @@ -373,7 +374,7 @@ private function updateProperties(string $path, array $properties): bool { ->executeStatement(); } } else { - [$value, $valueType] = $this->encodeValueForDatabase($propertyValue); + [$value, $valueType] = $this->encodeValueForDatabase($propertyName, $propertyValue); $dbParameters['propertyValue'] = $value; $dbParameters['valueType'] = $valueType; @@ -431,7 +432,7 @@ private static function checkIsArrayOfScalar(string $name, array $array): void { * @param mixed $value * @return array */ - private function encodeValueForDatabase($value): array { + private function encodeValueForDatabase(string $name, $value): array { if (is_scalar($value)) { $valueType = self::PROPERTY_TYPE_STRING; } elseif ($value instanceof Complex) {