fix(files_sharing): enforce minimum search length in getUsers() and getGroups()#41580
fix(files_sharing): enforce minimum search length in getUsers() and getGroups()#41580DeepDiver1975 wants to merge 3 commits into
Conversation
…etGroups() The admin-configurable user.search_min_length was only enforced in getRemote() via isSearchable() but not in getUsers() or getGroups(). A 1-character search bypassed the intended restriction and allowed authenticated users to enumerate users even when a higher minimum was configured. Add the missing isSearchable() guard to both methods. Signed-off-by: Thomas Müller <thomas.mueller@owncloud.com> Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>
|
Thanks for opening this pull request! The maintainers of this repository would appreciate it if you would create a changelog item based on your changes. |
Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>
… setUp Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>
DeepDiver1975
left a comment
There was a problem hiding this comment.
Code Review — fix(files_sharing): enforce minimum search length in getUsers() and getGroups()
Overview: Adds the missing isSearchable() guard to getUsers() and getGroups() in ShareesController. The remote search path already had this guard; the user/group paths only blocked empty strings, allowing a single-character query to bypass the admin-configured minimum search length.
Correctness
The fix is minimal and consistent — four identical lines added symmetrically to both methods, mirroring the existing pattern in getRemote(). ✅
Test default in setUp(): The willReturn(true) default for isSearchable is the right call — it makes existing tests transparent to the new guard without requiring them all to be updated. New tests override this default. ✅
testGetUsersBlocksShortSearchTerm: Correctly asserts:
isSearchable('a')returnsfalseuserManager->find()is never called- result
usersarray is empty
✅
testGetGroupsBlocksShortSearchTerm: Correctly asserts:
isSearchable('a')returnsfalsegroupManager->search()is never called- result
groupsarray is empty
✅
One minor observation: Both new tests call $this->userSearch->expects($this->any())->method('getSearchMinLength'). isSearchable() is what the production code calls; getSearchMinLength isn't directly invoked by the patched code paths. This any() expectation is unreferenced and effectively dead — harmless but slightly confusing. Not blocking.
Changelog
The changelog entry in changelog/unreleased/41580 accurately describes the bypass and the fix. ✅
Summary
| Aspect | Assessment |
|---|---|
| Fix | ✅ Consistent, minimal — mirrors existing getRemote() pattern |
| Tests | ✅ Both new cases assert backend is never queried for short terms |
| Test default | ✅ setUp() default willReturn(true) doesn't break existing tests |
| Changelog | ✅ Accurate and clear |
Verdict: Ready to merge.
Summary
getUsers()andgetGroups()inShareesControlleronly blocked empty strings, not strings shorter than the admin-configureduser.search_min_lengthisSearchable()was already enforced ingetRemote()but not in the other two search methodsisSearchable()guard, closing the bypassSecurity Impact
Low — authenticated-only endpoint; bypass only relevant when admin raises min length above default
Test plan
testGetUsersBlocksShortSearchTerm()andtestGetGroupsBlocksShortSearchTerm()assert that backends are never queried when search term is below configured minimummake test TEST_PHP_SUITE=apps/files_sharing🤖 Generated with Claude Code