-
-
Notifications
You must be signed in to change notification settings - Fork 181
feat: RLS Policy Playground API endpoints #1037
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
base: master
Are you sure you want to change the base?
feat: RLS Policy Playground API endpoints #1037
Conversation
Adds new API endpoints for simulating and debugging Row Level Security policies: - GET /rls-playground/roles - List available database roles - GET /rls-playground/tables?schema=X - List tables with RLS status - GET /rls-playground/policies/:schema/:table - Get policies for a table - GET /rls-playground/rls-status/:schema/:table - Check if RLS is enabled - POST /rls-playground/simulate - Run policy simulation with custom context - POST /rls-playground/evaluate-expression - Test single policy expression The simulation endpoint allows users to: - Set a database role (anon, authenticated, service_role, custom) - Provide JWT claims to simulate auth.jwt() - See which rows are accessible under the simulated context - Get policy-by-policy evaluation results for debugging All simulations run in rolled-back transactions for safety.
⛔ Snyk checks have failed. 3 issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
| const pgMeta = new PostgresMeta(config) | ||
| const rlsPlayground = new PostgresMetaRLSPlayground(pgMeta.query) | ||
|
|
||
| const { data, error } = await rlsPlayground.simulate({ |
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.
SQL Injection
Unsanitized input from the HTTP request body flows into query, where it is used in an SQL query. This may result in an SQL Injection vulnerability.
Line 123 | CWE-89 | Priority score 900 | Learn more about this vulnerability
Data flow: 18 steps
Step 1 - 4
| const { schema, table, operation, context, limit, testData } = request.body |
Step 5 - 6 src/server/routes/rls-playground.ts#L124
Step 7 src/server/routes/rls-playground.ts#L123
Step 8 src/lib/PostgresMetaRLSPlayground.ts#L106
Step 9 src/lib/PostgresMetaRLSPlayground.ts#L108
Step 10 - 13 src/lib/PostgresMetaRLSPlayground.ts#L271
Step 14 src/lib/PostgresMetaRLSPlayground.ts#L308
Step 15 src/lib/PostgresMetaRLSPlayground.ts#L289
Step 16 src/lib/PostgresMetaRLSPlayground.ts#L141
Step 17 - 18
| const { data: simResult, error: simError } = await this.query(simulationSql) |
| const pgMeta = new PostgresMeta(config) | ||
| const rlsPlayground = new PostgresMetaRLSPlayground(pgMeta.query) | ||
|
|
||
| const { data, error } = await rlsPlayground.evaluateExpression({ |
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.
SQL Injection
Unsanitized input from the HTTP request body flows into query, where it is used in an SQL query. This may result in an SQL Injection vulnerability.
Line 167 | CWE-89 | Priority score 900 | Learn more about this vulnerability
Data flow: 21 steps
Step 1 - 4
| const { schema, table, expression, context, testRow } = request.body |
Step 5 - 6 src/server/routes/rls-playground.ts#L168
Step 7 src/server/routes/rls-playground.ts#L167
Step 8 src/lib/PostgresMetaRLSPlayground.ts#L403
Step 9 src/lib/PostgresMetaRLSPlayground.ts#L405
Step 10 - 13 src/lib/PostgresMetaRLSPlayground.ts#L416
Step 14 - 15 src/lib/PostgresMetaRLSPlayground.ts#L424
Step 16 src/lib/PostgresMetaRLSPlayground.ts#L420
Step 17 src/lib/PostgresMetaRLSPlayground.ts#L436
Step 18 - 19 src/lib/PostgresMetaRLSPlayground.ts#L426
Step 20 - 21
| const { data, error } = await this.query(sql) |
| ORDER BY c.relname | ||
| ` | ||
|
|
||
| const { data, error } = await pgMeta.query(sql) |
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.
SQL Injection
Unsanitized input from an HTTP parameter flows into query, where it is used in an SQL query. This may result in an SQL Injection vulnerability.
Line 222 | CWE-89 | Priority score 900 | Learn more about this vulnerability
Data flow: 13 steps
Step 1 - 7
| const schema = request.query.schema || 'public' |
Step 8 - 9 src/server/routes/rls-playground.ts#L217
Step 10 - 11 src/server/routes/rls-playground.ts#L202
Step 12 - 13
| const { data, error } = await pgMeta.query(sql) |
Security fixes for Snyk HIGH severity issues: 1. Added validateRLSExpression() function to reject dangerous SQL patterns: - DDL statements (CREATE, DROP, ALTER, TRUNCATE) - DML statements (INSERT, UPDATE, DELETE) - Transaction control (COMMIT, ROLLBACK, SAVEPOINT) - Security commands (GRANT, REVOKE, SET ROLE) - Dangerous functions (pg_read_file, pg_terminate_backend, etc.) - Comment injection (-- and /*) - Statement separators (;) 2. evaluateExpression: Now validates user-provided expressions before execution and runs in a READ ONLY transaction that always rolls back 3. buildSelectSimulation: Added expression validation for policy definitions (defense in depth) and proper transaction isolation with ROLLBACK 4. buildInsertSimulation: Added validation for policy.check expressions and uses literal() for policy.id to prevent any potential injection 5. Route validation: Added input length limits and type validation for expression and context.role parameters 6. Limit sanitization: Ensured limit parameter is always a safe integer
Summary
This PR adds new API endpoints for simulating and debugging Row Level Security (RLS) policies. RLS debugging is consistently one of the most painful aspects of working with Supabase, and this feature provides a way to test policies without modifying data.
Problem
Debugging RLS policies is currently very difficult:
Solution
New API endpoints under
/rls-playground/:/roles/tables?schema=X/policies/:schema/:table/rls-status/:schema/:table/simulate/evaluate-expressionSimulation Features
The
/simulateendpoint allows:auth.jwt()Safety
All simulations run in rolled-back transactions - no data is ever modified.
Technical Details
PostgresMetaRLSPlaygroundclass insrc/lib/set_config()for context simulationpg-formatliteralsTesting
Manual testing with various RLS configurations. Automated tests can be added in a follow-up.
Related
This PR provides the backend for the Studio RLS Playground UI (separate PR to supabase/supabase).