BlackBox found a vulnerability in PHP¶
This happened early July when working on a simple dependency upgrade on innmind/filesystem.
Long story short: a bug in PHP's 8.5 Uri\WhatWg\Url::__construct() allowed to extract part of the process memory.
But let's backtrack a bit.
Finding the bug¶
Innmind handles URLs via the package innmind/url. Up to its 5.0 version it used league/uri-parser for the parsing, but it's been abandoned for quite a while. So when PHP 8.5 released with the new Uri APIs, innmind/url released a 5.1 version using them exclusively (meaning PHP 8.4 support was dropped).
Like many Innmind packages it uses innmind/black-box to test the package. So to make sure innmind/url handles a lot of cases it uses BlackBox's capability to generate random data. So far so good.
Fast forward a few months after the release of innmind/foundation v2. The foundation packages were in place stable enough to decide to update this documentation. But BlackBox was still in v6 with lots of deprecated code and a significant backlog of new features and BC breaks for an upcoming v7.
So instead of updating this documentation twice, the goal was to do the v7, update all the foundation packages that expose fixtures and then update this documentation.
So in innmind/url version 5.3 it updated BlackBox to its v7 and flag it as conflictual with its v6 to avoid dependent packages to use the fixtures with an incompatible version of BlackBox.
That meant that when updating innmind/filesystem, which depends on innmind/url, to BlackBox v7 it also had to use innmind/url 5.3 and thus PHP 8.5.
The PR was opened on May 14 with the CI failing. innmind/filesystem goes all the way on Property Based Testing with BlackBox and generate complex sequences of actions and data (random file content and directories structures) to make sure everything works as expected. The CI failure output seemed non trivial and was left as is for about 2 months due to a lack of time to work on it.
Then came early July, time to fix the CI.
The CI bug was reproducible locally. While debugging underlying issues a test failed with this output:

That's BlackBox own code.
The first reaction was: that's strange, there must be a bug in the test!
When looking at the stack strace and the generated input data, it showed that innmind/filesystem was trying to build a Innmind\Url\Path with lots of different characters and emojis, to represent a concrete file path. But BlackBox for some reason didn't shrink further this path string. So I did the process by hand.
Turned out that this was the minimal string that made the test fail:
$path = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa😨';
If you didn't scroll, it's 1010 as followed by 😨.
Inside innmind/url this path was fed to new \Uri\WhatWg\Url($path, new \Uri\WhatWg\Url('http://a.org')).
Prior to PHP 8.5.8 if there's a non encoded emoji after the 1010th character in the path then there's an internal bug that lead to leaking part of the process memory.
And if you played with the number of characters before the emoji then you could move around in the exposed memory.
Reporting the vulnerability to PHP¶
Before submitting the issue I looked at PHP's documentation to do this properly.
But due to some phrasing I wasn't sure this would be considered as a vulnerability. But on Romane Ledru's advice I went ahead and reported it the following day on July 4.
The very same day I got a kind response from Alexandre Daubois explaining that it was a bug in Lexbor, used for URL parsing, and had been fixed by Ilija Tovilo on July 1st and released in PHP 8.5.8 on July 3rd.
Conclusion¶
Even though the vulnerability had just been fixed, the experience was interesting.
This was the first time I had to report a security vulnerability. There's the self doubt initially of "Is this really a security problem?", then the "I don't want to put extra work on the PHP team if it doesn't pan out" and finally the submit form that looked a bit scary.
Before this event BlackBox had already found plenty of user land bugs. But I never foresaw it would find a bug in PHP itself (1).
- or more precisely in one of its depedencies.
BlackBox, and Property Based Testing, can be infuriating at times when it keeps telling you your code doesn't work. But everytime it finds this kind of bug it becomes more addictive .