Bug 2509253 (CVE-2026-18382)

Summary: CVE-2026-18382 project-koku/koku-metrics-operator: koku-metrics-operator: service-account client credentials sent to user-controlled token_url
Product: [Other] Security Response Reporter: OSIDB Bzimport <bzimport>
Component: vulnerabilityAssignee: Product Security <prodsec-ir-bot>
Status: NEW --- QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: cmyers, dnakabaa, kaycoth, lcouzens
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
A flaw was found in koku-metrics-operator. The operator's CostManagementMetricsConfig custom resource allows a user able to edit the CR to specify an arbitrary OAuth token endpoint. When authentication.type is set to service-account, the operator sends the tenant's Red Hat SSO client_id and client_secret to this user-controlled URL, allowing the attacker to obtain the credentials.
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description OSIDB Bzimport 2026-07-30 11:46:54 UTC
## Summary

The koku-metrics-operator CostManagementMetricsConfig CRD exposes `spec.authentication.token_url` as a writable field with no host validation. When `spec.authentication.type == service-account`, the operator POSTs `client_id` and `client_secret` (read from a user-referenced Secret) as form data to this user-supplied URL. The default is the Red Hat SSO endpoint, but a CR editor can override it to any URL.

## Impact

A principal with `create`/`update` permission on `costmanagementmetricsconfigs` can redirect the tenant's Red Hat SSO `client_id`/`client_secret` pair to an attacker endpoint. These credentials grant `api.console` scope on `console.redhat.com` for the customer organization.

## Affected Code

- `api/v1beta1/metricsconfig_types.go:117` — `token_url` field definition (no validation)
- `internal/controller/costmanagementmetricsconfig_controller.go:450` — `GetAccessToken(ctx, cr.Spec.Authentication.TokenURL)` call
- `internal/crhchttp/config.go:75-93` — POST to user-supplied `tokenURL`

## Remediation

Hard-code the Red Hat SSO token endpoint or enforce a suffix allow-list (`*.redhat.com`) in `GetAccessToken`. Reject non-HTTPS schemes:

```go
if !strings.HasSuffix(tokenURL, ".redhat.com") {
    return "", fmt.Errorf("token_url must be a *.redhat.com endpoint")
}
```