On July 30, 2026, Red Hat disclosed a CVSS 7.6 flaw in koku-metrics-operator, the OpenShift component that uploads cluster usage data to Red Hat's Cost Management service. The bug (CVE-2026-18381) doesn't involve a broken auth check, a leaked secret in a config map, or a container escape. It's simpler than that: the operator's CostManagementMetricsConfig custom resource has a user-editable upload URL, and the operator attaches its own Kubernetes service-account bearer token to every request it sends to that URL. Point the URL at a server you control, and the operator hands you its own credential — no separate exploit required.
That's the whole vulnerability. And it's worth your attention even if you've never touched koku-metrics-operator, because the shape of the bug — a CRD field that a lower-trust caller can edit, wired into a request that carries the operator's own privileged identity — is not specific to Red Hat's cost-management tooling. It's a pattern that shows up anywhere a Kubernetes operator reads a URL from a spec field and then reaches out to it while authenticated as itself. If you ship your own operators and CRDs — which any self-hosted PaaS with its own control plane does — the interesting question isn't "was I running this operator," it's "do any of my own CRDs have this shape."
How the token actually leaked
koku-metrics-operator runs on a schedule: every hour, it queries the cluster's Prometheus for usage metrics, packages them into a report, and uploads that report so Red Hat's Cost Management service can bill and chart it. The destination for that upload is normally console.redhat.com, but it's not hardcoded — it's read from CostManagementMetricsConfig, a CRD that also lets operators point the uploader at an internal proxy or an air-gapped collector, which is a legitimate reason for the field to be user-editable at all.
The request-building code looks, in shape, like this:
req, _ := http.NewRequest("POST", cr.Spec.UploadURL, reportBody)
req.Header.Set("Authorization", "Bearer "+serviceAccountToken)
client.Do(req)Nothing here checks whether cr.Spec.UploadURL still points somewhere the operator's own credential should be allowed to reach. Anyone with edit access to the CR — which, in practice, includes whatever RBAC role your organization grants for "manage cost reporting config," a role that has nothing to do with cluster-admin — can set UploadURL to https://attacker.example/collect. The operator's next scheduled run builds the request exactly as designed, attaches its own service-account bearer token in the Authorization header, and POSTs the report to the attacker's server. The token is now sitting in that server's access log.
No credential was stolen from a secret store. No RBAC boundary was crossed to get read access to the token — the operator delivered it voluntarily, as a side effect of a feature (configurable upload destination) that a legitimate admin might use for something as mundane as routing through an internal proxy.
This is a pattern, not a one-off
If this were an isolated Red Hat bug, it'd be worth a patch note and nothing else. It isn't isolated. Kyverno — one of the most widely deployed Kubernetes policy engines, running as an admission webhook with cluster-wide authority — shipped CVE-2026-4789 earlier this year: a namespace-scoped user could get the Kyverno admission controller to make arbitrary outbound HTTP requests, because a webhook-configuration field it read was insufficiently constrained. Different subsystem, different vendor, same underlying shape: a field a lower-privilege caller can set determines where a highly privileged component sends a request.
The tell is always the same two facts holding at once in the same code path:
- A spec, CRD, or webhook-config field sets or influences a request's destination, and that field is writable by someone with less trust than the component making the request — a tenant, a namespace-scoped user, an app owner, anyone who isn't the platform operator.
- The component attaches its own privileged identity — a bearer token, a mounted service-account credential, an API key — to that outbound request, unconditionally, regardless of what the destination turns out to be.
Neither half is a bug by itself. User-configurable destinations are often a real feature (an internal proxy, a customer-specified webhook, a log export target). Operators authenticating their own outbound calls is normal and often necessary. The bug is the combination: the credential travels to wherever the field points, without the code ever asking whether that destination still deserves it.
Concretely, the field types worth treating as suspect in any operator or platform control plane: upload/export URLs, webhook or notification-sink targets, callback URLs, and anything an operator dereferences on a timer or in response to an event using its own service identity.
An audit checklist you can run today
You don't need a fuzzer or a CVE database subscription to find this in your own codebase — it's a grep away, followed by five minutes of reading. Two passes:
Pass 1 — find the outbound request builders. Search your operator/controller code for HTTP client construction: http.NewRequest, http.Client{}.Do, resty.New(), whatever your stack uses. For each call site, trace where the URL argument comes from.
Pass 2 — find the credential attachment. In the same function or call chain, look for Authorization header sets, bearer token injection, or a client configured with a mounted service-account token, API key, or client certificate. If a call site shows up in both passes — the URL traces back to a CRD/webhook/spec field, and the same request carries a privileged credential — you've found a candidate.
Then ask, for each candidate: is the credential scoped to something the destination is allowed to have? A per-tenant, single-purpose signing secret handed to a tenant's own endpoint is fine — the tenant already had it. A cluster-scoped service-account token or a platform-wide API key attached to a caller-influenced destination is the CVE-2026-18381 shape, full stop.
Field categories to inventory first, roughly in order of how often platforms have them: upload/export URLs, deploy or build notification webhooks, log/metrics shipping sinks, and any "call me back at this URL" field in a CRD or admission-webhook config.
Running the checklist on our own CRDs
We ran this against bex's own operator surface, because "audit yourself before a tenant finds it first" is the point of the exercise, not just reader homework. The one place bex's control plane makes an outbound call to a tenant-supplied destination is deploy and build-status webhooks — an app owner can register a URL to be notified when a deploy starts, succeeds, or fails, the same shape as Render's webhook API.
Applying the checklist: does that outbound call carry a privileged credential? No. The payload is signed with an HMAC secret scoped to that single app's own webhook configuration — the same pattern GitHub and Stripe use for their webhook deliveries — not the operator's cluster-scoped service credential or any platform-wide API key. Pointing the notification URL at an attacker-controlled server nets the attacker nothing beyond a signed payload the app owner could already see in their own dashboard; there's no ambient credential riding along to steal, because none is attached to a request whose destination the tenant chose.
That's the finding, and it's also the rule we're holding any future tenant-configurable destination to — log export sinks, third-party notification integrations, anything along those lines: the request may carry a resource-scoped signing secret the caller already controls, never the operator's own privileged identity.
The fix isn't more RBAC
The instinctive response to "an under-privileged user can trigger this" is to tighten RBAC on the CRD — restrict who can edit CostManagementMetricsConfig, require a higher role for the upload-URL field specifically. That doesn't fix the underlying bug, and in most real deployments it isn't even practical: the whole reason the field is editable by a broader set of roles is that legitimate admins with narrower job functions — "manage cost reporting," "configure notification integrations" — genuinely need to set it. Locking the field to cluster-admin defeats the feature.
The actual fix has nothing to do with who can edit the field, and everything to do with what the operator does once the request is built:
- Never attach a privileged token to a request whose destination a lower-trust caller controls. If the operator's own identity needs to travel, the destination needs to be fixed, not read from a spec field.
- If a token must travel to a configurable destination, validate the resolved destination against an allowlist — after following redirects, not before. Validating the URL string and then letting the HTTP client follow a 302 to somewhere else is the same bug with extra steps.
- Route caller-configurable outbound calls through an egress path with no ambient credential, so that even a fully attacker-controlled destination has nothing privileged to receive.
Any of these closes the hole regardless of how permissive the CRD's RBAC ends up being — which is the property you actually want, since RBAC policy drifts and gets loosened for convenience, but "this code path never attaches a bearer token to a caller-controlled URL" doesn't drift.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own, with the operator/CRD layer in the open where anyone can run this same audit against it. Star the repo on GitHub or deploy your first app today.



