Background
PHP includes a built-in session interface via $_SESSION and session_start(). The default handler in PHP for this interface stores session data in temporary files on the web server. See also https://www.php.net/manual/en/session.configuration.php. Applications like MediaWiki can replace this default by implementing SessionHandlerInterface and calling session_set_save_handler(), after which PHP delegates these built-ins to your implementation.
MediaWiki has its own optimized session handler since 2016 (T111296), but maintained a backwards-compatible wrapper that implements the PHP SessionHandlerInterface, along with a compatible serialization library in the form of the https://gerrit.wikimedia.org/g/php-session-serializer library.
The $wgPHPSessionHandling variable controls how this wrapper implementation behaves, either "warn" to pass through (but send warnings to Logstash) or "disable" to be a no-op with hard error.
Following T362324: Disable PHPSessionHandler in Wikimedia production and its enforcement through $wgPHPSessionHandling = 'disable' since September 2025, we know that no WMF-deployed MediaWiki code relies on this anymore.
Following T431315: Remove PHPSessionHandler and $wgPHPSessionHandling, MediaWiki will remove this compatiblity layer. This means if any code in MediaWiki, in an upstream vendor library, or in wmf-config, or through private files, were to reference $_SESSION, it will start using this default handler in PHP and store temporary files along with non-MW-shapes session cookies. In particular, I worry that with rise of LLMs and inexperienced staff reviewing/deploying code, this may slip in somewhere as there isn't an obvious reason at glance why it would fail, as it will probably work fine locally and there'd be an abundence of training data and documentation telling you to use this, and might go undetected until after it is deployed to production. At this point it should fail fast and clear, rather silenlty with messy side-effects and a costly cleanup. Ref https://gerrit.wikimedia.org/r/c/mediawiki/core/+/1322795.
We should disable this in production so that:
- Detect when any such code is accidentally written, indirectly activated, or otherwise deployed.
- Prevent cascading issues that are hard to reason about (around caching and cookies).
How
There is not a dedicated boolean off switch for it. There two ways to do it.
Option 1: Compile PHP with --disable-session
This will presumably prevent the folllowing functions from existing:
- session_start
- session_name
- session_id
- session_write_close
- session_cache_limiter
- session_set_save_handler
The $_SESSION is lazy-created by PHP after calling session_start(), so is naturally undefined this way as well.
Upside: Clean and strict.
Downside:
- Somewhat unusual compile-time flag
- Harder to rollout gradually given it's a Debian package change
- If we want to reuse upstream Debian packages, this would be a required patch to carry.
Option 2: Disable via php.ini
Upside: Easy to change.
Downside: Easy to change.
There is not a clean global to turn it off. However, based on upstream's own unit tests, and based on various StackOverflow posts, it seems the conventional wisdom is to set session.save_handler to a value other than the "files" or "user" constants. Note that this INI value is mutable at runtime. For one, when you call session_set_save_handler it implicitly changes this from "files" to "user", and so that's what ini_get returns in production despite us not changing the default session.save_handler=files in php.ini.
This seems to achieve what we want.
krinkle@deploy1003.eqiad.wmnet:~$ php -a Interactive shell php > var_dump(ini_get('session.save_handler')); string(5) "files" krinkle@deploy1003.eqiad.wmnet:~$ mwscript eval.php testwiki > var_dump(ini_get('session.save_handler')); string(4) "user"
$ php -a Interactive shell php > var_dump(session_start()); bool(true) php > var_dump($_SESSION); array(0) { }
$ php -a Interactive shell php > var_dump($_SESSION); Warning: Undefined global variable $_SESSION in php shell code on line 1 NULL
$ php -d 'session.save_handler=nonexistent' -a Interactive shell php > var_dump(session_start()); Warning: session_start(): Cannot find session save handler "nonexistent" - session startup failed in php shell code on line 1 bool(false) php > var_dump($_SESSION); Warning: Undefined global variable $_SESSION in php shell code on line 1 NULL
The downside is that code can re-enable this at runtime via ini_set('session.save_handler', 'files'). However, this does not concern me because:
- There is no convention or precedent for code that reads/writes session data to change such as settings, so this would never happen by mistake.
- From a security perspective, it offers no additional access or side-effect. If someone wanted to read or write files in the /tmp directory, they could do so directly using PHP file functions. If someone wanted to read a cookie (request header) or send a cookie (response header), again this is readily available directly as well.
; One of "files" or "user" ; Upstream default: "files" session.save_handler=nonexistent ; Avoid implicit writing to $_SESSION['PHP_SESSION_UPLOAD_PROGRESS'] during a request ; that uploads a file. ; ; Upstream default: 1 ; Wikimedia override today: 0 session.upload_progress.enabled=0