kube-hunter, developed by Aqua Security, is an active penetration-testing tool that hunts for security weaknesses in Kubernetes clusters the way a real attacker would. Rather than statically checking configuration files (like kube-bench does), kube-hunter actively probes network services, APIs, and exposed ports to discover exploitable vulnerabilities — things like an anonymously accessible Kubelet API, an exposed etcd port without authentication, a Dashboard exposed without RBAC, or a container that can access the cloud metadata API to steal IAM credentials.
kube-hunter can run in three main modes:
- Remote scanning – target a cluster from outside, given one or more IPs/hostnames.
- Internal/pod scanning – deployed as a pod inside the cluster, it discovers other nodes and services from an insider’s perspective.
- Network scanning – scans an entire CIDR range or subnet to discover Kubernetes clusters.
Findings are categorized by “hunter” modules (e.g. Access Kubelet API, Etcd Remote Access, Dashboard Exposed, Cloud metadata API) and severity, and each finding is mapped to a specific attack vector with a public vulnerability description (khv code) explaining the exploitation path.
Installation
Method 1 – pip (Python package, most common on Kali):
sudo apt-get update
sudo apt-get install python3-pip -y
pip3 install kube-hunter --break-system-packages
Method 2 – Docker container:
docker pull aquasec/kube-hunter
docker run --rm -it aquasec/kube-hunter --remote SOME_IP
Method 3 – Clone from source:
git clone https://github.com/aquasecurity/kube-hunter.git
cd kube-hunter
pip3 install -r requirements.txt --break-system-packages
python3 kube_hunter/__main__.py --help
Verify installation:
kube-hunter --help
Expected output:
usage: kube-hunter [-h] [--list] [--interface] [--pod] [--quick]
[--cidr CIDR] [--remote REMOTE [REMOTE ...]] ...
Kube-Hunter: hunts for security weaknesses in Kubernetes clusters
Syntax
kube-hunter [OPTIONS]
At least one scanning scope flag is required: --remote, --cidr, --interface, or --pod (internal/active scan).
Command-Line Options
| Flag | Description |
|---|---|
--remote REMOTE [REMOTE ...] | Scan specific remote IP(s)/hostname(s) |
--cidr CIDR | Scan a CIDR range (e.g. 10.0.0.0/24) |
--interface | Auto-scan all interfaces on the local machine |
--pod | Run as if inside a pod, discovering cluster components from within |
--active | Enable active hunters that attempt exploitation (not just discovery) |
--quick | Scan only the main, most common ports, skipping less common ones |
--include-patched-versions | Don’t skip vulnerabilities on patched-version software |
--mapping | Only map cluster nodes/services, no vulnerability hunting |
--report {plain,yaml,json} | Set output report format |
--dispatch {stdout,http} | Where to send the report |
--log LOG_LEVEL | Logging level: DEBUG, INFO, WARNING |
--statistics | Include hunter statistics in report |
--network-timeout | Set network timeout for probes |
-h, --help | Show help |
--list | List all available hunter modules and exit |
-x, --exclude-namespaces | Exclude given namespaces during pod-scope hunts |
Basic Usage
kube-hunter --remote 192.168.1.50
Expected output:
~ Started
~ Discovering Open Kubernetes Services...
+-------------------+------------------+-------------+
| SERVICE | LOCATION | DESCRIPTION |
+-------------------+------------------+-------------+
| Kubelet API | 192.168.1.50:10250 | The Kubelet is the main... |
+-------------------+------------------+-------------+
~ Hunting for vulnerabilities...
+----------------------+-------------------+----------+-------------------------------+
| ID | LOCATION | CATEGORY | VULNERABILITY |
+----------------------+-------------------+----------+-------------------------------+
| KHV005 | 192.168.1.50:10250| Access Risk | Exposed Kubelet API allows anonymous access |
+----------------------+-------------------+----------+-------------------------------+
Nodes
+----------------+----------------+
| TYPE | LOCATION |
+----------------+----------------+
| Node/Master | 192.168.1.50 |
+----------------+----------------+
Practical Examples with Output
Example 1 – Quick scan against a single node (common ports only):
kube-hunter --remote 192.168.1.50 --quick
~ Started (quick scan mode - common ports only)
~ Discovering Open Kubernetes Services...
+------------+---------------------+
| SERVICE | LOCATION |
+------------+---------------------+
| API Server | 192.168.1.50:6443 |
+------------+---------------------+
Example 2 – Scan an entire subnet for clusters:
kube-hunter --cidr 192.168.1.0/24
~ Started
~ Scanning CIDR 192.168.1.0/24 ...
+-------------------+---------------------+
| SERVICE | LOCATION |
+-------------------+---------------------+
| Kubernetes API | 192.168.1.50:6443 |
| Kubelet API | 192.168.1.51:10250 |
+-------------------+---------------------+
Example 3 – Internal pod-based scan with active exploitation attempts:
kubectl run kube-hunter --rm -ti --image=aquasec/kube-hunter -- --pod --active
~ Started in pod mode, discovering cluster from within
~ Found open service: Kubelet API 10.0.1.5:10250
~ Attempting active hunter: Kubelet Command Execution
+--------+-------------------+----------+---------------------------------------+
| ID | LOCATION | CATEGORY | VULNERABILITY |
+--------+-------------------+----------+---------------------------------------+
| KHV002 | 10.0.1.5:10250 | Remote Code Execution | Kubelet exposes execution API |
+--------+-------------------+----------+---------------------------------------+
Example 4 – Output findings as JSON:
kube-hunter --remote 192.168.1.50 --report json --dispatch stdout > findings.json
cat findings.json | python3 -m json.tool | head -20
{
"nodes": [
{"type": "Node/Master", "location": "192.168.1.50"}
],
"services": [
{"service": "Kubelet API", "location": "192.168.1.50:10250"}
],
"vulnerabilities": [
{
"id": "KHV005",
"location": "192.168.1.50:10250",
"vid": "None",
"category": "Access Risk",
"severity": "medium",
"vulnerability": "Anonymous authentication is enabled"
}
]
}
Example 5 – List all available hunter modules:
kube-hunter --list
Discovery Hunters:
- ApiServiceDiscovery
- KubectlClientDiscovery
- KubeletDiscovery
Hunting Hunters:
- AccessApiServer
- AccessKubeletApi
- EtcdRemoteAccess
- DashboardExposer
- CloudMetadataApi
- PrivilegeEscalation
Example 6 – YAML report to a file:
kube-hunter --remote 192.168.1.50 --report yaml --dispatch stdout > report.yaml
cat report.yaml
nodes:
- type: Node/Master
location: 192.168.1.50
services:
- service: Kubelet API
location: 192.168.1.50:10250
vulnerabilities:
- id: KHV005
location: 192.168.1.50:10250
category: Access Risk
severity: medium
vulnerability: Anonymous authentication is enabled
Example 7 – Scan the local network interface (attacker on the same LAN):
sudo kube-hunter --interface
~ Started, scanning all local network interfaces
~ Discovered network 192.168.1.0/24 on eth0
+-------------------+---------------------+
| SERVICE | LOCATION |
+-------------------+---------------------+
| Kubernetes API | 192.168.1.50:6443 |
+-------------------+---------------------+
Example 8 – Enable debug logging for troubleshooting a scan:
kube-hunter --remote 192.168.1.50 --log DEBUG
[DEBUG] Sending probe to 192.168.1.50:443
[DEBUG] Sending probe to 192.168.1.50:6443
[DEBUG] Response received: HTTP 401 Unauthorized
~ Discovering Open Kubernetes Services...
Common Use Cases
- Red team / penetration testing engagements against Kubernetes clusters to identify real, exploitable exposure — not just configuration drift.
- Post-deployment verification that a newly built cluster is not accidentally exposing the Kubelet, etcd, or Dashboard to the internet.
- Insider-threat simulation by deploying kube-hunter as a pod to see what a compromised workload could discover and reach.
- Subnet reconnaissance during an internal network penetration test to discover the existence of undocumented “shadow” Kubernetes clusters.
- Validating network policies — confirming that NetworkPolicies actually block lateral movement to sensitive components like etcd.
Automation with Bash
#!/usr/bin/env bash
# kube-hunter-scan.sh - Automated remote scan with JSON archiving and alerting
set -euo pipefail
TARGET="$1"
OUTFILE="kube-hunter-$(date +%F-%H%M).json"
echo "[*] Running kube-hunter against $TARGET ..."
kube-hunter --remote "$TARGET" --report json --dispatch stdout --log WARNING > "$OUTFILE"
CRITICAL_COUNT=$(python3 -c "
import json
data = json.load(open('$OUTFILE'))
vulns = data.get('vulnerabilities', [])
print(sum(1 for v in vulns if v.get('severity') in ('high', 'critical')))
")
echo "[*] High/Critical findings: $CRITICAL_COUNT"
if [ "$CRITICAL_COUNT" -gt 0 ]; then
echo "[!] Critical exposure detected! Review $OUTFILE immediately."
exit 1
fi
echo "[+] No critical exposures found."
Run it:
chmod +x kube-hunter-scan.sh
./kube-hunter-scan.sh 192.168.1.50
Tips and Best Practices
- Always get written authorization before running kube-hunter (especially
--active) against any cluster you do not own — active hunters attempt real exploitation such as remote code execution via the Kubelet API. - Start with discovery-only scans (no
--active) to map exposure before attempting exploitation. - Run in
--podmode periodically inside production clusters to simulate what a compromised workload could reach; combine with strict NetworkPolicies to shrink the blast radius. - Use
--quickfor fast triage across many targets, then follow up with a full scan on interesting hosts. - Cross-reference findings with kube-bench and kubescape results — kube-hunter shows what’s exploitable right now, while the others show what’s misconfigured relative to a benchmark.
- Findings mentioning the Cloud Metadata API (KHV) are especially high priority — they often lead directly to cloud account compromise via stolen IAM credentials.
Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
| No services discovered on a known cluster | Firewall/NetworkPolicy blocking probes | Confirm network path with nc/nmap first, or run in --pod mode from inside the cluster |
ModuleNotFoundError on pip install | Missing dependency | Reinstall with pip3 install -r requirements.txt --break-system-packages |
| Scan is very slow | Full port scan on large CIDR | Use --quick or narrow the --cidr range |
--active hunters don’t run | Active hunters not enabled by default | Explicitly pass --active |
Permission denied on --interface | Requires raw socket access | Run with sudo |
References
- GitHub repository: https://github.com/aquasecurity/kube-hunter
- Vulnerability catalog (KHV codes): https://aquasecurity.github.io/kube-hunter/
- Aqua Security blog on Kubernetes attacks: https://www.aquasec.com/blog/
