Repository navigation
Conversation
The shared-root mapping read KCFinder's typeURL, which resolves a relative rb_base_url against the browser script (or gives up when DOCUMENT_ROOT is a symlink), so it never named the folder: restricted managers got an empty, read-only browser on shared storage. Use the configured URL instead. A type root the site serves from outside a narrowed filemanager_path carries no file groups again instead of refusing every action. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Since the icons became masks, background-color paints the glyph and the mask clips the border: the inactive toggle was white on white, and a selected toolbar button (Settings) showed a blue icon on blue. Draw the toggle button on the label and colour the glyphs through currentColor. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…managers Links below a file manager root are made by the operator, never by the CMS: a shared upload folder, a plugin checked out elsewhere, images from another disk. A link whose real target exists and is new (not inside or around the ACL root, not a loop, not inside anything the walk already named or a shared type folder) is now a folder or file like any other, named by its own path, with every rule applied by that name: protected folders, file groups, the executable-name rule and the media browser type folder. Links that dangle, loop or would give a file a second name stay inert entries, and `..` past a link is refused. Both managers key a shared type folder the same way, so the classic manager can now enter it and edit its groups; the link that stands for a type folder is never deleted, renamed or unlinked. Removing any other passable link removes the link only and keeps its groups. A new fixture builds the media browser the way a web request does ($_SERVER, the working directory of browse.php, config.php), through a public_html -> evolution -> release chain, which is how the typeURL bug slipped through. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks for preserving support for operator-managed shared folders. Two security boundaries still need attention before merging. Reviewed statically at 5a9b58d; I have not run this PR.
Please apply the safe-write-target guard to text saves before opening the file, reject final-component links consistently with other write operations, and retain the existing ACL and code-permission checks. Add a regression that invokes the actual text-save path as a user without code privileges against an existing final file link and verifies denial and unchanged target contents; also cover an ordinary allowed text file and a permitted parent-directory link.
Please keep the lexical identity for file-group ACLs while also checking the resolved filesystem target against protected real paths for every relevant read/change guard. For new write destinations, resolve and validate the nearest existing parent and the appended destination; retain the intended allowance for unrelated shared media directories. Add regression coverage for an external configured view directory reached through a passable directory link: text-save, create/upload, rename/move and delete must respect the protection for a user without code privileges, including non-PHP template extensions. Verify that an unrelated shared media directory remains usable. SokilAI |
…ough a linked file A passed link keeps its own name, which file groups are keyed by, but the protected-folder rule compared only that name. A link to a folder protected outside the ACL root (an external view path; core/, manager/ or views/ under a narrowed filemanager_path) opened it to managers without the permission. fileManagerPathIsProtected() and fileManagerPathTouchesProtected() now also match where a path lands: the real path of its nearest existing ancestor with the rest appended, so new destinations are covered too. Removing a link resolves only the folder it sits in. textsave() checked a linked file by its name while file_put_contents() followed the link, so a manager without code permissions could write PHP into the target through a text name. It now refuses a final link through fileManagerIsSafeWriteTarget(), as the classic upload over an existing name does now too (a move across file systems copies, and the copy follows a link). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks, both are confirmed and fixed in 022b864. Both are regressions of this PR: before it, no link was ever passed, so neither alias existed. 1. Text save through a final link. The classic upload over an existing name had the same gap: 2. Protected folders reached through a link. This applies to every protected folder whose real path is outside the ACL root: an external
Tests.
Also checked over HTTP on a Deployer-style container (
Full |
Follow-up to #2546, which broke the media browser for restricted managers on shared storage, plus the file-manager link model that the shared-storage case needed.
Why images broke after #2546
#2546 mapped a shared type folder (
rb_base_diroutside the release,assets/imagesa symlink to it) back to its oldassets/images/...file-group keys, and refused everything when it could not prove the mapping. It took the site-side spelling from KCFinder'stypeURL, which KCFinder builds by resolving a relativerb_base_urlagainst the browser script's working directory andDOCUMENT_ROOT:assets/becomes/manager/media/browser/mcpuk/assets/images;current, hostingpublic_html):path::rel2abs_url()returnsfalse, sotypeURLis/images.The mapping therefore never matched, and every group check refused: managers who are not administrators, with "Use access permissions" on, got an empty, read-only browser. Administrators were not affected. The #2546 tests set
typeURLto the correct value by hand, so they never saw it.Changes
config.phppasses the configuredrb_base_urlas_siteUploadURL(the leading_keeps it out of the session override), andgetFileGroupsRelPath()uses it instead oftypeURL. A type folder that the site serves from outside a narrowedfilemanager_pathcarries no file groups again (no row can name it), instead of refusing every action...past a link is refused: it climbs in the link's target, not back where the server walks.fileManagerStoredName()).assets/imageswhen it links to shared storage, with the browser's keys, so groups there can be edited again. The link that stands for a type folder is listed as a folder and is never deleted, renamed or unlinked.SharedTypeRootRequestTestruns the real browser constructor andconfig.phpwith$_SERVERand the working directory ofbrowse.php, through apublic_html -> evolution -> evo-3.6.2chain, for three layouts (canonical root, linked root,rb_base_dirin shared storage). The older link tests now use links that stay inert whatever the environment (loops, second names); the positive cases run in separate processes, because which links pass depends on the site settings.background-colorpaints the glyph and the mask clips the border: the inactive view toggle was white on white, and a selected toolbar button (Settings) showed a blue icon on blue. The toggle button is now drawn on the label and the glyphs takecurrentColor.The file-manager section of
AGENTS.mddescribes the link model.Known limits
FollowSymLinksdoes not serve a linked folder that the CMS now opens to managers; that is the operator's choice.Verification
tests/Unit tests/Featureon PHP 8.4 (Linux): all green exceptPhpThumbCacheImagesTest, which readsng.inxand fails only in agit archivecopy (the file isexport-ignore).current -> releases/1,assets/images -> ../../../shared/assets/images,rb_base_dir=/data/www/shared/assets/): a restricted manager lists, uploads to and creates folders innewsand does not see the HR-onlyhrfolder; the dashboard shows no path warning.🤖 Generated with Claude Code