Skip to content

fix(collections): check .permitted so permission filters take effect - #821

Open
bencap wants to merge 1 commit into
release-2026.2.7.1from
bugfix/bencap/collection-membership-leakage
Open

fix(collections): check .permitted so permission filters take effect#821
bencap wants to merge 1 commit into
release-2026.2.7.1from
bugfix/bencap/collection-membership-leakage

Conversation

@bencap

@bencap bencap commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

PermissionResponse defined no __bool__, so the object was always truthy. routers/collections.py was the only module testing the response directly rather than reading .permitted, which left every permission check in it inert.

  • 18 association filters kept every member, disclosing the URNs of private score sets and experiments to any caller who could read the collection
  • 6 roster checks never took their narrowing branch, disclosing the full collection user roster, names and ORCID iDs included, to non-admins and to anonymous readers of public collections

Raise TypeError from PermissionResponse.__bool__ so a bare if has_permission(...) cannot be written again.

Collapse the six duplicated roster blocks into
_narrow_user_roles_for_non_admins and route list_my_collections through it as well. That endpoint held the only working version of the rule, gating on the caller's own collection role; sharing one implementation stops the two endpoints drifting apart again. The rule is Action.ADD_ROLE: whoever may add a user to a collection may see who is in it.

Four existing tests asserted that editors and viewers see themselves in the roster, which was the bug's behaviour rather than the intended rule, and now expect the narrowed roster that list_my_collections has always returned.

New tests cover both disclosures from the outside via response bodies, the roster rule parameterized over each contribution role, and the fact that the newly active filters must not delete the association rows they decline to show, since they assign to delete-orphan collections.

Closes #822

`PermissionResponse` defined no `__bool__`, so the object was always
truthy. `routers/collections.py` was the only module testing the
response directly rather than reading `.permitted`, which left every
permission check in it inert.

- 18 association filters kept every member, disclosing the URNs of
  private score sets and experiments to any caller who could read the
  collection
- 6 roster checks never took their narrowing branch, disclosing the
  full collection user roster, names and ORCID iDs included, to
  non-admins and to anonymous readers of public collections

Raise `TypeError` from `PermissionResponse.__bool__` so a bare
`if has_permission(...)` cannot be written again.

Collapse the six duplicated roster blocks into
`_narrow_user_roles_for_non_admins` and route `list_my_collections`
through it as well. That endpoint held the only working version of the
rule, gating on the caller's own collection role; sharing one
implementation stops the two endpoints drifting apart again. The rule
is `Action.ADD_ROLE`: whoever may add a user to a collection may see
who is in it.

Four existing tests asserted that editors and viewers see themselves in
the roster, which was the bug's behaviour rather than the intended
rule, and now expect the narrowed roster that `list_my_collections`
has always returned.

New tests cover both disclosures from the outside via response bodies,
the roster rule parameterized over each contribution role, and the
fact that the newly active filters must not delete the association
rows they decline to show, since they assign to `delete-orphan`
collections.
@coveralls

Copy link
Copy Markdown

Coverage Report for CI Build 31213077228

Warning

No base build found for commit 20af8f3 on release-2026.2.7.1.
Coverage changes can't be calculated without a base build.
If a base build is processing, this comment will update automatically when it completes.

Coverage: 89.269%

Details

  • Patch coverage: 2 uncovered changes across 2 files (17 of 19 lines covered, 89.47%).

Uncovered Changes

File Changed Covered %
src/mavedb/lib/permissions/models.py 2 1 50.0%
src/mavedb/routers/collections.py 17 16 94.12%

Coverage Regressions

Requires a base build to compare against. How to fix this →


Coverage Stats

Coverage Status
Relevant Lines: 14248
Covered Lines: 12719
Line Coverage: 89.27%
Coverage Strength: 0.89 hits per line

💛 - Coveralls

@bencap
bencap marked this pull request as ready for review August 7, 2026 21:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Permission checks in the collections router were inert, disclosing private members and the user roster

2 participants