T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- api.md:23
- Finding
- Anonymous PostgREST Role Has Unrestricted Read and Write Access<![CDATA[ ## Vulnerability Details **File Location**: `api.md:23-50, 61-66, 92-98, 122-126`; also documented in `database.md:35-36` **Vulnerability Type**: Broken access control and excessive database privileges **Risk Level**: High ### Vulnerable Code ```markdown ## Verified PostgREST usage The `anon` role has full table access (granted by `db-setup`), so reads AND writes to the tables work without tokens. Tested live from inside the app container: ```bash # read (anon) - verified wget -qO- 'http://postgrest:3000/Build?select=id,projectId&limit=2' wget -qO- 'http://postgrest:3000/Project?select=id,title,domain&limit=3' # write (anon) - verified (returns the inserted row) wget -qO- --post-data='{"name":"x.txt","format":"text/plain","size":10}' \ --header='Content-Type: application/json' --header='Prefer: return=representation' \ 'http://postgrest:3000/File?select=name,format' # RPCs (verified) - see the full RPC list in the OpenAPI spec below wget -qO- --post-data='{"project_id":"<id>","from_build_id":"<id>"}' \ --header='Content-Type: application/json' \ 'http://postgrest:3000/rpc/restore_development_build' # -> "OK" wget -qO- --post-data='{"project_id":"<id>","deployment":"<name>"}' \ --header='Content-Type: application/json' \ 'http://postgrest:3000/rpc/create_production_build' # -> a Build id; sets deployment + PUBLISHED ``` To see the full anon-queryable surface (tables + RPCs), fetch the OpenAPI spec: ```bash wget -qO- http://postgrest:3000/ # swagger 2.0 JSON; paths = tables + /rpc/* ``` ``` The exposed schema includes sensitive and authorization-related tables: ```markdown - `AuthorizationToken` - `{token, projectId, name, relation, canClone, canCopy, canPublish, canUseApi}` - `User`, `Workspace`, `WorkspaceMember` - auth / multi-tenancy ``` ### Technical Analysis PostgREST derives API authorization from PostgreSQL roles, grants, and row-level security policies. Granting the anonymous role unrestricted access to all ...[truncated 2060 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Revoke blanket schema and table privileges from the PostgREST anonymous role. 2. Enable PostgreSQL row-level security on every tenant- or project-scoped table. 3. Prevent anonymous access to `AuthorizationToken`, `User`, `Workspace`, `WorkspaceMember`, domain, and administrative tables. 4. Require validated JWTs for PostgREST access and derive project/workspace scope from authenticated claims. 5. Expose narrowly scoped views or security-reviewed RPCs instead of the entire public schema. 6. Give each service a separate database role with only the operations it requires. 7. Apply explicit authorization checks inside all security-definer RPCs and set a safe `search_path`. 8. Restrict the Compose network so only required services can reach PostgREST. 9. Add automated tests proving unauthenticated requests receive `401` or `403` and cannot enumerate the OpenAPI schema. 10. Rotate authorization tokens if this configuration has ever been reachable by untrusted workloads. ]]>
