Pin session cookie name, stop deriving it from APP_NAME - #1585
Open
pilotso11 wants to merge 1 commit into
Open
Conversation
Heimdall doesn't ship a config/session.php, so the cookie name falls
back to Laravel's framework default:
Str::snake((string) env('APP_NAME', 'laravel')) . '_session'
Str::snake() only inserts underscores before capital letters; it does
not strip characters like "." or spaces. PHP mangles dots in incoming
cookie/GET/POST variable names to underscores when parsing a request,
so an APP_NAME containing a dot (e.g. "example.com") produces a cookie
the app can never read back: it looks for "example.com_session" but
PHP only ever hands it "example_com_session" in $_COOKIE.
That desyncs the session on every single request, so the CSRF token
embedded in any page never matches the token generated on submit,
producing a 419 Page Expired on every POST. Reproduced this with a
bare curl round-trip (fetch page, extract token+cookie, POST back
immediately) with no browser involved at all, which rules out any
browser-specific cause like cookie caching or extensions - this is a
server-side PHP request-parsing behavior, not a browser quirk.
Root cause and fix were worked out with Claude Code: it decrypted the
session cookie server-side and confirmed the mismatch with a $_COOKIE
probe against config('session.cookie') on a live instance where this
was happening.
This matches the symptoms in several previously-reported, unresolved
419 issues:
- linuxserver#398 - Getting 419 error code when trying to add apps
- linuxserver#443 - 419 "Sorry, your session has expired" when submitting new app
- linuxserver#590 - 419 error when hitting save
- linuxserver#873 - 419 Page Expired doing any POST requests
Setting SESSION_COOKIE explicitly in .env already works around this
today (the framework default respects it), but nothing points users
at that until they've already hit the bug. Adding config/session.php
pins the cookie name to a fixed value by default (still overridable
via SESSION_COOKIE) so it no longer depends on APP_NAME at all, fixing
it out of the box for new and existing installs alike.
App-level config files merge over the framework's defaults key by key
(Illuminate\Foundation\Bootstrap\LoadConfiguration), so this only
needs to override the one key - verified the rest of session.* still
resolves from the framework defaults unchanged.
pilotso11
force-pushed
the
fix/session-cookie-appname-dot
branch
from
August 8, 2026 21:40
58da435 to
0620ec2
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Heimdall doesn't ship a
config/session.php, so the session cookie name falls back to Laravel's framework default:Str::snake()only inserts underscores before capital letters — it does not strip characters like.or spaces. PHP mangles dots in incoming cookie/GET/POST variable names to underscores when parsing a request, so anAPP_NAMEcontaining a dot (e.g.example.com) produces a cookie the app can never read back: it looks forexample.com_session, but PHP only ever hands itexample_com_sessionin$_COOKIE.That desyncs the session on every single request, so the CSRF token embedded in any page never matches the token generated on submit, producing a 419 Page Expired on every POST. Reproduced this with a bare
curlround-trip (fetch page, extract token+cookie, POST back immediately) with no browser involved at all, which rules out any browser-specific cause like cookie caching or extensions — this is a server-side PHP request-parsing behavior, not a browser quirk.Root cause and fix were worked out with Claude Code: it decrypted the session cookie server-side and confirmed the mismatch with a
$_COOKIEprobe againstconfig('session.cookie')on a live instance where this was happening.This matches the symptoms in several previously-reported, unresolved 419 issues:
Setting
SESSION_COOKIEexplicitly in.envalready works around this today (the framework default respects it), but nothing points users at that until they've already hit the bug. Addingconfig/session.phppins the cookie name to a fixed value by default (still overridable viaSESSION_COOKIE) so it no longer depends onAPP_NAMEat all — fixing it out of the box for new installs and, since it ships with the code, for existing broken installs on upgrade too.