Skip to content
PhiloCyber logo
Guide index

Infrastructure Attacks

Source
12-infrastructure.md
State
Editorial review
Edition
2026-draft
Estimated reading time
14 min

Draft chapter under editorial review

This material is available for early reading, but it has not reached the reviewed 1.0 release. Technical references, examples, and wording may change.

AI systems run on infrastructure — cloud accounts, Kubernetes clusters, model registries, GPU nodes, inference clusters. From an offensive standpoint, the infrastructure inherits every classical attack surface plus a handful of AI-specific ones: model artifact stores writable by too many principals, unauthenticated inference endpoints inside VPCs, container-escape CVEs specific to GPU passthrough, IAM roles with ML-platform-scale permissions attached to services running attacker-influenced code.

2025-2026 sharpened this picture considerably. A wave of GPU container-toolkit and driver CVEs (NVIDIAScape and its neighbors), a steady drumbeat of unauthenticated-by-default ML platform services (Ray, MLflow, Ollama, TorchServe, vLLM), and continued exposure of admin dashboards to the open internet turned "infrastructure attacks against ML" from a theoretical chapter into one of the highest-yield paths in a real engagement. This chapter covers the classical infrastructure-attack techniques as they appear specifically in ML deployments, plus the ML-specific components and CVEs that don't have direct classical analogs.

12.1 The pattern to look for

The recurring compromise chain on cloud-hosted ML infrastructure:

  1. Initial foothold via an AI-specific vulnerability. Prompt injection into a chat application, SSRF via a URL-fetching tool, an unauthenticated ML platform dashboard exposed inside or even outside the VPC.
  2. Credential extraction from the compromised process. Instance metadata service (IMDS), environment variables, mounted Kubernetes secrets, cached OAuth tokens.
  3. IAM role chaining or service account traversal to reach progressively more privileged identities.
  4. Model registry / model artifact compromise as persistence — modify a deployed model to enable future re-entry.
  5. Cross-tenant or cross-project pivot — many ML deployments span accounts/projects; roles with cross-boundary permissions bridge them, and on shared GPU hardware a kernel or hypervisor bug can bridge tenants directly.

Section 12.2 through 12.8 walks each stage; Section 12.3 (renumbered from the earlier edition into a dedicated CVE inventory) profiles the infrastructure CVEs that dominated 2025-2026 disclosures.

12.2 Initial cloud foothold

Common patterns for reaching a cloud environment through an AI surface:

SSRF via LLM tools. Any tool that fetches user-influenced URLs (browsing agents, "summarize this webpage" tools, webhook consumers that follow redirects). Pointing at 169.254.169.254/latest/meta-data/iam/security-credentials/ on AWS EC2, metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token on GCP, or 169.254.169.254/metadata/instance on Azure returns the workload's credentials.

File-read via poorly-sandboxed tools. Filesystem tools with weak path checking (Chapter 07) reach /proc/self/environ on the container's filesystem, revealing environment variables that often include cloud temporary credentials.

Unauthenticated inference and platform endpoints. vLLM, TGI, Ray, MLflow, Ollama, TorchServe, and Jupyter routinely ship with no authentication on the assumption that the network boundary (VPC, firewall) is the real control. An attacker who reaches that network segment by any other means — SSRF, a misconfigured load balancer, an exposed NodePort — talks to the service directly, bypassing rate limits and application-layer guardrails entirely. Because several of these services accept code execution by design (job submission, model loading, notebook cells), reaching the network segment is frequently equivalent to remote code execution. Section 12.3 profiles the specific CVEs; Section 12.4 gives the exposure checks.

Model registry APIs. MLflow, SageMaker Model Registry, Vertex Model Registry. An unauthenticated or directory-traversal-vulnerable MLflow instance exposes artifact download URLs, model version metadata, and often environment variable configurations for the containers that will run each model — and, per CVE-2025-11201 below, can be an unauthenticated RCE primitive in its own right.

12.3 2025-2026 ML infrastructure CVE inventory

The following components accumulated critical, well-documented vulnerabilities across 2025 and into 2026. Treat this table as a checklist of "what version is this, and has it been patched" during any ML infrastructure assessment.

ComponentCVE(s)ClassImpactFixed in
NVIDIA Container Toolkit / GPU OperatorCVE-2025-23266 ("NVIDIAScape", CVSS 9.0)Container escape via unfiltered LD_PRELOAD in the OCI createContainer hookRoot code execution on the hostContainer Toolkit 1.17.8, GPU Operator 25.3.1
NVIDIA Container ToolkitCVE-2025-23267 (CVSS 9.0)Link-following in the update-ldcache hook via a crafted imageData tampering, denial of servicePatched alongside CVE-2025-23266
NVIDIA GPU Display Driver (kernel/hypervisor)CVE-2025-33217/33218/33219/33220/33237 (Jan 2026 bulletin); CVE-2026-24187/24190/24191/24192/24193/24198/24199/24200 (May 2026 bulletin)Use-after-free, integer overflow, missing authorization, TOCTOU, heap overflow in kernel and Virtual GPU Manager codePrivilege escalation, hypervisor compromise (VMware vSphere, XenServer, RHEL KVM, Ubuntu), cross-VM data leakageVendor bulletins Jan/May 2026
Ray (Anyscale)CVE-2023-48022 ("ShadowRay")Unauthenticated job-submission API on the Ray DashboardArbitrary Python code execution on every cluster nodeNo fix — by design; must not be exposed
OllamaCVE-2024-37032 ("Probllama")Path traversal in the model pull APIArbitrary file write, RCE as root (default Docker deployment binds 0.0.0.0)0.1.34+
Ollama (Windows updater)CVE-2026-42249 chained with CVE-2026-42248On Windows, an attacker able to influence the update response could combine path traversal through unvalidated HTTP headers with missing update-signature verificationPersistent code execution through the auto-update mechanism under those preconditionsTested against 0.12.10-0.17.5; consult the current NVD record and vendor guidance for affected and fixed versions
MLflowCVE-2025-11201Directory traversal in the tracking server's source parameter (CWE-22)Unauthenticated arbitrary file write into sys.path, leading to RCEPatched release post-disclosure (ZDI)
MLflowCVE-2025-14279Missing Origin header validation (≤3.4.0)DNS rebinding, CSRF-style unauthorized actions3.4.1+
TorchServeCVE-2023-43654 (x2), CVE-2022-1471 ("ShellTorch" chain)Unauthenticated management API, SSRF, Java deserializationFull RCE and server takeover; thousands of exposed instances found in the wildPatched releases; verify management API auth is enabled
vLLMCVE-2025-30165Pickle deserialization over a ZeroMQ SUB/XPUB socket in multi-node tensor-parallel deployments on the V0 engineRCE if the primary node is compromised, used as an escalation pointNot fixed — V0 engine disabled by default since v0.8.0; mitigate via network isolation

Multi-tenant GPU risk. In shared-GPU environments — training clusters, cloud inference services running multiple customers on the same physical GPU host — the kernel- and hypervisor-level driver CVEs above (particularly the Virtual GPU Manager use-after-free bugs) are direct cross-tenant escalation and data-leakage vectors. A guest VM or container on shared GPU hardware that can trigger one of these bugs may read or corrupt memory belonging to a different tenant's workload. When scoping a test of any multi-tenant GPU platform, confirm the exact driver and container-toolkit versions in use and treat any version predating the January/May 2026 bulletins as a finding regardless of whether a working exploit is reproduced.

12.4 Default ports, services, and exposure checks

Every one of the platforms in Section 12.3 ships with a predictable default port and, in most default configurations, no authentication. Port-scanning a target's cloud ranges or internal network segments for these is one of the highest-signal-to-effort reconnaissance steps available.

ServiceDefault port(s)Exposure check
Ray Dashboard / GCS8265 (dashboard), 6379 (GCS)curl http://<host>:8265/api/jobs/ — an empty or populated JSON job list without any auth prompt confirms unauthenticated job submission is reachable
MLflow Tracking Server5000curl http://<host>:5000/api/2.0/mlflow/experiments/search and probe source parameter handling on model-version creation endpoints for CVE-2025-11201-style traversal
Ollama11434curl http://<host>:11434/api/tags lists loaded models with no auth; check daemon version against CVE-2024-37032 and CVE-2026-42249/42248
TorchServe8080 (inference), 8081 (management)curl http://<host>:8081/models — reachable management API without credentials is the ShellTorch precondition
Jupyter Notebook/Lab8888curl http://<host>:8888/api/sessions — a 200 response with no token requirement means arbitrary code execution via a new notebook cell; also the most common target of opportunistic cryptomining campaigns against exposed AI infrastructure
Milvus9091 (metrics/REST), 19530 (gRPC)curl http://<host>:9091/api/v1/collections — full REST API on the metrics port with no auth; also check the /expr debug endpoint for the predictable etcd.rootPath-derived token (default by-dev)
vLLM (OpenAI-compatible API)8000curl http://<host>:8000/v1/models; for multi-node deployments, check whether the V0 engine's ZeroMQ ports are reachable from outside the cluster network

None of these should ever answer on a network segment reachable from outside the ML platform's own trust boundary, and several (Ray, Jupyter, Ollama, MLflow) should not answer without authentication even inside it. Treat any of these responding without a credential prompt as an immediate finding — in the case of Ray's job-submission API or Jupyter's kernel execution, it is equivalent to already having a shell on the cluster.

12.5 IAM role chaining

Once credentials are extracted, the escalation is via sts:AssumeRole chains. The pattern is a graph traversal — each role has an AssumeRolePolicyDocument listing which principals can assume it. The workload's execution role can often assume another role, which can assume another, until reaching a privileged one.

A canonical chain seen in enterprise ML deployments:

LambdaMLExportRole   (initial foothold via SSRF)
  → DataScientistRole   (via AssumeRole)
    → MLOpsRole         (via AssumeRole)
      → SageMakerExecutionRole   (via AssumeRole)
        ← AmazonSageMakerFullAccess + inline SageMakerExecutionExtra
          (SSM read, DynamoDB, API Gateway, cross-project S3)

Reconnaissance techniques for the chain:

  • aws sts get-caller-identity confirms the current identity
  • aws iam list-roles --max-items 100 enumerates roles the caller can see
  • aws iam get-role reveals trust policies (who can assume this role)
  • aws iam simulate-principal-policy simulates permissions the current identity has
  • PMapper, CloudMapper, Pacu — automate the graph traversal

The AI-specific escalation surface: SageMaker/Vertex/AzureML roles frequently have very broad managed policies (AmazonSageMakerFullAccess) with inline additions to reach ML-adjacent services (SSM for parameter store secrets, DynamoDB for feature stores, API Gateway for inference APIs, ECR for container registries). Reaching any of these ML-execution roles typically gives cross-service authority that would be scrutinized on a general-purpose role.

12.6 Secret extraction from ML infrastructure

Every ML deployment scatters secrets across multiple stores. Standard enumeration:

SSM Parameter Store. aws ssm describe-parameters + aws ssm get-parameter --with-decryption. Frequently contains DB passwords, API keys, service tokens. String type parameters (not SecureString) are unencrypted and version history is retrievable — a rotated secret's previous version is still available via get-parameter-history.

Secrets Manager. aws secretsmanager list-secrets + get-secret-value. Rotation history is not directly retrievable but the current value plus staged versions (AWSCURRENT, AWSPREVIOUS, AWSPENDING) are.

CloudWatch Logs. Training-job logs often carry DEBUG-level output that includes credential material. aws logs filter-log-events --filter-pattern "password OR secret OR key OR token" on training job log groups yields low-hanging fruit.

ECR image ENV. Container image manifests include environment variables set at build. aws ecr batch-get-image + inspecting the config blob's Env array frequently reveals hardcoded credentials.

Model Registry container definitions. SageMaker Model Package definitions include container configurations with environment variables. aws sagemaker describe-model-package returns them.

Kubernetes Secrets. Base64-encoded, not encrypted at rest by default. kubectl get secret -o yaml yields plaintext after base64 decoding. Cluster-wide read on secrets is a common misconfiguration (Section 12.7).

HashiCorp Vault. AppRole authentication is the common ML pattern. Compromising an MCP server or an inference container often yields the AppRole credentials in an environment variable or a mounted file.

12.7 Kubernetes RBAC misconfigurations

Kubernetes is the dominant orchestrator for ML workloads. The recurring RBAC failure modes:

ClusterRole vs Role confusion. Role is namespace-scoped; ClusterRole is cluster-wide. A ClusterRoleBinding grants a ClusterRole cluster-wide. Intent is often "give this agent read on secrets in the app namespace"; implementation is a ClusterRole with a ClusterRoleBinding, giving the agent cluster-wide secret read across every namespace including kube-system, pipeline-system, and any tenant namespaces.

The exploitation: exec into a pod with the misconfigured service account (via any path), read its token, use SelfSubjectRulesReview to enumerate its permissions, then enumerate secrets across every namespace.

# Inside the compromised pod:
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
CACERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
API=https://kubernetes.default.svc:443

# Enumerate my permissions cluster-wide
curl -sk -H "Authorization: Bearer $TOKEN" \
  $API/apis/authorization.k8s.io/v1/selfsubjectrulesreviews \
  -X POST -H "Content-Type: application/json" \
  -d '{"spec":{"namespace":"*"}}' | jq .

# Enumerate cross-namespace secrets
curl -sk -H "Authorization: Bearer $TOKEN" \
  $API/api/v1/namespaces/pipeline-system/secrets | jq '.items[].metadata.name'

Identity chaining via secrets. Once cluster-wide secret read is reached, extract other service accounts' tokens from their namespaces. Each service account has its own permission set. A pipeline-system controller service account (argo-workflow-controller, pipeline-operator, kubeflow-controller) frequently has pod-create permissions cluster-wide plus custom resource ownership — the same enumeration pattern applied to that identity extends the reach.

Multi-container pod abuse. Model-serving pods often have multiple containers: an init container that downloads the model, a main container that serves inference, a telemetry sidecar. Shared volumes (emptyDir mounted by all containers as /queue or /model) let one container read what the others produce. A less-restricted sidecar with a debug endpoint can dump the model container's requests, credentials, or in-flight embeddings.

GPU Operator privilege footprint. The NVIDIA GPU Operator's driver and toolkit containers require privileged: true, hostPID: true, and hostIPC: true to function, which widens the attack surface in any cluster where namespace segmentation between tenants is weak — a compromised pod that can reach the GPU Operator's own components inherits that privilege footprint.

12.8 Container escape and GPU passthrough

GPU workloads use passthrough — the container gets direct access to the GPU hardware. This weakens container isolation because passthrough involves kernel modules, device files, and shared memory outside standard container namespacing.

CVE-2025-23266 — NVIDIAScape. Discovered by Wiz Research, this is the highest-impact container escape disclosed against ML infrastructure in this period. The OCI createContainer hook in NVIDIA Container Toolkit and GPU Operator trusts environment variables — including LD_PRELOAD — without filtering them, and the hook's working directory is set to the container's own root filesystem, so a malicious shared library can be referenced by a simple relative path. The entire trigger fits in three lines of a Dockerfile:

FROM nvidia/cuda:12.4.0-base-ubuntu22.04
COPY poc.so /poc.so
ENV LD_PRELOAD=/poc.so

Exploitation:

  1. Craft a shared library with a __attribute__((constructor)) function that writes to /host/etc/sudoers.d/ (the host /etc mount is visible during GPU device management) or otherwise breaks out to the host.
  2. Build the Dockerfile above; no other Dockerfile complexity is required.
  3. Run or have the target's pipeline run the image on GPU-enabled infrastructure (CI/CD runner, shared notebook, Kubernetes node with GPU Operator).
  4. When the container starts, LD_PRELOAD fires before container isolation is fully applied, the constructor executes as root in the host namespace, and the escape is complete.

Affects Container Toolkit ≤1.17.7 and GPU Operator ≤25.3.0; fixed in 1.17.8 / 25.3.1. Wiz estimates that 37% of cloud environments expose the vulnerable toolkit. Root on the Kubernetes node grants access to every pod's memory (via /proc/<pid>/mem on kubelet), every secret currently loaded on the node, and the kubelet's own credentials — a typical path to cluster-admin.

CVE-2025-23267. A related hook (update-ldcache) in the same toolkit is vulnerable to link-following via a crafted container image, enabling data tampering and denial of service. Affected components span NVIDIA/gpu-operator, NVIDIA/k8s-device-plugin (<0.17.3), and NVIDIA/mig-parted (<0.12.2).

Escape from privileged containers. Model-serving containers sometimes run privileged (securityContext.privileged: true) because they need CUDA drivers. Privileged containers can mount arbitrary paths, load kernel modules, and access host devices — a container escape is trivial regardless of any specific CVE.

12.9 Multi-account / multi-project pivoting

Enterprise ML deployments frequently span accounts:

  • Production account for inference
  • Data science account for experimentation
  • Staging account for QA
  • Shared services account for identity, logging, model registry

Roles that span accounts (via cross-account trust policies) become pivot primitives. sts:AssumeRole across account boundaries requires the trust policy to name the source account or an IAM principal in it; enumerate the trust policies of every reachable role to find cross-account jumps.

Cross-project pivoting is often via shared S3 buckets — for example northstar-example-shared-models-* or northstar-example-training-data-* style naming conventions. Buckets set up for cross-project reads are frequently over-broad. Once a foothold in the ML platform has access to shared buckets, other projects' data is readable.

12.10 Vault and secrets-manager patterns

HashiCorp Vault is the dominant secrets manager in ML deployments that require rotation and dynamic credentials. Vault's attack surface in ML contexts:

AppRole authentication. The dominant service-to-Vault auth for ML services. role_id + secret_id combined into a login. Frequently the secret_id lives as a Kubernetes secret (already discussed) or a container environment variable. Compromise the container, get the AppRole credentials, log into Vault, retrieve the secrets scoped to that role.

Dynamic credentials. Vault issues short-lived DB credentials, cloud credentials, or SSH keys on demand. From a red-team perspective these look better (they expire) but the leases are usually long enough to complete an engagement. Renewing before expiry extends indefinitely.

Vault agent template rendering. Vault Agent renders secrets into a file for the application to read. The file is on disk in the container. Anyone with filesystem read access — a sidecar, a compromised process, a debug shell — reads the rendered secret regardless of Vault's auth model.

MCP tool authority at Vault. MCP tools like vault_rotate_secret (Chapter 07) act with their AppRole. Prompt-injecting the agent into calling the tool with an attacker-chosen path lets the attacker overwrite Vault secrets, replace legitimate credentials with attacker-owned values, and force downstream systems to authenticate against attacker infrastructure.

12.11 Persistence via ML infrastructure

Persistence patterns unique to ML:

Poisoned model in the registry. Modify a deployed model with a backdoor trigger (Chapter 09). The next inference deployment carries the trigger. Detection requires model provenance verification, which is inconsistent.

Malicious embedding in the vector store. Chapter 06 discussed poisoning for prompt injection; the same technique provides persistence. Every retrieval of the poisoned embedding executes the attacker's prompt.

Injected LoRA adapter. Ship an adapter update disguised as a model improvement. Base model remains unchanged; behavior changes silently. This is not theoretical: published research demonstrates LoRA sleeper agents that behave safely under one context marker and comply with harmful requests under another, with as little as 5% of fine-tuning examples poisoned.

Container image poisoning in ECR. Modify the container image the inference deployment consumes. The next pod restart pulls the poisoned image.

Cron-triggered fine-tune jobs. Some deployments retrain periodically. Poisoning the training-data source (Chapter 09) ensures the poison propagates through the retraining cycle.

Exploiting exposed platform panels as a re-entry point. Because Ray, Ollama, Jupyter, and similar services are often re-exposed after a remediation window closes (temporary debug access left open, a redeployed node reverting to defaults), a tester should note these as recurring persistence/re-entry candidates, not just initial-access findings — opportunistic cryptomining campaigns against exposed Jupyter instances are a real-world existence proof that attackers monitor for exactly this kind of drift.

12.12 Detection considerations

  • CloudTrail / audit-log completeness. Coverage of API calls varies; STS AssumeRole is logged, but token-refresh events are noisy.
  • Kubernetes audit logs. Frequently sampled or not shipped. Enumeration via SelfSubjectRulesReview is often uncaught.
  • GPU-specific monitoring. Rare. GPU escapes via LD_PRELOAD leave few detection artifacts beyond the successful shell; alerting on LD_PRELOAD set in container ENV at admission time is one of the few practical controls.
  • Model registry auditing. MLflow, SageMaker, Vertex all support access logs but review is manual.
  • Vector store bulk-read alerts. Increasingly common; extract detection rules first (Chapter 03).
  • Platform dashboard exposure scanning. Internet-wide scanning (Shodan-style) for Ray, MLflow, Ollama, TorchServe, Jupyter, and Milvus default ports is something attackers already do continuously; defenders should run the same scans against their own ranges on a schedule, not just at deployment time.

12.13 Practice checklist

  • Identified initial-foothold surface leading into the cloud environment
  • Checked every ML platform dashboard (Ray 8265, MLflow 5000, Ollama 11434, TorchServe 8080/8081, Jupyter 8888, Milvus 9091) for unauthenticated exposure
  • Verified NVIDIA Container Toolkit / GPU Operator / driver versions against the CVE-2025-23266, CVE-2025-23267, and Jan/May 2026 driver bulletin fixed versions
  • For shared GPU tenancy, flagged any pre-patch driver/hypervisor version as a cross-tenant risk regardless of exploit reproduction
  • Enumerated IAM roles reachable from the initial identity; mapped AssumeRole graph
  • Extracted secrets from SSM, Secrets Manager, CloudWatch logs, ECR ENVs, Model Registry, K8s Secrets, Vault
  • Enumerated Kubernetes RBAC for the compromised service account; probed for cluster-wide read
  • Identified other service accounts reachable via secret extraction; repeated enumeration
  • Assessed privileged-container and GPU-passthrough escape patterns beyond the specific CVEs
  • Enumerated cross-account/cross-project pivots
  • Considered persistence via poisoned model, embedding, LoRA adapter, ECR image, scheduled retraining, or re-exposure of a previously remediated platform panel

MITRE ATLAS references

IDTechnique
AML.T0012Valid Accounts
AML.T0035ML Artifact Collection
AML.T0037Data from Cloud Storage
AML.T0053LLM Plugin Compromise
AML.T0055Unsecured Credentials
AML.T0081Model Registry Poisoning

Further reading

Infrastructure Attacks | PhiloCyber