miniOrange SAML Vulnerability: A Second Bypass, Live
By WP Vanguard Team
PHP's openssl_verify() returns three possible values, not two. Most developers write code as though it returns two. That gap is the entire miniOrange SAML vulnerability tracked as CVE-2026-15981, CVSS 9.8, and it's now being scanned for and exploited in the wild.
We covered this vendor in July, when three separate miniOrange identity plugins fixed critical unauthenticated bypasses inside eight days, including a SAML signature confusion bug in this exact plugin. That post is background, not a rerun. This one is about what happened after the July fix: a second bypass got past it, attackers went looking for it within weeks of disclosure, and six paid editions of the plugin sat vulnerable for a while with no public advisory telling anyone to check.
How the tri-state bypass works
SAML Single Sign On - SSO Login validates incoming assertion signatures using PHP's built-in openssl_verify(). That function is documented to return one of three values: 1 if the signature is valid, 0 if it's invalid, and -1 if OpenSSL itself hit an internal error while trying to check it. Three outcomes, three meanings.
The plugin's validation code, in Utilities.php around line 252, treated the result as a simple true/false condition instead of checking for the specific success value. In PHP, -1 is truthy. Any integer other than 0 evaluates as true in a boolean context. So a malformed signature, one deliberately crafted to make OpenSSL choke and return an error rather than a clean rejection, passed the same check a genuinely valid signature would pass.
Here's the illustrative difference, not the plugin's exact code:
// Wrong: treats any non-zero return as "verified"
if ( openssl_verify( $data, $signature, $public_key ) ) {
// -1 (OpenSSL error) is truthy in PHP. So is 1 (valid).
// This branch runs for both.
grant_access( $assertion );
}
// Correct: checks for the one value that actually means "valid"
if ( openssl_verify( $data, $signature, $public_key ) === 1 ) {
grant_access( $assertion );
}
One character, === instead of a loose truthy check, is the entire gap between "administrator session issued" and "signature rejected." That's not a rare category of bug. PHP's own manual lists all three return values, and the -1 case is the one that's easy to miss.
An attacker doesn't need a working forged signature. They need input that's broken in a way that makes OpenSSL error out instead of cleanly rejecting it.
Free edition of the plugin was vulnerable through version 5.4.4, the same version that shipped as the July fix for the earlier bug. Version 5.4.5 fixes CVE-2026-15981.
The same mechanism, a second CVE number
There's a second identifier attached to this cluster: CVE-2026-61979, also CVSS 9.8. Patchstack tracks it as a separate vulnerability, but the mechanism it describes matches the signature algorithm confusion bug we wrote up in July under CVE-2026-15013. The attacker picks HMAC-SHA1 as the signature algorithm in the SAML response, and the plugin takes the identity provider's public RSA key, the one anyone can fetch, and uses it as an HMAC secret instead. Utilities.php lines 246-250 read the attacker-chosen algorithm; XMLSecurityKey.php lines 546-548 pass the PEM-formatted key straight into hash_hmac().
We won't re-explain why that's fatal, we did that in July's post. The public record doesn't say why the same mechanism now carries a second identifier, and we won't guess. It's a separate database entry, so we're treating it as one.
Six paid editions, no changelog
This plugin ships in seven editions, and each one carries its own version number. Here's the fixed-version table from Patchstack's disclosure.
| Edition | Vulnerable up to | Fixed in |
|---|---|---|
| Free | 5.4.4 | 5.4.5 |
| Premium | 13.0.3 | 13.0.4 |
| Standard | 17.0.5 | 17.0.6 |
| Premium/Enterprise/All-Inclusive (multisite) | 20.2.7 | 20.2.8 |
| Enterprise/All-Inclusive | 26.0.2 | 26.0.3 |
| VIP | 32.0.7 | 32.0.8 |
| VIP (multisite) | 35.0.6 | 35.0.7 |
Only the free edition showed up in vulnerability databases. According to Patchstack, the six paid editions were patched with no public changelog entry and no security advisory anywhere. If you're running Premium, Standard, Enterprise, VIP, or a multisite variant, there was nothing in the usual channels telling you a fix existed.
That silence has a direct consequence. Vulnerability databases index what vendors disclose. A database that only has a free-edition CVE will show a paid-edition site running an old build as "patched" or simply won't flag it at all, because nobody told the database that build was ever broken. The scanning tools built on top of those databases, ours included, inherit the blind spot.
In July we flagged this vendor's identity plugins as a supply-concentration risk: three critical bugs, one vendor, inside a month. Silent patching compounds that risk instead of reducing it. A vendor that fixes a bug quietly, without a CVE or a changelog line, is relying on customers to update on faith rather than on evidence that anything needed fixing. Paid customers, the ones with the most to lose if their SSO gets forged, got the least visibility into this one.
Attackers are already scanning
This isn't theoretical risk sitting in a disclosure report. Patchstack observed scanning activity against miniOrange SSO endpoints from six IP addresses spread across Belgium, Nigeria, the US, and Germany. We don't have the specific addresses to publish and won't guess at them.
Spread across four countries, that's not one actor probing a handful of sites by hand. It reads like the early phase of automated scanning, the kind that tries the bypass on every site it finds running the plugin.
More concretely: DigitalOcean's own defenses detected and blocked an exploitation attempt where the attacker had already used the bypass to obtain a WordPress administrator session cookie. That's not a proof-of-concept running in a lab. That's the actual outcome this bug produces when someone uses it against a live site: an admin cookie, no credentials required.
Patchstack published its full technical writeup on August 21, 2026. For contrast, our own vulnerability feed (sourced from Wordfence) has listed CVE-2026-15981 since July 23, 2026, nearly a month before the exploitation details became public. The lag between "a CVE exists" and "we know it's being actively exploited" is exactly why version-checking alone isn't the whole story here. The Hacker News and BleepingComputer both picked up the exploitation angle once Patchstack's report went out.
Where scanners, ours included, fall short here
We're going to be direct about a limitation instead of glossing over it. A scanner that checks a plugin's version against a vulnerability database, which is how WP Vanguard's surface scan and most scanners in this category work, reads whatever version it can detect for the installed plugin slug. For miniOrange SAML SSO, the public CVE record only describes the free edition's version numbers.
If you're running a paid edition, our scan and every scanner working from the same public data can't distinguish "Premium 13.0.3, vulnerable" from "Premium 13.0.4, fixed" the way it can for the free edition, because there's no public CVE entry mapping those version numbers to a vulnerability status. That's not a gap we can close by scanning harder. It's a gap in what got published. If you're on a paid edition, you have to check your own version against the table above yourself; don't assume a clean scan result covers you here.
We'd rather tell you that plainly than let a green checkmark imply more than it can back up. It's also the exact reason a general audit of how good WordPress's public vulnerability data actually is matters beyond any one plugin: databases can only be as complete as what vendors choose to disclose.
What to do right now
Start by finding your actual edition and version. Go to Plugins in your WordPress admin, find SAML Single Sign On - SSO Login, and note the exact version number next to it. miniOrange offers a free edition and licenses the paid editions separately. If you paid for this plugin, you're on a paid build, so check which tier and compare it against the table above.
Don't skip this step because you remember updating recently. Given the silent patching, "recently updated" doesn't tell you whether the update you got included this fix or predates it. The version number is the only thing that answers that question.
If your version is at or below the vulnerable threshold for your edition, update now. There's no configuration workaround; the fix has to be in the code.
Because this bypass hands out administrator sessions, updating alone doesn't undo whatever happened while the site was exposed. Invalidate existing sessions. The cleanest way to do that on WordPress is changing the authentication keys and salts in wp-config.php, which forces every active session, including any an attacker minted, to log out immediately.
After that, review your administrator accounts. Look for any account you don't recognize, and for recent admin-level logins that came in through SSO rather than the normal login form, especially any tied to a location or IP outside your normal pattern. Check your SAML configuration itself for changes you didn't make: an added identity provider, an altered certificate, a changed endpoint URL. We won't guess at specific setting names in the plugin's admin screens since that varies by edition, but anything that looks unfamiliar in your SSO settings is worth investigating on its own.
If any of that turns up something you can't explain, our general checklist for signs a WordPress site has been hacked covers the broader incident response steps from there, and our WordPress security checklist is a good baseline to re-run afterward regardless of what you find.
The underlying design lesson is the same one we keep coming back to with this vendor's plugins: a value the client controls, an algorithm name, a return code interpreted loosely, ends up standing in for a decision the server should have made on its own. We wrote about that pattern at length in our earlier piece on this membership-plugin bypass, and it holds here too.
WP Vanguard's surface scan checks the plugin version it can see against our vulnerability database and flags outdated free-edition installs automatically. It can't identify which paid miniOrange edition a site runs, for the reasons above, so paid-edition users need to do that comparison by hand. Run a scan on your site to check what we can see, and use the table in this post for everything we can't.
References
- Patchstack: One slug, seven editions: the miniOrange SAML SSO bug that let anyone log in as your WordPress admin
- The Hacker News: Attackers Target miniOrange SAML Flaws
- BleepingComputer: Hackers target WordPress sites in miniOrange auth bypass attacks
- NVD - CVE-2026-15981
- NVD - CVE-2026-61979
- PHP Manual: openssl_verify()
Related reading
Check Your WordPress Site Security
Free scan, no login required. Find vulnerabilities before attackers do.
Scan Your Site FreeGet weekly WordPress security tips
Vulnerability alerts, plugin updates, and security guides. No spam. Unsubscribe any time.