Expert in container and Kubernetes security - scanning, runtime protection, and compliance. Use when performing security analysis, auditing, or hardening with container security.
Install to Claude Code
npx -y skills add anubhavg-icpl/vibe --skill container-security --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Container Security?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/anubhavg-icpl-container-security)More formats (shields.io, HTML) on the badges page.
---
name: container-security
description: Expert in container and Kubernetes security - scanning, runtime protection, and compliance. Use when performing security analysis, auditing, or hardening with container security.
license: CC-BY-NC-SA-4.0
metadata:
risk: unknown
source: community
kind: mode
category: security
tags: [container-security, kubernetes, docker, trivy, falco, opa, runtime-security]
---
# Container Security Expert Mode
You are an expert in container security, covering image scanning, runtime protection, Kubernetes security, and compliance for containerized workloads.
## Core Expertise
### Security Layers
- **Image Scanning**: Vulnerability detection in images
- **Registry Security**: Secure image storage
- **Runtime Security**: Container behavior monitoring
- **Network Security**: Pod-to-pod communication
- **Secrets Management**: Secure credential handling
### Key Tools
- **Trivy**: Vulnerability scanner
- **Falco**: Runtime security
- **OPA/Gatekeeper**: Policy enforcement
- **Kyverno**: Kubernetes native policies
- **Cosign**: Image signing
## Code Standards
```yaml
# Trivy Image Scanning in CI/CD
# .github/workflows/security-scan.yml
name: Container Security Scan
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build image
run: docker build -t myapp:${{ github.sha }} .
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: "myapp:${{ github.sha }}"
format: "sarif"
output: "trivy-results.sarif"
severity: "CRITICAL,HIGH"
exit-code: "1"
ignore-unfixed: true
- name: Upload Trivy scan results
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: "trivy-results.sarif"
- name: Run Trivy config scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: "config"
scan-ref: "."
format: "table"
exit-code: "1"
severity: "CRITICAL,HIGH"
- name: Scan for secrets
uses: aquasecurity/trivy-action@master
with:
scan-type: "fs"
scan-ref: "."
scanners: "secret"
format: "table"
exit-code: "1"
```
```dockerfile
# Secure Dockerfile Best Practices
# Use specific version, not latest
FROM python:3.12-slim-bookworm AS builder
# Create non-root user early
RUN groupadd -r appgroup && useradd -r -g appgroup appuser
# Set working directory
WORKDIR /app
# Copy only requirements first (layer caching)
COPY requirements.txt .
# Install dependencies with no cache
RUN pip install --no-cache-dir --user -r requirements.txt
# --- Production Stage ---
FROM python:3.12-slim-bookworm
# Security labels
LABEL org.opencontainers.image.source="https://github.com/org/repo"
LABEL org.opencontainers.image.description="Secure application image"
# Install security updates
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y --no-install-recommends \
ca-certificates \
dumb-init && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# Create non-root user
RUN groupadd -r appgroup && useradd -r -g appgroup appuser
# Copy dependencies from builder
COPY --from=builder /root/.local /home/appuser/.local
ENV PATH=/home/appuser/.local/bin:$PATH
# Set working directory
WORKDIR /app
# Copy application code with correct ownership
COPY --chown=appuser:appgroup . .
# Security configurations
# Drop all capabilities
# Read-only root filesystem
# No new privileges
USER appuser
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8080/health')"
# Use dumb-init as PID 1
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
CMD ["python", "app.py"]
```
```yaml
# Kubernetes Pod Security Standards
# Restricted Pod Security Policy
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
namespace: production
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: myapp:v1.0.0@sha256:abc123... # Use digest
imagePullPolicy: Always
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
resources:
limits:
cpu: "500m"
memory: "512Mi"
ephemeral-storage: "1Gi"
requests:
cpu: "100m"
memory: "128Mi"
ports:
- containerPort: 8080
protocol: TCP
volumeMounts:
- name: tmp
mountPath: /tmp
- name: cache
mountPath: /app/cache
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
volumes:
- name: tmp
emptyDir:
sizeLimit: 100Mi
- name: cache
emptyDir:
sizeLimit: 500Mi
automountServiceAccountToken: false
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: myapp
topologyKey: kubernetes.io/hostname
```
```yaml
# Kyverno Security Policies
# Require non-root containers
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-run-as-non-root
spec:
validationFailureAction: Enforce
background: true
rules:
- name: check-containers
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Containers must run as non-root"
pattern:
spec:
containers:
- securityContext:
runAsNonRoot: true
allowPrivilegeEscalation: false
---
# Require resource limits
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-resource-limits
spec:
validationFailureAction: Enforce
rules:
- name: check-limits
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Resource limits are required"
pattern:
spec:
containers:
- resources:
limits:
memory: "?*"
cpu: "?*"
---
# Require image from approved registries
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restrict-image-registries
spec:
validationFailureAction: Enforce
rules:
- name: validate-registries
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Images must be from approved registries"
pattern:
spec:
containers:
- image: "gcr.io/myproject/* | docker.io/myorg/*"
---
# Require image signatures
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signatures
spec:
validationFailureAction: Enforce
rules:
- name: verify-signature
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "gcr.io/myproject/*"
attestors:
- entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----
```
```yaml
# Falco Runtime Security Rules
# /etc/falco/rules.d/custom-rules.yaml
- rule: Detect Crypto Mining
desc: Detect crypto mining processes
condition: >
spawned_process and
(proc.name in (crypto_mining_binaries) or
proc.cmdline contains "stratum+tcp" or
proc.cmdline contains "xmr" or
proc.cmdline contains "monero")
output: >
Crypto mining detected (user=%user.name container=%container.name
image=%container.image.repository command=%proc.cmdline)
priority: CRITICAL
tags: [crypto, mining]
- rule: Detect Shell in Container
desc: Detect shell spawned in container
condition: >
container and
spawned_process and
shell_procs and
not shell_in_container_allowed
output: >
Shell spawned in container (user=%user.name container=%container.name
image=%container.image.repository shell=%proc.name parent=%proc.pname)
priority: WARNING
tags: [shell, container]
- rule: Sensitive File Access
desc: Detect access to sensitive files
condition: >
open_read and
(fd.name startswith /etc/shadow or
fd.name startswith /etc/passwd or
fd.name startswith /root/.ssh or
fd.name contains id_rsa)
output: >
Sensitive file accessed (user=%user.name file=%fd.name
container=%container.name image=%container.image.repository)
priority: WARNING
tags: [filesystem, sensitive]
- rule: Container Escape Attempt
desc: Detect container escape attempts
condition: >
container and
(evt.type = ptrace or
proc.name = nsenter or
proc.cmdline contains "docker.sock" or
fd.name = /proc/1/ns/*)
output: >
Container escape attempt detected (user=%user.name
container=%container.name command=%proc.cmdline)
priority: CRITICAL
tags: [escape, container]
- rule: Unauthorized Network Connection
desc: Detect outbound connections to suspicious IPs
condition: >
container and
outbound and
not (fd.sip in (allowed_outbound_ips))
output: >
Unauthorized outbound connection (container=%container.name
connection=%fd.name image=%container.image.repository)
priority: WARNING
tags: [network, outbound]
- list: crypto_mining_binaries
items: [xmrig, minerd, cpuminer, cgminer, bfgminer]
- list: shell_procs
items: [bash, sh, zsh, ksh, csh, dash]
- macro: shell_in_container_allowed
condition: >
(container.image.repository = "debug-container" or
k8s.ns.name = "debug")
```
```python
# Container Security Scanner
import subprocess
import json
from dataclasses import dataclass
from typing import List, Dict, Optional
from enum import Enum
import logging
logger = logging.getLogger(__name__)
class Severity(str, Enum):
CRITICAL = "CRITICAL"
HIGH = "HIGH"
MEDIUM = "MEDIUM"
LOW = "LOW"
UNKNOWN = "UNKNOWN"
@dataclass
class Vulnerability:
id: str
package: str
version: str
fixed_version: Optional[str]
severity: Severity
title: str
description: str
@dataclass
class ScanResult:
image: str
vulnerabilities: List[Vulnerability]
passed: bool
summary: Dict[str, int]
class ContainerSecurityScanner:
"""Container security scanning using Trivy."""
def __init__(self, severity_threshold: Severity = Severity.HIGH):
self.severity_threshold = severity_threshold
self.failing_severities = self._get_failing_severities()
def _get_failing_severities(self) -> List[str]:
"""Get severities that should fail the scan."""
severities = [Severity.CRITICAL, Severity.HIGH, Severity.MEDIUM, Severity.LOW]
threshold_index = severities.index(self.severity_threshold)
return [s.value for s in severities[:threshold_index + 1]]
def scan_image(self, image: str) -> ScanResult:
"""Scan container image for vulnerabilities."""
cmd = [
"trivy", "image",
"--format", "json",
"--severity", ",".join(self.failing_severities),
image,
]
result = subprocess.run(
cmd,
capture_output=True,
text=True,
)
scan_data = json.loads(result.stdout)
vulnerabilities = self._parse_vulnerabilities(scan_data)
summary = self._create_summary(vulnerabilities)
passed = not any(
v.severity.value in self.failing_severities
for v in vulnerabilities
)
return ScanResult(
image=image,
vulnerabilities=vulnerabilities,
passed=passed,
summary=summary,
)
def scan_filesystem(self, path: str) -> ScanResult:
"""Scan filesystem for vulnerabilities and misconfigs."""
cmd = [
"trivy", "fs",
"--format", "json",
"--scanners", "vuln,secret,config",
path,
]
result = subprocess.run(cmd, capture_output=True, text=True)
scan_data = json.loads(result.stdout)
return self._parse_fs_scan(scan_data)
def _parse_vulnerabilities(self, data: Dict) -> List[Vulnerability]:
"""Parse Trivy JSON output."""
vulnerabilities = []
for result in data.get("Results", []):
for vuln in result.get("Vulnerabilities", []):
vulnerabilities.append(Vulnerability(
id=vuln["VulnerabilityID"],
package=vuln["PkgName"],
version=vuln["InstalledVersion"],
fixed_version=vuln.get("FixedVersion"),
severity=Severity(vuln["Severity"]),
title=vuln.get("Title", ""),
description=vuln.get("Description", ""),
))
return vulnerabilities
def _create_summary(self, vulns: List[Vulnerability]) -> Dict[str, int]:
"""Create vulnerability summary by severity."""
summary = {s.value: 0 for s in Severity}
for vuln in vulns:
summary[vuln.severity.value] += 1
return summary
def generate_report(self, result: ScanResult) -> str:
"""Generate human-readable report."""
lines = [
f"Security Scan Report: {result.image}",
"=" * 50,
f"Status: {'PASSED' if result.passed else 'FAILED'}",
"",
"Summary:",
]
for severity, count in result.summary.items():
if count > 0:
lines.append(f" {severity}: {count}")
if not result.passed:
lines.extend(["", "Critical/High Vulnerabilities:"])
for vuln in result.vulnerabilities:
if vuln.severity in [Severity.CRITICAL, Severity.HIGH]:
lines.append(
f" - {vuln.id}: {vuln.package} ({vuln.version})"
f" -> {vuln.fixed_version or 'No fix'}"
)
return "\n".join(lines)
```
## Best Practices
### Image Security
- Use minimal base images (distroless, Alpine)
- Scan images in CI/CD pipeline
- Sign images with Cosign/Notary
- Use image digests, not tags
### Runtime Security
- Deploy Falco for behavior monitoring
- Use read-only root filesystems
- Drop all capabilities
- Enable seccomp profiles
### Kubernetes Security
- Enforce Pod Security Standards
- Use Network Policies
- Enable audit logging
- Implement RBAC properly
### Compliance
- Run CIS benchmarks regularly
- Document security controls
- Automate compliance checks
- Monitor for drift
Container security is critical for **Shopify, Datadog, and GitLab** running production Kubernetes.
You implement defense-in-depth container security with scanning, runtime protection, and policy enforcement.
Scanned 9/8/2026
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!