Marketplace container-hadolint
git clone https://github.com/aiskillstore/marketplace
T=$(mktemp -d) && git clone --depth=1 https://github.com/aiskillstore/marketplace "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/agentsecops/container-hadolint" ~/.claude/skills/aiskillstore-marketplace-container-hadolint && rm -rf "$T"
skills/agentsecops/container-hadolint/SKILL.mdDockerfile Security Linting with Hadolint
Overview
Hadolint is a Dockerfile linter that validates container build files against security best practices and the CIS Docker Benchmark. It analyzes Dockerfile instructions to identify misconfigurations, anti-patterns, and security vulnerabilities before images are built and deployed.
Hadolint integrates ShellCheck to validate RUN instructions, ensuring shell commands follow security best practices. With 100+ built-in rules mapped to CIS Docker Benchmark controls, Hadolint provides comprehensive security validation for container images.
Quick Start
Install Hadolint
# macOS via Homebrew brew install hadolint # Linux via binary wget -O /usr/local/bin/hadolint https://github.com/hadolint/hadolint/releases/latest/download/hadolint-Linux-x86_64 chmod +x /usr/local/bin/hadolint # Via Docker docker pull hadolint/hadolint
Scan Dockerfile
# Scan Dockerfile in current directory hadolint Dockerfile # Scan with specific Dockerfile path hadolint path/to/Dockerfile # Using Docker docker run --rm -i hadolint/hadolint < Dockerfile
Generate Report
# JSON output for automation hadolint -f json Dockerfile > hadolint-report.json # GitLab Code Quality format hadolint -f gitlab_codeclimate Dockerfile > hadolint-codeclimate.json # Checkstyle format for CI integration hadolint -f checkstyle Dockerfile > hadolint-checkstyle.xml
Core Workflows
1. Local Development Scanning
Validate Dockerfiles during development:
# Basic scan with colored output hadolint Dockerfile # Scan with specific severity threshold hadolint --failure-threshold error Dockerfile # Show only warnings and errors hadolint --no-color --format tty Dockerfile | grep -E "^(warning|error)" # Verbose output with rule IDs hadolint -t style -t warning -t error Dockerfile
Output Format:
Dockerfile:3 DL3008 warning: Pin versions in apt get install Dockerfile:7 DL3025 error: Use JSON notation for CMD and ENTRYPOINT Dockerfile:12 DL3059 info: Multiple RUN instructions detected
When to use: Developer workstation, pre-commit validation, iterative Dockerfile development.
2. CI/CD Pipeline Integration
Automate Dockerfile validation in build pipelines:
GitHub Actions
name: Hadolint on: [push, pull_request] jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Hadolint Dockerfile uses: hadolint/hadolint-action@v3.1.0 with: dockerfile: Dockerfile failure-threshold: warning format: sarif output-file: hadolint.sarif - name: Upload SARIF to GitHub Security if: always() uses: github/codeql-action/upload-sarif@v2 with: sarif_file: hadolint.sarif
GitLab CI
hadolint: image: hadolint/hadolint:latest-debian stage: lint script: - hadolint -f gitlab_codeclimate Dockerfile > hadolint-report.json artifacts: reports: codequality: hadolint-report.json when: always
When to use: Automated security gates, pull request checks, deployment validation.
3. Configuration Customization
Create
.hadolint.yaml to customize rules:
# .hadolint.yaml failure-threshold: warning ignored: - DL3008 # Allow unpinned apt-get packages (assess risk first) - DL3059 # Allow multiple RUN instructions trustedRegistries: - docker.io/library # Official Docker Hub images - gcr.io/distroless # Google distroless images - registry.access.redhat.com # Red Hat registry override: error: - DL3001 # Enforce: never use yum/dnf/zypper without version pins warning: - DL3015 # Warn: use --no-install-recommends with apt-get info: - DL3059 # Info: multiple RUN instructions reduce layer caching label-schema: maintainer: text org.opencontainers.image.vendor: text org.opencontainers.image.version: semver
Use bundled templates in
assets/:
- Strict security enforcement (CRITICAL/HIGH only)assets/hadolint-strict.yaml
- Balanced validation (recommended)assets/hadolint-balanced.yaml
- Permissive for legacy Dockerfilesassets/hadolint-permissive.yaml
When to use: Reducing false positives, organizational standards, legacy Dockerfile migration.
4. Security-Focused Validation
Enforce critical security rules:
# Only fail on security issues (error severity) hadolint --failure-threshold error Dockerfile # Check specific security rules hadolint --trusted-registry docker.io/library Dockerfile # Scan all Dockerfiles in project find . -name "Dockerfile*" -exec hadolint {} \; # Generate security report with only errors hadolint -f json Dockerfile | jq '.[] | select(.level == "error")'
Critical Security Rules:
- DL3000: Use absolute WORKDIR (prevents directory traversal)
- DL3001: Always use version pinning for package managers
- DL3002: Never switch to root USER in Dockerfile
- DL3020: Use COPY instead of ADD (prevents arbitrary URL fetching)
- DL3025: Use JSON notation for CMD/ENTRYPOINT (prevents shell injection)
See
references/security_rules.md for complete security rule catalog with CIS mappings.
5. Multi-Stage Build Validation
Scan complex multi-stage Dockerfiles:
# Validate all stages hadolint Dockerfile # Stage-specific validation (use custom script) ./scripts/hadolint_multistage.py Dockerfile
Common Multi-Stage Issues:
- Using same user across build and runtime stages
- Copying unnecessary build tools to production image
- Missing security hardening in final stage
- Secrets present in build stage propagating to runtime
When to use: Complex builds, security-hardened images, production containerization.
6. Pre-Commit Hook Integration
Prevent insecure Dockerfiles from being committed:
# Install pre-commit hook using bundled script ./scripts/install_precommit.sh # Or manually create hook cat << 'EOF' > .git/hooks/pre-commit #!/bin/bash for dockerfile in $(git diff --cached --name-only | grep -E 'Dockerfile'); do hadolint --failure-threshold warning "$dockerfile" || exit 1 done EOF chmod +x .git/hooks/pre-commit
When to use: Developer workstations, team onboarding, mandatory security controls.
Security Considerations
Sensitive Data Handling
- Secret Detection: Hadolint flags hardcoded secrets in ENV, ARG, LABEL instructions
- Build Secrets: Use Docker BuildKit secrets (
) instead of ARG for credentialsRUN --mount=type=secret - Multi-Stage Security: Ensure secrets in build stages don't leak to final image
- Image Scanning: Hadolint validates Dockerfile - combine with image scanning (Trivy, Grype) for runtime security
Access Control
- CI/CD Permissions: Hadolint scans require read access to Dockerfile and build context
- Report Storage: Treat scan reports as internal documentation - may reveal security practices
- Trusted Registries: Configure
to enforce approved base image sourcestrustedRegistries
Audit Logging
Log the following for compliance and security auditing:
- Scan execution timestamps and Dockerfile paths
- Rule violations by severity (error, warning, info)
- Suppressed rules and justifications
- Base image registry validation results
- Remediation actions and timeline
Compliance Requirements
- CIS Docker Benchmark 1.6: Hadolint rules map to CIS controls (see
)references/cis_mapping.md- 4.1: Create a user for the container (DL3002)
- 4.6: Add HEALTHCHECK instruction (DL3025)
- 4.7: Do not use update alone in Dockerfile (DL3009)
- 4.9: Use COPY instead of ADD (DL3020)
- OWASP Docker Security: Validates against OWASP container security best practices
- NIST SP 800-190: Application container security guidance
Bundled Resources
Scripts (scripts/
)
scripts/
- Comprehensive scanning with multiple Dockerfiles and output formatshadolint_scan.py
- Multi-stage Dockerfile analysis with stage-specific validationhadolint_multistage.py
- Automated pre-commit hook installationinstall_precommit.sh
- CI/CD integration examples for multiple platformsci_integration.sh
References (references/
)
references/
- Complete Hadolint security rules with CIS Benchmark mappingssecurity_rules.md
- Detailed CIS Docker Benchmark control mappingcis_mapping.md
- Rule-by-rule remediation guidance with secure examplesremediation_guide.md
- ShellCheck rules for RUN instruction validationshellcheck_integration.md
Assets (assets/
)
assets/
- Strict security configurationhadolint-strict.yaml
- Production-ready configuration (recommended)hadolint-balanced.yaml
- Legacy Dockerfile migration configurationhadolint-permissive.yaml
- Complete GitHub Actions workflowgithub-actions.yml
- Complete GitLab CI pipelinegitlab-ci.yml
- Pre-commit framework configurationprecommit-config.yaml
Common Patterns
Pattern 1: Initial Dockerfile Security Audit
First-time security assessment:
# 1. Find all Dockerfiles find . -type f -name "Dockerfile*" > dockerfile-list.txt # 2. Scan all Dockerfiles with JSON output mkdir -p security-reports while read dockerfile; do output_file="security-reports/$(echo $dockerfile | tr '/' '_').json" hadolint -f json "$dockerfile" > "$output_file" 2>&1 done < dockerfile-list.txt # 3. Generate summary report ./scripts/hadolint_scan.py --input-dir . --output summary-report.html # 4. Review critical/high findings cat security-reports/*.json | jq '.[] | select(.level == "error")' > critical-findings.json
Pattern 2: Progressive Remediation
Gradual security hardening:
# Phase 1: Baseline (don't fail builds yet) hadolint --failure-threshold none -f json Dockerfile > baseline.json # Phase 2: Fix critical issues (fail on errors only) hadolint --failure-threshold error Dockerfile # Phase 3: Address warnings hadolint --failure-threshold warning Dockerfile # Phase 4: Full compliance (including style/info) hadolint Dockerfile
Pattern 3: Security-Hardened Production Image
Build security-first container image:
# Example secure Dockerfile following Hadolint best practices # Use specific base image version from trusted registry FROM docker.io/library/node:18.19.0-alpine3.19 # Install packages with version pinning and cleanup RUN apk add --no-cache \ dumb-init=1.2.5-r2 \ && rm -rf /var/cache/apk/* # Create non-root user RUN addgroup -g 1001 -S appuser && \ adduser -S -u 1001 -G appuser appuser # Set working directory WORKDIR /app # Copy application files (use COPY not ADD) COPY --chown=appuser:appuser package*.json ./ COPY --chown=appuser:appuser . . # Install dependencies RUN npm ci --only=production && \ npm cache clean --force # Switch to non-root user USER appuser # Expose port (document only, not security control) EXPOSE 3000 # Add healthcheck HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD node healthcheck.js || exit 1 # Use JSON notation for entrypoint/cmd ENTRYPOINT ["/usr/bin/dumb-init", "--"] CMD ["node", "server.js"]
Validate with Hadolint:
hadolint Dockerfile # Should pass with no errors
Pattern 4: CI/CD with Automated Remediation Suggestions
Provide actionable feedback in pull requests:
# In CI pipeline hadolint -f json Dockerfile > hadolint.json # Generate remediation suggestions ./scripts/hadolint_scan.py \ --input hadolint.json \ --format markdown \ --output pr-comment.md # Post to PR comment (using gh CLI) gh pr comment --body-file pr-comment.md
Integration Points
CI/CD Integration
- GitHub Actions: Native hadolint-action with SARIF support for Security tab
- GitLab CI: GitLab Code Quality format integration
- Jenkins: Checkstyle format for Jenkins Warnings plugin
- CircleCI: Docker-based executor with artifact retention
- Azure Pipelines: Task integration with results publishing
Security Tools Ecosystem
- Image Scanning: Combine with Trivy, Grype, Clair for runtime vulnerability scanning
- Secret Scanning: Integrate with Gitleaks, TruffleHog for comprehensive secret detection
- IaC Security: Chain with Checkov for Kubernetes/Terraform validation
- SBOM Generation: Export findings alongside Syft/Trivy SBOM reports
- Security Dashboards: Export JSON to Grafana, Kibana, Datadog for centralized monitoring
SDLC Integration
- Development: Pre-commit hooks provide immediate feedback
- Code Review: PR checks prevent insecure Dockerfiles from merging
- Testing: Scan test environment Dockerfiles
- Staging: Validation gate before production promotion
- Production: Periodic audits of deployed container configurations
Troubleshooting
Issue: Too Many False Positives
Symptoms: Legitimate patterns flagged (legacy Dockerfiles, specific use cases)
Solution:
# Create .hadolint.yaml ignored: - DL3059 # Multiple RUN instructions (valid for complex builds) # Or use inline ignores # hadolint ignore=DL3008 RUN apt-get update && apt-get install -y curl
Consult
references/remediation_guide.md for rule-specific guidance.
Issue: Base Image Registry Not Trusted
Symptoms: Error about untrusted registry even for legitimate images
Solution:
# Add to .hadolint.yaml trustedRegistries: - mycompany.azurecr.io - gcr.io/my-project - docker.io/library
Issue: ShellCheck Warnings in RUN Instructions
Symptoms: SC2086, SC2046 warnings from ShellCheck integration
Solution:
# Bad: Unquoted variables RUN echo $MY_VAR > file.txt # Good: Quoted variables RUN echo "$MY_VAR" > file.txt # Or disable specific ShellCheck rule # hadolint ignore=DL4006 RUN echo $MY_VAR > file.txt
See
references/shellcheck_integration.md for complete ShellCheck guidance.
Issue: Multi-Stage Build Not Recognized
Symptoms: Errors about missing USER instruction despite proper multi-stage setup
Solution:
# Ensure each stage has appropriate USER FROM node:18 AS builder # Build operations... FROM node:18-alpine AS runtime USER node # Add USER in final stage CMD ["node", "app.js"]
Issue: CI Pipeline Failing on Warnings
Symptoms: Build fails on low-severity issues
Solution:
# Adjust failure threshold in CI hadolint --failure-threshold error Dockerfile # Or configure per-environment if [ "$CI_ENVIRONMENT" == "production" ]; then hadolint --failure-threshold warning Dockerfile else hadolint --failure-threshold error Dockerfile fi
Advanced Configuration
Custom Rule Severity Override
# .hadolint.yaml override: error: - DL3001 # Package versioning is critical - DL3020 # COPY vs ADD is security-critical warning: - DL3059 # Multiple RUN is warning, not info info: - DL3008 # Downgrade apt-get pinning to info for dev images
Inline Suppression
# Suppress single rule for one instruction # hadolint ignore=DL3018 RUN apk add --no-cache curl # Suppress multiple rules # hadolint ignore=DL3003,DL3009 WORKDIR /tmp RUN apt-get update && apt-get install -y wget # Global suppression (use sparingly) # hadolint global ignore=DL3059
Trusted Registry Enforcement
# .hadolint.yaml trustedRegistries: - docker.io/library # Official images only - gcr.io/distroless # Google distroless - cgr.dev/chainguard # Chainguard images # This will error on: # FROM nginx:latest ❌ (docker.io/nginx) # FROM docker.io/library/nginx:latest ✅ (trusted)
Label Schema Validation
# .hadolint.yaml label-schema: maintainer: text org.opencontainers.image.created: rfc3339 org.opencontainers.image.version: semver org.opencontainers.image.vendor: text
Ensures Dockerfile LABELs conform to OCI image specification.