Bug 2511170 (CVE-2026-18950) - CVE-2026-18950 odh-dashboard: odh-dashboard: Confused-deputy privilege escalation via unchecked roleRef in RoleBinding creation
Summary: CVE-2026-18950 odh-dashboard: odh-dashboard: Confused-deputy privilege escala...
Keywords:
Status: NEW
Alias: CVE-2026-18950
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
urgent
urgent
Target Milestone: ---
Assignee: Product Security
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2026-08-04 18:45 UTC by OSIDB Bzimport
Modified: 2026-08-10 18:54 UTC (History)
1 user (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed:
Embargoed:


Attachments (Terms of Use)

Description OSIDB Bzimport 2026-08-04 18:45:26 UTC
Description

Description of problem
The POST route at backend/src/routes/api/rolebindings/index.ts:35-62 accepts the full V1RoleBinding body from the user and passes it to the K8s API. The requestSecurityGuard() validates metadata.namespace and metadata.name but does NOT validate roleRef.name.

A user can create a RoleBinding with an arbitrary roleRef (e.g., referencing cluster-admin or any other ClusterRole) as long as the name and namespace match the expected patterns. The dashboard SA has create rolebindings permission cluster-wide.

Impact:

Authenticated dashboard user can grant themselves any ClusterRole within their namespace

Combined with RHOAIENG-69306 (cluster-wide secrets access via dashboard SA), this enables privilege escalation

Enables persistent access by binding privileged roles to attacker-controlled service accounts

Prerequisites
RHOAI/ODH with dashboard component enabled

Authenticated dashboard user (any valid credential)

User must have access to the RHOAI dashboard UI

Steps to Reproduce
Authenticate to the dashboard as any user

Send a POST request to the rolebindings endpoint with a crafted roleRef:



curl -X POST -H "Authorization: Bearer <user-token>" \
  -H "Content-Type: application/json" \
  https://<dashboard-url>/api/rolebindings \
  -d '{
    "apiVersion": "rbac.authorization.k8s.io/v1",
    "kind": "RoleBinding",
    "metadata": {
      "name": "jupyter-nb-<username>",
      "namespace": "<user-namespace>"
    },
    "roleRef": {
      "apiGroup": "rbac.authorization.k8s.io",
      "kind": "ClusterRole",
      "name": "cluster-admin"
    },
    "subjects": [{
      "kind": "User",
      "name": "<attacker-username>"
    }]
  }'
The dashboard backend creates the RoleBinding without validating the roleRef, granting cluster-admin in the target namespace.

Actual results
The requestSecurityGuard() at route-security.ts:43-107 validates:

metadata.namespace: must be workbenchNamespace or dashboardNamespace

metadata.name: must match jupyter-nb-<translatedUsername>, jupyterhub-singleuser-profile-<translatedUsername>-envs, or <workbenchNamespace>-image-pullers

But roleRef.name is NOT validated. The dashboard SA creates the RoleBinding using its own permissions (which include cluster-wide rolebindings CRUD per RHOAIENG-69306).

Expected results
roleRef.name should be validated against an allowlist of permitted roles (e.g., only image-puller, notebook-access roles)

The RoleBinding should be created using the user's token (impersonation), not the SA token

Reproducibility
Always - The code path is deterministic.

Found in what build
CONFIRMED in code: opendatahub-io/odh-dashboard (current main branch)

LIKELY VULNERABLE: All RHOAI versions with dashboard rolebindings API

Describe any workarounds
Restrict dashboard access to trusted users only

Monitor for unexpected RoleBindings referencing cluster-admin (audit log alerting)

Implement OPA/Gatekeeper policy to reject RoleBindings with cluster-admin roleRef in user namespaces

Additional information
Root Cause:



// backend/src/routes/api/rolebindings/index.ts:35-62
// Uses secureRoute(fastify) (NOT secureAdminRoute)
// Entire request.body (V1RoleBinding) passed to createNamespacedCustomObject
// requestSecurityGuard checks metadata.namespace and metadata.name
// but does NOT check roleRef.name
CWEs:

CWE-441: Unintended Proxy or Intermediary (Confused Deputy)

CWE-863: Incorrect Authorization

CWE-269: Improper Privilege Management

Discovery Method:

Project Glasswing (Mythos) automated security audit.

Related issues:

RHOAIENG-69306: Dashboard SA cluster-wide RBAC permissions (enables the CRB creation)

RHOAIENG-69307: Cross-namespace SSRF via llama-stack proxy (same dashboard)


Note You need to log in before you can comment on or make changes to this bug.