fix(orm): forbid selecting @omit fields when allowQueryTimeOmitOverride is false#2708
Conversation
…de is false (#2671) `allowQueryTimeOmitOverride: false` only guarded the query-time `omit` clause, so an omitted field could still be un-omitted (leaked) via an explicit `select: { field: true }`. The select schema now only accepts `false` for config-omitted fields when query-time override is disallowed, rejecting such selects with a validation error. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughThe PR fixes a security vulnerability where fields marked ChangesOmit Field Protection
Estimated Code Review Effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Claude finished @ymc9's task —— View job PR Review: Security Fix for @omit Field Selection LeakReview Tasks:
SummaryThis PR effectively addresses the security vulnerability where Detailed Review✅ Security Fix QualityThe core fix in
✅ Implementation QualityHelper Function (
Integration:
✅ Test CoverageRegression Test (
Existing tests compatibility: The fix aligns perfectly with existing ✅ Performance & Security
Minor Observations
ConclusionThis is a high-quality security fix that:
Recommendation: ✅ Approve - This PR effectively closes a security gap with minimal, focused changes and comprehensive testing. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
tests/regression/test/issue-2671.test.ts (1)
29-58: ⚡ Quick winAdd one nested-relation regression to lock the recursive enforcement contract.
This suite verifies top-level
selectenforcement well, but it doesn’t assert the same rule through nested relationselectpaths. Adding one relation case would harden the security regression surface against future recursion regressions.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/regression/test/issue-2671.test.ts` around lines 29 - 58, The test misses asserting nested-relation enforcement of omitted fields; add a case that creates a related record (e.g., create a Profile or related model tied to user) and call db.user.findFirst with a nested relation select that attempts to include the omitted field (use db.user.findFirst with select: { relationName: { select: { passwordHash: true } } }) and assert it is rejected via toBeRejectedByValidation when allowQueryTimeOmitOverride is false; also add a complementary nested select that only picks non-omitted fields to assert it still succeeds (use select: { relationName: { select: { email: true } } } and expect the returned shape).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@tests/regression/test/issue-2671.test.ts`:
- Around line 29-58: The test misses asserting nested-relation enforcement of
omitted fields; add a case that creates a related record (e.g., create a Profile
or related model tied to user) and call db.user.findFirst with a nested relation
select that attempts to include the omitted field (use db.user.findFirst with
select: { relationName: { select: { passwordHash: true } } }) and assert it is
rejected via toBeRejectedByValidation when allowQueryTimeOmitOverride is false;
also add a complementary nested select that only picks non-omitted fields to
assert it still succeeds (use select: { relationName: { select: { email: true }
} } and expect the returned shape).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 5542b3f3-52e4-4142-a795-ae17f27b6349
📒 Files selected for processing (2)
packages/orm/src/client/zod/factory.tstests/regression/test/issue-2671.test.ts
Problem
Fixes #2671.
Fields marked with
@omitare excluded from default query results, but they could be leaked by explicitly selecting them viaselect: { field: true }. SettingallowQueryTimeOmitOverride: falsewas supposed to forbid un-omitting fields at query time, but it only guarded theomitclause — theselect-based override path remained open.Fix
makeSelectSchemanow consults a newisFieldOmittedByConfighelper (checking options-level and schema-level omit; query-level is excluded as it's mutually exclusive withselect). WhenallowQueryTimeOmitOverride === falseand a field is omitted by config, its select schema only acceptsfalse(z.literal(false)), soselect: { field: true }is rejected by validation — consistent with howomit: { field: false }is already rejected. This applies recursively to nested relation selects.Default behavior (
allowQueryTimeOmitOverrideunset/true) is unchanged: explicit select of an@omitfield still returns it, by design.Tests
Added
tests/regression/test/issue-2671.test.ts:@omitfield returns itallowQueryTimeOmitOverride: false:select: { passwordHash: true }is rejected; selecting non-omitted fields andselect: { passwordHash: false }still workExisting
omit.test.tssuite still passes.🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Tests