wheels: Scope chains are ignored by findByKey() and exists(key=)
What fixes it
- 4.2.0wheels, otherGitHub
A fixed version on one release line is not the upgrade target for every line. Check your exact version and any vendor backports.
Description
Impact
Wheels 4.0 added chainable model scopes (model("Book").published().findAll()). Two chain terminals ignore the scope's conditions:
findByKey(key)replaces the merged WHERE clause with the primary-key condition, somodel("Book").published().findByKey(id)returns the record even when it is outside the scope.exists(key=...)on a scope chain or the query builder does the same; in production (error information off) it returns true for an out-of-scope key instead of throwing.
Applications that use scopes for authorization or multi-tenancy (for example a currentTenant or ownedBy(user) scope chained into finders, as the multi-tenancy guide recommends) can therefore load, and then update or delete, records belonging to another user or tenant when the record key comes from the request.
findAll, findOne, findFirst, count and other aggregates, updateAll, deleteAll, findEach and findInBatches respect the scope and are not affected.
Patches
Fixed in 4.2.0. findByKey(), exists(key=...), updateByKey() and deleteByKey() now combine the key condition with an incoming scope chain, query builder or where argument (AND) instead of replacing it, so a key outside the scope matches nothing. Lookups with no where are unchanged.
Workarounds
Use findOne(where="id = #key#") or findAll(where=...) on the scope chain instead of findByKey, or check ownership explicitly after loading the record.
Text from GitHub Advisory Database
Affected versions 1
- wheels, other>= 4.0.0, <= 4.1.2GitHub