Bug 2498426 (CVE-2026-15218) - CVE-2026-15218 models-as-a-service: Red Hat OpenShift AI: maas-api and maas-controller ServiceAccounts with excessive permissions lead to privilege escalation
Summary: CVE-2026-15218 models-as-a-service: Red Hat OpenShift AI: maas-api and maas-c...
Keywords:
Status: NEW
Alias: CVE-2026-15218
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Product Security
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2026-07-09 08:06 UTC by OSIDB Bzimport
Modified: 2026-08-17 10:49 UTC (History)
1 user (show)

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


Attachments (Terms of Use)

Description OSIDB Bzimport 2026-07-09 08:06:59 UTC
The maas-api and maas-controller ServiceAccounts in the models-as-a-service project
(formerly maas-billing) are granted cluster-wide RBAC permissions far beyond what
either component's code actually uses, and in maas-controller's case, permissions
that allow full cluster-RBAC takeover if the ServiceAccount's identity is ever
obtained.

maas-api (deployment/base/maas-api/rbac/clusterrole.yaml, lines 13-22):

- apiGroups: [""]
  resources: ["namespaces"]
  verbs: ["get", "list", "watch", "create"]
- apiGroups: [""]
  resources: ["serviceaccounts"]
  verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
  # Needed for TokenRequest API
  resources: ["serviceaccounts/token"]
  verbs: ["create"]

A ServiceAccount holding serviceaccounts/token:create cluster-wide can mint a live,
valid token for any ServiceAccount in any namespace via the TokenRequest API, including
ServiceAccounts belonging to other, more privileged operators/controllers.

maas-controller (deployment/base/maas-controller/rbac/clusterrole.yaml):

Lines 22-29 (secrets, cluster-wide):
- apiGroups: [""]
  resources: ["endpoints", "pods", "secrets"]
  verbs: ["get", "list", "watch"]

Lines 61-64 (serviceaccounts/token, cluster-wide, same exposure as maas-api):
- apiGroups: [""]
  resources: ["serviceaccounts/token"]
  verbs: ["create"]

Lines 342-353 (cluster RBAC objects, cluster-wide):
- apiGroups: ["rbac.authorization.k8s.io"]
  resources: ["clusterrolebindings", "clusterroles"]
  verbs: ["create", "delete", "get", "list", "patch", "watch"]

Holding clusterroles/clusterrolebindings:create cluster-wide lets the ServiceAccount
create a new ClusterRoleBinding granting itself (or any other identity) the built-in
cluster-admin ClusterRole, a direct, self-service path to full cluster administrator.
The cluster-wide secrets:get/list/watch grant exposes every Secret in the cluster
(other components' credentials, TLS keys, etc.), not just this component's own
configuration.

Trigger / exploit path: neither grant is reachable through maas-api's or
maas-controller's own public API surface directly, no code path in either component
lets an external caller make it invoke serviceaccounts/token.Create or
clusterroles.Create on the caller's behalf. A previously-identified authentication
issue in this same product (request-header spoofing at the gateway/auth layer) does
not by itself yield either ServiceAccount's own Kubernetes API access, that issue
affects only the application-level authentication check, not RBAC. The actual trigger
here is one of:
  1. Genuine RCE/pod compromise of the maas-api or maas-controller pod (tracked
     separately), or
  2. Any principal able to create a Pod inside the maas-api/maas-controller namespace
     can set serviceAccountName: maas-api (or maas-controller) on their own Pod spec
     and directly assume that ServiceAccount's token, with no code-execution bug in
     either component required.
Once either path is reached, the grants above let the attacker escalate straight to
cluster-admin (via clusterrolebindings:create) or exfiltrate cluster-wide secrets,
well beyond what either component's documented function requires.

Verification: confirmed directly against opendatahub-io/models-as-a-service's current
main branch via the GitHub API on 2026-07-09. Note the finding's originally-cited
cluster-wide configmaps:get,list,watch,create,update,patch,delete grant for maas-api is
no longer present in the current clusterrole.yaml, only the namespaces/serviceaccounts/
serviceaccounts-token grants above remain live. The maas-controller grants (secrets,
clusterroles/clusterrolebindings) are unchanged and fully present as described.

CWE-269 (Improper Privilege Management): both ServiceAccounts are assigned far more
authority than their actual code paths use, creating an unintended sphere of control
that, if the ServiceAccount identity is ever obtained via either route above, extends
to full cluster compromise.

Source: Red Hat Product Security internal audit finding.


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