REDHAT-BUG-2498426: Medium severity Red Hat models-as-a-service (maas-api) vulnerability
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.