← Crucible

My first CVE, and it paid nothing

· disclosure bug-bounty patch-review

The first CVE this project was ever assigned went public today.

CVEPluginClassFixed in
CVE-2026-18056HivePress AuthenticationUnauthenticated authentication bypass · CVSS 7.51.1.5

Reported in July, assigned an identifier nine days later, published today. Nothing appears here until Wordfence says disclosure is finished, however long that takes.

Wordfence validated it and credited me. The bounty was zero.

What the bug was

HivePress Authentication lets people sign in with Facebook. A site running it holds a Facebook app ID.

When someone signs in, the plugin takes the access token off the request, asks Facebook's Graph API who that token belongs to, and trusts the email address that comes back.

It never checked which app had issued the token.

So a token issued by any app worked, not just the site's own. Hand a site a token belonging to somebody else, and it asks Facebook whose that token is, gets their email back, and signs you in as them.

The advisory states the limit plainly. You have to obtain the victim's token first, which is the interaction requirement sitting in the published CVSS vector.

The plugin's own Google path does check the issuing app. Facebook's didn't, and that's what makes it a defect rather than a design choice.

Why it paid nothing

I classified it as an authentication bypass to admin. That was the mechanism talking rather than the evidence. A bypass of the login sounds like it ends on an administrator.

My own impact statement, in the same submission, described the weaker outcome accurately. An attacker who gets a victim to authorise their app logs in as the WordPress user holding that victim's email. You take whichever account you can get a token for. Wordfence kept my score, and the published vector is the one I submitted. What they judged differently was the category, and the category is what the money hangs on.

They pay by vulnerability type, and every type carries a minimum install count. A bypass that lands you on an administrator pays from 25 installs. Stored cross-site scripting and SQL injection pay from 500. Everything else needs 50,000 at my tier, and this plugin has about a thousand.

Going by the impact rather than the label is the right call, and I should have made that call myself. Your category has to follow the impact you can demonstrate, not the mechanism it reminds you of. So eligibility now gets worked out from the provable impact before anything is submitted, and the type is picked to match.

Except that classifying it correctly would also have paid nothing here, so the install count is the tidy answer rather than the whole one. There are other reasons a finding earns nothing, and this one had more than the arithmetic going against it.

My report was right about the code and right about the score. It still paid nothing. The money turns on two numbers, and I check both on day one now. How many installs the plugin has, and the minimum that the impact I can actually prove requires.

Reading the fix

The advisory says 1.1.5 fixes it. That's the vendor's claim until I open the release, so I opened it.

The fix adds the check that was missing. Before the plugin asks Facebook who the token belongs to, it now asks Facebook who issued it. It sends the token to Facebook's token inspection endpoint, authenticated with the site's own app credentials. Facebook answers with the app ID that issued the token, and the plugin checks that against its own.

What I went looking for is whether anything acts on a refusal. It does. The calling code already refused any response carrying an error, so the new check lands on a branch that stops. If either call to Facebook fails outright, whether that is a network error, an error body or unparseable JSON, the request stops there too. Failing closed is the part that's easy to get wrong, and this gets it right.

There's a second change worth knowing about if you run this plugin. That inspection call needs an app secret, and the plugin had never asked anyone for one. So the fix release adds the field, and until an admin fills it in, Facebook login doesn't load at all. You get a notice in the admin area instead of a login button that quietly doesn't work. That will catch people on upgrade, and it's the right way round. If Facebook login disappears after you update, the answer is to add the app secret. Rolling back to 1.1.4 brings the bug back.

If you run HivePress Authentication, update to at least 1.1.5.

The limits of a read

I read the fix. I didn't install the patched release and fire the original token at it, which is the test that would actually settle it. Reading a check and watching it refuse a request are not the same evidence.

I don't have a settled answer on how far reading gets you. Standing every patched release up and firing the original attack at it costs a lot more than reading does, and I haven't worked out where that line sits. For now I read them, and I say which one I did.

I also only checked this one defect, in this one release. That's a much smaller claim than saying the whole plugin is safe.

There's no proof of concept here, no script and no request shapes, and there won't be one later. Wordfence doesn't publish one either. I don't publish them at all.


This work uses large language models throughout the toolchain, including in drafting this post. Every finding is checked by hand against the source before anything is submitted. The finding was reported through the Wordfence bug bounty programme, who coordinated disclosure with the vendor and assigned the identifier. The fix release was read directly from the vendor's published source.