security/tenant-isolation #28
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "security/tenant-isolation"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fixes the Critical and High findings from the codebase security review.
Critical
2a98ac6): the Host-headersubdomain flowed unvalidated into a filesystem path and auto-created tenant
DBs. Now charset-validated (invariant on
TenantContext), must be registeredvia
tenant:save, unknown → 404.49a3313): cookie was shared across alltenant subdomains. Now scoped to the exact host,
SameSite=Lax,Securebyreal HTTPS,
session_regenerate_id()on login.c14e95f): identity headers now onlyhonored from a configured trusted proxy (
AUTHELIA_TRUSTED_PROXIES); theHost-based localhost auto-login is removed.
</script>XSS (89a3190): public shared-recipe page now encodeswith
JSON_HEX_*.8ab820f): new SsrfGuard +SafeUrlFetcher (scheme allow-list, private/reserved IP blocking, per-hop
redirect validation, IP pinning, size cap).
High
438d3f3): per-session token, front-controllerenforcement, hidden form fields + HTMX header;
/api/*exempt.a602d82): edits preserved rating/category and nolonger re-emit
RecipeCreated.5bd3430): upsert onid, notname.4218b24): atomic claim, requeue-on-failure, dedup, andUNIQUE(stemmed_name)(migration 020).b4f8c7a).7cb1c69).db64c26):0600/0700, no more0777.Deploy notes
tenant:save(hard-reject policy).AUTHELIA_TRUSTED_PROXIESto the proxy IP in production (see.env.example).020addsUNIQUE(stemmed_name)and dedupes existing catalog rows.Verification
160 tests pass; phpstan level 8 clean.
The tenant id was taken from the Host-header subdomain and used unvalidated both as a filesystem path (var/tenant_<id>.sqlite) and as the tenant selector. An attacker-controlled Host could therefore traverse the filesystem, and any well-formed subdomain silently auto-provisioned a fresh tenant database, undermining tenant isolation. - TenantContext enforces ^[a-z0-9-]{1,63}$ as a constructor invariant (empty string remains the "no tenant" sentinel), so a malformed id can no longer be constructed. - SubdomainTenantDetector now requires a present subdomain to be both charset-valid and registered via `tenant:save`; otherwise it throws UnknownTenantException. A bare host (e.g. localhost) still maps to the default tenant for local development. - The front controller maps UnknownTenantException to a 404 so unregistered subdomains cannot auto-provision. - TenantAwarePdoFactory re-validates the id at the filesystem sink (defense in depth) and creates var/ as 0750 instead of 0777. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>