Back to list
abhaybhargav

k8s-security-audit

by abhaybhargav

1🍴 1📅 Jan 21, 2026

SKILL.md


name: k8s-security-audit description: Comprehensive Kubernetes cluster security audit and assessment. Use when Claude needs to analyze a Kubernetes cluster for security vulnerabilities, misconfigurations, RBAC issues, network policies, pod security, secrets management, and compliance gaps. Triggers on requests to audit, assess, review, or analyze Kubernetes security, including CIS benchmark checks, privilege escalation paths, container security, ingress/egress analysis, and generating security posture reports. Requires kubectl access with administrative permissions.

Kubernetes Security Audit

Perform comprehensive security audits of Kubernetes clusters, identifying vulnerabilities, misconfigurations, and compliance gaps.

Prerequisites

  • kubectl configured with administrative access (kubeconfig in ~/.kube/config or specified via KUBECONFIG)
  • Cluster admin or equivalent read permissions across all namespaces
  • Python 3.8+ with pyyaml, tabulate dependencies (optional, for report generation)

Audit Workflow Overview

  1. Cluster Access Validation - Verify connectivity and permissions
  2. Cluster Information Gathering - Version, nodes, namespaces inventory
  3. RBAC Analysis - Roles, bindings, privilege escalation paths
  4. Pod Security Assessment - Container privileges, security contexts
  5. Network Policy Review - Ingress/egress rules, default deny policies
  6. Secrets Management Audit - Encryption, exposure risks
  7. Workload Configuration Review - Resource limits, probes, images
  8. CIS Benchmark Checks - Alignment with Kubernetes security benchmarks
  9. Report Generation - Findings with severity and remediation

Step 1: Cluster Access Validation

Verify kubectl connectivity and permissions before proceeding:

# Test cluster connectivity
kubectl cluster-info

# Verify admin access
kubectl auth can-i '*' '*' --all-namespaces

# Check current context
kubectl config current-context

# List available contexts
kubectl config get-contexts

If kubectl auth can-i '*' '*' returns no, document limited permissions and adjust audit scope accordingly.

Step 2: Cluster Information Gathering

Collect cluster metadata for context:

# Kubernetes version (check for EOL or vulnerable versions)
kubectl version --output=yaml

# Node inventory with roles
kubectl get nodes -o wide

# Namespace inventory
kubectl get namespaces

# API resources available
kubectl api-resources --verbs=list -o name

# Cluster events (last 100, look for security-relevant)
kubectl get events -A --sort-by='.lastTimestamp' | tail -100

Version Security Check

Compare against references/k8s_cve_versions.md for known vulnerabilities in the running version.

Step 3: RBAC Analysis

See references/rbac_analysis.md for detailed RBAC security patterns.

Extract RBAC Configuration

# ClusterRoles (focus on high-privilege)
kubectl get clusterroles -o yaml > /tmp/clusterroles.yaml

# ClusterRoleBindings
kubectl get clusterrolebindings -o yaml > /tmp/clusterrolebindings.yaml

# Roles per namespace
kubectl get roles -A -o yaml > /tmp/roles.yaml

# RoleBindings per namespace
kubectl get rolebindings -A -o yaml > /tmp/rolebindings.yaml

# ServiceAccounts
kubectl get serviceaccounts -A -o yaml > /tmp/serviceaccounts.yaml

High-Risk RBAC Patterns to Flag

RiskPatternDetection
CriticalWildcard permissions (* on resources/verbs)grep -E "resources:.*\*|verbs:.*\*"
CriticalSecrets access cluster-wideClusterRole with get/list secrets
HighPod exec permissionsVerb create on pods/exec
HighServiceAccount token mountingautomountServiceAccountToken: true
HighImpersonation rightsVerb on users, groups, serviceaccounts impersonate
MediumExcessive namespace adminRoleBinding to admin or edit for broad groups

Quick RBAC Risk Detection

# Find wildcard cluster permissions
kubectl get clusterroles -o json | jq -r '.items[] | select(.rules[]?.resources[]? == "*" or .rules[]?.verbs[]? == "*") | .metadata.name'

# Find who can exec into pods
kubectl auth can-i create pods/exec --all-namespaces --list

# Find who can read secrets cluster-wide
kubectl auth can-i get secrets --all-namespaces --list

# ServiceAccounts with cluster-admin binding
kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name == "cluster-admin") | .subjects[]? | select(.kind == "ServiceAccount") | "\(.namespace)/\(.name)"'

Step 4: Pod Security Assessment

Gather Pod Security Contexts

# All pods with security context details
kubectl get pods -A -o json | jq -r '
  .items[] | 
  "\(.metadata.namespace)/\(.metadata.name): privileged=\(.spec.containers[].securityContext.privileged // false), runAsRoot=\(.spec.containers[].securityContext.runAsNonRoot // "unset"), hostNetwork=\(.spec.hostNetwork // false), hostPID=\(.spec.hostPID // false)"
'

Critical Security Flags

FlagRiskQuery
privileged: trueCritical - Full host accesskubectl get pods -A -o json | jq '.items[] | select(.spec.containers[].securityContext.privileged == true)'
hostNetwork: trueHigh - Network namespace escapekubectl get pods -A -o json | jq '.items[] | select(.spec.hostNetwork == true)'
hostPID: trueHigh - Process namespace escapekubectl get pods -A -o json | jq '.items[] | select(.spec.hostPID == true)'
hostPath volumesHigh - Host filesystem accesskubectl get pods -A -o json | jq '.items[] | select(.spec.volumes[]?.hostPath != null)'
runAsUser: 0Medium - Container runs as rootCheck securityContext.runAsUser
Missing readOnlyRootFilesystemLow - Writable container filesystemDefault is writable

Pod Security Standards Compliance

Check namespace labels for Pod Security Standards enforcement:

# Check PSS labels on namespaces
kubectl get namespaces -o json | jq -r '.items[] | "\(.metadata.name): enforce=\(.metadata.labels["pod-security.kubernetes.io/enforce"] // "none"), audit=\(.metadata.labels["pod-security.kubernetes.io/audit"] // "none")"'

Expected: Production namespaces should have restricted or baseline enforcement.

Step 5: Network Policy Review

See references/network_policy_analysis.md for network security patterns.

Inventory Network Policies

# All NetworkPolicies
kubectl get networkpolicies -A -o yaml > /tmp/netpols.yaml

# Namespaces without any NetworkPolicy
kubectl get namespaces -o name | while read ns; do
  ns_name=${ns#namespace/}
  count=$(kubectl get networkpolicies -n "$ns_name" --no-headers 2>/dev/null | wc -l)
  if [ "$count" -eq 0 ]; then
    echo "No NetworkPolicy: $ns_name"
  fi
done

Network Security Checklist

  • Default deny ingress policy exists in production namespaces
  • Default deny egress policy exists (prevents data exfiltration)
  • Policies use specific podSelectors (not empty {})
  • Egress to metadata API (169.254.169.254) is blocked
  • Cross-namespace communication is explicitly allowed only where needed

Default Deny Policy Template

Namespaces lacking this pattern are exposed:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

Step 6: Secrets Management Audit

Secrets Inventory

# Count secrets by namespace and type
kubectl get secrets -A -o json | jq -r '.items | group_by(.metadata.namespace) | .[] | "\(.[0].metadata.namespace): \(length) secrets"'

# Identify secret types
kubectl get secrets -A -o json | jq -r '.items | group_by(.type) | .[] | "\(.[0].type): \(length)"'

# Find secrets mounted in pods
kubectl get pods -A -o json | jq -r '.items[] | .spec.volumes[]? | select(.secret != null) | .secret.secretName' | sort -u

Secrets Security Checklist

  • Encryption at rest enabled (kubectl get apiservices v1 -o yaml - check for EncryptionConfiguration)
  • No secrets in environment variables (prefer volume mounts)
  • External secrets manager integration (e.g., Vault, AWS Secrets Manager, External Secrets Operator)
  • Secrets not stored in ConfigMaps
  • RBAC restricts secret access appropriately

Check for Secrets in ConfigMaps (Anti-pattern)

# Look for base64-encoded or password-like values in ConfigMaps
kubectl get configmaps -A -o json | jq -r '.items[] | select(.data != null) | select(.data | to_entries[] | .key | test("password|secret|key|token|credential"; "i")) | "\(.metadata.namespace)/\(.metadata.name)"'

Step 7: Workload Configuration Review

Image Security

# List all container images
kubectl get pods -A -o json | jq -r '.items[].spec.containers[].image' | sort -u

# Find images without explicit tags (using :latest or no tag)
kubectl get pods -A -o json | jq -r '.items[].spec.containers[] | select(.image | test(":latest$") or (test(":") | not)) | .image' | sort -u

# Find images from untrusted registries
kubectl get pods -A -o json | jq -r '.items[].spec.containers[].image' | grep -vE "^(gcr.io|docker.io|quay.io|registry.k8s.io|your-registry.com)" | sort -u

Resource Limits Check

# Pods without resource limits
kubectl get pods -A -o json | jq -r '.items[] | select(.spec.containers[] | .resources.limits == null) | "\(.metadata.namespace)/\(.metadata.name)"'

# Pods without resource requests
kubectl get pods -A -o json | jq -r '.items[] | select(.spec.containers[] | .resources.requests == null) | "\(.metadata.namespace)/\(.metadata.name)"'

Liveness/Readiness Probes

# Pods without health probes
kubectl get pods -A -o json | jq -r '.items[] | select(.spec.containers[] | (.livenessProbe == null) and (.readinessProbe == null)) | "\(.metadata.namespace)/\(.metadata.name)"'

Step 8: CIS Benchmark Quick Checks

See references/cis_benchmarks.md for complete CIS Kubernetes Benchmark mapping.

Control Plane Security (if accessible)

# Check API server flags (if running as pod)
kubectl get pods -n kube-system -l component=kube-apiserver -o yaml | grep -E "anonymous-auth|enable-admission-plugins|audit-log"

# Check etcd encryption
kubectl get pods -n kube-system -l component=etcd -o yaml | grep -E "client-cert-auth|peer-client-cert-auth"

Worker Node Security

# Kubelet configuration (requires node access or kubelet API)
# Check for --anonymous-auth=false, --authorization-mode not AlwaysAllow
kubectl get nodes -o json | jq -r '.items[].status.nodeInfo'

Step 9: Generate Audit Report

Use scripts/generate_report.py to compile findings:

python scripts/generate_report.py --kubeconfig ~/.kube/config --output audit_report.md

Report Structure

# Kubernetes Security Audit Report

**Cluster**: {context_name}
**Date**: {timestamp}
**Auditor**: Claude AI

## Executive Summary

| Category | Critical | High | Medium | Low |
|----------|----------|------|--------|-----|
| RBAC | X | X | X | X |
| Pod Security | X | X | X | X |
| Network | X | X | X | X |
| Secrets | X | X | X | X |
| Workloads | X | X | X | X |

**Overall Risk Level**: {Critical/High/Medium/Low}

## Cluster Information
- Kubernetes Version: {version}
- Nodes: {count}
- Namespaces: {count}

## Critical Findings
{findings with remediation}

## High-Risk Findings
{findings with remediation}

## Detailed Findings by Category

### RBAC Analysis
{detailed findings}

### Pod Security
{detailed findings}

### Network Policies
{detailed findings}

### Secrets Management
{detailed findings}

### Workload Configuration
{detailed findings}

## Remediation Priority Matrix
{ordered list by risk and effort}

## Appendix
- Raw data references
- Commands used

Quick Audit Commands

Run this script for a rapid security snapshot:

#!/bin/bash
echo "=== K8s Security Quick Audit ==="

echo -e "\n[1] Privileged Pods:"
kubectl get pods -A -o json | jq -r '.items[] | select(.spec.containers[].securityContext.privileged == true) | "\(.metadata.namespace)/\(.metadata.name)"'

echo -e "\n[2] Pods with hostNetwork/hostPID:"
kubectl get pods -A -o json | jq -r '.items[] | select(.spec.hostNetwork == true or .spec.hostPID == true) | "\(.metadata.namespace)/\(.metadata.name)"'

echo -e "\n[3] Cluster-admin ServiceAccounts:"
kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name == "cluster-admin") | .subjects[]? | "\(.kind): \(.namespace // "cluster")/\(.name)"'

echo -e "\n[4] Namespaces without NetworkPolicies:"
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
  [ $(kubectl get netpol -n $ns --no-headers 2>/dev/null | wc -l) -eq 0 ] && echo "$ns"
done

echo -e "\n[5] Pods with latest/untagged images:"
kubectl get pods -A -o json | jq -r '.items[].spec.containers[] | select(.image | test(":latest$") or (test(":") | not)) | .image' | sort -u

echo -e "\n[6] Pods without resource limits:"
kubectl get pods -A -o json | jq -r '.items[] | select(.spec.containers[] | .resources.limits == null) | "\(.metadata.namespace)/\(.metadata.name)"' | head -20

Reference Files

Report Template

Use assets/audit_report_template.md for consistent report formatting.

Common Remediation Patterns

FindingRemediation
Privileged podsAdd securityContext.privileged: false, use capabilities instead
Missing NetworkPoliciesApply default-deny, then allow required traffic
Overly permissive RBACFollow least-privilege, use namespaced Roles
Secrets in env varsMount as volumes with defaultMode: 0400
Latest image tagsPin to specific digests or semantic versions
Missing resource limitsDefine CPU/memory limits and requests
No Pod Security StandardsAdd pod-security.kubernetes.io/* labels to namespaces

Score

Total Score

50/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon