AI agents have made their way into virtually every layer of your environment. They run in the apps your employees adopt, on the endpoints where agents execute code, as users with access privileges those agents borrow, and in the cloud workloads that scale them. The platform that you trust to secure your endpoints is already already covering where AI operates today.
Here is the through-line that makes this one problem instead of four. Every AI attack starts as an interaction and ends as an action. A prompt gets manipulated, an agent gets tricked, and the damage lands on a host, reaches into an identity, or moves through the cloud. The tools that treat each surface as a separate product hand you fragments. SentinelOne treats them as one chain.
How SentinelOne Defends the Agentic Stack Today
Employee AI use is where the risk quietly enters. Your people are already using AI tools you never sanctioned, through browser, IDE, and API-connected apps and agentic AI tools. SentinelOne discovers that shadow AI use across browsers, IDEs, and copilots, highlights which tools and models are in play and governs it with policy. It keeps confidential data, PII, and secrets from reaching untrusted models, and it stops prompt injection and jailbreaks aimed at the tools you build. Legacy DLP reads patterns; this reads context, which is the only way to catch an attack aimed at AI systems that behave in a non-deterministic way.
The agent layer is where AI stops advising and starts acting. An employeeβs prompt sends text. An agent sends commands, holds credentials, calls APIs, and chain actions without a human approving each step. That makes them non-human identities with standing access. SentinelOne governs that access. It inventories the agents and MCP servers already operating and scores what each one can reach and holds every agent to the privileges its task requires. Then it inspects the tool calls themselves, so an injected instruction gets blocked at the moment it would execute. What gets executed lands in a searchable record, and the same enforcement doubles as a kill switch.
Inventory the agents already running in your environment, the connectors they reach, and every tool call they make.
While governance decides what an agent is allowed to do, the endpoint is where you find out what it actually did.
The endpoint is where agents execute. This is the frontier, and where SentinelOne has protected customers for over a decade. Our behavioral engine judges what a process does, not what it claims to be. That is how we caught QUIETVAULT β malware that spins up AI agents in βyoloβ mode to exfiltrate secrets to GitHub. It is how we autonomously stopped the LiteLLM supply chain attack, where adversaries weaponized the Claude CLI to install a malicious payload. It is how we surfaced a DLL side-loading attack hidden inside an AI tool installer. Real detections, on the endpoint, today. Agents run on the host, and so do we.
The identity is where a hijacked agent runs next. Picture an employeeβs AI coding agent that gets hijacked mid-task. It spawns a shell and reaches for cached credentials and cloud session tokens, trying to stop being a process and start being the user. That pivot to identity is what unlocks lateral movement, and it is where most AI attacks are headed. SentinelOne meets the move. It secures human and non-human identities alike, and seeds the environment with decoy credentials and honeytokens no legitimate user ever touches. The instant the hijacked agent grabs one, the trap trips, and Identity responds by forcing an MFA re-challenge, disabling the account, or isolating the host. Authorization at login is not enough. Access gets validated against behavior and pulled at runtime.
The cloud is where AI workloads scale. Consider an internal AI agent running in a Kubernetes cluster with standing access to a customer database. Security teams keep asking the same question about deployments like this. Where is the model connecting, and who is it talking to? SentinelOne answers with eBPF-native runtime protection that judges how the workload actually behaves, and flags the moment that inference service reaches an endpoint it has never touched before. It covers the control plane the deployment depends on, the secrets it reads, the pipelines it runs through, and the data it can access. Defending the AI you build takes more than watching it, it takes action on the workload in real time.
SentinelOneβs Singularity Platform Advantage
Each of these surfaces matters on its own. What closes the kill chain is following an attack across them without losing it at the handoff. This is where a single platform earns its keep. AI telemetry already streams into the Singularity Data Lake, alongside the endpoint data the platform has correlated for years. As identity and cloud signals join that same view, an analyst follows one attack from first prompt to final action, without stitching logs across six tools at two in the morning. A manipulated prompt, the process it spawns, the credential it reaches for, and the cloud resource it targets read as one story rather than six disconnected alerts.
Detection that only watches is observation. Runtime action is protection. When the Singularity Platform acts, autonomous response blocks the execution, rolls back the change, and revokes the access at the point of impact, without a human relaying orders between consoles. This is the difference between whether an attack is stopped or just gets logged.
That is the case for securing AI inside a platform built for autonomous runtime response. We are not adding a console to chase AI, we are extending the one already deployed where your agents run.
Questions to Ask When Assessing Your AI Security Options
When evaluating AI security, ask yourself three things.
Does the solution protect the endpoint where agents actually execute, or is it a roadmap item?
When a hijacked agent pivots to credentials and the cloud, does that telemetry land in the same platform, or are you manually connecting dots across three dashboards?
Can the solution act at the moment of execution, or only tell me what already happened?
SentinelOne protects the surfaces where AI runs today. This includes the apps your employees use, the agents they deploy, the endpoints where agents execute, the identities they borrow, and the cloud where they scale. One platform, built for autonomous response. While AI has changed the attack, it does not have to change your architecture.
See it for yourself. Talk to our team about securing AI across your endpoints, identities, cloud, and the AI apps your employees already use, all from the platform you run today. Contact SentinelOne today.
Third-Party Trademark Disclaimer:
All third-party product names, logos, and brands mentioned in this publication are the property of their respective owners and are for identification purposes only. Use of these names, logos, and brands does not imply affiliation, endorsement, sponsorship, or association with the third-party.
filepath.Join was never designed to be a security boundary. We found two CSI drivers that shipped on the assumption it was, and the result was cross-tenant data access with optional node destruction, using nothing more than a valid Kubernetes manifest. The vulnerable drivers are the Kubernetes CSI Driver for NFS (csi-driver-nfs) and the Kubernetes CSI Driver for SMB (csi-driver-smb), both maintained by the upstream kubernetes-csi organization. An attacker who can create a PersistentVolume can craft a volume identifier that escapes the subdirectory boundary and reaches another tenantβs data on the shared export.
The impact varies by deployment. In the default configuration, an attacker can read, modify, and delete files belonging to other tenants sharing the same export. In production deployments where the CSI controller is configured with broader hostPath mounts (a common pattern for log collection and operational tooling), the same primitive enables arbitrary directory deletion on the Kubernetes worker node, including paths like /var/lib/kubelet, /etc/kubernetes, and /etc/cni. Remove those and the node is dead.
The Kubernetes Security Response Committee published advisories and assigned CVE-2026-3864 to the NFS driver issue and CVE-2026-3865 to the SMB driver issue.Fixes shipped in csi-driver-nfs v4.13.1 and csi-driver-smb v1.20.1. We reported both vulnerabilities in January 2026 and worked with the maintainers through coordinated disclosure.
Kubernetes Storage Concepts
First, some background on how Kubernetes does storage. This section covers the four building blocks an attacker manipulates in this attack chain.
Container Storage Interface
Kubernetes does not implement storage directly. It delegates that responsibility to the Container Storage Interface, a gRPC contract between the Kubernetes kubelet and a vendor-supplied driver.
Figure 1. The CSI specification sits between Kubernetes and the underlying storage drivers, with each layer owned by a different party.
When a workload requests storage, Kubernetes issues calls such as CreateVolume, NodePublishVolume, and DeleteVolume to the CSI driver, which in turn provisions, mounts, and tears down the actual storage on the underlying system, whether that system is an NFS export, an SMB share, an Amazon Elastic File System filesystem, a block device, or anything else.
Figure 2. The CSI driver mediates between Kubernetes pods and the underlying storage backend.
The CSI specification is intentionally minimal about what drivers must validate. It specifies the gRPC interface and the lifecycle but leaves input validation, authorization, and isolation to each driver implementation. This design decision is the underlying reason the same class of bug recurs across multiple drivers.
PersistentVolume and the volumeHandle
A PersistentVolume is a Kubernetes API object that represents a unit of storage in the cluster. When a PersistentVolume references a CSI driver, it carries a string field called volumeHandle. This field is opaque to Kubernetes: the API server stores it but does not parse, validate, or interpret it. The driver alone is responsible for understanding the format of volumeHandle and using its contents safely.
Each driver defines its own format. The NFS CSI driver parses volumeHandle as {server}#{share}#{subDir}#{uuid}#{onDelete}
The SMB CSI driver parses it as //{server}/{share}#{subDir}#{uuid}#{secretNs}#{secretName}#{pvName}
In both drivers, the subDir component is the security boundary. Itβs also the one that breaks.
Subdirectory-Based Multi-Tenancy
Some clusters share a single NFS or SMB export across tenants by giving each one a dedicated subdirectory. Both driversβ deployment guides document this pattern. Itβs common wherever provisioning a separate export per tenant is expensive: on-premises NAS appliances, cloud file services that bill per share, shared storage systems that are slow to reconfigure.
In this model, the security boundary between tenants is the subdirectory path. Team Aβs PersistentVolume is scoped to subDir: team-a. Team Bβs is scoped to subDir: team-b. The driver mounts each tenant into their own directory, and the assumption is that neither tenant can reach the otherβs data, even though both share the same underlying export.
Role-Based Access Control and PersistentVolume Authorization
Kubernetes uses RBAC to control who does what. Creating a PersistentVolume (PV) is cluster-scoped, and the documented threat model assumes only cluster admins hold this permission. In practice? Itβs everywhere. CI/CD pipelines, ArgoCD, Helm automation, operator controllers. They all need persistentvolumes:create to provision storage for applications. Compromise any of those service accounts and youβre in.
That gap between the documented threat model and how clusters actually run is what makes these bugs practically exploitable.
Trusting the Wrong Function
Thereβs a misconception in the Go ecosystem that keeps burning people: the idea that filepath.Join prevents path traversal. It doesnβt. filepath.Join is a normalizer. It collapses ., .., and redundant separators into a canonical form. It has no concept of βbase directoryβ or βboundaryβ and canβt tell whether the result landed somewhere the caller never intended.
Try it yourself: give it β/var/lib/csi/team-aβ and β../../../etc/passwdβ. You get /etc/passwd. Clean path, totally canonical, pointing straight at a location outside the intended base directory. The function did what it was designed to do. It just didnβt do what the caller assumed. A safe-path function would take the base directory as a parameter and refuse to return anything outside it. A safe option exists in Go, but these drivers never adopted it. The community workaround is filepath-securejoin, which does the symlink-aware join and returns an error instead of letting you escape.
Both vulnerable drivers shipped this misconception. They pulled the subdirectory string out of volumeHandle, passed it through filepath.Join, and trusted the result.
CVE-2026-3864 β Kubernetes CSI Driver for NFS
We found the bug in the controller-server implementation of csi-driver-nfs. The driver parsed the volume identifier into its parts, pulled out the subdirectory string, and built an internal mount path by joining that subdirectory to a per-volume working directory.
Figure 3 (NFS code): The NFS CSI driver extracts subDir from the volume ID and passes it to filepath.Join without validation, then calls os.RemoveAll on the result.
Three things matter here. No validation on subDir between extraction and use. filepath.Join wonβt refuse a result that escapes its working directory. And the resulting path gets handed to os.RemoveAll. That last part is key: this isnβt just a read primitive. It deletes.
The exploit is a one-line modification to a PersistentVolume manifest:
Figure 4 (Exploit YAML): A malicious PersistentVolume manifest. The subDir component team-a/../../team-b escapes the legitimate tenant directory.
When a pod mounts this PersistentVolume, the path that actually gets bound is 10.0.0.50:/exports/team-b. Not team-a. The attackerβs pod now sees team Bβs files, can read them, modify them, and (if the reclaim policy is set to delete) trigger their recursive removal when the PersistentVolumeClaim (PVC) is deleted.
In production deployments where the CSI controller has been granted broader hostPath mounts of the worker node (common in clusters that integrate the controller with kubelet log collection or other operational tooling), the traversal can reach beyond the export and into the host filesystem itself. A volumeHandle containing the subdirectory string ../../../../../../var/lib/kubelet provides the controller with a recursive-delete primitive against the kubeletβs own state directory, rendering the node permanently non-functional.
Two things make this harder to fix than it looks. First, NFS servers from major vendors expose hidden .snapshot directories. Point-in-time copies, invisible to ls but reachable by path. A subdirectory of team-a/../.snapshot mounts the snapshot tree and surfaces data that admins thought was gone. Second, even after the driver patch, an attacker with write access inside their own tenant directory can plant symlinks that cross the tenant boundary through the NFS data plane. The control-plane fix is necessary but not sufficient. Data-plane mitigations require mounting with nosymfollow (Linux 5.10+) or enabling subtree_check on the export.
CVE-2026-3865 β Kubernetes CSI Driver for SMB
The SMB CSI driver is maintained by the same upstream organization and follows the same architectural shape. It contained the same vulnerability:
Figure 5 (SMB code): The SMB CSI driver follows the same pattern as NFS: subDir extracted at index 1, joined without validation.
The exploit is structurally identical. The volumeHandle for SMB is //{server}/{share}#{subDir}#β¦, and a payload of //smb.internal/shared#dept-engineering/../../dept-finance#uuid causes the same escape into a sibling tenantβs directory.
Honestly, the recurrence is the more interesting finding than either CVE on its own. Same org, same misconception, years apart. When a standard-library function looks like a sanitizer but only normalizes, people keep reaching for it. Every codebase that did has to be audited now. Every callsite patched.
One note for other researchers on this bug class. The Kubernetes triage team initially could not reproduce the SMB report because their reproduction harness ran the proof-of-concept against an SMB-server pod inside the cluster, and SMB exports are sandboxed by the underlying storage system. The vulnerability is in the CSI controllerβs internal file operations on its working-mount directory, not in protocol traffic to the SMB server. Researchers reporting CSI path traversal should lead with a host-mount reproducer and only attach protocol-level demonstrations as supplementary material. This pattern recurs because the server-side of NFS and SMB is usually well-defended by the storage vendor, while the driver-side code path between the Kubernetes API and the host filesystem is where the bug actually lives.
Multi-Tenant Storage as Attack Surface
These two CVEs are instances of something bigger. Kubernetes storage drivers sit on a trust boundary that the CSI spec doesnβt enforce. Nobody validates volumeHandle. The kubelet assumes the driver does it. The driver assumes whoever wrote the PV knew what they were doing. That was probably a CI/CD pipeline that assumed the API server would catch anything dangerous. The API server treats the field as opaque. So nobody checks. The string just flows through.
This isnβt just NFS and SMB. There are dozens of CSI drivers in production, each with its own volumeHandle format, each parsing user input with varying degrees of care, each forwarding strings into mount commands and host file operations. We havenβt audited all of them. But the pattern is there.
The bigger question is where input validation should live. The driver? Implemented inconsistently. The API server? Treats volumeHandle as opaque. An admission controller? Only works if someone remembers to deploy one. The CSI spec? Mandates none of the above. Until one of these layers owns the boundary, this bug class will keep producing CVEs.
The Full Chain β From PersistentVolume-Create to Cross-Tenant Compromise
The full attack chain:
Prerequisite: the attacker holds persistentvolumes:create (typically a CI/CD pipeline, GitOps controller, or operator service account) and identifies the cluster as using the NFS or SMB CSI driver with shared multi-tenant exports.
Craft a PersistentVolume whose volumeHandle contains a traversal payload in the subdirectory component.
Create a PersistentVolumeClaim bound to the malicious PV. The scheduler treats it as normal.
Schedule a pod mounting the claim. The CSI driver parses the malicious volumeHandle, joins the traversal string against its working directory, and mounts the victim tenantβs directory.
Read, modify, or delete the victimβs files. With onDelete=delete, deleting the PVC triggers recursive deletion.
(Optional) If the CSI controller has broader hostPath mounts, traverse into the host filesystem and destroy node-critical paths like /var/lib/kubelet.
The entire chain executes against the Kubernetes API server using only the persistentvolumes:create permission. No exploit code. Just YAML.
Fixes and Mitigations
The Kubernetes Security Response Committee released fixes for both vulnerabilities. The NFS driver fix shipped in csi-driver-nfs v4.13.1 and rejects subdirectory strings containing .. components outright. The SMB driver fix shipped in csi-driver-smb v1.20.1 and applies the same validation pattern.
Beyond the upstream patches, cluster operators have several additional mitigations that should be applied as defense-in-depth:
Restrict persistentvolumes:create authorization. Audit which service accounts in the cluster currently hold this permission. CI/CD pipelines, GitOps controllers, and operator service accounts should be reviewed, and the permission should be scoped down or wrapped behind admission-controller approval for any account that is not strictly an administrative identity.
Deploy admission-time validation. A ValidatingAdmissionPolicy (in Kubernetes 1.30 and later) or a ValidatingWebhookConfiguration (in earlier versions) can reject any PersistentVolume whose spec.csi.volumeHandle field contains .. or other suspicious patterns. This control survives any future zero-day in the same class. The next CSI driver to ship the same misconception is automatically defended.
Address the data-plane symlink amplification. The driver patches donβt cover the symlink variant. A tenant with write access to their own directory can still plant a relative symlink that crosses into someone elseβs. Mount NFS exports with the nosymfollow option (Linux 5.10 and later) where supported, enable subtree_check on the NFS server export configuration, or audit symlink targets on the storage server.
Treat the bug class as recurring. The pattern of filepath.Join on attacker-controlled input is present in many storage drivers, container network interface plugins, operators, and webhook servers throughout the cloud-native ecosystem. Any Go code that takes an untrusted string and joins it to a path should be audited and converted to use either strict validation or the filepath-securejoin library.
Conclusion
Path traversal is one of the oldest bug classes in computing. The fact that it keeps showing up in 2026, in actively maintained infrastructure running multi-tenant production clusters, says something. The safe path-handling already exists, but these drivers kept trustingΒ filepath.Join instead of using it.
The CSI specification doesnβt mandate input validation on volume identifiers. Individual drivers implement it inconsistently, or not at all. The protocols underneath (NFS and SMB here, but the pattern generalizes) were designed for trusted networks decades before multi-tenant container orchestration existed. Until one of these layers takes ownership of the boundary, the same misunderstanding will keep shipping.
For defenders: patch the drivers, restrict who can create PersistentVolumes, deploy admission-time validation, and treat any .. sequence in a volumeHandle as a credible alert. Validators reject. Normalizers donβt. Know which one youβre using.
Disclosure Timeline
January 15, 2026 β Vulnerabilities identified during CSI driver code review by SentinelOne Researchers.
January 16, 2026 β NFS and SMB reports submitted to the Kubernetes SecurityResponse Committee.
January 19, 2026 β NFS report triaged after proof-of-concept harness was clarified.
January 19, 2026 β SMB report triaged.
March 9, 2026 β NFS driver fix released in csi-driver-nfs v4.13.1.
March 17, 2026 β Public disclosure of the NFS finding; CVE-2026-3864 assigned.
March 21, 2026 β SMB driver fix released in csi-driver-smb v1.20.1.
April 11, 2026 β Public disclosure of the SMB finding; CVE-2026-3865 assigned.