One Request to Admin: Three Skipped Auth Checks in Bisheng
The interesting thing about the three bugs we found in Bisheng is not that they exist. It is that they are the same mistake, made three times, in three different files, by developers who clearly knew better. In every case a function that reads or acts on data belonging to a specific user simply skipped the ownership check that its sibling functions, sitting right next to it in the same class, already performed. The write paths were guarded. The read paths were not.
Bisheng is an open-source, enterprise-grade platform for building LLM applications: a RAG workflow builder and agent platform, typically self-hosted on Kubernetes or Docker, that teams use to wire together language models, tools, and knowledge bases. Its own documentation describes multi-tenant, multi-team enterprise deployments as a primary use case, and it ships a commercial "Bisheng Pro" mode with SSO for exactly that setting. That multi-user shape is what turns three skipped checks from a code-quality note into a cross-tenant breach.
The short version
We reported three missing-authorization flaws in Bisheng. The most serious, CVE-2026-96679 (CVSS 9.8), turns a single unauthenticated request into a super-admin session on any instance running with BISHENG_PRO=true — and it is still unpatched. The other two, CVE-2026-96681 (6.5) and CVE-2026-100156 (5.4), let any logged-in user read other users' workflow data and run work against other users' LLM API keys. All three were coordinated through CERT/CC as VU#166125.
The findings at a glance
| CVE | Issue | Severity | Fix status (verified 2026-09-25) |
|---|---|---|---|
| CVE-2026-96679 | Pre-auth admin takeover via /user/sso | 9.8 Critical | No fixed version. Legacy endpoint still live on main. |
| CVE-2026-96681 | Cross-user flow/workflow version disclosure (IDOR) | 6.5 Medium | Fixed in the v3.0.0 line only; every 2.x release remains vulnerable. |
| CVE-2026-100156 | Cross-user assistant LLM credential abuse | 5.4 Medium | Fixed in v2.5.0 — silently, before disclosure, never documented as security. |
Vendor: DataElem, Inc. Affected project: dataelement/bisheng. All three were discovered in a manual source-code audit on May 14, 2026, and reported to the vendor through GitHub Private Vulnerability Reporting on May 23, 2026. There was no SECURITY.md and no security contact; private reporting was the only channel available.
CVE-2026-96679: a flag is not a credential
Bisheng's "Pro" mode is designed to sit behind a separate, closed-source SSO gateway. The idea is that in a production Pro deployment, a trusted front end authenticates users and then tells Bisheng who they are. To support that, the open-source backend exposes an endpoint, POST /user/sso, that accepts a username and issues that user a signed session token.
The problem is the gate on that endpoint. The only thing standing between an anonymous caller and a valid session is a check that BISHENG_PRO is switched on. That is an environment-variable flag, not a credential. There is no shared secret, no signed assertion, no header token, no IP allowlist — nothing that verifies the caller is actually the trusted gateway rather than an anonymous visitor on the internet. The flag is meant to signal that a gateway is present. The code never confirms it.
With the flag on, the endpoint will issue a token for whatever username it is handed. And the account-provisioning logic behind it will, under ordinary first-run or configured-admin-name conditions, mint that session at the super-admin role. The result is that a single unauthenticated request can return a fully privileged administrative token. We are deliberately not publishing the request itself, because there is no fixed version to upgrade to.
Why we are withholding the proof-of-concept
CVE-2026-96679 has no patch as of this writing. Publishing a copy-paste exploit for an unpatched critical would hand attackers a weapon and give defenders nothing they cannot already act on. The mitigations below do not depend on the exact request, and we will not release exploit detail until a fix ships.
What an attacker gets
Super-admin on a Bisheng instance is not a contained prize. It reads as full control of everything the platform touches:
- Confidentiality: every user's flows, workflows, and assistants; every knowledge base; and every LLM-provider API key configured anywhere on the instance.
- Integrity: create, modify, or delete any user, flow, assistant, knowledge base, or system setting.
- Availability: delete administrators, lock out legitimate users, wipe knowledge bases.
Because Bisheng flow and assistant configurations routinely embed credentials for external systems — LLM providers, internal databases, REST APIs — an admin compromise here tends to chain outward into the connected infrastructure rather than stopping at the platform boundary.
This finding is dormant on default open-source deployments, which ship with BISHENG_PRO=false. It is live on precisely the enterprise Pro deployments the mode exists to serve.
Where it stands today
We re-checked the current dataelement/bisheng main source on September 25, 2026, reading the handler directly rather than trusting commit messages. The legacy endpoint's behavior is unchanged: it still issues a token for a supplied username with no caller authentication when Pro mode is on. The vendor has, in the interim, built a properly HMAC-authenticated replacement family of endpoints, and the legacy handler's own docstring now points to it. But the old, unauthenticated endpoint has not been removed, disabled, or gated behind the new check. It is still present and still reachable. No release in either the 2.x or 3.x line remediates it.
If you run Bisheng Pro, do this now
There is no fixed version, so mitigation is the whole game. Only set BISHENG_PRO=true if the deployment is genuinely fronted by a gateway that authenticates callers before they reach /user/sso. Migrate to the newer HMAC-authenticated /api/v1/internal/sso/login-sync endpoints. And as defense in depth, restrict /user/sso so it is reachable only from the gateway, not from general network traffic.
CVE-2026-96681: read any user's workflow, including its secrets
The second bug lives in the flow and workflow service. Bisheng versions a user's flows and workflows, and exposes endpoints to list the versions of a flow and to fetch the full contents of a specific version. Neither of those two read methods checks whether the caller owns, or has any relationship to, the flow they are asking about. The methods are even handed the caller's identity as a parameter — and then never use it.
What makes this more than an abstract information leak is what a version's contents actually hold. A Bisheng flow definition includes the configuration of every node in it: REST, SQL, and GraphQL nodes carry headers, connection strings, and parameters, which in practice frequently means hardcoded credentials. It also includes proprietary system prompts and the linkages between tools, flows, and knowledge bases. The listing path compounds it by returning soft-deleted versions too, so history a user believed they had retracted is still readable.
The tell is right there in the same class. The write operations on flow versions — delete, create, update, change-current — all call an ownership check before they act. Only the two read paths were missing it. Any authenticated account, including a freshly registered default-role user, can enumerate and read another user's workflow versions. In the multi-tenant deployments Bisheng markets to, that is a cross-team credential and intellectual-property exposure. It is read-only, which is why it lands at 6.5 rather than higher.
This one is fixed — but only partly, and in a way worth spelling out. The fix arrived as part of a broad migration to a relationship-based (ReBAC) permission model and first appears in the v3.0.0 line. We verified by reading the source at each release tag, not by tag names or dates: every 2.x release we checked, including the current 2.6.0 patch series, still lacks the check. Teams on the 2.x line, even fully up to date within it, remain exposed. Only moving to the 3.0.0 line closes it, and even there the change was never called out as a security fix.
CVE-2026-100156: running on someone else's dime
The third bug is in the assistant service, in the feature that auto-optimizes an assistant's prompt by running it through that assistant's own configured LLM. The endpoints that queue and stream that optimization took an assistant identifier from the caller and never checked whether the caller owned that assistant.
Two things follow. First, the optimization runs against the target assistant's LLM configuration — which means an attacker can drive inference billed to another user's provider account (OpenAI, Azure, Anthropic), spending their quota and their money on arbitrary prompts. Second, the streamed response describes the victim assistant's configured tools and flows, a smaller information leak that chains naturally with the flow disclosure above. Same structural mistake as the others: the sibling write methods all called the permission check; this read-and-execute path was the one that skipped it.
This is the one the vendor has fully fixed — but the timeline is its own story. The fix landed in v2.5.0, and we confirmed it by reading the source at the tags on either side. Crucially, the fix commit predates our discovery and our report. It was not a response to disclosure. It was incidental collateral from the same large permission-architecture migration DataElem was running that month, which happened to add the missing check while refactoring. From a user's point of view there was never any signal: no changelog entry, no release note, no advisory. The endpoint was quietly vulnerable, and then quietly not.
The pattern worth taking away
Three modules, one recurring gap: a read or execute path that skips the ownership check its neighboring write paths already enforce. If you build multi-tenant software, the lesson is that authorization belongs on every data path, and the fastest place to find where it is missing is to line up the methods that touch the same resource and look for the odd one out. That review takes an afternoon. It is the review that would have caught all three of these.
Disclosure timeline
- May 14, 2026Manual source-code audit of Bisheng identifies all three missing-authorization issues.
- May 23, 2026All three reported to DataElem via GitHub Private Vulnerability Reporting. No security policy or contact existed; private reporting was the only channel.
- June 18, 202626 days on, no vendor response of any kind. Reports prepared for CERT/CC coordination.
- July 28, 2026CERT/CC receives the bundled report and opens case VU#166125.
- August 19, 2026With vendor silence continuing, CERT/CC opens its own coordinating advisory covering the still-live issues, crediting the finder.
- September 3, 2026CVE-2026-96679 and CVE-2026-96681 assigned. Full technical detail supplied to the coordination case.
- September 21, 2026Public-disclosure floor for the vulnerability note.
- September 25, 2026CVE-2026-100156 assigned for the third finding. Patch status re-verified against upstream source for all three: the critical remains unpatched.
The vendor did not respond to the reporter or, as far as the coordination record shows, to CERT/CC across the entire window. Two of the three issues picked up fixes anyway — one incidentally before we ever reported it, one only in a still-young major-version line — as byproducts of an unrelated refactor rather than a deliberate security response. The highest-severity issue, the one that matters most, is the one still open.
What to do if you run Bisheng
- If you run Pro mode (BISHENG_PRO=true): treat CVE-2026-96679 as an active, unpatched critical. Confirm a gateway authenticates every caller before /user/sso, move to the HMAC-authenticated login-sync endpoints, and restrict the legacy endpoint to the gateway path only.
- If you run any 2.x release: you are still exposed to the cross-user workflow disclosure (CVE-2026-96681). Moving to the 3.0.0 line is currently the only code-level fix; until then, treat every credential stored inside a flow or workflow node as readable by any account on the instance and rotate accordingly.
- Everyone: stop hardcoding credentials in flow, workflow, and node configurations. Where Bisheng supports referencing secrets indirectly, use that. A disclosure bug hurts far less when the thing disclosed is a reference rather than a live key.
- Assume the audit is not over. Three instances of one pattern is a signal, not a coincidence. If you depend on Bisheng in a multi-tenant setting, the responsible assumption is that other read paths carry the same gap.
Is your platform's authorization actually enforced?
These bugs were not clever. They were checks that existed on some code paths and not others — the kind of gap a manual, source-aware review finds and an automated scan walks straight past. That is the work we do. If you are shipping multi-tenant software and want to know where your ownership checks are missing, let's talk.
Scope a penetration testMore Voke Cyber research: CVE-2026-17613: cross-team file takeover in Penpot · CVE-2026-15630: cross-tenant authorization bypass in Casdoor · the full advisory index.