fix(files_sharing): validate input in PublicPreviewController#getPreview#59253
fix(files_sharing): validate input in PublicPreviewController#getPreview#59253mvanhorn wants to merge 7 commits into
Conversation
|
Hi @mvanhorn - thanks for your bug fix! Hope you don’t mind, but while this was being fixed I took the liberty of adding a few directly related housekeeping improvements to your PR/branch:
Footnotes
|
|
/backport to stable33 |
|
/backport to stable32 |
|
Thanks for the improvements and backports, @joshtrichards. The variable renames and docblock clarification look great. |
e281c82 to
63171e6
Compare
There was a problem hiding this comment.
Pull request overview
Fixes input-validation edge cases in the public preview endpoint to avoid internal server errors when previewing public folder shares, aligning behavior with expected 4xx responses and supporting optional MIME icon fallback.
Changes:
- Add early 400 responses for invalid folder-share
$fileinputs (empty path or resolving to a folder) inPublicPreviewController::getPreview(). - Fix MIME fallback handling so it only runs when a file node was successfully resolved (avoids calling file methods on a string / unresolved node).
- Extend controller tests to cover empty
$filehandling and MIME-fallback redirect/not-found behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| apps/files_sharing/lib/Controller/PublicPreviewController.php | Adds stricter validation around resolving $file for folder shares and guards MIME fallback to prevent 500s. |
| apps/files_sharing/tests/Controller/PublicPreviewControllerTest.php | Updates existing calls for the new parameter and adds new tests for the reported error cases. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Sorry @mvanhorn, my rebase made the dco check fail. Could you rebase one more time to resolve it? ;) |
63171e6 to
ff483f2
Compare
|
Rebased in ff483f2. DCO sign-off intact on all 6 commits. |
|
Hello there, We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process. Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6 Thank you for contributing to Nextcloud and we hope to hear from you soon! (If you believe you should not receive this message, you can add yourself to the blocklist.) |
…bles Addresses review feedback on PR nextcloud#59253: * Catch `NotPermittedException` from `$shareNode->get()` and return 403 FORBIDDEN instead of propagating an internal server error (per @kesselb on line 133). * Drop the unused `$e` capture from the existing `NotFoundException` and `\InvalidArgumentException` catch blocks, using PHP 8.0 no-capture syntax (per @kesselb on line 150). * Add `testPreviewFolderSubfolderReturnsBadRequest` covering the branch where a folder share resolves `$file` to a subfolder and must return 400 (per @Copilot on line 136). Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
|
@kesselb @joshtrichards - pushed a510dfa addressing the three inline comments from the review:
One thing I can't fix myself: DCO is still failing and I think it's on the housekeeping commits @joshtrichards pushed - the |
…bles Addresses review feedback on PR nextcloud#59253: * Catch `NotPermittedException` from `$shareNode->get()` and return 403 FORBIDDEN instead of propagating an internal server error (per @kesselb on line 133). * Drop the unused `$e` capture from the existing `NotFoundException` and `\InvalidArgumentException` catch blocks, using PHP 8.0 no-capture syntax (per @kesselb on line 150). * Add `testPreviewFolderSubfolderReturnsBadRequest` covering the branch where a folder share resolves `$file` to a subfolder and must return 400 (per @Copilot on line 136). Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
9f7fa41 to
b9683e0
Compare
…bles Addresses review feedback on PR nextcloud#59253: * Catch `NotPermittedException` from `$shareNode->get()` and return 403 FORBIDDEN instead of propagating an internal server error (per @kesselb on line 133). * Drop the unused `$e` capture from the existing `NotFoundException` and `\InvalidArgumentException` catch blocks, using PHP 8.0 no-capture syntax (per @kesselb on line 150). * Add `testPreviewFolderSubfolderReturnsBadRequest` covering the branch where a folder share resolves `$file` to a subfolder and must return 400 (per @Copilot on line 136). Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
|
Rebased onto latest master - all 7 commits retain sign-off. DCO should be green now. Sorry for the delay! |
|
All three are addressed in the current head: the catch is now the non-capturing |
Return 400 Bad Request when the file parameter is empty and the shared node is a folder, instead of passing the folder itself to getPreview which triggers an internal server error. Also rename the local variable to $fileNode to prevent the catch block from calling getMimeType() on the original string parameter when get() throws NotFoundException. Fixes nextcloud#59229 Signed-off-by: Matt Van Horn <mvanhorn@users.noreply.github.com> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Signed-off-by: Josh <josh.t.richards@gmail.com> Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
…variable naming And slightly streamline the logic for clarity. Signed-off-by: Josh <josh.t.richards@gmail.com> Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
…ler#getPreview edge cases Signed-off-by: Josh <josh.t.richards@gmail.com> Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
… in tests Signed-off-by: Josh <josh.t.richards@gmail.com> Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
…lean Signed-off-by: Josh <josh.t.richards@gmail.com> Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
…bles Addresses review feedback on PR nextcloud#59253: * Catch `NotPermittedException` from `$shareNode->get()` and return 403 FORBIDDEN instead of propagating an internal server error (per @kesselb on line 133). * Drop the unused `$e` capture from the existing `NotFoundException` and `\InvalidArgumentException` catch blocks, using PHP 8.0 no-capture syntax (per @kesselb on line 150). * Add `testPreviewFolderSubfolderReturnsBadRequest` covering the branch where a folder share resolves `$file` to a subfolder and must return 400 (per @Copilot on line 136). Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
b9683e0 to
edbf7b5
Compare
|
Rebased onto latest master - DCO is green again. There was one small conflict in PublicPreviewControllerTest.php around the added tests, resolved during the rebase; the diff is otherwise unchanged. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
apps/files_sharing/tests/Controller/PublicPreviewControllerTest.php:406
- The controller now catches \OCP\Files\NotPermittedException (and returns 403), but this behavior is not covered by a unit test in this test class. Adding a dedicated test helps prevent regressions where NotPermitted would bubble up as a 500 again.
$res = $this->controller->getPreview('token', 'file', 10, 10, true, false);
$expected = new FileDisplayResponse($preview, Http::STATUS_OK, ['Content-Type' => 'myMime']);
$expected->cacheFor(3600 * 24);
$this->assertEquals($expected, $res);
}
|
Hey, thanks a lot again for your PR, and sorry it's still not merged! We do require an Assisted-by line in the commit message (before the Signed-off-by trailers) to signal AI usage for tracking. Here's how it should look for you:
Could you please squash the commits together, rebase once more, and add the Assisted-by trailer to the commit message? Please keep the sign-offs from you and Josh. Sorry for the extra round trip on this. Let me know if that's too much trouble, I usually can't push to branches on forks directly, so if I did it myself it'd mean opening a fresh PR instead of updating this one, which is a bit more churn. Happy to do that if you'd rather not touch it again, just let me know. |
|
To make the openapi check green: diff --git a/apps/files_sharing/openapi.json b/apps/files_sharing/openapi.json
index c31231f8ee9..db484a93aeb 100644
--- a/apps/files_sharing/openapi.json
+++ b/apps/files_sharing/openapi.json
@@ -1474,7 +1474,8 @@
"/index.php/apps/files_sharing/publicpreview/{token}": {
"get": {
"operationId": "public_preview-get-preview",
- "summary": "Get a preview for a shared file",
+ "summary": "Get a preview for a public share.",
+ "description": "For shares pointing to a single file, the $file parameter is ignored. For folder shares, $file must be the relative path to a file inside the shared folder.",
"tags": [
"public_preview"
],
@@ -1500,7 +1501,7 @@
{
"name": "file",
"in": "query",
- "description": "File in the share",
+ "description": "Relative path to a file inside a shared folder; ignored for single-file shares",
"schema": {
"type": "string",
"default": ""
diff --git a/openapi.json b/openapi.json
index 9371409d2bf..bfb6c3bbbd9 100644
--- a/openapi.json
+++ b/openapi.json
@@ -25590,7 +25590,8 @@
"/index.php/apps/files_sharing/publicpreview/{token}": {
"get": {
"operationId": "files_sharing-public_preview-get-preview",
- "summary": "Get a preview for a shared file",
+ "summary": "Get a preview for a public share.",
+ "description": "For shares pointing to a single file, the $file parameter is ignored. For folder shares, $file must be the relative path to a file inside the shared folder.",
"tags": [
"files_sharing/public_preview"
],
@@ -25616,7 +25617,7 @@
{
"name": "file",
"in": "query",
- "description": "File in the share",
+ "description": "Relative path to a file inside a shared folder; ignored for single-file shares",
"schema": {
"type": "string",
"default": "" |
Summary
Fixes two cases where
PublicPreviewController::getPreview()triggers aninternal server error due to incomplete input validation:
Case A - Empty
$fileparameter on folder shares:$node->get('')returns the Folder itself, thengetPreview()fails becauseit expects a File. Now returns 400 Bad Request early.
Case B - Non-existent file with
mimeFallback=1:When
$node->get($file)throwsNotFoundException, the catch block called$file->getMimeType()on the original string parameter. Renamed the localvariable to
$fileNodeand added anisset()guard so the mime fallbackonly runs when the file node was successfully resolved.
Fixes #59229