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
References
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-05 |
| Last Updated | 2026-05 |
| Author / Researcher | oscerd |
| CVE / Advisory | CVE-2026-40564 |
| Category | cloud |
| Severity | High |
| CVSS Score | Not specified in source |
| Status | PoC |
| Tags | ssrf, kubernetes, flink, operator, kubernetes-operator, jarURI, cloud-metadata, crd |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | Apache flink-kubernetes-operator |
| Versions Affected | 1.14.0, and main (1.15-SNAPSHOT as of 2026-04-09) |
| Language / Platform | Java operator on Kubernetes; PoC driven via Makefile + kind + Helm + kubectl |
| Authentication Required | Yes — attacker needs permission to create FlinkSessionJob/FlinkDeployment custom resources in the cluster (a common, often broadly-granted, namespaced RBAC permission) |
| Network Access Required | Yes (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
- Obtain (or already hold) permission to create
FlinkSessionJob/FlinkDeploymentresources in a namespace the operator watches. - Set
spec.job.jarURIto an attacker-controlled or sensitive-target URL (e.g. a webhook collector, the cloud metadata service, or an internal-only endpoint). - The operator reconciles the resource and calls
ArtifactManager.fetch, which routes toHttpArtifactFetcher(or the filesystem fetcher for non-http schemes) and issues the request directly from the operator’s pod. - 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
Makefileandmanifests/vulnerable-sessionjob.yaml,manifests/session-cluster.yamlin this folder.
| |
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:
jarURIvalues pointing at169.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
| Action | Detail |
|---|---|
| Primary fix | No 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 mitigation | Add 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.