The vulnerability (GHSA-cwwm-hr97-qfxm) in SpiceDB caused incorrect 'NO_PERMISSION' responses for certain permission checks that should have resulted in 'HAS_PERMISSION'. This primarily occurred in schemas where relations involved caveats, and the permission resolution path required evaluating multiple caveated branches, especially when 'arrow' relations (->) were used.
The root cause was traced to how SpiceDB's dispatch graph handled these complex caveated checks. Specifically, the checkTupleToUserset function within internal/graph/check.go (a method of ParallelChecker) did not always ensure that all possible resolution paths were explored when incoming caveats were present. It was missing logic to explicitly require all results (v1.DispatchCheckRequest_REQUIRE_ALL_RESULTS) in such scenarios. This oversight meant that the system might make a premature decision based on incomplete information, particularly if one evaluation path resolved faster but didn't grant permission, while another valid, caveated path was not fully processed.
A secondary, potentially contributing issue, was addressed in the populateFoundSubjects function in internal/developmentmembership/membership.go. If the flawed evaluation of caveated branches led to a situation where an intersection of subject sets resulted in no common subjects (an 'intersection with no children'), the function would previously error out. This error could halt the entire check or prevent other valid branches from being considered, thereby contributing to the incorrect final permission.
The patches address these issues by:
- Modifying
checkTupleToUserset to explicitly set crc.resultsSetting = v1.DispatchCheckRequest_REQUIRE_ALL_RESULTS when dd.hasIncomingCaveats is true, ensuring a thorough evaluation.
- Modifying
populateFoundSubjects to return an empty set instead of an error for empty intersections, improving the robustness of membership resolution.
These changes ensure that caveated checks are evaluated more completely and resiliently, correcting the false negative permission results. Runtime profiles during exploitation or when triggering the bug would likely show these functions being invoked under conditions where their pre-patch logic would lead to an incorrect outcome.