From 79b4d22a71dab9b249c5cf2bdbf469148c7bcc59 Mon Sep 17 00:00:00 2001 From: Anna Larch Date: Thu, 1 Oct 2026 17:57:22 +0200 Subject: [PATCH] docs(security): use the Files API in the directory traversal example The old example used the private OC_User API and wrote to the data directory directly; the new one goes through IRootFolder. Assisted-by: ClaudeCode:claude-opus-5-5 Signed-off-by: Anna Larch --- developer_manual/prologue/security.rst | 31 +++++++++++++++++++------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/developer_manual/prologue/security.rst b/developer_manual/prologue/security.rst index cb76ea810ba..bd2982b8365 100644 --- a/developer_manual/prologue/security.rst +++ b/developer_manual/prologue/security.rst @@ -136,26 +136,41 @@ Code executions and file inclusions can be easily prevented by **never** allowin Directory traversal ------------------- -Very often developers forget about sanitizing the file path (removing all \\ and /), this allows an attacker to traverse through directories on the server which opens several potential attack vectors including privilege escalations, code executions or file disclosures. +Directory traversal happens when a file path built from user input escapes the folder it was meant for, for example with ``../``. This opens several attack vectors, including file disclosure, privilege escalation and code execution. + +Never build paths into the data directory yourself. Access files through the Files API instead: it rejects paths containing ``..``, and it also applies permissions, encryption and external storage handling. **DON'T** .. code-block:: php rootFolder is an injected IRootFolder, $userId the ID of the current user, + // $path the user-supplied path + try { + $node = $this->rootFolder->getUserFolder($userId)->get($path); + } catch (NotFoundException|NotPermittedException $e) { + // NotPermittedException is also thrown for paths containing ".." + return new DataResponse([], Http::STATUS_NOT_FOUND); + } + if (!$node instanceof File) { + return new DataResponse([], Http::STATUS_NOT_FOUND); + } + $content = $node->getContent(); Shell injection