Lateral credential harvesting via process namespace sharing

Lateral credential harvesting via process namespace sharing

1 3 17
calendar_today agoschedule1 min read

Github Source:
https://github.com/ndouglas-edera/hostpid-risk/tree/main

In a multi-tenant or shared Kubernetes node environment, containers are supposed to be isolated environments. However, this demo proves that if a malicious or compromised pod is deployed with host-level privileges, it can spy on neighbouring workloads running on the same node without needing a software vulnerability or zero-day exploit.

Example script

You can download the automation script from Github:

wget https://raw.githubusercontent.com/ndouglas-edera/hostpid-risk/refs/heads/main/hostpid-risk.sh
chmod +x hostpid-risk.sh

If you have a Kubernetes cluster already running (like on Docker Desktop or kind), you can run the below script:

./hostpid-risk.sh

What is the security misconfiguration exactly?

The exploit relies on 2 specific fields in the inspector-pod YAML manifest working together:

spec:
  hostPID: true            # <--- Misconfiguration #1: Breaks PID isolation
  containers:
  - name: inspector
    securityContext:
      privileged: true     # <--- Misconfiguration #2: Overrides Linux permissions

How it works technically

  1. Normally, Linux container runtimes place each pod in their own isolated Process ID (PID) namespace.
    Setting hostPID: true actually forces the pod to share the host node’s global PID namespace.
  2. Suddenly, ps -ef inside the container displays every process running on the underlying node.
    This includes processes belonging to other pods (target-app).
  3. This would bypass Linux kernel profiles like AppArmor and SELinux - granting full capabilities (like CAP_SYS_ADMIN).
  4. In Linux, the virtual /proc filesystem exposes process metadata. The file /proc/<PID>/environ holds the environment variables loaded into memory when that process was spawned.
  5. Because inspector-pod has host-level permissions, it can read /proc/30629/environ belonging to target-app before extracting the DB_PASSWORD=SuperSecretPassword123! creds.

Strategy 1 - PSS in Kubernetes

Pod Security Standards (or PSS, for short) is a built-in policy Kubernetes framework managed by the Pod Security Admission (PSA) controller. It categorises security into 3 levels:

  • Privileged: Unrestricted (Allowing hostPID: true & privileged: true)
  • Baseline: Prevents known privilege escalations (Blocking hostPID: true, host paths, and host networking)
  • Restricted: Hardened best practices (Requires dropping capabilities, non-root users, and more..)

So, how do PSS policies block the attack?
By either applying a Baseline or Restricted policy to the target namespace, Kubernetes will reject inspector-pod at the API server before it can ever be scheduled. Here's an example of enforcing the baseline profile on the default namespace

kubectl label --overwrite ns default pod-security.kubernetes.io/enforce=baseline

If an attacker tries to apply inspector-pod.yaml now, the Kubernetes API server responds with an immediate error, similar to other admission control technologies like OPA:

Error from server (Forbidden): pods "inspector-pod" is forbidden: 
violates PodSecurity "baseline:latest": hostPID (spec.hostPID=true), 
privileged (container "inspector" must not set securityContext.privileged=true)

Strategy 2 - Runtime Isolation

While PSS works at the API controlplane-level (by stopping bad YAML from being accepted), the ideal runtime isolation approach should be applied at the Kernel-level.

For context, hostPID: true and privileged: true are commonly enabled purely by accident, oftentimes by developers while troubleshooting nodes, and through legacy Helm charts, or by third-party monitoring and observability agents (like eBPF probes, custom log forwarders, or node-exporters) that require node visibility. And when this happens in a multi-tenant cluster (that's shared across departments or clients), compromising a single pod with host privileges instantly compromises all secrets across all pods on that same node, rendering the entire namespace-level isolation useless.

So, what if an attacker has cluster-admin privileges or bypasses PSS?
Standard Kubernetes containers share a single, common Linux kernel. If namespace boundaries break, everything on that kernel is exposed. In the case of Edera Zones (and microVM-based runtimes like Kata Containers or gVisor, more generally) they implement a defence-in-depth strategy by isolating all your workloads into distinct hypervisor boundaries or independent kernel spaces.

Under gVisor, Kata Containers, or Edera Zones, even if a pod sets hostPID: true and privileged: true, hostPID only shares the PID namespace of the isolated guest kernel / microVM sandbox, not the underlying bare-metal host node. The malicious pod sees only itself and its sandbox. In this way, it can't see processes from neighbouring pods running in parallel sandboxes.

Note: I will continue to update the Github repository to better improve these security automation demos.

🔥 Join developers growing publicly
Share your knowledge, build in public, and grow your developer presence with a global community.

More Posts

Comparison: Universal Import vs. Plaid/Yodlee

Pocket Portfolio - Mar 12

The Death of Smart Contract Audits: Why NexusVeritas Hunts Web3 Scammers via Behavioral DNA

VeritasLab - Jun 12

Kamal vs Kubernetes: An Honest Comparison for Teams Who Don’t Need 1,000 Services

Alexandre Vazquez - Jul 24

MCP Is the USB-C of AI. So Why Are You Plugging Everything In?

Ken W. Algerverified - Jun 10

The Interface of Uncertainty: Designing Human-in-the-Loop

Pocket Portfolio - Mar 10
chevron_left
1.3k Points21 Badges
10Posts
8Comments
11Connections
Head of Developer Relations at Cloudsmith. Working on projects related to Kubernetes, Software Development, and securing the Software Supply Chain.

Commenters (This Week)

38 comments
5 comments
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!