Onyx AI

HIGH CVSS 8.7 · CWE-798 · onyx-dot-app/onyx · Fixed fb912b6c ↗

Hardcoded Default Value for SUPER_CLOUD_API_KEY Exposes Impersonation Endpoint in Multi-Tenant Enterprise Deployments

Onyx Enterprise Edition (MULTI_TENANT)
All versions before Jun 24 2026
backend/ee/onyx/configs/app_configs.py:119
CWE-798
8.7 HIGH: AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:N
2026-06
Fixed in commit fb912b6c

A traditional scanner pointed at this codebase would have flagged a hardcoded string and filed a medium-confidence finding. Kira did something different: it traced the credential forward through the auth stack, identified what endpoint it protected, mapped what that endpoint could do, and reasoned through the full blast radius: cross-tenant session token issuance, silent access to every connected data source, and no audit trail. The hardcoded default was the entry point. What Kira surfaced was the impact.

SUPER_CLOUD_API_KEY, the credential protecting the /tenants/impersonate endpoint in Onyx Enterprise Edition, defaulted to the literal string "api_key" when the environment variable was not set. This value is publicly visible in the open-source repository. Any MULTI_TENANT deployment where SUPER_CLOUD_API_KEY was not explicitly configured was operating with a trivially known credential on a privileged platform endpoint.

01 Root Cause

The default value was hardcoded verbatim in the configuration module:

# backend/ee/onyx/configs/app_configs.py line 119, pre-patch SUPER_CLOUD_API_KEY = os.environ.get("SUPER_CLOUD_API_KEY", "api_key")

The current_cloud_superuser dependency in backend/ee/onyx/auth/users.py (pre-patch lines 40–53) validated the caller’s Authorization header against this value using a plain string comparison:

# backend/ee/onyx/auth/users.py, pre-patch async def current_cloud_superuser( request: Request, user: User = Depends(require_permission(Permission.FULL_ADMIN_PANEL_ACCESS)), ) -> User: api_key = request.headers.get("Authorization", "").replace("Bearer ", "") if api_key != SUPER_CLOUD_API_KEY: # plain != comparison; accepts "api_key" by default raise HTTPException(status_code=401, detail="Invalid API key") if user and user.email not in SUPER_USERS: raise HTTPException(status_code=403, ...) return user

On any deployment where SUPER_CLOUD_API_KEY was not set in the environment, the effective credential was the well-known string "api_key", present verbatim in the public source code and requiring no brute force to discover. The comparison also used != rather than a constant-time function, introducing a timing side channel.

02 How Kira Reasoned Through This

Kira did not stop at flagging the hardcoded string. It traced the credential forward through the codebase: SUPER_CLOUD_API_KEY flows into current_cloud_superuser in auth/users.py, which is the dependency guarding POST /tenants/impersonate in server/tenants/api.py. Kira then read what that endpoint actually does: it resolves the target user across all tenants and returns a live session token. From there it mapped the downstream scope: that token authenticates against every connected data source the victim has authorised, including Google Drive, Confluence, Slack, GitHub, Jira, and Notion.

The reasoning chain Kira followed:

Step 1: Credential discovery  ·  SUPER_CLOUD_API_KEY defaults to "api_key" in app_configs.py. Value is public. Any deployment without explicit env var is using a known credential.

Step 2: Auth flow trace  ·  The credential is the only secret protecting current_cloud_superuser. The second check, the SUPER_USERS email allowlist, is set by the platform operator and cannot be modified by a tenant admin.

Step 3: Endpoint capability  ·  /tenants/impersonate performs a global user lookup across all tenants and returns a valid session token for any target email, with no scope restriction.

Step 4: Blast radius  ·  The returned token is a full session credential. Kira traced it through the integration layer to enumerate what it unlocks: every data source the victim has connected. The victim has no visibility that impersonation occurred. No audit event existed (pre-patch).

# Step 3: impersonation call on any unpatched MULTI_TENANT deployment POST /tenants/impersonate HTTP/1.1 Host: <onyx-enterprise-host> Authorization: Bearer api_key Content-Type: application/json {"email": "victim@targetorg.com"} HTTP/1.1 200 OK {"token": "<valid session token for victim>"}

That session token carries the victim’s full Onyx workspace: every document, every connector, and every integration authorised under their account. Google Drive, Confluence, Slack, GitHub, Jira, and Notion are all silently readable. No notification to the victim. No entry in logs (pre-patch).

03 Patches

Fix commit fb912b6c ↗, June 24 2026

Three changes in a single commit:

# 1. Default removed; key now defaults to None SUPER_CLOUD_API_KEY: str | None = os.environ.get("SUPER_CLOUD_API_KEY") # 2. Fails closed when key is unconfigured (HTTP 401) # 3. Comparison uses secrets.compare_digest; timing side channel removed

Feature flag commit 2878d850 ↗, June 23 2026

Adds an IMPERSONATION_ENABLED feature flag (default off). When disabled, the route is not registered at all, so requests return 404 before reaching the authentication layer.

# backend/ee/onyx/configs/app_configs.py IMPERSONATION_ENABLED = os.environ.get("IMPERSONATION_ENABLED", "").lower() == "true"
04 Scope & Affected Versions

This vulnerability only affects deployments running in MULTI_TENANT mode, which is the Onyx Enterprise Edition cloud configuration. Single-tenant self-hosted deployments do not mount the /tenants/impersonate route and are not affected.

All Onyx Enterprise Edition versions before commit fb912b6c (June 24 2026) where SUPER_CLOUD_API_KEY was not explicitly set in the deployment environment are affected.

05 Operator Remediation

Any MULTI_TENANT deployment where SUPER_CLOUD_API_KEY was not explicitly set should be treated as potentially compromised:

1. Upgrade  ·  Apply the patched version containing commit fb912b6c.

2. Rotate the key  ·  Set SUPER_CLOUD_API_KEY to a strong random secret in your deployment environment. Do not rely on any default.

3. Invalidate sessions  ·  Rotate all active user sessions in case the endpoint was used to issue tokens.

4. Review logs  ·  Check access logs for unexpected calls to POST /tenants/impersonate before your upgrade date.

5. Notify administrators  ·  Consider notifying affected tenant administrators per your incident response policy.

06 Vendor Response

Onyx AI thanked Offgrid Security for the report and shipped fixes promptly across two commits. The CWE-798 finding (hardcoded default credential) was acknowledged as a valid catch and fully remediated: the "api_key" default is removed, the check now fails closed with HTTP 401 when the key is unconfigured, and the comparison uses secrets.compare_digest eliminating the timing side channel. No formal security advisory was published.

CWE-798 fixed in fb912b6c ↗. No advisory published because Onyx considers MULTI_TENANT mode outside documented deployment scope. Reported by Kira, Offgrid Security.