Skip to content

Defer __Host- session-cookie prefix (no native Better Auth support) #824

Description

@zachdunn

Deferred from #731 phase E, which listed the __Host- cookie prefix as an optional final step. On investigation it's not the clean flag the plan assumed, so we're holding it deliberately rather than shipping a workaround now.

Current state (already strong)

The production session cookie is __Secure-better-auth.session_token:

What __Host- would add

A __Host--named cookie cannot carry a Domain attribute, so a sibling subdomain cannot set/overwrite it for the apex origin. This closes one specific vector the current cookie does not: subdomain session fixation — an attacker with code execution on a user-content subdomain (storage/store/embed.uploads.sh serve untrusted bytes; see the stored-XSS note in apps/api/src/guards.ts) could plant Set-Cookie: Domain=uploads.sh; __Secure-better-auth.session_token=<attacker session>, shadowing the victim's cookie so the victim operates inside the attacker's session. __Host- prevents the subdomain from setting it at all.

Narrow but real: it requires a chained compromise (code-exec on a content subdomain) before it's exploitable.

Why it's held, not shipped

Better Auth (1.7.1 and current main) has no native __Host- support — the cookie writer only ever prepends __Secure- (or nothing); there is no __Host- toggle. Achieving it today is a workaround:

  • prod-gated cookiePrefix: "__Host-better-auth" and useSecureCookies: false (to stop the auto __Secure- prefix double-prefixing the name) and defaultCookieAttributes: { secure: isProduction } to re-assert Secure;
  • gated to production so dev / stack-raw over http://127.0.0.1 still work (__Host-/Secure cookies are rejected over http);
  • it renames every Better Auth cookie, so it also needs the hardcoded clearer in apps/web/src/lib/auth-proxy.ts updated and an audit that no plugin cookie (OAuth state/PKCE, device, magic-link) uses a non-/ path (which __Host- silently breaks);
  • and it forces a one-time re-login for every web user.

Fragile-across-upgrades workaround + forced re-login, for a narrow defense-in-depth gain, is a poor trade right now.

Revisit when

  • Better Auth ships first-class __Host-/host-prefix support — then it's a clean config change worth the one-time re-login; or
  • the user-content subdomain surface grows in a way that raises the fixation risk.

At that point the security rationale above still applies; this is a deliberate deferral, not a rejection.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions