phase0: frozen error list with 21 findings (10 P0, 7 P1 open, 4 P1 fixed)

This commit is contained in:
Agent Zero
2026-07-31 01:58:43 +02:00
parent 032a7e80a8
commit cdbbc1b6f0
+162
View File
@@ -0,0 +1,162 @@
# Phase 0 — Frozen Error List (P0/P1)
**Date:** 2026-07-31
**Baseline commit:** 11d6faa (tag: v-phase0-baseline)
**Phase 0 commit:** 032a7e8
---
## P0 — Critical Security Issues
### P0-01: All tables owned by SUPERUSER role
- **Severity:** P0
- **Files:** All 123 tables in `public` schema
- **Tables:** ALL
- **Reproduction:** `SELECT tableowner FROM pg_tables WHERE schemaname='public'` → all `crm_user`
- **Target:** Owner = `crm_migration` (NOSUPERUSER, NOBYPASSRLS)
- **Status:** Open — Phase 1
### P0-02: `crm_migration` has BYPASSRLS
- **Severity:** P0
- **Files:** DB role `crm_migration`
- **Reproduction:** `SELECT rolbypassrls FROM pg_roles WHERE rolname='crm_migration'``true`
- **Target:** `ALTER ROLE crm_migration NOBYPASSRLS`
- **Status:** Open — Phase 1
### P0-03: RLS disabled on ~70+ tenant tables
- **Severity:** P0
- **Tables:** contacts, addresses, attachments, ai_*, calendar_*, comm_*, mail_*, workflows, etc.
- **Reproduction:** `SELECT relname FROM pg_class WHERE relrowsecurity=false AND relforcerowsecurity=true`
- **Target:** ENABLE ROW LEVEL SECURITY on all tenant tables
- **Status:** Open — Phase 1
### P0-04: Old RLS policies scoped to `{public}` — potential cross-transaction leak
- **Severity:** P0
- **Tables:** ~70+ tables with old `tenant_isolation` policy
- **Reproduction:** `SELECT policyname, roles FROM pg_policies WHERE roles='{public}'`
- **Target:** Drop old policies, create new ones scoped to `{crm_api, crm_worker}`
- **Status:** Open — Phase 1
### P0-05: No separate database connections for auth/api/worker/migration
- **Severity:** P0
- **Files:** `app/config.py`, `app/core/db/__init__.py`
- **Reproduction:** `grep -n 'auth_database_url\|worker_database_url' app/config.py` → not found
- **Target:** 4 separate engines with separate pools and roles
- **Status:** Open — Phase 1
### P0-06: Worker uses `crm_api` role instead of `crm_worker`
- **Severity:** P0
- **Files:** `docker-compose.yml` worker environment
- **Reproduction:** `docker exec leocrm-worker env | grep DATABASE_URL``crm_api`
- **Target:** Worker uses `crm_worker` role
- **Status:** Open — Phase 1
### P0-07: `crm_runtime` legacy role with full CRUD on ALL tables
- **Severity:** P0
- **Files:** DB role `crm_runtime`
- **Reproduction:** `SELECT count(*) FROM information_schema.role_table_grants WHERE grantee='crm_runtime'` → 492
- **Target:** Remove role or revoke all grants
- **Status:** Open — Phase 1
### P0-08: `crm_api` and `crm_worker` have access to `alembic_version`
- **Severity:** P0
- **Tables:** `alembic_version`
- **Reproduction:** `SELECT * FROM information_schema.role_table_grants WHERE table_name='alembic_version' AND grantee IN ('crm_api','crm_worker')`
- **Target:** Revoke access — only `crm_migration` should access alembic_version
- **Status:** Open — Phase 1
### P0-09: `crm_auth` missing `password_reset_tokens` access
- **Severity:** P0
- **Tables:** `password_reset_tokens`
- **Reproduction:** `SELECT * FROM information_schema.role_table_grants WHERE grantee='crm_auth' AND table_name='password_reset_tokens'` → empty
- **Target:** Grant SELECT, INSERT, UPDATE on `password_reset_tokens` to `crm_auth`
- **Status:** Open — Phase 1
### P0-10: `crm_auth` has access to `groups`, `roles`, `user_groups` — too broad
- **Severity:** P0
- **Tables:** `groups`, `roles`, `user_groups`
- **Reproduction:** `SELECT table_name FROM information_schema.role_table_grants WHERE grantee='crm_auth'`
- **Target:** Revoke — auth only needs users, user_tenants, tenants, password_reset_tokens
- **Status:** Open — Phase 1
## P1 — High Priority Issues
### P1-01: `app.tenant_id` legacy variable still set
- **Severity:** P1
- **Files:** `app/core/db/__init__.py:128` (now fixed)
- **Reproduction:** `grep -rn 'app.tenant_id' app/ --include='*.py'` (was setting both vars)
- **Target:** Only `app.current_tenant_id` — FIXED in Phase 0
- **Status:** ✅ Fixed
### P1-02: Cross-plugin import in report_generator
- **Severity:** P1
- **Files:** `app/plugins/builtins/report_generator/jobs.py:79`
- **Reproduction:** `grep 'from app.plugins.builtins.dms' app/plugins/builtins/report_generator/jobs.py`
- **Target:** Use DmsContract via contract registry — FIXED in Phase 0
- **Status:** ✅ Fixed
### P1-03: `test_cross_tenant_security_v2.py` was deleted (contained `§§include()`)
- **Severity:** P1
- **Files:** `tests/test_cross_tenant_security_v2.py`
- **Reproduction:** File did not exist
- **Target:** Recreate with real RLS tests using unprivileged role — FIXED in Phase 0
- **Status:** ✅ Fixed
### P1-04: Existing tests reference `app.tenant_id` in assertions
- **Severity:** P1
- **Files:** `tests/test_cross_tenant_security.py`, `tests/test_cross_tenant_standalone.py`
- **Reproduction:** `grep 'app.tenant_id' tests/test_cross_tenant*.py`
- **Target:** Only test `app.current_tenant_id` — FIXED in Phase 0
- **Status:** ✅ Fixed
### P1-05: No `crm_platform_admin` role defined
- **Severity:** P1
- **Files:** DB roles
- **Reproduction:** `SELECT * FROM pg_roles WHERE rolname='crm_platform_admin'` → not found
- **Target:** Create role for one-time infrastructure setup
- **Status:** Open — Phase 1
### P1-06: No Default Privileges set for future tables
- **Severity:** P1
- **Files:** DB configuration
- **Reproduction:** `SELECT * FROM pg_default_privileges WHERE defaclrole='crm_migration'` → empty
- **Target:** Set default privileges for `crm_migration` owner
- **Status:** Open — Phase 1
### P1-07: Login path uses same DB connection as API
- **Severity:** P1
- **Files:** `app/routes/auth.py`, `app/core/db/__init__.py`
- **Reproduction:** Login endpoint uses `get_db()` (crm_api engine)
- **Target:** Login uses `get_auth_db()` (crm_auth engine)
- **Status:** Open — Phase 1
### P1-08: Startup code accesses tenant tables without tenant context
- **Severity:** P1
- **Files:** `app/main.py:169-231`
- **Reproduction:** Plugin activation during startup may access tenant tables
- **Target:** Per-tenant context for tenant operations
- **Status:** Open — Phase 1
### P1-09: No RLS coverage check automation
- **Severity:** P1
- **Files:** None — needs creation
- **Target:** Automated test/script checking all tenant tables for RLS
- **Status:** Open — Phase 1
### P1-10: `crm_worker` has full CRUD on ALL tables including global tables
- **Severity:** P1
- **Tables:** users, tenants, user_tenants, sessions, plugins, etc.
- **Reproduction:** `SELECT count(*) FROM information_schema.role_table_grants WHERE grantee='crm_worker'` → 492
- **Target:** Narrow to only necessary job/outbox/tenant tables
- **Status:** Open — Phase 1
---
## Summary
| Status | Count |
|--------|-------|
| Open (P0) | 10 |
| Open (P1) | 7 |
| Fixed (P1) | 4 |
| Total | 21 |