CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-23990

The Invisible User: Escaping RBAC in Flux Operator via OIDC Null-States

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 15, 2026·8 min read·22 visits

Executive Summary (TL;DR)

The Flux Operator Web UI fails to validate empty OIDC claims. If a user's identity maps to an empty string, the backend skips adding impersonation headers to Kubernetes API requests. Consequently, the request falls back to using the Operator's own Service Account (usually cluster-admin), allowing any authenticated user to escalate privileges and take over the cluster.

A critical logic flaw in the Flux Operator Web UI's OIDC handling allows authenticated users to bypass Kubernetes impersonation mechanisms. By manipulating OIDC claims to resolve to empty values, attackers can force the Operator to execute API requests using its own high-privileged Service Account rather than the user's restricted credentials, effectively granting full cluster administrative access.

The Setup: A Wolf in Sheep's Clothing

Kubernetes operators are the unsung heroes of modern infrastructure, automating the tedious tasks that would otherwise drive SysAdmins to drink. The Flux Operator is particularly nifty: it provides a slick Web UI to manage Flux CD, giving developers a window into their GitOps pipelines. To do this securely, it employs a technique called User Impersonation.

Here is how it should work: You log in via OIDC (say, Google or GitHub). The Operator takes your token, verifies who you are, and then says to the Kubernetes API, "Hey, I'm the Operator, but please execute this next command as Bob from Accounting." This is handled via Impersonate-User headers. The Kubernetes API checks if Bob has permission to delete the production database (he shouldn't), and allows or denies the request accordingly. The Operator is just the messenger.

But in security, the messenger is often the most dangerous link in the chain. This vulnerability, CVE-2026-23990, exists in the handshake between the Operator's authentication logic and the Kubernetes client library. It turns out, if you whisper your name quietly enough (or don't say it at all), the Operator forgets to tell Kubernetes who you are. And when the Operator forgets to impersonate you, it accidentally acts as itself—a Service Account with god-mode privileges.

The Flaw: The Sound of Silence

The root cause here is a classic "fail-open" scenario born from a misunderstanding of the underlying client-go library. The Flux Operator allows administrators to define CEL (Common Expression Language) expressions to map OIDC claims (like email or groups) to Kubernetes identities. For example, claim.email becomes the Kubernetes username.

But what happens if that expression resolves to an empty string? Perhaps the OIDC provider didn't send an email claim, or the CEL expression was malformed. The code handled this by creating an internal Impersonation object where Username was "" and Groups were [].

Here is the fatal flaw: The developer assumed that an empty impersonation config would result in an error or a harmless no-op. Instead, they handed this empty configuration to the Kubernetes client-go transport wrapper.

When client-go sees an impersonation config, it checks: "Is there a username?" If yes, it adds the Impersonate-User header. If no, it simply doesn't add the header. It doesn't throw an error; it just sends a standard request. Since the Operator runs inside the cluster, it uses its own Service Account token for authentication. Without the impersonation header acting as a filter, the Kubernetes API treats the request as coming directly from the Flux Operator Service Account.

It is the digital equivalent of a bouncer checking your ID. If you show a fake ID, he kicks you out. But if you show him nothing, he apparently assumes you own the club and lets you into the VIP room.

The Code: Autopsy of a Null Pointer Logic

Let's look at the "smoking gun" in the code. Prior to version 0.40.0, the authentication flow extracted claims and happily passed them along without ensuring they actually contained data. The logic resided in how the Impersonation struct was populated and subsequently used.

The vulnerability existed because there was no gatekeeper ensuring len(Username) > 0. The fix, introduced in commit 0845404, adds a specific SanitizeAndValidate method that is called immediately after claim extraction.

Here is the breakdown of the fix:

// internal/web/user/user.go
 
func (imp *Impersonation) SanitizeAndValidate() error {
    // Trim spaces to prevent " " from bypassing empty checks
    imp.Username = strings.TrimSpace(imp.Username)
    for i, g := range imp.Groups {
        imp.Groups[i] = strings.TrimSpace(g)
    }
 
    // THE FIX: Explicitly forbid the "invisible man" scenario
    if imp.Username == "" && len(imp.Groups) == 0 {
        return fmt.Errorf("at least one of 'username' or 'groups' must be set for user impersonation")
    }
 
    // ... additional validation ...
    return nil
}

Before this patch, the code would simply proceed. If Username was empty, the transport layer in client-go would construct the HTTP request without the Impersonate-User header. The request would look like this on the wire:

Vulnerable Request (Effective Admin):

GET /api/v1/pods HTTP/1.1
Authorization: Bearer <OPERATOR_SERVICE_ACCOUNT_TOKEN>
Accept: application/json

Intended Request (Restricted):

GET /api/v1/pods HTTP/1.1
Authorization: Bearer <OPERATOR_SERVICE_ACCOUNT_TOKEN>
Impersonate-User: bob@example.com
Accept: application/json

By ensuring the Impersonation struct is never empty, the patch forces the second path, or errors out before the network call is ever made.

The Exploit: Becoming the System

To exploit this, we don't need buffer overflows or heap spraying. We just need to be a "nobody." The goal is to authenticate against the Flux Operator Web UI but ensure our resulting identity claims are empty.

Attack Scenario

  1. Reconnaissance: The attacker identifies a Flux Operator Web UI exposed to the network. They have a valid login (perhaps they are a low-level developer or a contractor).
  2. Configuration Analysis: The attacker creates an OIDC token state where the mapped claims are missing. For example, if the Operator is configured to map preferred_username to the K8s user, the attacker might modify their OIDC profile (if they have control over the IdP) or use an IdP that omits this claim for their specific user scope.
  3. The Login: The attacker logs into the Flux UI. The OIDC flow completes successfully (authentication works). The ClaimsProcessor runs the CEL expression.
    • Expression: claim.preferred_username
    • Input: {"sub": "123", "email": "attacker@evil.com"} (Note: missing preferred_username)
    • Result: "" (Empty String)
  4. The Action: The attacker navigates to the "Cluster Resources" page. The UI requests a list of Secrets.
  5. The Bypass: The backend constructs the Kubernetes client with an empty Impersonation config. The request goes out signed by the Operator's Service Account.
  6. Success: The Kubernetes API sees a request from system:serviceaccount:flux-system:flux-operator. Since this account needs to manage the entire Flux lifecycle, it has permissions to read Secrets, create Deployments, or delete Namespaces. The attacker receives the JSON response containing the cluster's secrets.

This is a clean, logic-based privilege escalation. No crashing services, no noisy binaries—just one "empty" string turning a guest into a god.

The Impact: Why This Matters

The severity of this vulnerability is deceptive. The CVSS score sits at a "Medium" 5.3, mostly because it requires a specific configuration (OIDC claims resulting in empty values) and authenticated access. However, in the environments where it is exploitable, the impact is catastrophic.

The Flux Operator is not a lowly web app; it is a control plane component. By design, its Service Account requires extensive permissions—often cluster-admin or near-equivalent roles—to reconcile arbitrary Kubernetes manifests defined in Git.

If an attacker exploits this:

  • Data Exfiltration: They can read every Secret and ConfigMap in the cluster, compromising database credentials, API keys, and cloud provider tokens.
  • Cluster Takeover: They can deploy malicious workloads (crypto miners, backdoors) by creating new Deployments acting as the Operator.
  • Destruction: They can delete critical namespaces, effectively wiping the cluster.

Because the vulnerability exploits the lack of an identity, audit logs will likely show the actions as being performed by the flux-operator service account, making attribution difficult. The security team will see the "system" doing system things, while the attacker sits quietly behind the web interface.

Remediation: Patching the Void

The path to safety is straightforward, but urgency is key. If you are running flux-operator versions 0.36.0 through 0.39.0, you are vulnerable.

Immediate Steps

  1. Upgrade: Update the Flux Operator to v0.40.0 or later immediately. The patch logic is robust and explicitly prevents empty impersonation contexts.
  2. Audit CEL Expressions: Review your FluxOperator resource configuration. Look at the authentication.oidc.claims section. Ensure that your CEL expressions have fallbacks.
    • Bad: claim.preferred_username
    • Better: has(claim.preferred_username) ? claim.preferred_username : claim.email
    • Even Better: Ensure your IdP enforces the presence of these claims.

Detection

Since this exploit abuses legitimate Service Account tokens, network-level detection is hard. Focus on Kubernetes Audit Logs. Look for an anomaly in the behavior of the flux-operator Service Account. If the Service Account is making API calls that correlate exactly with user HTTP sessions on the Flux UI, but are not impersonated requests, that is a red flag.

Normally, the Operator's automated reconciliation loop is periodic and predictable. User-driven actions (via this exploit) will be sporadic and might access resources the reconciliation loop typically ignores (like reading specific Secrets outside of managed namespaces).

Official Patches

ControlPlaneOfficial Release v0.40.0 containing the fix

Fix Analysis (1)

Technical Appendix

CVSS Score
5.3/ 10
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:N/A:N
EPSS Probability
0.03%
Top 90% most exploited

Affected Systems

Flux Operator Web UI

Affected Versions Detail

Product
Affected Versions
Fixed Version
flux-operator
controlplaneio-fluxcd
>= 0.36.0, < 0.40.00.40.0
AttributeDetail
CWECWE-269 (Improper Privilege Management)
CVSS v3.15.3 (Medium)
Attack VectorNetwork (Authenticated)
Attack ComplexityHigh (Requires specific OIDC/CEL state)
Exploit MaturityPoC Available
ImpactFull Cluster Privilege Escalation

MITRE ATT&CK Mapping

T1068Exploitation for Privilege Escalation
Privilege Escalation
T1078Valid Accounts
Initial Access
CWE-269
Improper Privilege Management

The application does not properly assign, modify, track, or check privileges for an actor, creating an unintended sphere of control for that actor.

Known Exploits & Detection

Internal ResearchThe advisory details the lack of validation in claims processing.

Vulnerability Timeline

Fix commit merged to main branch
2026-01-20
CVE-2026-23990 Published
2026-01-21
SentinelOne analysis released
2026-01-23

References & Sources

  • [1]GHSA Advisory
  • [2]CISA Bulletin SB26-026

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 1 hour ago•CVE-2026-14669
8.8

CVE-2026-14669: PostgreSQL to_char() Timezone Abbreviation Heap-Based Buffer Overflow

CVE-2026-14669 is a critical heap-based buffer overflow vulnerability in PostgreSQL's date/time formatting function to_char(timestamptz). The flaw arises from unsafe copying of user-controlled timezone abbreviations into a fixed-size internal buffer. An authenticated database user can trigger this issue by setting a long POSIX timezone abbreviation containing custom formatting, allowing them to overwrite adjacent heap structures and hijack execution control to achieve remote code execution (RCE) with the privileges of the 'postgres' operating system user.

Alon Barad
Alon Barad
1 views•6 min read
•2 days ago•CVE-2026-63462
7.5

CVE-2026-63462: Unauthenticated Stack Overflow Denial of Service in Unleash Server

An unauthenticated remote denial of service vulnerability exists in the Unleash feature management platform. By submitting a crafted JSON payload containing deeply nested structures to an OpenAPI-validated endpoint, an attacker can trigger uncontrolled recursion within the error formatting module. This leads to a call-stack exhaustion (RangeError: Maximum call stack size exceeded) inside the Node.js runtime, causing the service to crash immediately without recovery.

Alon Barad
Alon Barad
11 views•6 min read
•2 days ago•CVE-2026-63004
5.5

CVE-2026-63004: Server-Side Request Forgery in Unleash Addon and Integration Subsystem

CVE-2026-63004 is a server-side request forgery (SSRF) vulnerability in the Unleash feature management platform. Authenticated administrators with CREATE_ADDON or UPDATE_ADDON privileges can exploit this vulnerability to initiate requests to loopback addresses, private networks, and cloud metadata endpoints, potentially leading to information disclosure and credential extraction.

Amit Schendel
Amit Schendel
8 views•8 min read
•2 days ago•CVE-2026-63466
4.1

CVE-2026-63466: Process-Wide Security Degradation via Global Module Mutation in Unleash

Prior to version 8.0.3, Unleash's Markdown event formatter directly mutated the global template-escaping function of the shared mustache Node.js module, resulting in a process-wide security degradation where HTML/Markdown escaping was permanently disabled for the application lifetime.

Alon Barad
Alon Barad
3 views•6 min read
•2 days ago•CVE-2026-76904
9.8

CVE-2026-76904: Unauthenticated SQL Injection in GeoTools PostGIS DataStore Component

A critical SQL injection vulnerability exists in the GeoTools open-source Java library. This vulnerability is situated within the post-processing phase of OGC Filter conversion inside the PostGIS DataStore module. Specifically, the `jsonArrayContains` function does not validate or sanitize its arguments before constructing PostgreSQL SQL/JSON path evaluation queries. An unauthenticated remote attacker can exploit this weakness by submitting crafted filters via standard OGC services like WFS or WMS to execute arbitrary SQL commands on the underlying database system.

Alon Barad
Alon Barad
13 views•5 min read
•2 days ago•CVE-2026-61824
8.2

CVE-2026-61824: High-Severity Cross-Site Scripting (XSS) via Unsanitized Site Extractors in Defuddle

CVE-2026-61824 is a high-severity Cross-Site Scripting (XSS) vulnerability in kepano/defuddle before version 0.19.1. Custom site extractors for platforms such as X/Twitter, Substack, and YouTube constructed HTML representations via template string interpolation without output escaping. This allowed malicious pages to bypass standard parser sanitization routines and execute arbitrary JavaScript.

Amit Schendel
Amit Schendel
6 views•7 min read