Skip to content

DockHound

Container security starts at the file, not the cluster.

DockHound sniffs out risky misconfigurations in Dockerfiles, Docker Compose files and Kubernetes manifests before they reach production. Aligned with Snyk and CIS benchmarks: no cloud credentials, no network calls, just fast local static analysis.

View on GitHub


Features

  • Three scanners in one: Dockerfile, Docker Compose, and Kubernetes manifests
  • Benchmark-aligned checks: coverage modeled after Snyk and CIS benchmarks
  • Severity-graded output: HIGH / MEDIUM / LOW with color coding
  • CI/CD ready: predictable exit codes designed for pipeline gates
  • Auto-detection: identifies file type automatically with scan
  • Minimal footprint: depends only on click and pyyaml

Installation

# From source
pip install -e .

# Or install dependencies directly
pip install -r requirements.txt

Usage

# Scan a Dockerfile
dockhound docker ./Dockerfile

# Scan a Docker Compose file
dockhound compose ./docker-compose.yaml

# Scan Kubernetes manifests (file or entire directory)
dockhound k8s ./manifests/

# Let DockHound detect the file type
dockhound scan ./path/to/file

Security Checks

Dockerfile

Check Severity What it catches
Runs as root HIGH USER root or USER 0 directive
Unpinned images MEDIUM FROM with :latest or no tag
Hardcoded secrets HIGH ENV/ARG containing PASSWORD, SECRET, API_KEY, TOKEN
Risky ADD usage LOW Using ADD instead of COPY for local files
Curl pipe to shell HIGH Downloading and executing scripts inline

Docker Compose

Check Severity What it catches
Privileged mode HIGH privileged: true on any service
Docker socket mount HIGH Mounting /var/run/docker.sock
Hardcoded secrets HIGH Sensitive keys in environment variables
Host network / PID HIGH / MEDIUM Using host network or PID namespace
Exposed ports MEDIUM Services bound to 0.0.0.0
Unpinned images MEDIUM Image uses :latest or no tag
Missing resource limits LOW No deploy.resources.limits defined

Kubernetes

Check Severity What it catches
Privileged container HIGH securityContext.privileged: true
Runs as root HIGH Missing or false runAsNonRoot
Overly permissive RBAC HIGH Wildcard * in resources or verbs
Privilege escalation MEDIUM Missing allowPrivilegeEscalation: false
Capabilities not dropped MEDIUM Not dropping ALL capabilities
Ingress without TLS MEDIUM No spec.tls configured
Unpinned images MEDIUM Image uses :latest or no tag
Writable root filesystem LOW readOnlyRootFilesystem not set
Missing probes LOW No liveness / readiness probes
Missing resource limits LOW No CPU or memory limits
Outdated image policy LOW imagePullPolicy not set to Always
UID clash risk LOW runAsUser below 10000

CI/CD Integration

GitHub Actions

name: Container Security Scan
on: [push, pull_request]

jobs:
  dockhound:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - run: pip install click pyyaml
      - run: python -m dockhound.cli k8s ./manifests/

GitLab CI

dockhound:
  image: python:3.12-slim
  script:
    - pip install click pyyaml
    - python -m dockhound.cli scan ./

Exit Codes

Code Meaning
0 No issues, or only LOW severity
1 HIGH severity issues found — pipeline should fail
2 Tool error (invalid file type, parse failure)

Requirements

  • Python 3.9+
  • Dependencies: click, pyyaml

Project Structure

dockhound/
├── cli.py
└── scanners/
    ├── dockerfile_scanner.py
    ├── compose_scanner.py
    └── k8s_scanner.py
examples/
tests/

MIT License — Copyright © 2026 Skellman.io