PHP's session extension has three settings that matter for security, and out of the box all three default to the less secure option. This RFC from Jorg Sowa flips those defaults, so a fresh PHP install is safer without any code changes.
What changes#
| Setting |
Old default |
New default |
session.use_strict_mode |
0 |
1 |
session.cookie_httponly |
0 |
1 |
session.cookie_samesite |
not set |
Lax |
Here's what each one does:
use_strict_mode prevents session fixation, where an attacker plants a session ID they know and waits for you to log in with it. With strict mode on, PHP rejects any ID it doesn't already have stored and generates a fresh one instead.
cookie_httponly hides the session cookie from JavaScript, so a script on the page, including one injected by an attacker, can't read it through document.cookie. PHP has supported this setting since PHP 5.2.0.
cookie_samesite=Lax stops the browser from sending the session cookie with most cross-site requests, which helps block cross-site request forgery. Chrome, Firefox and Edge already treat cookies this way by default. Safari doesn't, so setting it in PHP makes every browser behave the same.
Laravel, Symfony, Django and ASP.NET Core already default to HttpOnly and Lax. Each change is a one-line edit in PHP's source, with no new settings or functions.
What it means for existing code#
Most apps won't notice, but a few patterns will break:
- Passing your own session ID with the files handler, like sharing one ID between subdomains. It gets rejected. The fix is to call
session_write_close() on the first side before the other side uses the ID. Handlers that always report an ID as valid, like the default Redis and Memcached handlers, aren't affected.
- Reading the session cookie in JavaScript stops working. The RFC suggests using a separate token that JavaScript is allowed to read.
- Cross-site POST requests that need the session, like some SAML login flows. You'll need to set
SameSite=None; Secure for those endpoints, or switch to a token-based flow.