Install
$ agentstack add skill-briiirussell-cybersecurity-skills-container-audit ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Container Audit — Docker & Kubernetes Security Review
Audit container images, Dockerfiles, Helm charts, Kustomize overlays, and Kubernetes manifests for misconfiguration, excessive privilege, exposed secrets, and runtime security gaps. Distinct from cloud-audit (cloud-provider IAM and managed services) and dependency-audit (package CVEs in the application). This skill is the container/orchestration layer between them.
Scope the Audit
- Inventory the surface — Dockerfiles, base images, registries, Helm charts, K8s manifests, Kustomize overlays, CI build pipelines that produce images
- Identify the runtime — vanilla K8s, EKS, GKE, AKS, OpenShift, ECS Fargate, Cloud Run, Fly.io
- Identify the network model — service mesh, ingress controller, default-deny vs default-allow
- Identify the secret model — K8s Secrets (base64-only), External Secrets Operator, sealed-secrets, Vault, Doppler
Audit Checklist — Dockerfile
Base image & supply chain
- Pinned by digest, not tag —
FROM node:20@sha256:abc...notFROM node:20(which can move) - Distroless / minimal where possible —
gcr.io/distroless/nodejs20,alpine(be aware of musl quirks),chainguard/* - Not using
:latest— non-reproducible builds - Multi-stage builds discard build-time tooling —
FROM build AS builder→FROM runtimefinal stage - Grep for:
FROM .*:latest,FROM .*:[0-9]+$(tag without digest)
Build-time exposure
- Secrets passed via
--build-argend up in image layers visible to anyone who pulls the image — use BuildKit secrets (--mount=type=secret) or runtime env vars instead COPY . .ships everything in the build context —.dockerignoreshould exclude.git,.env,node_modules,*.pem,.aws/,.ssh/ADDfollows redirects and disables checksum verification — preferRUN curl ... && sha256sum -c- Grep for:
ARG .*KEY,ARG .*TOKEN,ARG .*SECRET,ENV .*=.*[A-Za-z0-9]{32,},ADD http
Runtime posture
- Non-root user —
USER 1001(or any non-zero UID) beforeCMD - No
chmod 4755SUID binaries in the final image - No unnecessary shells / package managers in the final stage — distroless / FROM scratch is the strong default
HEALTHCHECKdefined so orchestrator can detect unhealthy containers- Read-only root filesystem at runtime (set via K8s; verify nothing in the image writes outside
/tmpor a declared volume) - Grep for:
USER root(or absence of anyUSERdirective),chmod 4755,apt-get install.*sudo
Audit Checklist — Kubernetes manifests
Pod security
securityContext.runAsNonRoot: trueandrunAsUserset to a non-zero UIDsecurityContext.allowPrivilegeEscalation: falsesecurityContext.readOnlyRootFilesystem: truewith explicitemptyDirmounts where the app needs to writesecurityContext.capabilities.drop: ["ALL"]then add only what's neededsecurityContext.privilegedis nevertruein app workloads (Falco, kube-proxy, some CSI drivers are the rare legit exceptions)hostNetwork,hostPID,hostIPCallfalse— yes on these is "container can see / talk to the node"hostPathvolumes — every one is a node-escape risk; review case by case- Grep for:
privileged: true,runAsUser: 0,hostNetwork: true,hostPath:
Pod Security Standards (PSS) / admission
- Cluster enforces
restrictedprofile via PSS admission, or equivalent via OPA Gatekeeper / Kyverno - Pod Security Policies (deprecated since 1.21, removed in 1.25) are NOT what's enforcing this — confirm a current admission controller
- No workloads in the
kube-systemnamespace running app code
Network
NetworkPolicyexists for every namespace running app workloads — default-deny ingress AND egress, then allow specific pods- Missing NetworkPolicy = every pod can talk to every other pod on every port, including kube-apiserver and metadata service
- Service mesh (Istio, Linkerd) mTLS in STRICT mode for sensitive namespaces, not PERMISSIVE
- Ingress controllers terminate TLS properly; backend
tls.crt/tls.keyin K8s Secrets rotate
Secrets
- K8s Secrets are base64-encoded, NOT encrypted — by default they're plain bytes in etcd
- etcd encryption at rest enabled —
--encryption-provider-configon kube-apiserver - Workloads consume secrets via projected volumes, not environment variables (env vars leak via
/proc//environ, error reports, crash dumps) - External Secrets Operator / Vault / sealed-secrets bridge so the Git repo never contains plaintext
- Grep for:
kind: Secretin Git withdata:fields (base64-encoded values committed)
RBAC
- No
ClusterRolewith*verbs on*resources exceptcluster-admin(audit who's bound to it) ServiceAccountper workload, not shared "default" SAautomountServiceAccountToken: falseon workloads that don't need API access- Bindings of
system:authenticatedgroup are visible to every legitimate workload — almost always wrong - Grep for:
verbs: ["*"],resources: ["*"],apiGroups: ["*"],system:authenticated
Resource limits
- Every container has
resources.requestsandresources.limitsset — missing limits = noisy neighbor + DoS surface (one pod can starve the node) LimitRangeper namespace as a backstopResourceQuotaper namespace prevents tenant-vs-tenant resource exhaustion
Image policy
imagePullPolicy: Alwaysfor:latest(you shouldn't use :latest, but if you do) — otherwise the node caches stale images- Cluster-level policy that all images come from approved registries (your own + a small allow-list); enforced via Gatekeeper / Kyverno / image-policy-webhook
- Image signature verification — cosign + sigstore policy controller, or Notary v2
Audit Checklist — runtime
- Image scanning in CI —
trivy image,grype,docker scout cves. Must run on every build; advisories should not block but should surface - Runtime detection — Falco / Tracee / Tetragon catches "shell spawned in a pod that has never opened a shell" patterns
- Audit logs enabled — kube-apiserver audit log captures
exec,attach,port-forwardevents for incident response kubectl execaccess tracked — not free for any cluster-admin to silently shell into prod
Useful one-liners
# All Dockerfiles in the repo + their first FROM line
git ls-files | grep -E '(^|/)Dockerfile(\.|$)' | xargs -I{} sh -c 'echo "==> {}"; grep ^FROM "{}"'
# Manifests missing securityContext
grep -rL "securityContext" --include="*.yaml" --include="*.yml" .
# Manifests with privileged containers
grep -rln "privileged: *true" --include="*.yaml" --include="*.yml" .
# Manifests with hostPath volumes
grep -rln "hostPath:" --include="*.yaml" --include="*.yml" .
# Secrets in Git (base64-encoded but readable)
grep -rln "kind: *Secret" --include="*.yaml" --include="*.yml" . | xargs grep -l "^data:"
# Image scan (Trivy)
trivy image --severity HIGH,CRITICAL --exit-code 0
# Manifest scan (Trivy)
trivy config --severity HIGH,CRITICAL .
# Cluster posture (kube-bench, run inside the cluster)
kube-bench run --targets master,node,policies
Verify Fixes at Runtime
runAsNonRoot: true— verify the pod restarts cleanly and stays Running; if the image'sENTRYPOINTcallschownit'll crashloop- NetworkPolicy default-deny — verify legitimate traffic still works (run an in-cluster
kubectl run -it --rm debug ... curl); silent partial outages are common after default-deny rollout readOnlyRootFilesystem: true— verify the app doesn't write outside declaredemptyDirmounts; log writes, PID files, and tmp files are common breakers- Image-policy enforcement — try to deploy an unsigned / off-list image; verify admission rejects it
Report Format
# Container Security Audit
## Target: [cluster name / image registry / repo path]
## Date: [date]
### Summary
- Dockerfiles audited: N
- Manifests audited: N
- Cluster posture checks: pass / fail counts
### Findings
| ID | Severity | Category | Location | Issue |
|----|----------|----------|----------|-------|
### Per-finding detail
#### [SEVERITY] [Title]
**File:** `path/to/manifest.yaml:42`
**Category:** Dockerfile | Pod security | RBAC | NetworkPolicy | Secrets | Resource limits | Image policy | Runtime
**Description:** [what the issue is]
**Vulnerable config:**
```yaml
[snippet]
Remediation:
[fixed snippet]
Verification: [observed behavior proving the fix holds]
Disposition rule (Fixed / Deferred / Accepted Risk) matches `owasp-audit`.
## Boundaries
- Only audit clusters and registries the user provides or has authorization for
- Never `kubectl delete` or modify cluster state during an audit — read-only operations only (`get`, `describe`, `auth can-i`)
- For runtime evidence, prefer non-disruptive checks (a `kubectl run -it --rm` ephemeral debug pod) over modifying running workloads
- Refuse cluster-takeover scenarios — escalating from a found weakness to a full pivot is exploitation, not audit
- Flag low-confidence findings as "Potential" rather than confirmed
## References
- CIS Docker Benchmark
- CIS Kubernetes Benchmark
- NSA/CISA Kubernetes Hardening Guide
- Pod Security Standards (PSS) — restricted, baseline, privileged
- OWASP Docker Security Cheat Sheet
- OWASP Kubernetes Security Cheat Sheet
- MITRE ATT&CK for Containers
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [briiirussell](https://github.com/briiirussell)
- **Source:** [briiirussell/cybersecurity-skills](https://github.com/briiirussell/cybersecurity-skills)
- **License:** MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.