On 16 August, DigitalOcean’s security team picked up exploitation attempts against WordPress sites running miniOrange’s SAML 2.0 Single Sign-On plugin. They reproduced the attack the following day against version 16.1.9, coordinated disclosure through Patchstack, and a public proof of concept now exists. Scanning is ongoing from at least six addresses across Belgium, Nigeria, Germany and the United States.
Two unauthenticated authentication bypasses, one of them CVSS 9.8, in a plugin whose entire job is deciding who gets to be an administrator. But the number that should stop you is 16.1.9, because every public advisory lists the affected range as 3.0.0 to 5.4.7. A site running a version eleven major releases above the published fix was exploitable, and it showed green in every vulnerability database and every WordPress dashboard that checked it.
TL;DR
- miniOrange SAML 2.0 SSO has two unauthenticated auth bypasses under active exploitation since mid-August 2026: CVE-2026-61979 (signature algorithm confusion) and CVE-2026-15981 (CVSS 9.8, a truthiness bug in signature verification).
- Both let an attacker forge a SAML assertion and log in as any user, including an administrator, with no credentials and no user interaction.
- The plugin ships seven independently versioned editions under a single WordPress slug. Advisories covered the free edition only; the paid tiers were patched quietly, without a public changelog entry.
- Vulnerability databases track one affected version range per slug, so a paid install on 16.1.9 or 26.0.1 sits above the “fixed in 5.4.5” line and is reported as safe. Version metadata is failing open.
- The fix matrix for all seven editions is below. Check which edition you run before you check the number, and treat silent patching of paid tiers as a vendor red flag in its own right.
Two ways to forge an assertion
SAML single sign-on works because the service provider, here your WordPress site, trusts a cryptographic signature made by the identity provider. Strip away the XML and the whole security model is one question: does this signature verify against the IdP’s public key. Both bugs are different ways of answering yes when the honest answer is no.
CVE-2026-61979 is signature algorithm confusion. A signed SAML response nominates its own SignatureMethod, and the plugin obligingly used whatever the document asked for. So an attacker sets the algorithm to HMAC-SHA1 and supplies the identity provider’s RSA public key as the HMAC shared secret. That key is public by design: it is in the IdP metadata, often published at a well known URL. Verification then succeeds, because the attacker has performed the exact computation the verifier is about to repeat. The signature is valid. It is simply not a signature from anybody in particular.
CVE-2026-15981 is smaller and, if anything, more instructive. PHP’s openssl_verify() returns three values: 1 for a good signature, 0 for a bad one, and -1 when verification itself errors out. The plugin treated the result as a boolean. In PHP, -1 is truthy. A signature malformed enough to break the verifier outright therefore did not fail closed, it passed. One missing comparison against a literal 1, and the trust boundary evaporates. Hence the 9.8.
This is JWT algorithm confusion wearing a SAML costume
If the first bug sounds familiar, it should. It is structurally identical to the alg: none and RS256-to-HS256 attacks that made JWT libraries a running joke a decade ago, and the root cause is the same one we set out in our session architecture piece: the verifier let the attacker choose the verification method. The token format changed, the format’s age changed, the mistake did not.
The rule that fixes both is unglamorous and absolute: the relying party decides which algorithm is acceptable, pins it in configuration, and rejects anything else before touching the key material. Nothing inside an untrusted document gets a vote on how that document is checked. If you have written or inherited code that consumes assertions, tokens or webhook signatures, that is the line to go and look for this week.
Note also where in the chain this sits. Last week we wrote about a critical flaw in Keycloak, at the identity provider end of the same trust relationship. This is the mirror image: the service provider end, in a plugin, on a CMS, installed by whoever set the site up and never thought about again. Both ends of an SSO integration are load-bearing security software. Only one of them tends to get treated that way.
The version number is not the version number
Here is the part that generalises well beyond this plugin, and the reason we are writing about it at all.
miniOrange distributes SAML SSO as seven separately versioned editions, all under the single WordPress slug miniorange-saml-20-single-sign-on: free, single-site and multisite premium tiers, standard, enterprise, all-inclusive and VIP. Their version numbers are unrelated. The free edition is in the 5.x range; VIP multisite is on 35.x. They are not one codebase at different maturities, they are different products sharing an identifier.
The public advisories named the free edition and its range, 3.0.0 through 5.4.7, because that is the artefact researchers can freely download and analyse. The paid editions were fixed too, but quietly, with no changelog line announcing a critical authentication bypass. Every automated system downstream then made the same reasonable inference: slug matches, installed version 16.1.9 is greater than the fixed version 5.4.5, so this site is patched. Your scanner was not lying to you. It was answering a narrower question than the one you asked.
The general lesson: “no known vulnerabilities” is a statement about a database’s coverage, not about your code. Slug-level or package-level version matching quietly breaks on any product with paid tiers, private forks, vendor-patched distributions or long-term-support branches where the number carries a different meaning. It also breaks whenever a vendor decides that customers who pay do not need to be told what was fixed.
The fix matrix
Identify your edition first (the plugin’s licence page or the admin footer will tell you), then compare against the corresponding minimum version. Comparing your number against the advisory’s number will mislead you.
- Free: 5.4.5
- Premium, single site: 13.0.4
- Standard, single site: 17.0.6
- Premium / Enterprise / All-Inclusive, multisite: 20.2.8
- Enterprise / All-Inclusive, single site: 26.0.3
- VIP, single site: 32.0.8
- VIP, multisite: 35.0.7
With a public proof of concept and active scanning, assume compromise on any site exposed while unpatched. Updating removes the hole, not an administrator account created through it. Audit the user table for accounts nobody recognises, check for changed administrator email addresses, rotate application passwords and API keys, and review recent plugin and theme installations.
What to do about it
- Patch by edition, today. Read the edition, then the number, then the matrix above. Do not shortcut to “we are on a higher version than the advisory”.
- Stop treating your scanner’s clean result as evidence. It is evidence that your version string did not match a range in a database. For anything sitting on the authentication path, that is not the same as safety, and it never was.
- Inventory your paid-tier and vendor-patched components. These are the ones automated tooling cannot reason about correctly. A short list of “things our scanner cannot check properly” is among the cheapest security artefacts you can keep, and the most useful during an incident.
- Grade vendors on disclosure, not just response time. A vendor who fixes paid editions without a public changelog entry has decided its customers’ visibility into their own risk is a marketing consideration. That belongs in your assessment alongside uptime and support.
- Audit your own signature verification. Pin the algorithm in configuration, reject anything the document proposes, and compare verification return values against the exact success value rather than for truthiness. Both of these bugs are one line each.
- Treat SSO plugins as identity infrastructure. Same patch window, same monitoring, same review cadence as your IdP, because they hold the same power to make somebody an administrator.
The uncomfortable general case
We build on WordPress, so this one landed close to home, but nothing about the failure is WordPress specific. Anywhere a version string stands in for a security property, and that string is issued by the same party whose bugs you are trying to detect, you have monitoring that fails open. Vendor-backported distributions of open source packages have exactly this shape, as do enterprise builds of runtimes and any dependency where “we are on the latest supported release” is asserted rather than verified.
Automated scanning is still worth having: it catches the ordinary case cheaply and no team should be without it. What it cannot do is tell you about the components it does not model properly, and it will never report that gap, because a scanner has no way to signal the absence of coverage. That judgement stays human, and it starts with knowing which parts of your estate the tooling is guessing at.
REPTILEHAUS builds and maintains production web platforms where authentication is treated as infrastructure rather than a plugin: SSO and identity integrations audited properly, dependency and patch management with an inventory of what the tooling genuinely covers, incident response when something has already got through, and security review of the code in your estate that verifies signatures and issues sessions. If you are running SSO on a site nobody has looked at in a year, get in touch.
📷 Photo by Lance Chang on Unsplash


