-
-
Notifications
You must be signed in to change notification settings - Fork 19
fix(policy): reject access to undefined models #499
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThe PR marks a TODO item as completed and introduces validation logic to reject policy operations targeting nonexistent models. A new private helper method Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 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 Code Review Complete ✅I've conducted a comprehensive review of this PR which adds validation to reject access to undefined/non-existent models in the policy system. Here's my detailed analysis: Review Checklist
Review SummaryThis is a solid security improvement that prevents access to models not defined in the schema. The implementation is clean, well-tested, and follows established patterns in the codebase. Code Quality ⭐⭐⭐⭐⭐Strengths:
Security Assessment ⭐⭐⭐⭐⭐Excellent security enhancement:
Test Coverage ⭐⭐⭐⭐⭐Comprehensive test coverage in
Performance Impact ⭐⭐⭐⭐⭐Minimal performance overhead:
Potential Issues & SuggestionsMinor suggestions:
Code style note:
Architecture Alignment ⭐⭐⭐⭐⭐
Recommendation: APPROVE ✅This PR effectively closes a potential security gap by preventing access to undefined models. The implementation is robust, well-tested, and maintains good performance characteristics. The code quality meets high standards and follows established patterns in the codebase. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds security enforcement to reject queries accessing database tables that are not defined in the schema. The policy handler now validates that all tables referenced in queries correspond to either schema-defined models or implicit many-to-many join tables before processing them.
Key Changes
- Added
tryRejectNonexistentModel()method to validate model existence before allowing operations - Integrated validation checks at three key points: mutations, joins, and SELECT FROM clauses
- Comprehensive test coverage for various query operations against undefined tables
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
packages/plugins/policy/src/policy-handler.ts |
Implements the tryRejectNonexistentModel() method and calls it at strategic points (mutations, joins, and FROM clause processing) to reject access to undefined models |
tests/e2e/orm/policy/nonexistent-models.test.ts |
Adds comprehensive test coverage verifying that all types of operations (read, create, update, delete, join) are properly rejected when accessing tables not defined in the schema |
TODO.md |
Updates the TODO list to mark "Accessing tables not in the schema" as completed |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
tests/e2e/orm/policy/nonexistent-models.test.ts (1)
31-57: LGTM - Comprehensive coverage of policy rejection scenarios.The test thoroughly validates that all operations (read, join, create, update, update-with-from, delete) on the nonexistent Bar table are rejected by policy. This directly exercises the new
tryRejectNonexistentModel()validation introduced inpolicy-handler.ts.Minor observation: Line 39 attempts to insert with
id: '1'which duplicates the existing row from line 23. While the policy rejection will prevent this from reaching the database, using a unique id like'2'would make the test intent clearer.Consider this optional clarification:
// create -await expect(db.$qb.insertInto('Bar').values({ id: '1', string: 'test' }).execute()).toBeRejectedByPolicy(); +await expect(db.$qb.insertInto('Bar').values({ id: '2', string: 'test' }).execute()).toBeRejectedByPolicy();
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
TODO.md(1 hunks)packages/plugins/policy/src/policy-handler.ts(4 hunks)tests/e2e/orm/policy/nonexistent-models.test.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
tests/e2e/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
E2E tests should validate real-world schema compatibility with established projects
Files:
tests/e2e/orm/policy/nonexistent-models.test.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to **/*.zmodel : ZModel schema files should define database structure and policies that compile to TypeScript via `zenstack generate`
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to packages/zenstackhq/orm/**/*.test.{ts,tsx} : ORM package tests should include comprehensive client API tests and policy tests
Applied to files:
tests/e2e/orm/policy/nonexistent-models.test.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to tests/e2e/**/*.{ts,tsx} : E2E tests should validate real-world schema compatibility with established projects
Applied to files:
tests/e2e/orm/policy/nonexistent-models.test.ts
🧬 Code graph analysis (1)
tests/e2e/orm/policy/nonexistent-models.test.ts (1)
packages/testtools/src/client.ts (1)
createPolicyTestClient(258-269)
🪛 markdownlint-cli2 (0.18.1)
TODO.md
107-107: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Agent
- GitHub Check: build-test (20.x, sqlite)
- GitHub Check: build-test (20.x, postgresql)
- GitHub Check: claude-review
🔇 Additional comments (8)
TODO.md (1)
107-107: LGTM - TODO item appropriately marked as complete.The checkbox toggle correctly reflects the new policy enforcement that rejects access to nonexistent models, implemented in
packages/plugins/policy/src/policy-handler.ts.Note: The markdownlint indentation warning appears to be a style preference issue, as the 4-space indentation is consistent with other items at the same nesting level (lines 103-106).
tests/e2e/orm/policy/nonexistent-models.test.ts (3)
1-3: LGTM - Imports are correct.The test properly imports the policy test client and testing utilities.
6-24: LGTM - Test setup correctly creates the scenario for testing nonexistent model access.The test appropriately:
- Defines a Foo model in the schema with permissive policies
- Creates a Bar table outside the schema via raw SQL
- Sets up test data for both tables
This aligns with the E2E testing guidelines for validating real-world schema compatibility.
25-28: LGTM - Validation checks are correct.The test correctly verifies:
db.baris undefined since Bar is not in the schema- Unknown relation field access is rejected by validation (not policy)
packages/plugins/policy/src/policy-handler.ts (4)
1019-1023: LGTM - Validation logic correctly rejects nonexistent models.The implementation properly:
- Checks model existence using
QueryUtils.hasModel- Excludes many-to-many join tables which are implicitly created
- Throws an appropriate policy error with
NO_ACCESSreasonThe method name uses the "try" prefix which could suggest it returns a boolean, but the "try and reject if needed" pattern is acceptable here.
93-93: LGTM - Early validation prevents mutations on nonexistent models.The call is correctly placed after extracting the mutation model and before any pre-mutation policy work. This ensures fast rejection of invalid operations.
336-336: LGTM - Join validation rejects references to nonexistent tables.The check correctly validates that the joined table exists in the schema before building policy filters. This prevents joins with tables outside the schema definition.
879-879: LGTM - Read policy validation rejects nonexistent tables in FROM/USING clauses.The check ensures all tables referenced in read operations exist in the schema before building policy filters. This validation applies to tables in FROM clauses, USING clauses (for DELETE), and join references.
Summary by CodeRabbit
Bug Fixes
Tests
✏️ Tip: You can customize this high-level summary in your review settings.