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