@soulbatical/tetra-dev-toolkit 1.17.0 → 1.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -280,6 +280,35 @@ function isWideOpen(using) {
280
280
  return using.trim() === 'true' || using.trim() === '(true)'
281
281
  }
282
282
 
283
+ /**
284
+ * Forbidden patterns in RLS policies — these bypass RLS and defeat the purpose.
285
+ * Valid patterns (from sparkbuddy-live):
286
+ * - organization_id IN (SELECT auth_admin_organizations())
287
+ * - user_id = auth.uid()
288
+ * - USING(true) for public tables only
289
+ * - Subquery to parent table with org/user check
290
+ *
291
+ * Everything else that grants blanket access is a security hole.
292
+ */
293
+ const FORBIDDEN_RLS_PATTERNS = [
294
+ { pattern: /service_role/i, label: 'service_role bypass' },
295
+ { pattern: /current_setting\s*\(\s*'role'/i, label: 'PostgreSQL role check bypass' },
296
+ { pattern: /current_setting\s*\(\s*'request\.jwt\.claims'/i, label: 'JWT claims role bypass' },
297
+ { pattern: /session_user\s*=\s*'postgres'/i, label: 'session_user postgres bypass' },
298
+ { pattern: /current_user\s*=\s*'postgres'/i, label: 'current_user postgres bypass' },
299
+ { pattern: /auth\.role\s*\(\)\s*=\s*'service_role'/i, label: 'auth.role() service_role bypass' },
300
+ { pattern: /pg_has_role/i, label: 'pg_has_role bypass' },
301
+ ]
302
+
303
+ /**
304
+ * Check if a USING/WITH CHECK clause contains forbidden bypass patterns
305
+ * Returns array of { label } for each forbidden pattern found
306
+ */
307
+ function findForbiddenPatterns(clause) {
308
+ if (!clause) return []
309
+ return FORBIDDEN_RLS_PATTERNS.filter(({ pattern }) => pattern.test(clause)).map(({ label }) => label)
310
+ }
311
+
283
312
  export async function run(config, projectRoot) {
284
313
  const results = {
285
314
  passed: true,
@@ -446,6 +475,27 @@ export async function run(config, projectRoot) {
446
475
  }
447
476
  }
448
477
 
478
+ // CHECK 4b: No forbidden bypass patterns in any policy clause
479
+ for (const p of policies) {
480
+ const usingViolations = findForbiddenPatterns(p.using)
481
+ const checkViolations = findForbiddenPatterns(p.withCheck)
482
+ const allViolations = [...new Set([...usingViolations, ...checkViolations])]
483
+
484
+ if (allViolations.length > 0) {
485
+ results.passed = false
486
+ results.findings.push({
487
+ file: p.file,
488
+ line: 1,
489
+ type: 'rls-bypass-pattern',
490
+ severity: 'critical',
491
+ message: `Policy "${p.name}" on table "${tableName}" contains forbidden bypass pattern(s): ${allViolations.join(', ')}. RLS policies must ONLY use auth.uid(), auth_admin_organizations(), or parent-table subqueries. Service role bypasses RLS automatically — adding it to policies defeats the purpose.`,
492
+ fix: `Remove the bypass clause. Valid patterns: USING (organization_id IN (SELECT auth_admin_organizations())) or USING (user_id = auth.uid()).`
493
+ })
494
+ results.summary.critical++
495
+ results.summary.total++
496
+ }
497
+ }
498
+
449
499
  // CHECK 5: Write policies (INSERT/UPDATE) must have WITH CHECK for org isolation
450
500
  if (cfg.accessLevel === 'admin' || cfg.accessLevel === 'user') {
451
501
  const writePoilciesWithoutCheck = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soulbatical/tetra-dev-toolkit",
3
- "version": "1.17.0",
3
+ "version": "1.17.1",
4
4
  "publishConfig": {
5
5
  "access": "restricted"
6
6
  },