NEWS

PHP package created as a quick fix in 2014 racks up nearly 20 million installs and gets deprecated

Jake A. Smith wrote 174 lines of PHP to work around a CMS upgrade at AOL. Twelve years later, the polyfill had become a transitive dependency of WordPress, Debian, and Ubuntu, until he decided to retire it.

PHP package created as a quick fix in 2014 racks up nearly 20 million installs and gets deprecated
Image: Redação iMasters

On September 15, 2026, developer Jake A. Smith marked as deprecated a PHP package he wrote in 2014 as a temporary fix. The catch: that "temporary" fix has already surpassed nearly 20 million installs on Packagist and still adds more than 400,000 new installs per month. He told the full story on his blog, and it's a perfect case study of how legacy code slips out of its author's control.

Where the "temporary fix" came from

In 2014, Smith was working on upgrading AOL's CMS from PHP 5.2 to 5.3. Part of the migration involved dropping version 1 of the pecl_http extension, which provided the http_build_url() function. The legacy system called that function in dozens of places, and rewriting every call site wasn't a viable option within the deadline. The workaround was to reproduce the function as a polyfill: a custom implementation of http_build_url(), defined only if the native function didn't exist. The old code kept working without knowing that nothing had changed underneath.

Composer was taking off at the time, so publishing the polyfill on Packagist for anyone else who needed it was trivial. Smith expected the package to last a year or two, until the PHP community moved on to something else.

How a shim becomes critical infrastructure

That's not what happened. The package has now been downloaded from Packagist nearly 20 million times in total, with more than 400,000 recurring monthly installs. And Composer is only part of its reach: WPML, the leading multilingual plugin for WordPress, bundles the polyfill directly into its own code and claims to be installed on more than 1.5 million sites. The domain conversion library idna-convert also depends on it, which brings the polyfill into SPIP (a French CMS) and, by extension, into packages bundled in Debian and Ubuntu.

Smith only grasped the scale of this a few months ago, when he revisited the package after years away from PHP. Back in 2021, already surprised by the numbers, he even publicly asked for a new maintainer; three people volunteered. Shortly after, he unexpectedly lost a family member, which reshuffled his priorities for a long while. The handoff process was never resumed, and the package went years without anyone reviewing it.

The bug that went unnoticed for years

Among the issues piled up on GitHub was one specific bug: joining a path to a URL when the path ends in a slash strips out every "a" letter from that path. The cause is a workaround commented in the code as // Workaround for trailing slashes, which appends an artificial "a" to the end of the path to guarantee there's always a last segment to trim, then removes that segment with a find-and-replace. When the path already ends in a slash, that last segment is just the added "a", and the find-and-replace ends up taking along any other "a" that exists in the path. A simple string bug, but one that went unnoticed for years inside a package with tens of millions of installs, precisely because no one was paying close attention to the code anymore.

Why he didn't pass the package on

With the package back on his radar, Smith had three options: get back into PHP after nearly a decade away, hand the package off to one of the 2021 volunteers, or leave it as it was. He chose none of the three: deprecating it for good instead. In his assessment, keeping the package alive would only delay the migration everyone should be making, and handing off maintenance would add a risk on top of that. It's not distrust of the volunteers, it's recognizing the pattern: a widely installed package that changes maintainers without anyone downstream auditing that change is exactly the kind of target supply-chain attackers look for. Smith cites the Veritasium channel's video on the xz Utils backdoor as the best description he's ever seen of how that scenario plays out in practice.

What changes for PHP developers

The package will still be installable, but it will no longer receive fixes, not even for the missing-"a" bug. After so long without changes, even a one-line fix could have unpredictable side effects for those who depend on it today, with no one left to provide support.

Smith's recommendation, and the direct reason for the deprecation, is that the ecosystem has had better alternatives for years: the PHP League's URI library has been the community's answer in this space for quite a while, and PHP 8.5 now ships a standards-compliant URI API directly in the language (he credits user jawira for pointing out that change). The package's README lays out step by step how to swap http_build_url() calls for one of these options.

For anyone maintaining PHP systems in production, the case works as a practical checklist. First, it's worth auditing transitive dependencies and not just your project's direct composer.json: a package can reach your code bundled inside another one, as happened with WPML, without ever showing up as an explicit dependency anywhere you look. Second, a high install count on Packagist isn't synonymous with active maintenance; check the date of the last commit and whether there are issues that have sat open for years without a response. Third, if your stack touches http_build_url() in any way (directly, via WPML, via SPIP, or via a Debian/Ubuntu package that bundles it), now is the time to migrate to PHP 8.5's native API or to the PHP League's library before the polyfill effectively becomes dead code that no one is watching.

The bigger lesson, beyond PHP, is about the distance between writing clean code and monitoring the real-world impact of what you publish. Smith wrote 174 lines to solve a problem of his own, with no intention of creating infrastructure for millions of sites. The package kept running in AOL's CMS, never migrated away, until the whole platform was shut down around 2020, six years after it was supposedly replaced.

Translated from the Brazilian Portuguese original · Read the original