Asi scanning-kubernetes-manifests-with-kubesec
Perform security risk analysis on Kubernetes resource manifests using Kubesec to identify misconfigurations, privilege escalation risks, and deviations from security best practices.
git clone https://github.com/plurigrid/asi
T=$(mktemp -d) && git clone --depth=1 https://github.com/plurigrid/asi "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/asi/skills/scanning-kubernetes-manifests-with-kubesec" ~/.claude/skills/plurigrid-asi-scanning-kubernetes-manifests-with-kubesec && rm -rf "$T"
plugins/asi/skills/scanning-kubernetes-manifests-with-kubesec/SKILL.mdScanning Kubernetes Manifests with Kubesec
Overview
Kubesec is an open-source security risk analysis tool developed by ControlPlane that inspects Kubernetes resource manifests for common exploitable risks such as privilege escalation, writable host mounts, and excessive capabilities. It assigns a numerical security score to each resource and provides actionable recommendations for hardening. Kubesec can be used as a CLI binary, Docker container, kubectl plugin, admission webhook, or REST API endpoint.
When to Use
- When conducting security assessments that involve scanning kubernetes manifests with kubesec
- When following incident response procedures for related security events
- When performing scheduled security testing or auditing activities
- When validating security controls through hands-on testing
Prerequisites
- Kubernetes manifest files (YAML/JSON) for Deployments, Pods, DaemonSets, StatefulSets
- Docker or Go runtime for local installation
- kubectl access for scanning live cluster resources
- CI/CD pipeline access for automated scanning integration
Core Concepts
Security Scoring System
Kubesec assigns a score to each Kubernetes resource based on security checks:
- Positive scores: Awarded for security-enhancing configurations (readOnlyRootFilesystem, runAsNonRoot)
- Zero or negative scores: Indicate missing security controls or dangerous configurations
- Critical advisories: Flagged configurations that represent immediate security risks
Check Categories
- Privilege Controls: Checks for privileged containers, host PID/network access, root execution
- Capabilities: Identifies excessive Linux capabilities (SYS_ADMIN, NET_RAW)
- Volume Mounts: Detects dangerous host path mounts and writable sensitive paths
- Resource Limits: Validates presence of CPU/memory resource constraints
- Security Context: Verifies seccomp profiles, AppArmor annotations, SELinux contexts
Installation
Binary Installation
# Linux/macOS curl -sSL https://github.com/controlplaneio/kubesec/releases/latest/download/kubesec_linux_amd64.tar.gz | \ tar xz -C /usr/local/bin/ kubesec # Verify installation kubesec version
Docker Installation
docker pull kubesec/kubesec:v2 # Scan a manifest file docker run -i kubesec/kubesec:v2 scan /dev/stdin < deployment.yaml
kubectl Plugin
kubectl krew install kubesec-scan kubectl kubesec-scan pod mypod -n default
Practical Scanning
Scanning a Single Manifest
# Scan a deployment manifest kubesec scan deployment.yaml # Scan with JSON output kubesec scan -o json deployment.yaml # Scan from stdin cat pod.yaml | kubesec scan -
Sample Output
[ { "object": "Pod/web-app.default", "valid": true, "fileName": "pod.yaml", "message": "Passed with a score of 3 points", "score": 3, "scoring": { "passed": [ { "id": "ReadOnlyRootFilesystem", "selector": "containers[] .securityContext .readOnlyRootFilesystem == true", "reason": "An immutable root filesystem prevents applications from writing to their local disk", "points": 1 }, { "id": "RunAsNonRoot", "selector": "containers[] .securityContext .runAsNonRoot == true", "reason": "Force the running image to run as a non-root user", "points": 1 }, { "id": "LimitsCPU", "selector": "containers[] .resources .limits .cpu", "reason": "Enforcing CPU limits prevents DOS via resource exhaustion", "points": 1 } ], "advise": [ { "id": "ApparmorAny", "selector": "metadata .annotations .\"container.apparmor.security.beta.kubernetes.io/nginx\"", "reason": "Well defined AppArmor policies reduce the attack surface of the container", "points": 3 }, { "id": "ServiceAccountName", "selector": ".spec .serviceAccountName", "reason": "Service accounts restrict Kubernetes API access and should be configured", "points": 3 } ] } } ]
Scanning Multiple Resources
# Scan all YAML files in a directory for file in manifests/*.yaml; do echo "=== Scanning $file ===" kubesec scan "$file" done # Scan multi-document YAML kubesec scan multi-resource.yaml
Using the HTTP API
# Scan via the public API curl -sSX POST --data-binary @deployment.yaml \ https://v2.kubesec.io/scan # Run a local API server kubesec http --port 8080 & # Scan against local server curl -sSX POST --data-binary @deployment.yaml \ http://localhost:8080/scan
CI/CD Integration
GitHub Actions
name: Kubesec Scan on: [pull_request] jobs: kubesec: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install Kubesec run: | curl -sSL https://github.com/controlplaneio/kubesec/releases/latest/download/kubesec_linux_amd64.tar.gz | \ tar xz -C /usr/local/bin/ kubesec - name: Scan Manifests run: | FAIL=0 for file in k8s/*.yaml; do SCORE=$(kubesec scan "$file" | jq '.[0].score') echo "$file: score=$SCORE" if [ "$SCORE" -lt 0 ]; then echo "FAIL: $file has critical issues (score: $SCORE)" FAIL=1 fi done exit $FAIL
GitLab CI
kubesec-scan: stage: security image: kubesec/kubesec:v2 script: - | for file in k8s/*.yaml; do kubesec scan "$file" > /tmp/result.json SCORE=$(cat /tmp/result.json | jq '.[0].score') if [ "$SCORE" -lt 0 ]; then echo "CRITICAL: $file scored $SCORE" cat /tmp/result.json | jq '.[0].scoring.critical' exit 1 fi done artifacts: paths: - kubesec-results/
Admission Webhook
Deploy Kubesec as a ValidatingWebhookConfiguration to reject insecure manifests at deploy time:
apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: name: kubesec-webhook webhooks: - name: kubesec.controlplane.io rules: - apiGroups: [""] apiVersions: ["v1"] operations: ["CREATE", "UPDATE"] resources: ["pods"] - apiGroups: ["apps"] apiVersions: ["v1"] operations: ["CREATE", "UPDATE"] resources: ["deployments", "daemonsets", "statefulsets"] clientConfig: service: name: kubesec-webhook namespace: kube-system path: /scan failurePolicy: Fail sideEffects: None admissionReviewVersions: ["v1"]
Security Checks Reference
Critical Checks (Negative Score)
| Check | Selector | Risk |
|---|---|---|
| Privileged | | Full host access |
| HostPID | | Process namespace escape |
| HostNetwork | | Network namespace escape |
| SYS_ADMIN | | Near-root capability |
Best Practice Checks (Positive Score)
| Check | Points | Description |
|---|---|---|
| ReadOnlyRootFilesystem | +1 | Prevents filesystem writes |
| RunAsNonRoot | +1 | Non-root process execution |
| RunAsUser > 10000 | +1 | High UID reduces collision risk |
| LimitsCPU | +1 | Prevents CPU resource exhaustion |
| LimitsMemory | +1 | Prevents memory resource exhaustion |
| RequestsCPU | +1 | Ensures scheduler resource awareness |
| ServiceAccountName | +3 | Explicit service account |
| AppArmor annotation | +3 | Kernel-level MAC enforcement |
| Seccomp profile | +4 | Syscall filtering |