Scanning kubernetes manifests with kubesec
Open-source security arsenal for AI coding agents: 784 cybersecurity skills, scanner integrations, and a security MCP for Claude Code, Cursor, opencode, Gemini CLI, Cline, and any agentskills.io agent. Mapped to OWASP, MITRE ATT&CK, NIST CSF, D3FEND, ATLAS.
npx -y skills add Mikaru0Mystic/sectinel --skill scanning-kubernetes-manifests-with-kubesecAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 11 stars11 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Perform security risk analysis on Kubernetes resource manifests using Kubesec to identify misconfigurations, privilege escalation risks, and deviations from security best practices.
The file declares its own license as Apache-2.0. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
8.5 KB, ~2.0k tokens by cl100k_base, as published. Nobody here has run it
Scanning 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 | securityContext.privileged == true | Full host access |
| HostPID | spec.hostPID == true | Process namespace escape |
| HostNetwork | spec.hostNetwork == true | Network namespace escape |
| SYS_ADMIN | capabilities.add contains 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 |
References
What ships with it: 7 files
31.7 KB alongside SKILL.md, 2 of them executable
assets/
- template.md1.1 KB
references/
- api-reference.md1.8 KB
- standards.md1.8 KB
- workflows.md2.0 KB
scripts/
- agent.pyruns5.7 KB
- process.pyruns8.3 KB
- LICENSE11.0 KB