Skip to content

fix: enforce tenant isolation on multi-tenant session and login#11

Merged
mindsers merged 3 commits intomainfrom
fix/cross-tenant-session-leakage
Apr 10, 2026
Merged

fix: enforce tenant isolation on multi-tenant session and login#11
mindsers merged 3 commits intomainfrom
fix/cross-tenant-session-leakage

Conversation

@mindsers
Copy link
Copy Markdown
Contributor

@mindsers mindsers commented Apr 10, 2026

Summary

  • Security fix: session cookies shared across *.unitae.app subdomains allowed cross-tenant data access. A user authenticated on one congregation's subdomain could navigate to another subdomain and see their own congregation's data there.
  • Adds resolveCongregationFromRequest() to resolve the congregation from the request hostname (subdomain slug or custom domain), and validates it against the session in verifySession() and the login flow.
  • Scopes validateCredentials() to the subdomain's congregation so login rejects accounts belonging to other tenants (shows generic "Email ou mot de passe invalide" — no information leakage).
  • Adds /congregation-not-found error page for unknown subdomains.
  • All tenant checks are no-ops in single-tenant mode (MULTI_TENANT !== 'true').

Test plan

  • Log into congregation A's subdomain, navigate to congregation B's subdomain → should see congregation B's login page (session destroyed)
  • On congregation B's login page, enter congregation A's credentials → should get "Email ou mot de passe invalide"
  • Visit fake-slug.unitae.app → should see "Assemblée non trouvée" error page
  • Single-tenant mode (MULTI_TENANT unset) → no behavioral change
  • Custom domain congregation access still works
  • pnpm test:unit — all 316 tests pass
  • pnpm test:typecheck — clean
  • pnpm test:lint — clean

Session cookies shared across *.unitae.app subdomains allowed a user
authenticated on one congregation's subdomain to access their data from
another congregation's subdomain. The login form also accepted any valid
credentials regardless of subdomain.

- Add resolveCongregationFromRequest() to resolve congregation from the
  request hostname (subdomain slug or custom domain)
- Validate tenant match in verifySession(), destroying the session and
  redirecting to /login on mismatch
- Scope validateCredentials() to the subdomain's congregation so login
  rejects accounts belonging to other tenants
- Validate existing sessions in the login loader before auto-redirecting
- Add /congregation-not-found error page for unknown subdomains
- All checks are no-ops in single-tenant mode (MULTI_TENANT !== 'true')
@mindsers mindsers merged commit 6dbac1a into main Apr 10, 2026
4 checks passed
@mindsers mindsers deleted the fix/cross-tenant-session-leakage branch April 10, 2026 06:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant