payloadcms / payloadcms/payload
findVersionByID (collection and global) never runs sanitizeWhereQuery on the merged access-control where, unlike every other read operation
- Dominant language
- TypeScript
- Stars
- 44.8k
- Forks
- 4.2k
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 53
Description
Every other read operation sanitizes the merged where before handing it to the db layer: findByID.ts, findVersions.ts (line 110), countVersions.ts, find.ts, count.ts and findDistinct.ts all call sanitizeWhereQuery({ fields, payload, where }) on the combined access-control where so relationship-backed virtual fields referenced in an access function's returned where get rewritten to their real underlying path.
Both findVersionByID.ts (collections/operations/findVersionByID.ts) and its global counterpart (globals/operations/findVersionByID.ts) skip this step entirely, the merged where from combineQueries(where, accessResults) goes straight to payload.db.findVersions/findGlobalVersions.
Concretely: if a collection or global's access.readVersions returns a where constraint on a virtual field (e.g. a field defined as virtual: 'related.label'), every other read operation would resolve that to the real path first. findVersionByID doesn't, so the db layer gets an unresolvable virtual field path and the lookup silently returns nothing, the caller sees Forbidden/NotFound instead of the correct version.
I found PR #17804 which implements exactly this fix ("fix: sanitize where query on findVersionByID for inherited read access", explicitly noting "findByID, findVersions, and countVersions all sanitize the merged where in the same spot"), but it targets a feature branch (codex/pyld-3081-versions-access-control), not main, and I don't see any open or merged PR bringing it into main. Confirmed against the current main HEAD that both files still lack the sanitizeWhereQuery call.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with collections/operations/findVersionByID.ts and globals/operations/findVersionByID.ts, then compare their merged access-control where handling with findByID.ts, findVersions.ts, countVersions.ts, find.ts, count.ts, and findDistinct.ts. Verify the behavior against the virtual-field example described in the issue and confirm both version lookup paths sanitize the merged where before the database call.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- authorization, backend-api-design
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100