
Your Vulnerability Scanner Says This Plugin Is Patched. It Has Seven Versions and Six of Them Are Not.
Two miniOrange SAML SSO flaws let anyone log in as admin. Paid editions read as patched because seven version lines share one plugin slug.

For about a month, a large number of WordPress sites running the miniOrange SAML SSO plugin were vulnerable to an unauthenticated admin takeover while every tool built to warn them said they were fine. Not because a scanner was broken, and not because anyone hid anything. Because the plugin ships seven separately versioned products under one WordPress.org slug, the public advisories described only one of them, and a version number on its own does not tell you which product you have.
If you run this plugin, the fix is short and you should do it today. But the reason this happened is the more useful thing to take away, and it applies to a plugin you probably have installed right now. Vulnerability tracking across the entire WordPress ecosystem is keyed on a slug and a version string. That model assumes a version number means the same thing to everyone with that slug installed. Here it did not, and the result was a green tick on sites that had been compromised.
TL;DR
- Two flaws in the miniOrange SAML 2.0 Single Sign On plugin (
miniorange-saml-20-single-sign-on), CVE-2026-61979 and CVE-2026-15981, let an unauthenticated attacker forge a SAML response and log in as any WordPress user, including an administrator.- The plugin has seven independently versioned editions under one slug. Public advisories covered only the free edition. Every paid install carries a higher version number than the free edition's fixed version, so scanners read them all as already patched.
- Find your edition, check it against the version table below, and update. On the free line, update to 5.4.7, not 5.4.5, because a third issue was fixed after those two.
- If you are on a paid 16.x build, expect no update prompt in your dashboard. The patched release is on the 17.x line and moving there is a manual upload.
- Exploitation attempts have been observed. At least one bypass succeeded far enough to obtain an admin session cookie before other controls stopped it.
- The durable lesson: if an advisory names your plugin and you cannot find your exact edition in its affected-versions table, the correct reading is "unknown," not "safe."
If you run miniOrange SAML SSO, do this first
Find out which edition you have. Check it against the table below. Update to at least the patched version for that edition. If you are on a 16.x build, expect to upload the new version by hand, because no update will appear in your dashboard.
The plugin identifies its own edition in its file header, which is the fastest reliable way to check. Over SSH:
wp plugin list --fields=name,title,version,update,update_version | grep -i samlThe title column is the plugin's registered name and names the edition. If you cannot use WP-CLI, read the header directly from the plugin folder:
grep -rn "Plugin Name\|Version:" \
wp-content/plugins/miniorange-saml-20-single-sign-on/*.php | headDo not rely on the version number alone. Each edition spans several major versions, and the ranges do not overlap, so 26.0.2 and 5.4.4 can be the same bug in the same code.
The version table
miniOrange supplied this breakdown to Patchstack on 18 August 2026, and it had not been published anywhere before that. The patched column closes both CVEs.
| Edition | First version | Latest version | Vulnerable up to | Patched in |
|---|---|---|---|---|
| Free (single site) | 3.0.0 | 5.4.7 | 5.4.4 | 5.4.5 |
| Premium (single site) | 11.3.0 | 13.1.0 | 13.0.3 | 13.0.4 |
| Standard (single site) | 15.1.0 | 17.1.0 | 17.0.5 | 17.0.6 |
| Premium / Enterprise / All-Inclusive (multisite) | 20.0.0 | 20.2.8 | 20.2.7 | 20.2.8 |
| Enterprise / All-Inclusive (single site) | 25.0.0 | 26.1.0 | 26.0.2 | 26.0.3 |
| VIP (single site) | 32.0.0 | 32.0.8 | 32.0.7 | 32.0.8 |
| VIP (multisite) | 35.0.0 | 35.0.7 | 35.0.6 | 35.0.7 |
Two things about this table are worth stating plainly, because they are the difference between reading it correctly and reading it wrongly.
On the free line, 5.4.5 is not where you want to stop. That is the version that closes the two CVEs above. A third, separate issue was disclosed afterwards and is fixed in 5.4.7, which is the current release on WordPress.org. Update to 5.4.7.
On the Standard line, the two fixes landed one release apart. The algorithm confusion bug was fixed in 17.0.5 and the signature verification bug in 17.0.6. That is why 17.0.5 appears in the vulnerable column and 17.0.6 in the patched one. The same one-release gap exists on the free line, where 5.4.4 fixed the first bug and 5.4.5 the second. For every other edition the public detail is one combined patched version, not a per-CVE breakdown.
If you are on a 16.x build
There is no 16.x patch. The fix for the Standard line is 17.0.6, and WordPress's update mechanism does not offer a jump between major version lines for this plugin, so a vulnerable 16.x install shows no available update at all. You already hold the licence; you just have to fetch the newer package from miniOrange and install it yourself.
Important: Take a backup before a manual plugin upload, and do the upload on staging first if the site matters. An SSO plugin sits directly in the login path. If the new version rejects your identity provider's configuration, nobody can log in, including you. MagicWP offers an on-demand backup before every change and one-click staging for exactly this kind of upgrade.
Before you start, confirm you can still reach wp-login.php with a local WordPress administrator account, or that you have SSH or WP-CLI access to deactivate the plugin. A working fallback route into the site is the difference between a ten-minute upgrade and an emergency.
If you cannot update immediately
Ranked by how much they actually reduce risk:
- Disable the plugin. SSO stops working and users fall back to WordPress logins, which is disruptive but decisive. On a site where SAML is the only login method, this is only viable if you have a local admin account that still works.
- Restrict
/wp-adminand the plugin's assertion consumer endpoint at the network edge. This is what saved DigitalOcean. The attacker got a valid admin session cookie and still could not do anything with it, because admin operations were reachable only from a trusted network. A firewall rule does not care which edition you run, which makes it the one mitigation that scales across all seven. - Apply the published hotfixes. DigitalOcean wrote two narrow patches and published them through Patchstack. One rejects HMAC signature methods before the plugin recasts the identity provider's key. The other replaces the loose truthiness check on
openssl_verify()with a strict comparison against1. Both are a few lines. They are meant to buy time, not to replace the vendor fix, and the line numbers in the published patch come from Standard 16.1.9, so they will not line up on a different edition. - Check your web application firewall coverage. Mitigation rules for both CVEs exist from the major WordPress security vendors, and rule-based blocking is edition-agnostic in a way that version-based alerting is not.
What the two bugs actually do
Both are signature verification failures. SAML works by having your identity provider sign an assertion that says "this is who this person is," and your site verifying that signature with the provider's public key. Break the verification and anyone can write their own assertion.
CVE-2026-61979: the response chooses its own signature algorithm
The plugin read the signature algorithm from the incoming SAML response rather than enforcing the one the administrator configured. Setting it to HMAC-SHA1 changes the verification from an asymmetric check to a symmetric one, and the plugin then used the identity provider's RSA public key as the HMAC shared secret.
The public key is public. That is its entire job. It is published at the identity provider's metadata endpoint, and anyone can fetch it. So an attacker takes the key, uses it as the secret to sign their own assertion, and the plugin verifies it as genuine.
This is not a novel class of bug. Algorithm confusion has a well-documented history in authentication libraries, including the JWT alg issues of 2015 and a SimpleSAMLphp incident in 2018. The lesson each time is the same: the algorithm is part of your security policy, not part of the message. A verifier that lets the thing it is verifying pick the verification method is not verifying anything.
CVE-2026-15981: an error treated as a success
PHP's openssl_verify() returns three things, not two. It returns 1 for a valid signature, 0 for an invalid one, and -1 when OpenSSL itself errors out. The plugin checked the result loosely, and in PHP -1 is truthy.
So a malformed signature that trips OpenSSL's internal error path came back as -1, the loose check read that as true, and the plugin called wp_set_auth_cookie() for whatever account name the attacker put in the assertion. No credentials, no interaction, no account required.
For anyone writing PHP that touches cryptography, this is the takeaway in five lines:
// openssl_verify() is tri-state: 1 = valid, 0 = invalid, -1 = error.
// A loose check treats -1 as success, because -1 is truthy in PHP.
if ( openssl_verify( $data, $signature, $public_key, OPENSSL_ALGO_SHA256 ) === 1 ) {
// Verified. Everything else, including the error case, must fail closed.
}Any function whose failure mode is a negative number needs a strict comparison. It is a small habit that would have prevented a critical authentication bypass on ten thousand-plus sites.
The third issue, and why "patched" needed a second look
WPScan lists a further problem on the same plugin, published 17 August 2026: an unauthenticated administrator account takeover via SAML trust anchor overwrite, scored 8.8, affecting versions 4.8.85 through 5.4.6 on the free line and fixed in 5.4.7. Patchstack's advisory refers to a third issue processed on 19 August that requires an administrator to click something, which is consistent with that score. The free-edition changelog for 5.4.7 records the removal of a certificate mismatch option "to enhance security" without naming a vulnerability.
The practical consequence is the one in the first section: on the free line, update to 5.4.7. The editorial consequence is worth noticing too. Even after a coordinated write-up corrected the record for seven editions, the current state of this plugin required checking a second database to see completely.
Why every scanner said these sites were fine
Here is how vulnerability tracking works, whether it is Patchstack, Wordfence, WPScan, a host's dashboard, or wp plugin list piped into something you wrote. The tool reads two values from the plugin header: the slug and the version string. It looks that pair up against records shaped like "slug X is vulnerable in versions up to Y, fixed in Z."
That model has one hard assumption baked in. It assumes a version number means the same thing to everyone who has that slug installed.
Now put the numbers in. The only public advisory described the free edition: vulnerable up to 5.4.4, fixed in 5.4.5. Apply that record to the slug and every paid install carries a higher number than 5.4.5. Enterprise 26.0.2 is vulnerable. It is also, arithmetically, far above the fixed version. It reads as patched. So does Standard 16.1.9, Premium 13.0.3, multisite 20.2.7, VIP 32.0.7 and VIP multisite 35.0.6. Every one of them was vulnerable and every one of them scanned clean.
Widening the range does not save you either. Stretch it to 17.0.5 so a vulnerable 16.1.9 gets caught, and now every free-edition site on 5.4.5 or later starts reporting as vulnerable, because 5.4.5 is the smaller number. As Patchstack put it, one range cannot be right for seven version lines at once.
The fix, once the data existed, was straightforward: because the seven bands never overlap, the affected set can be expressed exactly as seven disjoint ranges on one slug. That is what the database record carries now. The missing piece was never the matching logic. It was the vendor's table, which had not been published anywhere.
Who is responsible for what
The temptation here is to write "security plugin insecure, lol," and it produces a worse and less useful article. Three parties did three different things, and only one of them made a decision that could have gone another way.
The vendor shipped two real bugs, which happens to everyone. More consequentially, it chose a distribution model that makes accurate advisories structurally difficult, and then patched six editions with no public changelog entry and no advisory. The second thing is the bigger problem and it is a decision, not an accident. Publishing a version matrix at disclosure time costs a vendor almost nothing.
The advisory process initially published a range describing only the free edition, which is the edition anyone can download and inspect. That record was correct about what it described. Once the matrix arrived, Patchstack corrected the database within about a day. That is fast, and it deserves saying rather than implying negligence.
The databases did exactly what they are built to do with the data available. This is a data-model limitation, not a bug in anyone's scanner, and every scanner in the ecosystem shares it.
What to do about the general problem
Not about miniOrange. About the class of problem, which will happen again with a different plugin.
Know which of your plugins have a paid edition on a different version line. This is a short list on most sites and almost nobody has written it down. It is the list where a green tick from a scanner means less than it looks like. Plugins with separate free and pro packages that share a slug, plugins distributed only from a vendor's own server, and plugins with per-tier builds all belong on it.
Read advisories for the plugin, not for your version number. If an advisory names a plugin you run and you cannot find your exact edition in its affected-versions table, the correct reading is "unknown," not "safe." That single reframing is the most valuable habit in this article, and it costs nothing.
Ask the vendor when the advisory does not name your edition. DigitalOcean's find and Patchstack's follow-up produced a full matrix from miniOrange in a day. A support ticket that says "which build of the Enterprise edition contains the fix for CVE-2026-61979" is a reasonable thing to send and takes two minutes to write.
Check that your paid plugins can actually receive an update. The 16.x situation is the whole point: a plugin that shows no update available is not necessarily up to date. Separately, and for a different reason, a premium plugin with a lapsed licence key will also silently stop receiving security updates while continuing to work perfectly. Both failure modes look identical from the dashboard, which shows nothing.
Record the edition alongside the version in whatever inventory you keep. If you manage sites at any scale, your plugin inventory almost certainly stores slug and version. Add a field for the edition or licence tier on the handful of plugins where it differs. On the day an advisory lands, that field is the difference between an answer and an afternoon.
The SSO angle, and being honest about scope
SAML SSO on WordPress is a minority deployment. It is agencies, intranets, universities, membership organisations and companies wiring a WordPress site into a corporate identity provider. Most WordPress sites will never install a plugin like this.
But those are exactly the sites where an administrator account is worth the most, and where the security team's mental model is "we removed passwords, so password attacks do not apply to us." That model is usually right. It has no slot for an authentication bypass in the SSO layer itself, which is not a password attack and does not care how strong your identity provider's MFA policy is. The forged assertion never reaches your identity provider at all.
This is not an argument against SAML, and it is not an argument that SSO plugins are risky. These are two implementation bugs in one plugin, in a bundled XML security library, of a kind that has appeared in Java, Python, Node and Ruby SAML implementations too. It is an argument for one thing only: treat the SSO integration as part of your authentication attack surface and patch it with the same urgency you would give a login-related core update. If you run WordPress inside a wider identity estate, that plugin deserves a line in the same security review as the rest of it.
What actually worked was noticing
Nobody found this by auditing code. There was no advisory to read, no database entry flagging the paid editions, and the plugin reported itself as fully up to date. Every signal that normally warns of a problem was saying everything was fine.
What surfaced it was an anomalous WordPress administrator session attempt appearing from outside a trusted network, and someone watching for that. The attacker had already used the bypass to obtain a valid admin session cookie. They were stalled because admin panel operations sat restricted behind the trusted network, which is defence in depth doing precisely the job it exists to do. The bugs had presumably been reachable for a long time. The thing that worked was not prevention. It was detection.
Scanning against the plugin's SSO endpoints has been observed from six addresses across Belgium, Nigeria, Germany and the United States, mostly VPN, datacentre and cloud VPS ranges plus one mobile carrier. Patchstack characterises the spread as opportunistic scanning rather than a targeted campaign, which means the attacker is throwing the exploit at every site with the plugin installed without checking which edition is behind it. The full indicator list is in Patchstack's advisory. The attacker does not need to know which edition you run. You do.
The one detection step that does not depend on knowing your version: review your logs for authenticated administrator sessions from addresses outside your expected ranges. On a site using SSO, an admin session that did not pass through your identity provider is worth explaining. If you have SSH access, a first pass over the access log costs a minute:
# Which addresses reached the plugin's SAML endpoints, most active first.
# Substitute the access log path your host uses.
grep -iE "saml|acs" /path/to/access.log \
| awk '{print $1}' | sort | uniq -c | sort -rn | head -20Compare those against your identity provider's own sign-in records. Anything that produced a WordPress session without a matching entry at the provider is the signal that matters. If you find one, treat the site as compromised: rotate credentials and salts, audit administrator accounts and application passwords, and restore from a backup taken before the earliest suspicious session rather than cleaning in place.
What a managed host can and cannot do about this
The honest answer is worth more than the marketing one, so here it is. A managed host's security dashboard is subject to exactly the same slug-plus-version limitation as everyone else's, and MagicWP's tooling is not an exception. Any product that tells you a plugin is patched is reading a slug and a version and comparing them to a database, and when the database is wrong about an edition, so is the dashboard. Anyone who tells you their scanner would have caught this is describing a database they do not have.
What good hosting actually contributes here is more boring and more real. It is being able to answer "which exact build is on this site" in seconds across every site you run, rather than logging into each one. It is having SSH and WP-CLI available so a manual plugin upload is a command rather than a project. It is a firewall in front of the application, where rule-based blocking covers all seven editions at once because it matches the exploit pattern rather than the version string. And it is a backup you can restore in one click when a manual upgrade to a plugin in the login path goes wrong, which it sometimes will.
Protection scaled fine through this incident. Reporting is what broke. That distinction is worth carrying into how you evaluate any security tooling, hosted or otherwise.
Frequently Asked Questions
Am I affected if I use the free miniOrange SAML SSO plugin?
If you are running 5.4.4 or earlier, yes, you were vulnerable to both CVEs. Version 5.4.5 closed them. A separate issue disclosed afterwards affects versions up to 5.4.6 and is fixed in 5.4.7, so 5.4.7 is the version to be on. The free edition has more than 10,000 active installations according to WordPress.org, and it is the only edition with a public install figure. Paid editions publish no usage statistics at all, so the real scale of exposure is unknown.
How do I tell which miniOrange edition I have?
Read the plugin's file header rather than trusting the version number. The registered plugin name includes the edition. Run wp plugin list --fields=name,title,version over SSH and look at the title column, or grep the Plugin Name line out of the PHP files in wp-content/plugins/miniorange-saml-20-single-sign-on/. Your licence or purchase receipt from miniOrange also names the tier. Version ranges are a reasonable cross-check: the free line is 3.x to 5.x, Premium 11.x to 13.x, Standard 15.x to 17.x, and so on up to VIP multisite at 35.x.
Why did my security plugin say the site was up to date?
Because it compared your plugin slug and version against a database record that described the free edition only, and every paid edition carries a higher version number than the free edition's fixed version. Your scanner worked correctly on the data it had. The record now carries seven separate version ranges for the one slug, so a rescan today should give the right answer.
Is a CVSS score of 8.1 or 9.8 correct for CVE-2026-61979?
Both figures are published. Patchstack's database records 8.1 and WPScan records 9.8 for the same issue, and the gap most likely comes from how each scores the step where an attacker fetches the identity provider's public key. CVE-2026-15981 is recorded as 9.8 by Wordfence as the CNA of record, with the vector AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H. The disagreement does not change what you should do: both are unauthenticated, both end in an administrator session, and both are fixed in the same release.
Should I stop using SAML SSO on WordPress?
No. These are two implementation bugs in one plugin's signature verification, not a weakness in SAML. Signature verification bugs of this exact shape have appeared in SAML libraries across most major languages. The reasonable response is to treat the SSO plugin as part of your authentication attack surface, patch it with the urgency you would give a core login fix, and keep at least one administrator route into the site that does not depend on the identity provider.
What should I check if I think a site was already compromised?
Look for administrator sessions that produced a WordPress login without a corresponding sign-in at your identity provider, and for administrator or editor accounts you do not recognise. Check for new application passwords, changed admin email addresses, unexpected scheduled events, and modified files under wp-content. If you find evidence of access, restore from a backup taken before the earliest suspicious session rather than cleaning the live site, then rotate salts, passwords and any API keys stored in the database.
Does a web application firewall protect me if I cannot update yet?
Partly, and it is the mitigation that generalises best here. A firewall rule matches the exploit pattern in the request, so it protects all seven editions equally whether or not the database knows which one you run. That is genuinely different from version-based alerting, which only works if it knows exactly what you have installed. Treat it as time bought rather than a fix: the vendor patch is still the thing that removes the vulnerability.
How do I stop this from happening again with a different plugin?
Write down which of your plugins have a paid edition on a version line separate from the free one, and record the edition alongside the version in whatever inventory you keep. When an advisory names one of those plugins, read it for the plugin rather than for your version number, and if your edition is not in the affected-versions table, ask the vendor which build contains the fix instead of assuming you are covered.
Conclusion
The immediate job is small. Identify your miniOrange SAML SSO edition, compare it to the version table, and update to at least the patched build for that edition, remembering that the free line should go to 5.4.7 and that a 16.x install needs a manual upload to 17.0.6 because no update prompt will appear. Back up first, and test on staging if the site matters, because a broken SSO plugin locks everyone out of the login page including you.
The longer-lived point is the one to keep. For roughly a month, the entire vulnerability-tracking apparatus of the WordPress ecosystem told paying customers of a security plugin that they were patched, and they were not, because a version number does not identify a product when one slug ships seven of them. No dashboard fixes that on its own, and any host claiming otherwise is overselling. What helps is knowing exactly which build is on each site, being able to update or roll back quickly when the answer turns out to be wrong, and reading "my edition is not in this table" as unknown rather than safe. MagicWP gives you the first two through SSH, WP-CLI, staging and one-click restore; the third is a habit, and it is free.
Get the best of MagicWP in your inbox.
Monthly engineering notes, product updates, and WordPress performance tips. No spam, unsubscribe anytime.

