Container Security Scanning Best Practices
· 5 min read
Containers are everywhere, but they can introduce significant security risks. Learn how to scan and secure your container images with Pentora.
Container Security Risks
Containers package applications with all dependencies, which means:
- Vulnerable Base Images: OS packages with known CVEs
- Application Dependencies: Vulnerable libraries (npm, pip, etc.)
- Configuration Issues: Running as root, exposed ports
- Secrets in Images: Hardcoded credentials, API keys
- Supply Chain Attacks: Malicious or compromised images
Scanning Container Images
Basic Image Scan
# Scan local image
pentora scan container nginx:latest
# Scan from registry
pentora scan container docker.io/myorg/myapp:1.0.0
# Scan before pushing
docker build -t myapp:1.0.0 .
pentora scan container myapp:1.0.0 --severity critical,high
docker push myapp:1.0.0
What Pentora Checks
OS Vulnerabilities:
❌ [CRITICAL] CVE-2024-1234 in libssl1.1
Package: libssl1.1 (1.1.1f-1ubuntu2)
Fix: Upgrade to 1.1.1f-1ubuntu2.19
Application Dependencies:
❌ [HIGH] CVE-2024-5678 in express
Package: express@4.16.0
Fix: Upgrade to express@4.18.2
Configuration Issues:
⚠️ [HIGH] Container runs as root
Recommendation: Add USER directive in Dockerfile
❌ [MEDIUM] Port 22 (SSH) exposed
Recommendation: Remove SSH from container
Secrets Detection:
❌ [CRITICAL] AWS Access Key in /app/.env
Location: Layer 8, /app/.env:12
Dockerfile Best Practices
Use Minimal Base Images
# ❌ Bad - Large attack surface
FROM ubuntu:latest
# ✅ Good - Minimal image
FROM alpine:3.18
# ✅ Better - Distroless
FROM gcr.io/distroless/nodejs:18
Run as Non-Root
# ❌ Bad
FROM node:18
COPY . /app
WORKDIR /app
CMD ["node", "server.js"]
# ✅ Good
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN addgroup -S appgroup && \
adduser -S appuser -G appgroup && \
chown -R appuser:appgroup /app
USER appuser
CMD ["node", "server.js"]
Multi-Stage Builds
Reduce image size and attack surface:
# Build stage
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# Production stage
FROM node:18-alpine
WORKDIR /app
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
USER appuser
EXPOSE 3000
CMD ["node", "dist/server.js"]
Pin Versions
# ❌ Bad
FROM node:latest
# ✅ Good
FROM node:18.19.0-alpine3.18
Kubernetes Security
Scan Kubernetes Manifests
# Scan deployment files
pentora scan kubernetes --file deployment.yaml
# Scan entire directory
pentora scan kubernetes --directory ./k8s
Secure Deployment Example
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
template:
spec:
# Pod-level security
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: myapp
image: myapp:1.2.3 # ✅ Specific version
imagePullPolicy: Always
# Container-level security
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: [ALL]
# Resource limits
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
# Health checks
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
readinessProbe:
httpGet:
path: /ready
port: 8080
CI/CD Integration
Scan in GitHub Actions
- name: Build Image
run: docker build -t myapp:${{ github.sha }} .
- name: Scan Container
run: |
pentora scan container myapp:${{ github.sha }} \
--output-format sarif \
--output container.sarif
- name: Upload Results
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: container.sarif
- name: Security Gate
run: |
pentora scan container myapp:${{ github.sha }} \
--max-critical 0 \
--max-high 5 \
--fail-on-threshold
GitLab CI Example
container-scan:
stage: security
image: docker:latest
services:
- docker:dind
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- pentora scan container $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
artifacts:
reports:
container_scanning: pentora-results.json
Registry Scanning
Monitor container registries for vulnerabilities:
# Scan image in registry
pentora scan container registry.example.com/myapp:latest \
--registry-auth $AUTH_TOKEN
# Continuous registry monitoring
pentora registry monitor \
--registry-url registry.example.com \
--namespaces production,staging \
--schedule "0 */6 * * *"
Secrets Management
Detect Secrets
pentora scan container myapp:latest --secrets-scan
Best Practices
# ❌ Bad - Hardcoded
ENV DB_PASSWORD=supersecret123
ENV API_KEY=sk_live_abc123
# ✅ Good - Runtime injection
# Secrets provided via Kubernetes secrets or environment
Using Kubernetes secrets:
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
stringData:
db-password: mysecretpassword
api-key: myapikey
---
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: myapp
envFrom:
- secretRef:
name: app-secrets
Best Practices Summary
- Use Minimal Base Images: Alpine, distroless, or scratch
- Run as Non-Root: Always specify non-root user
- Pin Versions: Never use
:latesttags - Multi-Stage Builds: Reduce final image size
- Scan Regularly: Scan on build and continuously
- No Secrets in Images: Use runtime injection
- Security Contexts: Apply restrictive security policies
- Resource Limits: Define CPU and memory limits
- Read-Only Filesystem: When possible
- Drop Capabilities: Remove unnecessary Linux capabilities
Automated Remediation
Generate fixes automatically:
# Scan with fix suggestions
pentora scan container myapp:latest --suggest-fixes
# Generate updated Dockerfile
pentora scan dockerfile --file Dockerfile --auto-fix
Monitoring and Alerting
Set up continuous monitoring:
# pentora-monitor.yaml
registries:
- url: registry.example.com
namespaces: [production]
schedule: "0 */6 * * *"
alerts:
new_vulnerability:
severity: [critical, high]
notify:
- slack: "#security"
- email: "security@example.com"
pentora daemon --config pentora-monitor.yaml
Conclusion
Container security requires a layered approach: secure base images, secure builds, and continuous monitoring. Pentora helps automate this process throughout the container lifecycle.
Start scanning:
pentora scan container your-image:tag
For more details, visit docs.pentora.ai/container-security
