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

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

Amit Schendel
Amit Schendel
Senior Security Researcher

Nov 10, 2026·11 min read·1 visit

Executive Summary (TL;DR)

An authenticated Server-Side Request Forgery (SSRF) vulnerability in Kubeflow Pipelines prior to 2.17.0 allows attackers with pipeline creation privileges to probe internal cluster services, RFC 1918 networks, and cloud metadata endpoints via unvalidated pipeline specification URLs.

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.

Vulnerability Overview

Kubeflow Pipelines (kubeflow/pipelines) is a platform for building and deploying portable, scalable machine learning workflows on Kubernetes. A core component of this platform is the backend API server (ml-pipeline), which exposes HTTP REST and gRPC endpoints to manage pipeline definitions, versions, experiments, and runs. Users can register new pipelines either by uploading a packaged specification file directly or by instructing the API server to fetch the specification from an external URI via the pipelineURL or PipelineSpecURI parameters.

In Kubeflow Pipelines versions prior to 2.17.0, the API server's URL retrieval mechanism contains a Server-Side Request Forgery (CWE-918) and Confused Deputy (CWE-441) vulnerability, tracked as CVE-2026-88983 (and internally under audit identifier ADA-KUBEFL-01). When processing a pipeline registration request containing a remote URL, the API server directly passes the user-supplied string to Go's standard http.DefaultClient without performing destination validation, hostname allowlisting, or network boundary checks.

Because the ml-pipeline API server pod executes within the Kubernetes cluster network namespace, it possesses ambient network access to cluster-internal DNS, Kubernetes service IP ranges, pod subnets, loopback interfaces, and link-local cloud provider instance metadata services. An authenticated attacker with basic RBAC permissions to create a pipeline or pipeline version can supply arbitrary internal destinations as the pipelineURL, coercing the API server into initiating outbound TCP connections and HTTP GET requests on their behalf.

Furthermore, the API server's error handling logic distinguishes between TCP-level connection failures and non-200 HTTP responses, returning distinct error messages and status codes to the caller. While the response body of a non-pipeline endpoint is not directly returned to the attacker, this differential error reporting establishes a reliable HTTP status-code and port-scanning oracle across the internal Kubernetes topology.

Root Cause Analysis

The root cause of CVE-2026-88983 lies in the initialization and unguarded invocation of the HTTP client within backend/src/apiserver/server/pipeline_server.go. Both the v1 (PipelineServerV1) and v2 (PipelineServer) server implementations initialized their internal httpClient struct field using http.DefaultClient. The vulnerable code paths reside within the createPipelineAndPipelineVersion and createPipelineVersion methods, which handle pipeline ingestion over both REST and gRPC interfaces.

When a caller provides a remote URI for a pipeline specification, the server extracts the URL string and executes s.httpClient.Get(pipelineURL.String()). Prior to the patch in version 2.17.0, the application performed zero validation on the parsed URL components. Specifically, there were no checks to restrict the URL scheme (allowing plain http://), no restrictions on destination ports (allowing requests to arbitrary internal ports such as :6379, :8080, or :22), and no filtering of the target hostname or resolved IP addresses against private or reserved CIDR blocks.

In addition to missing pre-request validation, reliance on http.DefaultClient introduced secondary transport-layer weaknesses. By default, Go's http.Client automatically follows up to 10 HTTP redirects (301, 302, 307, 308) without re-evaluating the target destination. Even if superficial string checks had existed at the API boundary, an attacker could bypass them using an external server that responds with a redirect to an internal IP address.

Finally, standard HTTP client resolution is susceptible to DNS rebinding (Time-of-Check to Time-of-Use, or TOCTOU). If an application validates a hostname by resolving its IP prior to calling http.Client.Get(), the underlying network dialer performs a second DNS lookup when establishing the TCP socket. An attacker controlling an authoritative DNS server can return a public IP during the validation check with a Time-To-Live (TTL) of zero, and subsequently return a loopback (127.0.0.1) or metadata (169.254.169.254) IP address when the dialer connects.

Code Analysis

In versions prior to 2.17.0, backend/src/apiserver/server/pipeline_server.go retrieved remote pipeline specifications directly using the server's default HTTP client and reflected the resulting transport or HTTP errors back to the client:

// Vulnerable code in backend/src/apiserver/server/pipeline_server.go (prior to v2.17.0)
resp, err := s.httpClient.Get(pipelineURL.String())
if err != nil {
    // Reflects low-level dial/network errors as HTTP 500
    return nil, nil, util.NewInternalServerError(err, "error downloading the pipeline spec from %v", pipelineURL.String())
} else if resp.StatusCode != http.StatusOK {
    // Reflects exact remote HTTP status string (e.g., "403 Forbidden") as HTTP 400
    return nil, nil, util.NewInvalidInputError("error fetching pipeline spec from %v - request returned %v", pipelineURL.String(), resp.Status)
}

To remediate this vulnerability in Pull Request #12750 (commit 504d7797c1e061327ddb2bcb8bc1c5dd4940cfc3), the maintainers introduced a dedicated validation and transport package at backend/src/apiserver/validation/pipeline_url.go. First, the patch establishes an explicit IP/CIDR blocklist covering loopback interfaces, RFC 1918 private networks, IPv6 Unique Local Addresses (ULA), link-local subnets, and cloud metadata endpoints:

// Patched code in backend/src/apiserver/validation/pipeline_url.go
var blockedCIDRs = []string{
    // Loopback
    "127.0.0.0/8",
    "::1/128",
 
    // Private Subnets (RFC 1918 & IPv6 ULA)
    "10.0.0.0/8",
    "172.16.0.0/12",
    "192.168.0.0/16",
    "fc00::/7",
 
    // Link-local
    "169.254.0.0/16",
    "fe80::/10",
 
    // Cloud Metadata Endpoints (AWS, GCP, Azure, OpenStack)
    "169.254.169.254/32",
    "fd00:ec2::254/128",
 
    // Invalid / Unspecified
    "0.0.0.0/8",
    "::/128",
}

Second, the patch implements ValidatePipelineURL, which enforces scheme restrictions (https only by default unless PIPELINE_URL_ALLOW_HTTP is set), blocks non-standard ports (permitting only port 443 for HTTPS and 80 for HTTP), and verifies the hostname against a strict allowlist (defaulting to storage.googleapis.com, s3.amazonaws.com, github.com, and raw.githubusercontent.com, extensible via PIPELINE_URL_ALLOWED_DOMAINS).

Third, to prevent DNS rebinding (TOCTOU) and redirect-based bypasses, the patch replaces http.DefaultClient with SafePipelineHTTPClient. This custom client disables ambient environment proxies (transport.Proxy = nil), implements safeDialContext to validate resolved IP addresses at TCP connection time before dialing the verified IP directly, and attaches a CheckRedirect handler:

// Redirect validation in SafePipelineHTTPClient
CheckRedirect: func(req *http.Request, via []*http.Request) error {
    if len(via) >= 10 {
        return util.NewInvalidInputError("too many redirects")
    }
    // Re-validate every redirect target against scheme, port, domain allowlist, and CIDR blocklist
    return ValidatePipelineURL(req.URL.String())
},

Fix Completeness Assessment

The remediation implemented in PR #12750 is comprehensive and addresses both direct SSRF vectors and common bypass techniques. By combining a strict domain allowlist with socket-level IP verification inside safeDialContext, the fix eliminates the TOCTOU window required for DNS rebinding. Re-running ValidatePipelineURL on every redirect hop prevents open-redirect pivoting from allowed domains (such as GitHub or S3) to internal addresses. One operational caveat is the PIPELINE_URL_VALIDATION_ENABLED environment variable: while it defaults to true, administrators must ensure it is never set to false in production deployments, as doing so completely disables these controls.

Exploitation

Exploiting CVE-2026-88983 requires network access to the Kubeflow Pipelines API server (either directly or through the Kubeflow central dashboard/Istio ingress gateway) and an authenticated session with RBAC privileges to create a pipeline or pipeline version (pipelines.kubeflow.org create verbs). In standard multi-user Kubeflow deployments, any authenticated data scientist or developer assigned to a user namespace possesses these permissions.

To execute the attack, the adversary submits an HTTP POST request to the v1beta1 (/apis/v1beta1/pipelines) or v2beta1 (/apis/v2beta1/pipelines) endpoint, or invokes the corresponding CreatePipeline / CreatePipelineVersion gRPC methods. In the request payload, the attacker sets the pipeline_url field to the target internal resource.

Scenario 1: Probing Cloud Instance Metadata Services (IMDS)

An attacker attempting to discover whether IMDSv1 is accessible from the ml-pipeline pod submits the following payload:

{
  "pipeline": {
    "name": "metadata-probe",
    "url": {
      "pipeline_url": "http://169.254.169.254/computeMetadata/v1/"
    }
  }
}

On Google Cloud Platform (GCP), requests to /computeMetadata/v1/ without the Metadata-Flavor: Google header are rejected by the metadata server with an HTTP 403 Forbidden status. The Kubeflow API server processes this response and returns: 400 Invalid Input: error fetching pipeline spec from http://169.254.169.254/computeMetadata/v1/ - request returned 403 Forbidden. This confirms to the attacker that the pod has network routing to the metadata endpoint.

Scenario 2: Internal Kubernetes Service and Port Discovery

An attacker can systematically enumerate internal cluster services and open TCP ports by targeting Kubernetes DNS names or ClusterIP ranges:

{
  "pipeline": {
    "name": "internal-service-scan",
    "url": {
      "pipeline_url": "http://metadata-grpc-service.kubeflow.svc.cluster.local:8080/healthz"
    }
  }
}

By analyzing the returned error codes, the attacker differentiates the state of internal targets:

  • Closed Port / Unreachable Host: The API server returns 500 Internal Server Error containing the Go net.OpError string (e.g., dial tcp 10.96.x.x:8080: connect: connection refused or no such host).
  • Open Port with Non-200 HTTP Response: The API server returns 400 Bad Request / InvalidArgument along with the exact HTTP status line (e.g., 401 Unauthorized, 404 Not Found, 405 Method Not Allowed).
  • Open Port with 200 OK Response: The API server attempts to parse the response body as a pipeline archive or YAML specification, failing with a deserialization error if the content is not a valid pipeline spec.

Impact Assessment

CVE-2026-88983 is assigned a CVSS v3.1 base score of 5.0 (Medium) with the vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:N. The Attack Vector is Network (AV:N) and Attack Complexity is Low (AC:L), as exploitation requires only standard HTTP/gRPC API calls without race conditions. Privileges Required is Low (PR:L), reflecting the requirement for an authenticated user account capable of registering pipelines.

The Scope metric is Changed (S:C) because the vulnerable component is the Kubeflow Pipelines API server, whereas the impacted resources are separate microservices within the Kubernetes cluster network, underlying host loopback services, or cloud infrastructure metadata planes. The Confidentiality impact is rated Low (C:L), while Integrity (I:N) and Availability (A:N) are rated None.

The primary concrete impact of this vulnerability is unauthorized internal network reconnaissance and topology mapping. Because the API server expects the remote response body to conform to a valid Kubeflow pipeline package or YAML structure, arbitrary raw response bodies from internal services (such as credentials from an IMDSv1 endpoint) are not directly echoed back to the client if they fail pipeline deserialization. However, the verbose error reporting acts as a reliable oracle that reveals internal DNS records, active IP addresses, open TCP ports, and HTTP endpoint existence.

Furthermore, if any internal microservice within the cluster or local pod network exposes state-changing operations via unauthenticated HTTP GET requests, an attacker can trigger those actions through this SSRF primitive. As of publication, the Exploit Prediction Scoring System (EPSS) score for CVE-2026-88983 is 0.00199 (9.82nd percentile), and the vulnerability is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog.

Remediation

Patching Guidance

Organizations running Kubeflow Pipelines must upgrade the ml-pipeline API server component to version 2.17.0 or later. Version 2.17.0 incorporates the URL validation engine, CIDR blocklist, and hardened HTTP dialer introduced in Pull Request #12750.

Configuration Hardening (v2.17.0+)

When deploying Kubeflow Pipelines 2.17.0 or later, administrators should review the environment variables passed to the ml-pipeline deployment to ensure defensive defaults remain active:

  • PIPELINE_URL_VALIDATION_ENABLED: Must be set to "true" (the default). Never disable this setting in non-test environments.
  • PIPELINE_URL_ALLOW_HTTP: Keep set to "false" (the default) to enforce TLS (https://) for all remote pipeline specification downloads.
  • PIPELINE_URL_ALLOWED_DOMAINS: By default, only storage.googleapis.com, s3.amazonaws.com, github.com, and raw.githubusercontent.com are permitted. If an organization stores pipeline specifications in an internal artifact repository (such as an enterprise GitLab instance or MinIO gateway), add only the specific FQDN to PIPELINE_URL_ALLOWED_DOMAINS rather than disabling URL validation.
  • PIPELINE_URL_TIMEOUT: Defaults to 30 seconds; can be lowered to reduce connection hold times.

Workarounds and Defense-in-Depth

For environments that cannot immediately upgrade to version 2.17.0, administrators should apply Kubernetes NetworkPolicy resources to restrict egress traffic from the ml-pipeline API server pod:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: restrict-ml-pipeline-egress
  namespace: kubeflow
spec:
  podSelector:
    matchLabels:
      app: ml-pipeline
  policyTypes:
    - Egress
  egress:
    # Allow DNS resolution
    - to:
        - namespaceSelector: {}
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53
    # Allow external HTTPS while blocking RFC 1918 and Link-Local/IMDS
    - to:
        - ipBlock:
            cidr: 0.0.0.0/0
            except:
              - 10.0.0.0/8
              - 172.16.0.0/12
              - 192.168.0.0/16
              - 169.254.0.0/16
      ports:
        - protocol: TCP
          port: 443

> [!NOTE] > When applying an egress NetworkPolicy to ml-pipeline, ensure explicit egress rules are added for required cluster-internal dependencies, including the relational database (mysql or postgres), the object store (minio-service), and the ML Metadata (metadata-grpc-service) endpoints on their respective ports.

Official Patches

KubeflowFix Pull Request #12750 implementing pipeline URL validation and hardened HTTP client
KubeflowKubeflow Pipelines v2.17.0 Official Release
GitHub Security AdvisoryOfficial GitHub Security Advisory GHSA-f7vj-6669-qvv4

Fix Analysis (1)

Technical Appendix

CVSS Score
5.0/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:N
EPSS Probability
0.20%
Top 90% most exploited

Affected Systems

Kubeflow Pipelines (kubeflow/pipelines) < 2.17.0

Affected Versions Detail

Product
Affected Versions
Fixed Version
Kubeflow Pipelines
Kubeflow
< 2.17.02.17.0
AttributeDetail
CVE IDCVE-2026-88983 (GHSA-f7vj-6669-qvv4)
Weakness ClassCWE-918 (Server-Side Request Forgery) / CWE-441 (Confused Deputy)
Attack VectorNetwork (Authenticated REST/gRPC API request)
CVSS v3.1 Score5.0 Medium (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:N)
EPSS Score0.20% (9.82nd Percentile)
Primary ImpactInternal Kubernetes service/port scanning and HTTP status-code oracle
Patched VersionKubeflow Pipelines 2.17.0
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1005Data from Local System
Collection
T1046Network Service Discovery
Discovery
CWE-918
Server-Side Request Forgery (SSRF)

The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but does not sufficiently ensure that the request is being sent to the expected destination.

Vulnerability Timeline

Remediation implemented and committed under Pull Request #12750 (ADA-KUBEFL-01)
2026-05-17
CVE-2026-88983 published by GitHub CNA and GitHub Advisory GHSA-f7vj-6669-qvv4 released
2026-11-05
Official patch released in Kubeflow Pipelines v2.17.0
2026-11-05
NVD analysis and CVSS v3.1 scoring completed
2026-11-06

References & Sources

  • [1]GitHub Security Advisory: GHSA-f7vj-6669-qvv4
  • [2]Official CVE Record: CVE-2026-88983
  • [3]NVD Vulnerability Details: CVE-2026-88983
  • [4]CVEListV5 JSON Record: CVE-2026-88983
  • [5]Kubeflow Pipelines Fix Pull Request #12750
  • [6]Kubeflow Pipelines Fix Commit (504d7797c1e061327ddb2bcb8bc1c5dd4940cfc3)
  • [7]Kubeflow Pipelines Release v2.17.0
  • [8]FIRST.org EPSS Data Service for CVE-2026-88983
  • [9]CISA Known Exploited Vulnerabilities Catalog

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-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 2 hours ago•CVE-2026-88986
6.1

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

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.

Alon Barad
Alon Barad
4 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