Enterprise SSO is the control B2B companies use to make sure the right people get in. Flowise shipped a vulnerability that made it a door anyone could walk through. Not by breaking the SSO protocol. By attacking the API endpoint that decides which SSO configuration the tenant uses.
CVE-2026-30823 is an Insecure Direct Object Reference vulnerability in Flowise, the widely-used open-source drag-and-drop LLM workflow builder. CVSS 8.8. Fixed in v3.0.13. The companion vulnerability, CVE-2026-30820, exposed a related trust boundary failure: an x-request-from: internal header that components accepted without verification.
How the Attack Works
The vulnerable endpoint is PUT /api/v1/loginmethod. This endpoint controls a tenant's login configuration, including whether they use Basic auth, external SSO, or enterprise identity providers.
No authentication check on the endpoint. An unauthenticated attacker can send a PUT request with a target tenant's ID and replace their login configuration entirely.
The attack chain is four steps: identify a target Flowise instance, send an unauthenticated PUT to /api/v1/loginmethod with the tenant ID and an attacker-controlled SSO configuration, authenticate using the attacker's identity provider, and take over the tenant's account. No credentials. No prior relationship with the target organization.
The attack doesn't break the SSO protocol. It bypasses the question of SSO entirely by controlling which SSO configuration the platform uses. The enterprise security feature becomes the attack surface precisely because it controls authentication, and the endpoint managing it was left unprotected.
Why This Pattern Is Everywhere
This isn't a Flowise-specific failure. It's a pattern that appears in multi-tenant SaaS platforms whenever authorization is applied inconsistently across the API surface.
The dangerous assumption: authentication at the perimeter means authorization inside it. An app that requires login for most endpoints will often have gaps where high-privilege actions skip per-request checks. Administrative and configuration endpoints are especially prone to this. They're built early, tested lightly, and often treated as internal-facing even when they're reachable from the internet.
The IDOR compound makes it worse. Even if the endpoint had required authentication, an IDOR vulnerability means the authorization logic doesn't verify that the authenticated caller owns the resource they're modifying. In a multi-tenant platform, that means any authenticated user in any tenant can modify any other tenant's configuration.
Multi-tenant platforms amplify the blast radius. In a single-tenant application, a missing authorization check is serious. In a multi-tenant platform, every tenant is exposed to every other tenant's attack surface. One misconfigured endpoint means the entire tenant estate is affected.
Why Your Tools Won't Find This
Traditional security tooling isn't built to catch authorization logic failures.
SAST tools analyze code for known-bad patterns. An IDOR isn't a syntax error or an injection sink. The code is structurally valid. The problem is logical: the right check isn't being made, not that a dangerous function is being called.
WAFs protect against known attack signatures. An unauthenticated PUT request to a legitimate application endpoint doesn't match any attack pattern. It's a normal HTTP request.
Dependency scanners identify known CVEs in third-party libraries. They don't analyze the authorization logic the application builds on top of those libraries.
Compliance checks verify settings. They don't test runtime behavior. Checking whether SSO is enabled tells you nothing about whether the endpoint that configures SSO is protected.
The only tool that catches authorization logic failures is one that tests the API from the outside: without credentials, with wrong credentials, with other tenants' credentials, in combinations the developer didn't explicitly test. This is architectural testing, not signature matching.
The Trust Boundary Problem
CVE-2026-30820, the companion vulnerability, is a useful illustration of the same root cause expressed differently. That vulnerability involved an x-request-from: internal header that application components accepted without verification. The implicit assumption: requests with that header came from internal services and could be trusted.
An attacker can set any header they want. Trusting a header as proof of origin is a design-level mistake. The fix isn't to change the header value. It's to remove the architectural assumption that headers encode trust.
Both CVE-2026-30823 and CVE-2026-30820 trace back to the same class of failure: implicit trust assumptions that were never tested under adversarial conditions. They're invisible until someone decides to check whether the assumption holds.
What You Need to Do
Patch to Flowise v3.0.13 immediately. If you're running an older version with external access, audit your user list for unauthorized accounts and check for unexpected SSO configuration changes.
Audit every API endpoint that touches authentication or authorization configuration. These are the highest-privilege actions in your application. They deserve more scrutiny than endpoints that read data. Start there.
Test authorization with explicit negative cases. Can an unauthenticated caller hit this endpoint? Can a caller in tenant A access tenant B's resources? Can a low-privilege user access an admin-only action? These questions don't get answered by reading the code. They get answered by testing the API.
Review your trust boundaries explicitly. Map every place your application makes a trust decision: headers, tenant IDs, session tokens, service-to-service calls. Ask what happens if that trust assumption is wrong. If you can't answer, it hasn't been tested.
The Bigger Lesson
The feature that looked like a security control wasn't enforcing anything. The endpoint behind it never asked who was calling.
Authorization failures are different from most vulnerability classes because they're invisible in the code. There's no dangerous function call, no injection sink, no malformed input. The code does exactly what it was written to do. The problem is what it was written to do doesn't include checking whether the caller is allowed.
For security teams, the lesson is the same one Azure APIM's "disable signup" toggle taught: the interface is a representation of intent. The API is what's actually enforced. If you're not testing the API under adversarial conditions, you're trusting representations, not reality.
Your SSO is only as secure as the endpoint that decides which SSO you use. Test whether that endpoint has an opinion about who's asking.