fix(webdav): reject PROPPATCH on protected DAV:/oc:/nc:/ocs: props

DeadPropertyStore let PROPPATCH set any namespace/name verbatim,
incl. names the server itself emits as live state (DAV: entirely,
plus oc:/nc:/ocs: names used by write_file_response /
write_folder_response). That either forges a live prop or stores
dead rows nothing ever reads. is_protected_property() denylists
them; both PROPPATCH handlers (native + NC) now return per-property
403 instead of storing. oc:favorite stays writable via its existing
special-case, which runs before the protection check.
This commit is contained in:
M.Schmidt
2026-07-01 22:54:48 +02:00
parent 94e0145855
commit 0ad0ea1a43
3 changed files with 54 additions and 2 deletions
+7 -1
View File
@@ -14,7 +14,7 @@ use std::sync::Arc;
use uuid::Uuid;
use crate::application::adapters::webdav_adapter::{
PropFindRequest, PropPatchOp, QualifiedName, WebDavAdapter,
PropFindRequest, PropPatchOp, QualifiedName, WebDavAdapter, is_protected_property,
};
use crate::application::dtos::pagination::PaginationRequestDto;
use crate::application::ports::favorites_ports::FavoritesUseCase;
@@ -556,6 +556,12 @@ async fn handle_proppatch(
}
results.push((name, true));
}
PropPatchOp::Set(pv) if is_protected_property(&pv.name) => {
results.push((&pv.name, false));
}
PropPatchOp::Remove(name) if is_protected_property(name) => {
results.push((name, false));
}
PropPatchOp::Set(pv) => {
dead_props
.set(resource_ref, pv.name.clone(), pv.value.clone())