Fedora Account System
Red Hat Associate
Red Hat Customer
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)