From security-snyk
Use when fixing Snyk Container vulnerabilities — base image selection, multi-stage builds, package cleanup, non-root user configuration
How this skill is triggered — by the user, by Claude, or both
Slash command
/security-snyk:snyk-container-remediationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Snyk Container scans Docker images for OS-level vulnerabilities in base images and installed packages. This skill provides remediation patterns for reducing image attack surface and vulnerability count.
Snyk Container scans Docker images for OS-level vulnerabilities in base images and installed packages. This skill provides remediation patterns for reducing image attack surface and vulnerability count.
Choose base images in priority order based on your needs:
What: Minimal image with only the application and runtime (no package manager, shell, or unnecessary utilities)
Pros:
Cons:
Examples:
# Node.js distroless
FROM gcr.io/distroless/nodejs20-debian12
# Python distroless
FROM gcr.io/distroless/python3-debian12
# Java distroless
FROM gcr.io/distroless/java17-debian12
# Go distroless
FROM gcr.io/distroless/static-debian12
Use case: Production microservices where debuggability isn't critical
What: Lightweight Linux distribution (~5 MB base) with package manager
Pros:
Cons:
Examples:
# Node.js Alpine
FROM node:20-alpine3.18
# Python Alpine
FROM python:3.12-alpine3.18
# Java Alpine
FROM eclipse-temurin:21-jre-alpine
# Go Alpine
FROM golang:1.21-alpine3.18
Use case: Most microservices and applications
What: Full OS base image with non-essential packages removed
Pros:
Cons:
Examples:
# Node.js Slim
FROM node:20-bookworm-slim
# Python Slim
FROM python:3.12-slim-bookworm
# Java Slim
FROM eclipse-temurin:21-jre-slim-bookworm
Use case: Legacy applications, complex dependencies
What: Complete Linux distribution with all standard packages
Pros:
Cons:
Examples:
# Ubuntu
FROM ubuntu:22.04
# Debian
FROM debian:bookworm
# CentOS
FROM centos:7
Use case: Development, CI/CD workers, legacy apps
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y \
python3 \
curl \
git \
build-essential
COPY app.py .
CMD ["python3", "app.py"]
Issues:
FROM python:3.12-alpine3.18
RUN apk add --no-cache \
curl
COPY app.py .
CMD ["python3", "app.py"]
Improvements:
# Build stage
FROM python:3.12-alpine3.18 AS builder
RUN apk add --no-cache \
gcc \
musl-dev \
libffi-dev
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Runtime stage
FROM python:3.12-alpine3.18
# Copy only built artifacts from builder
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY app.py .
CMD ["python3", "app.py"]
Improvements:
FROM python:3.12-alpine3.18 AS builder
RUN apk add --no-cache \
gcc \
musl-dev
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
FROM gcr.io/distroless/python3-debian12
# Copy only Python packages
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY app.py .
ENTRYPOINT ["python3", "app.py"]
Improvements:
Multi-stage builds eliminate build dependencies from the final image.
# Stage 1: Build
FROM <build-image> AS builder
# Install build tools
RUN apt-get install -y build-essential
# Copy source
COPY . .
# Build application
RUN make build
# Stage 2: Runtime
FROM <runtime-image>
# Copy only build artifacts, not build tools
COPY --from=builder /app/dist /app/dist
CMD ["./app/dist/main"]
JavaScript/Node.js:
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci && npm run build
FROM node:20-alpine
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/index.js"]
Python:
FROM python:3.12-alpine AS builder
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
FROM python:3.12-alpine
COPY --from=builder /root/.local /root/.local
COPY app.py .
ENV PATH=/root/.local/bin:$PATH
CMD ["python", "app.py"]
Java:
FROM eclipse-temurin:21-jdk-alpine AS builder
COPY . /src
WORKDIR /src
RUN ./mvnw clean package
FROM eclipse-temurin:21-jre-alpine
COPY --from=builder /src/target/app.jar .
CMD ["java", "-jar", "app.jar"]
Go:
FROM golang:1.21-alpine AS builder
COPY . /app
WORKDIR /app
RUN go build -o main .
FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/main .
CMD ["./main"]
Only install runtime dependencies, never build tools:
Bad:
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y \
build-essential \
git \
curl \
vim \
python3-dev
Good:
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y \
python3 \
curl \
&& rm -rf /var/lib/apt/lists/*
--no-install-recommendsAvoid recommended packages that aren't needed:
RUN apt-get update && apt-get install -y --no-install-recommends \
python3 \
&& rm -rf /var/lib/apt/lists/*
Remove package manager cache after installation:
For apt (Debian/Ubuntu):
RUN apt-get update && apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
For apk (Alpine):
RUN apk add --no-cache curl
For yum (CentOS/RHEL):
RUN yum install -y curl && yum clean all
Always run application as non-root to limit damage from compromises:
# Create non-root user
RUN addgroup -g 1000 app && adduser -D -u 1000 -G app app
# Set ownership
COPY --chown=app:app app.py .
# Switch to non-root user
USER app
CMD ["python3", "app.py"]
For Alpine:
RUN addgroup -g 1000 app && adduser -D -u 1000 -G app app
USER app
For Debian/Ubuntu:
RUN groupadd -g 1000 app && useradd -m -u 1000 -g app app
USER app
After changes, verify vulnerabilities are reduced:
# Scan base image
snyk container test node:20-alpine
# Scan built image
docker build -t myapp:1.0.0 .
snyk container test myapp:1.0.0 --json > results.json
# Get base image recommendations
snyk container test myapp:1.0.0 --file=Dockerfile
# Stage 1: Builder
FROM node:20-alpine3.18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci && npm run build
# Stage 2: Runtime
FROM node:20-alpine3.18
RUN addgroup -g 1000 app && adduser -D -u 1000 -G app app
WORKDIR /app
COPY --from=builder --chown=app:app /app/dist ./dist
COPY --from=builder --chown=app:app /app/node_modules ./node_modules
COPY --chown=app:app package.json ./
USER app
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node -e "require('http').get('http://localhost:3000/health', (r) => {if (r.statusCode !== 200) throw new Error(r.statusCode)})"
CMD ["node", "dist/index.js"]
After container remediation:
docker images myappdocker run myapp whoamisnyk container testdocker run myappnpx claudepluginhub gagandeepp/software-agent-teams --plugin security-snykGuides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Enforces test-driven development: write failing test first, then minimal code to pass. Use when implementing features or bugfixes.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.