A week after two critical bugs in PHP's own engine, someone asked the internals list to stop. No new features and no cosmetic deprecations, until PHP has a formal spec and four independent implementations, written in formal-methods frameworks. Four people who work on PHP replied. One of them called fixing PHP's bugs a money problem.
Hello world, it's Thursday, October 29, 2026, and here's what happened This Week in PHP Internals. 15 stories this week, so let's get into it. But first,
AI made building software easy, and owning it hard. Scalpels installs open source apps into your own Laravel Cloud or Forge account in one click, so your data never leaves your infrastructure. There are 15 apps in the catalog, from a private Composer registry to a mail trap for staging. The Free plan is zero dollars, forever, and Laravel bills you directly for the hosting. There's even a guide to patching PHP on your own servers. Scalpels launches this Saturday, October 31st, at scalpels.app.
Spec Debate (01:21)
This week's top story: after last week's emergency releases, Brian Nguyen argued that PHP's two critical bugs show the cost of having no formal specification and only one implementation. He proposed a living spec of the bytecode and the parser, executable semantics in research frameworks like K and PLT Redex, and testing any second runtime against WordPress, Laravel and Symfony. His first mail said it was not an embargo. The next morning, he opened a second thread asking for one, until four formal implementations exist. He wrote: "Not adding a feature cannot break apps. Not deprecating (integer) cannot break apps. A corrupt allocator can."
Rowan Tommins doubted a spec would have helped, since memory management is exactly what differs between implementations. And on .NET, he pointed out that if 0.01% of Microsoft's roughly 200,000 employees work on it full time, that's still twice as many as have ever been paid to work full time on PHP. Sjoerd Langkemper wrote: "I think PHP is not starved for bugs. The bottleneck is bugfixes." And Larry Garfield wrote: "This is a money problem, just like most major OSS projects. It's nothing more complicated than that."
His fix is to get PHP-using companies to become significant PHP Foundation sponsors, or to put their own employees on PHP full time. Ben Ramsey asked whether Brian wanted PHP's maintainers to stop building PHP. Other runtimes were built by their communities, he wrote, and companies with the resources should be doing that work. Brian hasn't replied yet.
Links: Brian Nguyen, "From mono-implementation risk to spec" · Larry Garfield, "This is a money problem"
Security Follow-ups (03:02)
If you run PHP on Windows, there's one more update to install. On Monday, Shivam Mathur announced rebuilt Windows packages for PHP 8.2 through 8.5, with Brotli 1.2.1. That fixes a critical out-of-bounds write in the Brotli decoder, rated 9.2, which PHP can reach through the curl extension when automatic response decompression is on. It's off by default in curl, but HTTP client libraries can turn it on. The PHP versions don't change, and the dash-1 marks the rebuilt package.
And on Friday, php.net posted an informational advisory: "We suggest you set session.upload_progress.enabled=0 until the next regular bugfix release, to fully protect from an unlikely RCE vector." It needs an unusual combination of configuration and application code, so the full advisory, for a new CVE, comes with the next release. If you applied that setting as a mitigation last week, keep it in place.
Links: Updated PHP Windows builds for the Brotli fix · Informational advisory: session upload progress
Newcomer PRs (04:07)
About half of the pull requests from first-time contributors to php-src have been accepted, and the first success matters most. Artem Ukrainskiy went through a year of data: 831 pull requests from 219 people who opened their first one in that time. 418 were accepted, 157 closed without a merge, and the rest have no outcome yet. A first PR was accepted 29% of the time, and after a first acceptance, 66%. PRs with AI-written descriptions were accepted around 20% of the time, against 55%.
And speed matters. When a maintainer responds within a day, the median PR closes in about 20 hours. When the first response takes over a week, it's about 32 days. So he asked whether a bot is worth prototyping, one that checks the mechanical things as soon as a PR opens: missing tests, an empty description, the wrong target branch, an obvious duplicate.
Sjoerd Langkemper replied that his biggest friction as a newish contributor was opening a pull request and having nobody respond. Artem's question started from a new rule by Weilin Du, merged Saturday, that asks contributors, and AI agents, to review an existing fix instead of opening a duplicate. No maintainer has answered the bot question yet.
Links: Artem Ukrainskiy, "What happens to newcomers' PRs in php-src"
Scope RFC (05:30)
PHP has no object that represents a request, because until now a request has been one run of the engine, from startup to shutdown. That breaks down when one process serves many requests at once, and Frode Børli's Scope RFC gives each unit of work an identity: an HTTP request, a queue job, a CLI command. Code anywhere in that request can ask which scope it's in, and keep its own state, like a database connection, keyed by it.
Fibers and generators belong to the scope they were created in. The primary vote adds only that identity. Two secondary votes would make the superglobals and the session, and then the default locale and timezone, follow the scope. Code that never creates a scope behaves exactly as today, and there's already an extension and a polyfill.
Larry Garfield called it promising and tightly focused, but asked what it looks like with real dependency injection, rather than a service locator. He also called new scopes with empty superglobals a footgun for legacy code that reads $_POST. Frode replied that the server fills them when it creates the request scope, the same place that fills them today, and that he'll swap the examples for a container.
Links: RFC: Scope
Effect Declarations (06:46)
What if a function had to declare that it starts processes, reads files or makes network requests? Arsan Gamal proposed effect declarations, written after the return type, with optional parameters that narrow them, like the one command this function may run. A separate runtime mechanism would decide what's actually allowed. He named PHP2Shell, the finders' name for last week's vulnerabilities, as the motivation, and compared it to app permissions on a phone. He wrote: "My intention is not to promote process execution, but to make potentially dangerous operations explicit and controllable."
David Maye liked it, noted that a use-after-free couldn't be contained this way, and suggested prototyping it as an extension with attributes. Damian Jóźwiak asked the same thing: why new syntax instead of attributes? Larry Garfield replied that attributes work for static analysis, but for the engine to enforce it, backward compatibility is the problem. He wrote: "A new PHP release that fails on any function that has a print or fopen statement in it until you add new syntax not available in earlier versions is a complete non-starter." So his first question is how to make it piecemeal opt-in. Calvin Buckley added that these aren't algebraic effects, and suggested a name other than effects or capabilities.
Links: Arsan Gamal's proposal
Array Partition (08:12)
Splitting an array into the items that pass a check and the ones that don't takes two passes today, one of them negated. Ayoub Ezzini's RFC adds array_partition, which returns both halves in one pass, matching first, with keys preserved, so you can destructure straight into two variables.
mickmackusa asked for any number of groups, keyed by the callback's result, and Morgan for a result keyed true and false. Ayoub kept it to two. Partition means a two-way split in Ruby, Kotlin, Rust, Haskell and Laravel, he wrote, and PHP casts boolean array keys to 1 and 0, so a true-and-false result would quietly swap your variables.
Tim Düsterhus said a co-worker hand-wrote his own array_partition just last week, and wrote: "It's a well-written, well-researched and well-argued RFC and I'm in favor of the proposal." Writing the polyfill Tim asked for turned up the open question: whether array_partition keeps references, like array_filter, or drops them, like array_find.
Links: RFC: array_partition()
Votes (09:22)
Two votes are open, heading in opposite directions. Sjoerd Langkemper's RFC to make hexdec, octdec, bindec and base_convert throw on invalid characters is at 25 to 1, and it closes November 1st. Muhammed Arshid's Filter enums RFC is at 2 to 11, with 1 abstention, and it closes November 4th.
Links: Throw exception for invalid characters in number base functions · Add Filter\Filter and Filter\Flag Enums
Quick Hits (09:44)
Quick hits. Sjoerd Langkemper reviewed Pratik Bhujel's Io\Terminal RFC and found two bugs. Pratik pushed fixes within a day, plus one he found himself, and the vote stays on hold.
Links: Io\Terminal RFC
Damian Jóźwiak planned the CSV extension vote for November 2nd. Tim Düsterhus asked him to wait after the security release, and questioned giving CSV its own top-level namespace, so Damian postponed it.
Links: CSV extension RFC
Sjoerd also proposed openssl_get_channel_binding, which ties a login to the TLS connection it runs over, so mail and database clients can offer the PLUS variants of SCRAM logins. Tim asked why it returns null instead of throwing.
Links: openssl_get_channel_binding RFC
On blocking server-side request forgery in curl, Nicolas Grekas wrote "Yes, please make this happen!", for Symfony's HTTP client, and Levi Morrison asked why it should be curl-only rather than cover streams too.
Links: SSRF protection in curl
Máté Kocsis is keeping the length limit in his query parameters RFC, citing the recent CVEs.
Links: Query parameter manipulation RFC
Abbas proposed async and await keywords on top of Fibers, and Frode Børli replied that PHP should go the way of Go, choosing concurrency at the call site.
Links: async/await on top of Fibers
A developer who validates JSON from AI models asked the pattern matching RFC to keep a missing key different from null.
Links: Pattern matching RFC
And a proposal to call scalar extension methods without parentheses got a strong minus one from Rowan Tommins, for saving two characters per call.
TL;DR (11:15)
So that's the week. After last week's critical bugs, a call to freeze PHP until it has a formal spec met pushback, and Larry Garfield called the bug-fix bottleneck a money problem. Windows users have rebuilt packages to install, and php.net suggests one session setting until the next release. A year of data showed how much a newcomer's first pull request depends on a fast reply, Frode Børli's Scope RFC would give every request an identity, and array_partition arrived with Tim's support. Links below.
The PHP Foundation funds more than half of ongoing php-src commits, so if you use the language, maybe consider donating at opencollective.com/phpfoundation — or try guilting your employer into it.
If you found this useful, a like or a comment helps more people find it. And if you missed last week's episode, where two critical PHP vulnerabilities leaked a day before their fix, that's a good one to watch next. Thanks again to Scalpels.app for supporting this week's episode. We're Artisan Build. See you next week.
Top comments (0)