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-88986

CVE-2026-88986: Reflected Cross-Site Scripting in Kubeflow Pipelines Frontend Error Responses

Alon Barad
Alon Barad
Software Engineer

Nov 10, 2026·10 min read·4 visits

Executive Summary (TL;DR)

Kubeflow Pipelines versions prior to 2.15.0 are vulnerable to reflected XSS (CVE-2026-88986) in the '/pipeline/k8s/pod' and '/pipeline/k8s/pod/events' endpoints due to unescaped query parameters in error responses. Upgrading to version 2.15.0 resolves this issue by enforcing strict DNS-1123 naming validation and suppressing raw backend errors.

A reflected Cross-Site Scripting (XSS) vulnerability exists in the Kubeflow Pipelines frontend server prior to version 2.15.0. Specifically, the Express route handlers for '/pipeline/k8s/pod' and '/pipeline/k8s/pod/events' reflect unvalidated 'podname' and 'podnamespace' query parameters, along with backend Kubernetes API error messages, directly into HTML-capable HTTP error responses. An unauthenticated attacker can exploit this flaw by convincing an authenticated user to visit a crafted URL, resulting in arbitrary JavaScript execution within the context of the Kubeflow Pipelines frontend origin.

Vulnerability Overview

Kubeflow Pipelines is a platform for building and deploying portable, scalable machine learning (ML) workflows based on Docker containers within Kubernetes environments. The platform includes a web-based user interface (kfp-frontend) built on Node.js and Express, which acts as an intermediary between the user's browser and the underlying Kubernetes API and pipeline backend services. This frontend server exposes several internal proxy and helper endpoints that allow users to inspect the execution state, logs, and Kubernetes events of individual pods corresponding to pipeline steps.

In Kubeflow Pipelines versions prior to 2.15.0, the frontend server endpoints /pipeline/k8s/pod and /pipeline/k8s/pod/events contain a reflected Cross-Site Scripting (XSS) vulnerability, tracked as CVE-2026-88986 (GHSA-g3qx-frcg-j979) and classified under CWE-79 (Improper Neutralization of Input During Web Page Generation). When processing client requests to retrieve pod details or associated cluster events, the backend helper routines in frontend/server/k8s-helper.ts take user-supplied query parameters—specifically podname and podnamespace—and pass them to the Kubernetes client API.

When the Kubernetes API call fails (for example, when querying a non-existent pod or an invalid namespace format), the error handling logic constructs a diagnostic message containing the raw, unvalidated podname and podnamespace values alongside the backend error string. The Express application then returns this string directly in the HTTP 500 response body via res.status(500).send(err.message).

Because Express defaults to a Content-Type of text/html when sending string responses without an explicit MIME type override, the victim's web browser interprets the error response as an HTML document. Consequently, any HTML markup or JavaScript payloads injected into the query parameters are parsed and executed within the security context of the Kubeflow frontend origin.

Root Cause Analysis

The root cause of CVE-2026-88986 is the combination of missing input validation on Kubernetes resource identifiers, unsafe string interpolation in error catch blocks, and reliance on Express's default text/html content-type assignment in res.send().

When an HTTP GET request reaches /pipeline/k8s/pod or /pipeline/k8s/pod/events, the Express route handlers extract podname and podnamespace from req.query. Prior to version 2.15.0, the server did not verify whether these strings conformed to Kubernetes resource naming conventions (such as RFC 1123 DNS label standards, which restrict names to lowercase alphanumeric characters and hyphens). Instead, arbitrary strings containing HTML control characters (<, >, ", ') were passed directly to getPod(podName, podNamespace) or listPodEvents(podName, podNamespace) inside frontend/server/k8s-helper.ts.

Inside frontend/server/k8s-helper.ts, the functions invoke k8sV1Client.readNamespacedPod(podName, podNamespace) or k8sV1Client.listNamespacedEvent(...). When passed a malformed namespace or a non-existent pod name containing an XSS payload, the Kubernetes API server rejects the request and throws an exception. The catch (error) block intercepts this exception, calls parseError(error) to extract the downstream message, and formats a composite string:

const userMessage = \Could not get pod ${podName} in namespace ${podNamespace}: ${message}`;`

This userMessage is returned to the caller in frontend/server/app.ts (or modular route handlers), which executes res.status(500).send(err.message). In the Express framework, passing a String argument to res.send() automatically sets the HTTP response Content-Type header to text/html; charset=utf-8 unless another type was previously set via res.type() or res.set(). Because no output encoding (such as HTML entity encoding) is applied to podName, podNamespace, or message, the browser renders the reflected string as active HTML.

Code Analysis

The vulnerability was remediated in commit fedc25e3f7251933d4a37b964bc3e8176beea28e (Pull Request #12295). The patch addresses the flaw across multiple layers: introducing strict allowlist validation for Kubernetes resource identifiers, removing reflected backend error details, and hardening adjacent handlers for artifacts and TensorBoard integration.

1. Resource Name Validation (frontend/server/utils.ts)

The patch introduces a new validation helper function, isAllowedResourceName, which enforces that resource strings strictly match the Kubernetes DNS-1123 label specification (between 1 and 63 characters, consisting solely of lowercase alphanumeric characters or internal hyphens):

// Added in frontend/server/utils.ts
export function isAllowedResourceName(name: string): boolean {
  return name.length > 0 && name.length <= 63 && /^[a-z0-9]([-a-z0-9]*[a-z0-9])?$/.test(name);
}

Because this regular expression forbids <, >, ", ', /, and all uppercase or special characters, any string passing this check cannot break out of text contexts or introduce HTML tags.

2. Securing Error Generation (frontend/server/k8s-helper.ts)

In frontend/server/k8s-helper.ts, the error handling blocks within getPod, getConfigMap, and listPodEvents were modified to validate inputs before reflecting them and to strip raw Kubernetes error details (message and additionalInfo) from client-facing responses:

// Before Patch (Vulnerable)
export async function getPod(
  podName: string,
  podNamespace: string,
): Promise<[V1Pod | undefined, K8sError | undefined]> {
  try {
    const { body } = await k8sV1Client.readNamespacedPod(podName, podNamespace);
    return [body, undefined];
  } catch (error) {
    const { message, additionalInfo } = await parseError(error);
    // FLAW: Unvalidated podName, podNamespace, and message interpolated directly
    const userMessage = `Could not get pod ${podName} in namespace ${podNamespace}: ${message}`;
    return [undefined, { message: userMessage, additionalInfo }];
  }
}
 
// After Patch (Remediated)
export async function getPod(
  podName: string,
  podNamespace: string,
): Promise<[V1Pod | undefined, K8sError | undefined]> {
  try {
    const { body } = await k8sV1Client.readNamespacedPod(podName, podNamespace);
    return [body, undefined];
  } catch (error) {
    let userMessage = `Could not get pod ${podName} in namespace ${podNamespace}`;
    // FIX: Validate both parameters against strict DNS-1123 regex
    if (!isAllowedResourceName(podName) || !isAllowedResourceName(podNamespace)) {
      userMessage = `Invalid resource name`;
    }
    // FIX: Downstream error message and additionalInfo are omitted
    return [undefined, { message: userMessage }];
  }
}

Identical validation logic was applied to listPodEvents(podName, podNamespace) and getConfigMap(configMapName, configMapNamespace) within the same file.

3. Hardening Additional Frontend and Backend Handlers

The commit also audited other request handlers for similar input reflection and verbose error exposure patterns:

// frontend/server/handlers/artifacts.ts
if (!isAllowedResourceName(bucket)) {
  res.status(500).send('Invalid bucket name');
  return;
}
 
// frontend/server/handlers/tensorboard.ts
if (typeof namespace !== 'string' || !isAllowedResourceName(namespace as string)) {
  res.status(400).send('invalid namespace');
  return;
}

Additionally, in the Go backend (backend/src/apiserver/server/pipeline_upload_server.go), detailed internal error strings returned during pipeline creation and upload failures were replaced with static messages (errors.New("Failed to create a pipeline") and errors.New("Failed to create a pipeline version")), while preserving full diagnostic logging server-side via glog.Errorf.

Fix Completeness Assessment

The introduction of isAllowedResourceName effectively blocks HTML/JavaScript injection via podname, podnamespace, configMapName, bucket, and namespace parameters by restricting the character set to [a-z0-9-]. Furthermore, removing ${message} from the error string eliminates the risk of secondary XSS or sensitive information disclosure originating from upstream Kubernetes API server error responses. However, the application still uses res.status(500).send(...) without explicitly setting Content-Type: text/plain or application/json. While the strict character allowlist prevents XSS in the patched routes, setting an explicit text/plain content type alongside X-Content-Type-Options: nosniff would provide stronger defense-in-depth against future regressions.

Exploitation

Exploiting CVE-2026-88986 requires no authentication on the part of the attacker to construct the payload, though user interaction (UI:R) is required. Specifically, a user who satisfies the Kubeflow deployment's authentication and route-access requirements must navigate to an attacker-supplied link.

Attack Prerequisites

  1. Network Access & Authentication: The target victim must have active network access to the Kubeflow Pipelines frontend and possess an active authenticated session (if the deployment enforces authentication via an identity-aware proxy such as Istio/OAuth2 Proxy or Dex).
  2. Navigation Interaction: Because the vulnerability is triggered via an HTTP GET request to a top-level URL (/pipeline/k8s/pod or /pipeline/k8s/pod/events), standard browser SameSite=Lax cookie policies do not block session cookies when a user clicks a link from an external site, email, or chat client.

Proof-of-Concept Analysis

In the regression unit tests introduced in frontend/server/app.test.ts within commit fedc25e3f7251933d4a37b964bc3e8176beea28e, the following paths demonstrate the attack vector:

GET /pipeline/k8s/pod?podname=test-pod-name&podnamespace=test-namespace%7d%7dt93g1%3Cscript%3Ealert(1)%3C%2fscript%3Ej66h HTTP/1.1
Host: kubeflow.example.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

As well as the events endpoint variant:

GET /pipeline/k8s/pod/events?podname=test-pod-name&podnamespace=test-namespace%7d%7dt93g1%3Cscript%3Ealert(1)%3C%2fscript%3Ej66h HTTP/1.1
Host: kubeflow.example.com

Exploitation Flow

  1. The victim clicks the URL containing the URL-encoded <script>alert(1)</script> payload inside the podnamespace (or podname) parameter.
  2. The Express server decodes the query parameter into test-namespace}}t93g1<script>alert(1)</script>j66h and queries the Kubernetes API.
  3. The Kubernetes API returns an error because the namespace does not exist and violates Kubernetes naming rules.
  4. In versions prior to 2.15.0, the server responds with HTTP 500 and an HTML body:
Could not get pod test-pod-name in namespace test-namespace}}t93g1<script>alert(1)</script>j66h: ...
  1. The victim's browser parses the <script> tag and executes the JavaScript payload under the Kubeflow frontend's origin. In patched versions (>= 2.15.0), the server detects that podnamespace fails isAllowedResourceName() and returns the static text Invalid resource name.

Impact Assessment

CVE-2026-88986 is rated as Medium severity with a CVSS v3.1 base score of 6.1 (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N).

Security Impact Breakdown

  • Arbitrary Frontend Action Execution (Integrity Impact: Low): Because the injected JavaScript executes within the origin of the Kubeflow Pipelines web interface, the script can issue authenticated XMLHttpRequest (XHR) or Fetch requests to any Kubeflow Pipelines API endpoint accessible to the victim. In a machine learning platform context, an attacker can programmatically trigger pipeline runs, modify experiment configurations, upload malicious pipeline definitions (which subsequently execute container workloads on the Kubernetes cluster), or read sensitive pipeline artifacts.
  • Data and Session Exposure (Confidentiality Impact: Low): The payload can read any sensitive data accessible via the DOM, localStorage, or sessionStorage, as well as query backend APIs for pipeline parameters, environment variables, or artifact contents. Whether session cookies can be directly exfiltrated via document.cookie depends on whether the deployment's authentication layer sets the HttpOnly attribute on session cookies.
  • Scope Change (S:C): While the vulnerability resides in the server-side Node.js response generation logic, the impact manifests within the client's web browser, crossing a security boundary from the web server to the client execution environment.
  • Server-Side Isolation (A:N): As noted in the official advisory, the flaw does not directly provide server-side code execution on the kfp-frontend Node.js container or disrupt service availability.

Threat Intelligence Context

As of November 2026, the FIRST Exploit Prediction Scoring System (EPSS) assigns CVE-2026-88986 a score of 0.00276 (0.28% probability of exploitation within 30 days, placing it in the 20.17th percentile). It is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog, and no weaponized exploitation in the wild has been reported.

Remediation and Mitigation

Organizations running Kubeflow Pipelines should apply the official patch or implement compensating controls at the ingress layer.

1. Upgrade to Patched Release

Upgrade Kubeflow Pipelines to version 2.15.0 or later. Version 2.15.0 incorporates commit fedc25e3f7251933d4a37b964bc3e8176beea28e, which enforces strict input validation on podname, podnamespace, configMapName, bucket, and namespace parameters and removes verbose error reflection.

> [!NOTE] > Ensure that both the kfp-frontend container image and the kfp-apiserver image are updated to version 2.15.0 to benefit from both the frontend XSS protections and backend verbose error suppression.

2. Web Application Firewall (WAF) & Ingress Filtering

If an immediate upgrade is not feasible, administrators can block exploitation attempts at the Kubernetes Ingress controller, Envoy/Istio gateway, or external WAF by enforcing parameter validation on /pipeline/k8s/pod and /pipeline/k8s/pod/events:

  • Allowlist Enforcement: Restrict the podname and podnamespace query parameters to match the regular expression ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ with a maximum length of 63 characters.
  • XSS Meta-Character Filtering: Block HTTP requests to /pipeline/k8s/* containing raw or URL-encoded HTML special characters (<, >, ", ', %3C, %3E, %22, %27).

3. Response Header Hardening

Configure the reverse proxy or ingress gateway fronting kfp-frontend to inject defensive HTTP response headers:

  • Content-Security-Policy (CSP): Enforce a strict CSP header such as Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; to prevent the execution of inline <script> tags and event handlers injected via reflected parameters.
  • X-Content-Type-Options: Set X-Content-Type-Options: nosniff to prevent browsers from MIME-sniffing responses away from declared content types.
  • Cookie Security: Ensure that any authentication proxy (e.g., OAuth2 Proxy, Istio EnvoyFilter) sets the HttpOnly, Secure, and SameSite=Strict (or Lax) attributes on all session cookies.

Official Patches

KubeflowGitHub Security Advisory GHSA-g3qx-frcg-j979 for CVE-2026-88986
KubeflowRemediation commit in kubeflow/pipelines
KubeflowPull Request #12295 implementing input validation and error suppression
KubeflowKubeflow Pipelines 2.15.0 Release Notes

Fix Analysis (1)

Technical Appendix

CVSS Score
6.1/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
EPSS Probability
0.28%
Top 80% most exploited

Affected Systems

Kubeflow Pipelines (kubeflow/pipelines)

Affected Versions Detail

Product
Affected Versions
Fixed Version
Kubeflow Pipelines
Kubeflow
< 2.15.02.15.0
AttributeDetail
Vulnerability TypeCWE-79: Cross-Site Scripting (Reflected)
Affected Componentfrontend/server/k8s-helper.ts (/pipeline/k8s/pod & /pipeline/k8s/pod/events)
Attack VectorNetwork (Crafted URL via HTTP GET parameters podname and podnamespace)
CVSS v3.1 Score6.1 Medium (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N)
EPSS Score0.28% (20.17th Percentile)
ImpactArbitrary JavaScript execution in the victim's browser under the frontend origin
Exploit StatusPoC in unit tests (No known active exploitation)
Patched VersionKubeflow Pipelines 2.15.0

MITRE ATT&CK Mapping

T1189Drive-by Compromise
Initial Access
T1185Browser Session Hijacking
Collection
CWE-79
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.

Vulnerability Timeline

Fix implemented and merged into kubeflow/pipelines via PR #12295 (commit fedc25e3f7251933d4a37b964bc3e8176beea28e).
2025-10-10
Official security advisory GHSA-g3qx-frcg-j979 published and CVE-2026-88986 issued by GitHub CNA.
2026-11-05
CVE-2026-88986 published to NVD and CVE.org databases.
2026-11-05
NVD analysis updated with CVSS v3.1 score of 6.1 and CWE-79 assignment.
2026-11-06
EPSS score recorded at 0.00276 (20.17th percentile).
2026-11-09

References & Sources

  • [1]GitHub Security Advisory: GHSA-g3qx-frcg-j979
  • [2]GitHub Pull Request #12295: Fix XSS and error reflection in Kubeflow Pipelines
  • [3]GitHub Commit fedc25e3f7251933d4a37b964bc3e8176beea28e
  • [4]Kubeflow Pipelines Release 2.15.0
  • [5]National Vulnerability Database (NVD): CVE-2026-88986
  • [6]CVE.org Record: CVE-2026-88986
  • [7]CVEListV5 JSON Record: CVE-2026-88986

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

•10 minutes ago•CVE-2026-88983
5.0

CVE-2026-88983: Authenticated Server-Side Request Forgery in Kubeflow Pipelines API Server

CVE-2026-88983 is an authenticated Server-Side Request Forgery (SSRF) vulnerability affecting the Kubeflow Pipelines API server in versions prior to 2.17.0. When an authenticated user creates a pipeline or pipeline version using a remote specification URI, the backend server retrieves the document via Go's default HTTP client without validating the target scheme, hostname, port, or IP address. Because the API server reflects remote connection errors and HTTP status codes in its response, an attacker with pipeline creation permissions can exploit the server as a status-code and port-scanning oracle against Kubernetes cluster-internal services, private networks, and cloud metadata endpoints.

Amit Schendel
Amit Schendel
1 views•11 min read
•about 1 hour ago•CVE-2026-88985
6.5

CVE-2026-88985: SQL Injection via Pagination Token Deserialization and Metric Sorting in Kubeflow Pipelines API Server

CVE-2026-88985 is a SQL injection vulnerability (CWE-89) in the Kubeflow Pipelines (KFP) API server prior to version 2.17.0. The flaw stems from the untrusted deserialization of base64-encoded JSON pagination tokens (page_token) and the direct concatenation of metric names during run list sorting. Authenticated users with permissions to invoke REST or gRPC list endpoints can inject arbitrary SQL syntax into structural query identifiers and JOIN predicates, enabling unauthorized cross-tenant read access to all database records accessible by the API server.

Alon Barad
Alon Barad
2 views•10 min read
•about 3 hours ago•CVE-2026-88984
7.2

CVE-2026-88984: RBAC Authorization Bypass in Kubeflow Pipelines Multi-User API Server

CVE-2026-88984 (GHSA-ghgh-57qv-h687) is an incorrect authorization vulnerability affecting Kubeflow Pipelines (KFP) prior to version 2.16.1 in multi-user deployments. The multi-user API server treats the empty Kubernetes namespace associated with shared or global pipelines as an unconditional authorization exception across all API verbs. Consequently, any authenticated user can modify, overwrite, or delete shared pipeline definitions and pipeline versions without possessing the required Kubernetes RBAC permissions, compromising the integrity and availability of global machine learning workflows.

Amit Schendel
Amit Schendel
5 views•10 min read
•about 4 hours ago•CVE-2026-102340
8.5

CVE-2026-102340: Missing Authentication and Authorization in Telepresence Traffic Manager gRPC API

Prior to version 2.31.0, the Telepresence Traffic Manager exposed an unauthenticated gRPC API on cluster-internal port 8081 that lacked caller identity verification and Kubernetes RBAC authorization checks. An attacker operating any pod with network access to the Traffic Manager can register a session in an arbitrary managed namespace, establish service intercepts, redirect live production traffic, and exfiltrate the complete container environment of victim workloads, including mounted secrets and service account tokens.

Amit Schendel
Amit Schendel
5 views•10 min read
•about 5 hours ago•CVE-2026-63198
7.3

CVE-2026-63198: OAuth 2.0 Silent Authorization Scope Escalation in traQ

CVE-2026-63198 (GHSA-8cfq-jgf7-8m27) is an incorrect authorization vulnerability (CWE-863) in traQ, an open-source messaging platform developed in Go by Digital Creators Club traP. The flaw resides in the OAuth 2.0 authorization endpoint handler (`router/oauth2/authorization_endpoint.go`). When processing silent authorization requests (`prompt=none`) with an omitted or empty `scope` parameter, the application evaluates prior user consent against the empty requested scope set prior to applying default scope fallback logic. Because an empty set vacuously satisfies the subset check against any existing token, consent verification succeeds if the user has ever authorized the client for any single scope. Subsequently, the token issuance logic defaults the empty scope parameter to all scopes registered to the client (`req.ValidScopes`), allowing a client application with partial consent to silently escalate privileges without user interaction.

Alon Barad
Alon Barad
4 views•9 min read
•about 6 hours ago•CVE-2026-63475
4.3

CVE-2026-63475: Persistent Denial of Service via Circular Symbolic References in isomorphic-git

CVE-2026-63475 (GHSA-96wc-2m84-2cj7) is an uncontrolled recursion and infinite loop vulnerability in isomorphic-git prior to version 1.38.6. When processing Git protocol responses from a malicious or man-in-the-middle (MitM) server, isomorphic-git writes server-advertised symbolic reference (symref) capabilities directly to the local repository filesystem without validating for circular dependencies. Because the reference resolution logic in GitRefManager.resolve() lacks both cycle detection and a default recursion depth limit, any subsequent operation that resolves the circular references enters a non-terminating asynchronous recursion loop. Because the malicious references are persisted on disk, this condition induces a persistent denial of service (DoS) against the affected repository.

Amit Schendel
Amit Schendel
5 views•12 min read