Skip to content

cr0hn/dockerfile-security

Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Repository files navigation

dockerfile-sec logo

dockerfile-sec

A fast, rule-based security scanner for Dockerfiles

Detect misconfigurations, exposed credentials, and security anti-patterns before they reach production.

CI/CD Go Report Card Go Version License Docker Latest Release GitHub Marketplace

Quick StartInstallationGitHub ActionUsageRulesCustom RulesContributing


Table of Contents


Why dockerfile-sec?

Dockerfiles can contain security issues that are easy to miss during code reviews:

  • Hardcoded credentials - Passwords, API keys, and tokens accidentally committed
  • Running as root - Missing USER directive leads to container privilege escalation
  • Insecure base images - Using latest tag or images without SHA256 verification
  • Exposed secrets in build args - Sensitive data passed via ARG instead of secrets
  • Recursive copies - COPY . . accidentally including .env files and credentials

dockerfile-sec catches these issues automatically, integrating seamlessly into your development workflow and CI/CD pipelines.


Features

Feature Description
35 Built-in Rules Comprehensive coverage of security best practices and credential detection
Blazing Fast Written in Go for maximum performance on large codebases
Flexible Output ASCII tables for humans, JSON for machines and automation
CI/CD Ready Exit codes and quiet mode for seamless pipeline integration
Extensible Load custom rules from local files or remote URLs
Zero Dependencies Single static binary, no runtime required
Docker Support Available as a minimal container image
Cross-Platform Linux, macOS, and Windows support (amd64/arm64)

Quick Start

# Download the binary (Linux/amd64)
curl -L https://github.com/cr0hn/dockerfile-security/releases/latest/download/dockerfile-sec-linux-amd64 -o dockerfile-sec
chmod +x dockerfile-sec

# Scan a Dockerfile
./dockerfile-sec Dockerfile

# Scan with exit code for CI/CD (exits 1 if issues found)
./dockerfile-sec -E Dockerfile

Example output:

+----------+-------------------------------------------+----------+
| Rule Id  | Description                               | Severity |
+----------+-------------------------------------------+----------+
| core-002 | Posible text plain password in dockerfile | High     |
| core-003 | Recursive copy found                      | Medium   |
| core-005 | Use image tag instead of SHA256 hash      | Medium   |
| cred-001 | Generic credential                        | Medium   |
+----------+-------------------------------------------+----------+

Installation

Binary

Download the latest release for your platform from the releases page.

Platform Architecture Download
Linux amd64 dockerfile-sec-linux-amd64
Linux arm64 dockerfile-sec-linux-arm64
macOS amd64 dockerfile-sec-darwin-amd64
macOS arm64 (M1/M2) dockerfile-sec-darwin-arm64
Windows amd64 dockerfile-sec-windows-amd64.exe

Docker

# Using GitHub Container Registry
docker pull ghcr.io/cr0hn/dockerfile-security:latest

# Scan a Dockerfile via stdin
cat Dockerfile | docker run --rm -i ghcr.io/cr0hn/dockerfile-security

# Scan a local file (mount as volume)
docker run --rm -v $(pwd):/app ghcr.io/cr0hn/dockerfile-security /app/Dockerfile

From Source

Requires Go 1.22 or later.

# Install directly
go install github.com/cr0hn/dockerfile-security/cmd/dockerfile-sec@latest

# Or build manually
git clone https://github.com/cr0hn/dockerfile-security.git
cd dockerfile-security
make build

Using as GitHub Action

You can use dockerfile-sec directly in your GitHub Actions workflows without manual installation.

Basic Usage

name: Dockerfile Security Scan

on: [push, pull_request]

jobs:
  security-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Scan Dockerfile
        uses: cr0hn/dockerfile-security@v0.2.0
        with:
          dockerfile: 'Dockerfile'

Advanced Usage

name: Advanced Dockerfile Security Scan

on: [push, pull_request]

jobs:
  security-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Scan with custom settings
        id: scan
        uses: cr0hn/dockerfile-security@v0.2.0
        with:
          dockerfile: 'docker/Dockerfile.prod'
          categories: 'core,credentials,security'
          ignore-rules: 'core-001'
          output-file: 'security-results.json'
          fail-on-issues: true

      - name: Upload results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: security-scan-results
          path: security-results.json

      - name: Comment on PR
        if: github.event_name == 'pull_request' && failure()
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const results = JSON.parse(fs.readFileSync('security-results.json', 'utf8'));
            const comment = `## 🔒 Dockerfile Security Scan Results\n\n` +
              `Found ${results.length} security issues:\n\n` +
              results.map(i => `- **${i.id}**: ${i.description} (${i.severity})`).join('\n');

            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: comment
            });

Action Inputs

Input Description Required Default
dockerfile Path to Dockerfile to analyze No Dockerfile
categories Rule categories (comma-separated): all, core, credentials, security, packages, configuration No all
ignore-rules Comma-separated rule IDs to ignore No ''
ignore-file Path to ignore file No ''
custom-rules Path to custom rules YAML file or URL No ''
output-format Output format: table, json No table
output-file Path to save JSON output No ''
fail-on-issues Exit with code 1 if issues found No true
quiet Quiet mode (suppress output) No false
version Version of dockerfile-sec to use No latest

Action Outputs

Output Description
issues-found Number of security issues found
exit-code Exit code of the scan (0=success, 1=issues)

Examples

Scan Multiple Dockerfiles

jobs:
  scan-all:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        dockerfile:
          - Dockerfile
          - docker/Dockerfile.dev
          - docker/Dockerfile.prod
    steps:
      - uses: actions/checkout@v4

      - name: Scan ${{ matrix.dockerfile }}
        uses: cr0hn/dockerfile-security@v0.2.0
        with:
          dockerfile: ${{ matrix.dockerfile }}

Only Scan Credentials

- name: Credential Scan Only
  uses: cr0hn/dockerfile-security@v0.2.0
  with:
    dockerfile: 'Dockerfile'
    categories: 'credentials'

Use Custom Rules

- name: Scan with Custom Rules
  uses: cr0hn/dockerfile-security@v0.2.0
  with:
    dockerfile: 'Dockerfile'
    custom-rules: '.github/dockerfile-rules.yaml'

Usage

Basic Analysis

# Scan a Dockerfile (outputs ASCII table in terminal, JSON when piped)
dockerfile-sec Dockerfile

# Read from stdin
cat Dockerfile | dockerfile-sec

# Quiet mode with exit code for scripts
if dockerfile-sec -E -q Dockerfile; then
  echo "No security issues found"
else
  echo "Security issues detected!"
  exit 1
fi

Using Docker

The Docker image is available at ghcr.io/cr0hn/dockerfile-security.

Basic usage:

# Scan a Dockerfile via stdin
cat Dockerfile | docker run --rm -i ghcr.io/cr0hn/dockerfile-security

# Scan a local file (mount current directory)
docker run --rm -v $(pwd):/workspace ghcr.io/cr0hn/dockerfile-security /workspace/Dockerfile

# Scan with exit code for CI/CD
docker run --rm -v $(pwd):/workspace ghcr.io/cr0hn/dockerfile-security -E /workspace/Dockerfile

Advanced usage:

# Use a specific version
docker run --rm -i ghcr.io/cr0hn/dockerfile-security:v1.0.0

# With custom rules (mount rules file)
docker run --rm -i \
  -v $(pwd)/Dockerfile:/Dockerfile \
  -v $(pwd)/custom-rules.yaml:/rules.yaml \
  ghcr.io/cr0hn/dockerfile-security -r /rules.yaml /Dockerfile

# Output JSON to a file
docker run --rm -v $(pwd):/workspace ghcr.io/cr0hn/dockerfile-security \
  -o /workspace/results.json /workspace/Dockerfile

# Ignore specific rules
docker run --rm -v $(pwd):/workspace ghcr.io/cr0hn/dockerfile-security \
  -i core-001 -i core-004 /workspace/Dockerfile

# Only credential rules
docker run --rm -v $(pwd):/workspace ghcr.io/cr0hn/dockerfile-security \
  -R credentials /workspace/Dockerfile

Docker Compose integration:

# docker-compose.yml
services:
  dockerfile-sec:
    image: ghcr.io/cr0hn/dockerfile-security:latest
    volumes:
      - ./Dockerfile:/Dockerfile:ro
    command: ["-E", "/Dockerfile"]

Shell alias for convenience:

# Add to ~/.bashrc or ~/.zshrc
alias dockerfile-sec='docker run --rm -i -v $(pwd):/workspace ghcr.io/cr0hn/dockerfile-security'

# Usage
dockerfile-sec /workspace/Dockerfile
dockerfile-sec -E /workspace/Dockerfile

Pipeline Integration

dockerfile-sec works seamlessly in UNIX pipelines:

# Chain with jq for JSON processing
cat Dockerfile | dockerfile-sec | jq '.[] | select(.severity == "High")'

# Process multiple Dockerfiles
find . -name "Dockerfile*" -exec dockerfile-sec -E {} \;

CI/CD Integration

GitHub Actions

name: Security Scan

on: [push, pull_request]

jobs:
  dockerfile-security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Scan Dockerfile
        run: |
          curl -sL https://github.com/cr0hn/dockerfile-security/releases/latest/download/dockerfile-sec-linux-amd64 -o dockerfile-sec
          chmod +x dockerfile-sec
          ./dockerfile-sec -E Dockerfile

GitLab CI

dockerfile-security:
  image: ghcr.io/cr0hn/dockerfile-security:latest
  script:
    - dockerfile-sec -E Dockerfile
  rules:
    - changes:
        - Dockerfile
        - "*.dockerfile"

Jenkins

pipeline {
    agent any
    stages {
        stage('Dockerfile Security') {
            steps {
                sh '''
                    curl -sL https://github.com/cr0hn/dockerfile-security/releases/latest/download/dockerfile-sec-linux-amd64 -o dockerfile-sec
                    chmod +x dockerfile-sec
                    ./dockerfile-sec -E Dockerfile
                '''
            }
        }
    }
}

Configuration

Rule Sets

Control which built-in rules are loaded:

# All rules (default)
dockerfile-sec Dockerfile

# Core rules only (best practices)
dockerfile-sec -R core Dockerfile

# Credential detection rules only
dockerfile-sec -R credentials Dockerfile

# Security rules only
dockerfile-sec -R security Dockerfile

# Package management rules only
dockerfile-sec -R packages Dockerfile

# Configuration rules only
dockerfile-sec -R configuration Dockerfile

# Combine multiple categories (comma-separated)
dockerfile-sec -R core,security Dockerfile
dockerfile-sec -R credentials,security,packages Dockerfile

# Disable built-in rules (use with -r for custom rules only)
dockerfile-sec -R none -r my-rules.yaml Dockerfile

Output Formats

# ASCII table (default in terminal)
dockerfile-sec Dockerfile

# JSON output (automatic when piped, or explicit with -o)
dockerfile-sec Dockerfile | cat
dockerfile-sec -o results.json Dockerfile

# Quiet mode (no output, useful with -E for CI/CD)
dockerfile-sec -q -E Dockerfile

JSON Output Format:

[
  {
    "id": "core-002",
    "description": "Posible text plain password in dockerfile",
    "reference": "https://snyk.io/blog/10-docker-image-security-best-practices/",
    "severity": "High"
  }
]

Ignoring Rules

By rule ID (CLI):

# Ignore single rule
dockerfile-sec -i core-001 Dockerfile

# Ignore multiple rules
dockerfile-sec -i core-001 -i core-007 Dockerfile

By ignore file:

Create a file with rule IDs to ignore (one per line):

# .dockerfile-sec-ignore
# Ignore USER requirement for this project
core-001

# We use ADD intentionally for tar extraction
core-004
dockerfile-sec -F .dockerfile-sec-ignore Dockerfile

External Rules

Load custom rules from files or URLs:

# From local file
dockerfile-sec -r my-rules.yaml Dockerfile

# From URL
dockerfile-sec -r https://example.com/rules.yaml Dockerfile

# Combine with built-in rules
dockerfile-sec -r my-rules.yaml Dockerfile

# Use only external rules
dockerfile-sec -R none -r my-rules.yaml Dockerfile

Built-in Rules

dockerfile-sec includes 35 built-in rules across 5 categories:

Core Rules (10 rules)

Best practices and security guidelines for Dockerfiles.

ID Description Severity
core-001 Missing USER sentence (running as root) High
core-002 Possible plaintext password in Dockerfile High
core-003 Recursive copy found (COPY . .) Medium
core-004 Use of ADD instead of COPY Low
core-005 Use image tag instead of SHA256 hash Medium
core-006 Use of latest tag in FROM Medium
core-007 Use of deprecated MAINTAINER Low
core-008 Use of --insecurity=insecure in RUN High
core-009 Secrets passed via ARG instead of ENV High
core-010 HEALTHCHECK contains sensitive information High

Credential Rules (11 rules)

Detection of exposed secrets and credentials.

ID Description Severity
cred-001 Generic credential patterns Medium
cred-002 AWS Access Key ID High
cred-003 AWS MWS Key High
cred-004 EC Private Key High
cred-005 Google API Key High
cred-006 Slack Webhook URL High
cred-007 GitHub Personal Access Token Critical
cred-008 RSA Private Key Critical
cred-009 OpenAI API Key High
cred-010 Stripe API Key Critical
cred-011 Docker Registry Authentication Token High

Security Rules (7 rules)

Advanced security checks for container security.

ID Description Severity
sec-001 Docker socket mounted in container (container escape) Critical
sec-002 WORKDIR pointing to system directories or root Medium
sec-003 chmod 777 or dangerous permissions High
sec-004 Use of sudo in RUN commands Medium
sec-005 BuildKit secret mount without cleanup High
sec-006 Setting SUID/SGID bits on binaries High
sec-007 ENV directive with embedded credentials High

Package Rules (4 rules)

Package manager best practices and security.

ID Description Severity
pkg-001 apt-get without cleanup Medium
pkg-002 pip install without --no-cache-dir Low
pkg-003 npm install without cache cleanup Low
pkg-004 Piping curl/wget to bash High

Configuration Rules (3 rules)

Container runtime configuration issues.

ID Description Severity
cfg-001 Using --privileged flag Critical
cfg-002 Exposing dangerous ports (22, 23, 3389, etc.) Medium
cfg-003 Non-standard STOPSIGNAL defined Low

Creating Custom Rules

Rule Format

Rules are defined in YAML format. Each rule requires:

Field Type Required Description
id string Yes Unique identifier (e.g., custom-001)
description string Yes Human-readable description
regex string Yes Regular expression pattern to match
reference string Yes URL with more information
severity string Yes Low, Medium, or High

Rule Examples

custom-rules.yaml:

# Detect hardcoded IP addresses
- id: custom-001
  description: Hardcoded IP address found
  regex: '(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'
  reference: https://example.com/security-guidelines
  severity: Medium

# Detect curl without certificate verification
- id: custom-002
  description: Use of curl without certificate verification
  regex: '(curl.*-k|curl.*--insecure)'
  reference: https://example.com/security-guidelines
  severity: High

# Detect wget without certificate verification
- id: custom-003
  description: Use of wget without certificate verification
  regex: '(wget.*--no-check-certificate)'
  reference: https://example.com/security-guidelines
  severity: High

# Detect EXPOSE directive
- id: custom-004
  description: EXPOSE directive detected - verify port is necessary
  regex: '^(EXPOSE[\s]+[\d]+)'
  reference: https://docs.docker.com/reference/dockerfile/#expose
  severity: Low

Using custom rules:

# Add to built-in rules
dockerfile-sec -r custom-rules.yaml Dockerfile

# Replace built-in rules entirely
dockerfile-sec -R none -r custom-rules.yaml Dockerfile

# Multiple rule files
dockerfile-sec -r rules1.yaml -r rules2.yaml Dockerfile

Regex Tips

Tip Example
Match at line start ^FROM
Case-insensitive (?i)password
Match any character .
Match literal dot \.
Match word boundary \b
Non-greedy match .*?

Test your regex at regex101.com (select Go flavor).


CLI Reference

Usage: dockerfile-sec [OPTIONS] [DOCKERFILE]

Analyze a Dockerfile for security issues.

Arguments:
  DOCKERFILE    Path to Dockerfile (reads from stdin if not provided)

Options:
  -E            Exit with code 1 if issues are found (for CI/CD)
  -F file       Ignore file containing rule IDs to skip (repeatable)
  -R selection  Built-in rules: all, core, credentials, security, packages, configuration, none (comma-separated, default: all)
  -i id         Ignore specific rule ID (repeatable)
  -o file       Write JSON output to file
  -q            Quiet mode (suppress stdout output)
  -r file       External rules file or URL (repeatable)
  -h, --help    Show help message
  -v, --version Show version information

Exit Codes:
  0             Success (no issues found, or -E not specified)
  1             Issues found (only when -E is specified)
  2             Error (invalid arguments, file not found, etc.)

Contributing

We welcome contributions! Please see our Contributing Guide for details on:

  • Setting up the development environment
  • Code style guidelines
  • How to submit pull requests
  • Adding new security rules

Before contributing, please read our Code of Conduct.

Quick Start for Contributors

# Clone the repository
git clone https://github.com/cr0hn/dockerfile-security.git
cd dockerfile-security

# Run tests
make test

# Run linter
make lint

# Build
make build

Security

For information about reporting security vulnerabilities, please see our Security Policy.

Please do not report security vulnerabilities through public GitHub issues.


License

This project is licensed under the BSD 3-Clause License - see the LICENSE file for details.

BSD 3-Clause License

Copyright (c) 2020-2025, Daniel Garcia (cr0hn)
All rights reserved.

Acknowledgments


References


Related Projects

You might also be interested in dockerscan - A Docker image security analyzer that complements dockerfile-sec by scanning built Docker images for vulnerabilities, malware, and security issues.


Made with ❤️ by Daniel Garcia (cr0hn)

⭐ Star us on GitHub

About

Static security checker for Dockerfiles

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors