Skip to content
Back to skills

Minimal

BSecurity

Reduce what a container can do and what it contains, so that code execution inside it yields as little as possible.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 10, 2026
securitypythonshellbashnodedockerkubernetesgitapisecurity

Works with

  • api

Security analysis

B84/100
  • criticalAccesses sensitive system or user directories
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned September 10, 2026

npx -y skills add snoodleboot-io/prompticorn --skill minimal --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Minimal?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Minimal
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/snoodleboot-io-minimal-d6b3bda1/badge)](https://www.skillsdirectory.com/skills/snoodleboot-io-minimal-d6b3bda1)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# Container Security Hardening (Minimal)

## Purpose
Reduce what a container can do and what it contains, so that code execution inside it yields as little as possible.

## Core Techniques

### 1. Shrink the Image and Drop Root
```dockerfile
# ❌ Before — full OS, root, build tooling baked in
FROM python:3.12
COPY . /app
RUN pip install -r /app/requirements.txt
CMD ["python", "/app/main.py"]
```
```dockerfile
# ✅ After — multi-stage, non-root, minimal runtime
FROM python:3.12-slim AS build
WORKDIR /app
COPY requirements.txt .
RUN pip install --prefix=/install --no-cache-dir -r requirements.txt

FROM python:3.12-slim
RUN useradd --uid 10001 --no-create-home --shell /usr/sbin/nologin app
COPY --from=build /install /usr/local
COPY --chown=10001:10001 . /app
USER 10001
WORKDIR /app
CMD ["python", "main.py"]
```
The build stage keeps compilers, headers, and package caches out of the shipped image. A numeric `USER` matters: Kubernetes `runAsNonRoot` validates the numeric UID and cannot resolve a username at admission time.

### 2. Never Put Secrets in a Layer
```dockerfile
# ❌ The token is in the layer forever — ENV and later RUN rm do not remove it
ARG NPM_TOKEN
RUN echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > .npmrc && npm ci

# ✅ BuildKit secret mount — never written to any layer
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ci
```
Build with `docker build --secret id=npmrc,src=$HOME/.npmrc .`, and audit what actually shipped with `docker history --no-trunc myapp:1.4.2`.

### 3. Pin Base Images by Digest
`FROM python:3.12-slim` resolves to a different image over time; `FROM node:latest` is unreproducible by construction. You cannot say what shipped, cannot reproduce a build, and a rollback may not restore the bits you had.

```dockerfile
FROM python:3.12-slim@sha256:<digest>   # immutable; renovate bots can bump it
```

### 4. Constrain the Runtime
```yaml
securityContext:                 # pod level
  runAsNonRoot: true
  runAsUser: 10001
  fsGroup: 10001
  seccompProfile: {type: RuntimeDefault}
containers:
  - name: api
    image: registry.example.com/api@sha256:<digest>
    securityContext:             # container level
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities: {drop: ["ALL"]}
    volumeMounts:
      - {name: tmp, mountPath: /tmp}
volumes:
  - name: tmp
    emptyDir: {}
```
`allowPrivilegeEscalation: false` sets `no_new_privs`, blocking setuid binaries from gaining privilege. `drop: ["ALL"]` removes even the default set — most apps need none; a listener on a port below 1024 needs `NET_BIND_SERVICE`, or better, just listen on 8080.

### 5. Scan in CI and Again on a Schedule
```bash
trivy image --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 myapp:$SHA
```
Gate the build on reachable Critical/High, and re-scan running images nightly — a CVE published after your last deploy is invisible to a build-time-only scan. Triage the output with the vulnerability-assessment skill; do not fail builds on unfixable findings.

## Warning Signs

- No `USER` in the Dockerfile, or a username instead of a numeric UID
- `FROM ...:latest` or any unpinned tag in a production image
- `docker history` shows tokens, `.git`, `.env`, or SSH keys in a layer
- Containers running with `privileged: true` or the default capability set
- `readOnlyRootFilesystem` unset, so an attacker can drop a binary anywhere
- Compilers, `curl`, and a package manager present in the runtime image
- Secrets injected as env vars readable via `/proc/1/environ` or a crash dump
- Namespaces without a Pod Security Admission label, so anything can be scheduled
- Image scanning only at build time, never against what is actually running

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…