This repository was archived by the owner on May 29, 2026. It is now read-only.
Commit d9434ab
committed
fix(validate-self-folder-access): address PR #1431 third-pass review (1 blocker + 2 concerns)
Closes the three findings from Wilco's 3rd-pass review (commit d0b2839).
**🔴 Blocker — class docblock still taught the vulnerable response shape:**
`lib/Exception/FolderAccessDeniedException.php:34` documented
`{"error": "folder_access_denied", "folder": "<requested-id>"}` as the
canonical 403 body, contradicting every other artifact (code, controller,
spec, `docs/api/objects.md`) that says the body MUST NOT echo the
attempted folder ID. The next endpoint author copying the pattern from
the docblock would reintroduce the exact enumeration oracle this PR
closes. Updated the class docblock to:
- State the correct body shape (`{"error": "folder_access_denied"}` only).
- Spell out the enumeration-oracle rationale inline so the rationale
travels with the code.
- Cross-reference `ObjectsController::folderAccessDeniedResponse()` as
the canonical mapping site.
- Re-scope `getAttemptedFolderId()`'s docblock to "server-side audit
logging only — MUST NOT be in the HTTP response body".
**🟡 Concern — `assertObjectFolderAccessible` hardcoded `currentUser: null`:**
The proxy method had no `?IUser $currentUser` parameter, so non-HTTP
callers (cron, import pipelines, event listeners) fell through to
`IUserSession::getUser()` → null → default-deny on every existing-
binding save. Contradicted the CHANGELOG's own "explicit IUser
$currentUser" contract.
Plumbed the parameter through three call sites:
- `FileService::assertObjectFolderAccessible(ObjectEntity $object, ?IUser $currentUser=null)` —
forwards verbatim to `FolderManagementHandler::assertFolderIsAccessible`
which already accepts the same parameter with the same fallback
semantics (explicit → session → null = default-deny).
- `ObjectService::ensureObjectFolder(?string $uuid, ?IUser $currentUser=null)` —
plumbs the user through to the proxy.
- `ObjectService::saveObject(..., ?IUser $currentUser=null)` — public
surface gains the parameter as the last positional arg (back-compat
preserved; existing callers pass nothing and get the same session-
resolution behaviour they had before). Non-HTTP callers can now
pass an explicit acting user end-to-end.
Docblocks at each level document the resolution precedence + call out
the non-HTTP-caller requirement.
**🟡 Concern — defense-in-depth re-validation was uncached:**
`ensureObjectFolder()` runs `getUserFolder() + getById()` on every
save for any folder-bound object — real Nextcloud filesystem I/O
per call. Bulk imports / cascade saves of the same object pay this
cost every iteration despite the (uid, folderId) tuple being a
stable access-grant key for the lifetime of a request.
Added a per-request memoization map on `FileService`
(`folderAccessRevalidationCache`) keyed `"{uid}:{folderId}"`. Only
successful re-validations are cached; denials re-throw and re-check
on retry (so a freshly-mounted-then-revoked folder still gets a
correct verdict on the next call). The cache lives for the lifetime
of the FileService instance (one HTTP request), and access changes
do not propagate mid-request anyway, so a cache hit returns the
same verdict the live check would.
**Verification:**
- PHPCS clean on all 3 touched files.
- PHPStan clean.
- `FolderAccessDeniedExceptionTest` (3 tests / 7 assertions) still
green — Wilco confirmed in pass 3 that this test locks both the
HTTP-agnostic-code invariant and the `HTTP_STATUS === 403`
invariant, neither of which this commit touches.
- `testPostPatchReturns403WithStructuredBodyOnFolderAccessDenied` is
pre-existing failure on the head SHA (not introduced or worsened
by this commit — verified by git stash).
Refs: #1431, Wilco's third-pass review
`4335769385`1 parent d0b2839 commit d9434ab
3 files changed
Lines changed: 81 additions & 13 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
33 | | - | |
34 | | - | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
35 | 44 | | |
36 | 45 | | |
37 | 46 | | |
| |||
96 | 105 | | |
97 | 106 | | |
98 | 107 | | |
99 | | - | |
100 | | - | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
101 | 111 | | |
102 | 112 | | |
103 | 113 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
319 | 319 | | |
320 | 320 | | |
321 | 321 | | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
322 | 341 | | |
323 | 342 | | |
324 | 343 | | |
| |||
844 | 863 | | |
845 | 864 | | |
846 | 865 | | |
847 | | - | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
848 | 877 | | |
849 | 878 | | |
850 | 879 | | |
851 | 880 | | |
852 | 881 | | |
853 | | - | |
| 882 | + | |
854 | 883 | | |
855 | 884 | | |
856 | 885 | | |
857 | 886 | | |
858 | 887 | | |
859 | 888 | | |
| 889 | + | |
| 890 | + | |
| 891 | + | |
| 892 | + | |
| 893 | + | |
| 894 | + | |
| 895 | + | |
| 896 | + | |
| 897 | + | |
| 898 | + | |
860 | 899 | | |
861 | 900 | | |
862 | | - | |
| 901 | + | |
863 | 902 | | |
864 | 903 | | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
865 | 907 | | |
866 | 908 | | |
867 | 909 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
79 | 79 | | |
80 | 80 | | |
81 | 81 | | |
| 82 | + | |
82 | 83 | | |
83 | 84 | | |
84 | 85 | | |
| |||
1071 | 1072 | | |
1072 | 1073 | | |
1073 | 1074 | | |
| 1075 | + | |
| 1076 | + | |
| 1077 | + | |
| 1078 | + | |
| 1079 | + | |
| 1080 | + | |
1074 | 1081 | | |
1075 | 1082 | | |
1076 | 1083 | | |
| |||
1089 | 1096 | | |
1090 | 1097 | | |
1091 | 1098 | | |
1092 | | - | |
| 1099 | + | |
| 1100 | + | |
1093 | 1101 | | |
1094 | 1102 | | |
1095 | 1103 | | |
| |||
1171 | 1179 | | |
1172 | 1180 | | |
1173 | 1181 | | |
1174 | | - | |
| 1182 | + | |
1175 | 1183 | | |
1176 | 1184 | | |
1177 | 1185 | | |
| |||
1457 | 1465 | | |
1458 | 1466 | | |
1459 | 1467 | | |
1460 | | - | |
| 1468 | + | |
| 1469 | + | |
| 1470 | + | |
| 1471 | + | |
| 1472 | + | |
| 1473 | + | |
1461 | 1474 | | |
1462 | 1475 | | |
1463 | 1476 | | |
1464 | | - | |
| 1477 | + | |
1465 | 1478 | | |
1466 | 1479 | | |
1467 | 1480 | | |
| |||
1504 | 1517 | | |
1505 | 1518 | | |
1506 | 1519 | | |
1507 | | - | |
1508 | | - | |
| 1520 | + | |
| 1521 | + | |
| 1522 | + | |
| 1523 | + | |
| 1524 | + | |
1509 | 1525 | | |
1510 | 1526 | | |
1511 | 1527 | | |
| |||
0 commit comments