Back to BlogEngineering

Docker Security Rules: Detect 47 Container Vulnerabilities & Misconfigurations [2025]

Shivasurya
Shivasurya
Core Maintainer

Docker security rules are essential for detecting container misconfigurations, privilege escalations, and critical vulnerabilities in Dockerfile and docker-compose.yml files. Code Pathfinder v1.1.1 ships with 47 comprehensive security rules (37 Dockerfile + 10 Docker Compose) that catch issues like Docker socket exposure, root containers, and secret leaks before they reach production.

Why Container Security Matters in the AI Code Generation Era

With AI-powered tools like Claude Code, Windsurf, and GitHub Copilot generating thousands of lines of code in seconds, writing code has become commoditized. Developers can scaffold entire applications, write boilerplate, and implement features at unprecedented speed. The bottleneck has shifted from writing code to reviewing, understanding, and securing code at scale.

Traditional static analysis tools struggle with this new reality. They're designed for human-written code patterns, not AI-generated codebases that mix languages, frameworks, and infrastructure-as-code in the same repository. When your codebase contains Go microservices, Dockerfiles, docker-compose configurations, dependency manifests, and CI pipelines all working together, you need a different approach.

Wait, but aren't Code Pathfinder rules also written by humans? Yes, but here's the key difference: traditional linters hardcode language-specific patterns into their implementation. A Python security linter can't query your Dockerfile. A Dockerfile linter can't trace data flow from your application code. Each tool operates in isolation with brittle regex or AST pattern matching that breaks when code structure changes slightly.

Code Pathfinder flips this model. Rules are written as composable, language-agnostic queries over your codebase's semantic structure. Instead of "find lines matching this regex in Python files," you write "find data flows from HTTP request parameters to shell execution, regardless of whether it happens in Python, the Dockerfile ENTRYPOINT, or docker-compose command overrides." The same query engine works across all languages because code is indexed as structured data, not text files.

This is what I crave as a security engineer: being able to express complex security invariants precisely instead of chaining together brittle grep commands and hoping they catch edge cases. When you're hunting for vulnerabilities or tracking down CVEs, naive regex doesn't cut it. You need to understand control flow, data propagation, and cross-file dependencies.

Code Pathfinder indexes your entire codebase as structured, queryable data. Your code isn't just text to pattern-match. It's parsed into an abstract syntax tree (AST), control flow graph (CFG), and data flow graph (DFG) that you can query like a database. Instead of running separate linters for each language, you write deterministic, cross-language queries that express security invariants across your entire stack:

  • Query Go code and Dockerfile commands in a single rule (e.g., "Find Go apps using os.Setuid(0) that also expose privileged ports in Docker")
  • Cross-reference code and dependency versions (e.g., "Detect Log4j 2.x usage in Java code where docker-compose.yml exposes JMX ports")
  • Trace data flows across language boundaries (e.g., "User input from Python Flask → shell command in Docker ENTRYPOINT")

This language-agnostic querying is critical for CVE detection and vulnerability research. When a new supply chain vulnerability drops, you don't just need to find the dependency. You need to understand how it's used, what privileges it runs with, and what attack surface it exposes.

That's why Code Pathfinder v1.1.1 includes 47 container security rules as a foundation. These rules demonstrate how to query infrastructure-as-code with the same precision you'd query application code, catching privilege escalations, socket exposures, and misconfigurations before they reach production.

What I'm Shipping

Code Pathfinder v1.1.1 includes comprehensive container security analysis:

37 Dockerfile Rules covering:

  • Container Security (4 rules): Privilege escalation, socket exposure, secrets leakage
  • Best Practices (28 rules): Image optimization, cache management, reproducible builds
  • Correctness (3 rules): Build failures, syntax errors, invalid configurations
  • Audit (2 rules): Supply chain security, base image pinning

10 Docker Compose Rules covering:

  • Compose Security (10 rules): Privileged containers, capability management, isolation violations

Every rule includes:

  • CWE mappings for compliance tracking
  • Severity ratings (CRITICAL, HIGH, MEDIUM, LOW)
  • Attack scenarios explaining real-world impact
  • Secure alternatives with code examples

The Critical Security Issues It Catches

Docker Socket Exposure (CRITICAL)

This is the #1 container escape vector. OWASP's Docker Security Cheat Sheet explicitly warns that exposing the Docker daemon socket is equivalent to granting root on the host. When you mount /var/run/docker.sock into a container, you're giving it full control over the host Docker daemon with unrestricted access. Security researchers at Quarkslab and Dreamlab have documented detailed attack chains showing how this leads to complete host compromise.

Vulnerable Code:

FROM docker:latest

# CRITICAL: Exposes Docker socket as volume
VOLUME ["/var/run/docker.sock"]
CMD ["docker", "ps"]

Attack Chain:

# Step 1: Attacker gains shell in container
# Step 2: Create privileged container mounting host root
docker run -it -v /:/host --privileged alpine /bin/sh

# Step 3: Chroot into host filesystem
chroot /host /bin/bash

# Step 4: Now has root access - install backdoor
echo "* * * * * root /tmp/backdoor.sh" >> /etc/crontab

Code Pathfinder detects this instantly:

@dockerfile_rule(
id="DOCKER-SEC-006",
severity="CRITICAL",
cwe="CWE-250"
)
def docker_socket_in_volume():
"""Detects Docker socket mounted as volume."""
return any_of(
    instruction(
        type="VOLUME",
        contains="/var/run/docker.sock"
    ),
    instruction(
        type="VOLUME",
        contains="/run/docker.sock"
    )
)

Containers Running as Root (HIGH)

Missing USER instructions mean containers run with UID 0 (root). If an attacker compromises the container, they have root privileges, both inside and potentially outside the container.

Vulnerable Code:

FROM node:18

# Missing USER instruction - runs as root!
WORKDIR /app
COPY . .
CMD ["node", "server.js"]

Secure Alternative:

FROM node:18

WORKDIR /app
COPY . .

# Add non-root user
RUN useradd -m -u 1000 appuser && \
chown -R appuser:appuser /app

USER appuser  # Switch to non-root user
CMD ["node", "server.js"]

Secrets in Build Arguments (CRITICAL)

ARG instructions are visible in docker history. Passing secrets via build args leaks them into every layer of the image.

Vulnerable Code:

FROM python:3.11

# CRITICAL: Secret visible in image history
ARG DATABASE_PASSWORD
ENV DB_PASS=${DATABASE_PASSWORD}

RUN pip install psycopg2

What attackers see:

$ docker history myimage:latest
IMAGE          CREATED BY
abc123         ARG DATABASE_PASSWORD=prod_db_p@ssw0rd!  # Exposed!

Secure Alternative:

FROM python:3.11

# Use secrets mount (BuildKit)
RUN --mount=type=secret,id=db_password \
export DB_PASS=$(cat /run/secrets/db_password) && \
pip install psycopg2

Privileged Containers in Docker Compose (CRITICAL)

Setting privileged: true disables all container isolation. It's equivalent to running code directly on the host with root privileges.

Vulnerable Code:

version: '3'
services:
  app:
image: myapp
privileged: true  # CRITICAL: Disables all isolation!

Attack Impact:

  • Access raw devices (/dev/sda, /dev/mem)
  • Load kernel modules
  • Modify kernel parameters
  • Complete container breakout

How the Python DSL Makes Writing Rules Easy

I designed an intuitive Python DSL that reads like natural language:

from rules.container_decorators import dockerfile_rule
from rules.container_matchers import instruction, missing
from rules.container_combinators import any_of

# Detect missing healthchecks
@dockerfile_rule(
id="DOCKER-BP-008",
severity="MEDIUM"
)
def missing_healthcheck():
"""Detects Dockerfiles without HEALTHCHECK instruction."""
return missing(instruction="HEALTHCHECK")


# Detect latest tags
@dockerfile_rule(
id="DOCKER-BP-001",
severity="MEDIUM"
)
def using_latest_tag():
"""Detects FROM instructions using :latest tag."""
return instruction(
    type="FROM",
    image_tag="latest"
)


# Detect package manager cache
@dockerfile_rule(
id="DOCKER-BP-003",
severity="LOW"
)
def apt_without_cleanup():
"""Detects apt-get install without cleanup."""
return any_of(
    instruction(
        type="RUN",
        contains="apt-get install",
        not_contains="rm -rf /var/lib/apt/lists"
    ),
    instruction(
        type="RUN",
        regex=r"apt-get\s+install.*(?<!&& rm)"
    )
)

No complex AST manipulation. No tree-sitter queries. Just Python.

Coverage: The Complete Rule Set

Dockerfile Rules (37 Total)

Rule IDDescriptionCategorySeverityCWE
DOCKER-SEC-001Container Running as RootSecurityHIGHCWE-250
DOCKER-SEC-005Secret in Build ArgumentSecurityCRITICALCWE-538
DOCKER-SEC-006Docker Socket Mounted as VolumeSecurityCRITICALCWE-250
DOCKER-SEC-007Sudo Usage in DockerfileSecurityMEDIUMCWE-250
DOCKER-BP-001Base Image Uses :latest TagBest PracticeMEDIUM-
DOCKER-BP-003Deprecated MAINTAINER InstructionBest PracticeLOW-
DOCKER-BP-005apt-get Without --no-install-recommendsBest PracticeLOW-
DOCKER-BP-006Avoid apt-get upgradeBest PracticeMEDIUM-
DOCKER-BP-007apk add Without --no-cacheBest PracticeLOW-
DOCKER-BP-008pip install Without --no-cache-dirBest PracticeLOW-
DOCKER-BP-009Avoid dnf updateBest PracticeMEDIUM-
DOCKER-BP-010Missing pipefail in Shell CommandsBest PracticeMEDIUM-
DOCKER-BP-011Prefer COPY Over ADDBest PracticeLOW-
DOCKER-BP-012Missing yum clean allBest PracticeLOW-
DOCKER-BP-013Missing dnf clean allBest PracticeLOW-
DOCKER-BP-014Remove apt Package ListsBest PracticeLOW-
DOCKER-BP-015Missing Image VersionBest PracticeHIGH-
DOCKER-BP-016Prefer JSON Notation for CMD/ENTRYPOINTBest PracticeLOW-
DOCKER-BP-017Use WORKDIR Instead of cdBest PracticeLOW-
DOCKER-BP-018Use Absolute Path in WORKDIRBest PracticeLOW-
DOCKER-BP-019Avoid zypper updateBest PracticeMEDIUM-
DOCKER-BP-020Missing zypper cleanBest PracticeLOW-
DOCKER-BP-021Missing -y flag for apt-getBest PracticeLOW-
DOCKER-BP-022Missing HEALTHCHECK InstructionBest PracticeLOW-
DOCKER-BP-023Prefer apt-get over aptBest PracticeLOW-
DOCKER-BP-024Install Only One of wget or curlBest PracticeLOW-
DOCKER-BP-025Missing -y flag for yumBest PracticeLOW-
DOCKER-BP-026Missing -y flag for dnfBest PracticeLOW-
DOCKER-BP-027Avoid --platform Flag with FROMBest PracticeLOW-
DOCKER-BP-028Avoid apk upgradeBest PracticeMEDIUM-
DOCKER-BP-029Avoid yum updateBest PracticeMEDIUM-
DOCKER-BP-030Nonsensical CommandBest PracticeLOW-
DOCKER-COR-001Multiple ENTRYPOINT InstructionsCorrectnessMEDIUM-
DOCKER-COR-002Invalid Port NumberCorrectnessHIGH-
DOCKER-COR-003Multiple CMD InstructionsCorrectnessMEDIUM-
DOCKER-AUD-001Dockerfile Source Not PinnedAuditLOW-
DOCKER-AUD-003Privileged Port ExposedAuditMEDIUM-

Docker Compose Rules (10 Total)

Rule IDDescriptionCategorySeverityCWE
COMPOSE-SEC-001Privileged Container ServiceSecurityCRITICALCWE-250
COMPOSE-SEC-002Docker Socket Exposed to ContainerSecurityCRITICALCWE-250
COMPOSE-SEC-003Seccomp Confinement DisabledSecurityHIGHCWE-284
COMPOSE-SEC-006Container Filesystem is WritableSecurityLOWCWE-732
COMPOSE-SEC-007Using Host Network ModeSecurityHIGHCWE-250
COMPOSE-SEC-008Dangerous Capability AddedSecurityHIGHCWE-250
COMPOSE-SEC-009Using Host PID ModeSecurityHIGHCWE-250
COMPOSE-SEC-010Using Host IPC ModeSecurityMEDIUMCWE-250
COMPOSE-SEC-011Missing no-new-privileges Security OptionSecurityMEDIUMCWE-732
COMPOSE-SEC-012SELinux Separation DisabledSecurityMEDIUMCWE-732

Get Started in 30 Seconds

Install Code Pathfinder:

# macOS/Linux
brew install shivasurya/tap/pathfinder

# Windows
choco install code-pathfinder --version=1.1.0

Scan your container configurations:

# Scan all Dockerfiles
pathfinder scan --ruleset cpf/docker

# Scan docker-compose files
pathfinder scan --ruleset cpf/docker-compose

# Scan everything
pathfinder scan --ruleset cpf/docker --ruleset cpf/docker-compose

# CI/CD mode (fails on HIGH+ issues)
pathfinder ci --ruleset cpf/docker --severity HIGH

Try It Today

Browse all 47 container security rules in our registry: https://codepathfinder.dev/registry

Key Statistics:

  • 47 total rules (37 Docker + 10 Docker Compose)
  • 11 CRITICAL severity rules catching container escapes
  • 15 CWE mappings for compliance tracking
  • Sub-10s scan time for typical projects
  • Open source • AGPL-3.0 license

Frequently Asked Questions

What are Docker security rules?

Docker security rules are automated security checks that scan Dockerfiles and docker-compose.yml files for misconfigurations, privilege escalations, and vulnerabilities. They detect issues like exposed Docker sockets (CWE-250), containers running as root, and secrets in build arguments before deployment.

How do Docker security rules prevent container escapes?

Container escapes occur when attackers break out of container isolation to access the host system. Docker security rules detect dangerous configurations like privileged mode, Docker socket mounts (/var/run/docker.sock), and missing USER instructions that enable escape attacks.

What is the most critical Docker security vulnerability?

Docker socket exposure is the #1 container escape vector. Mounting /var/run/docker.sock into a container grants root-level access to the host Docker daemon, allowing attackers to create privileged containers and gain full system control.

How long does it take to scan Docker containers for security issues?

Code Pathfinder scans typical Docker projects in under 10 seconds. The tool analyzes Dockerfiles and docker-compose files using deterministic AST queries, providing instant feedback without false positives.

Can I use Docker security rules in CI/CD pipelines?

Yes. Code Pathfinder integrates into CI/CD workflows with the pathfinder ci command. It fails builds when HIGH or CRITICAL severity issues are detected, preventing vulnerable containers from reaching production.

What's the difference between SAST and runtime container security?

SAST (Static Application Security Testing) analyzes code before deployment to find misconfigurations. Runtime security monitors running containers for suspicious behavior. Code Pathfinder provides SAST for containers, catching issues during development.

Join the Community

I'd love your feedback and contributions:

Container security doesn't have to be complicated. With Code Pathfinder, it's just another step in your CI/CD pipeline.

Ship containers confidently. Scan with Code Pathfinder.

Learn more about Docker security best practices from Aqua Security, Better Stack, and Sourcery.

Try Code Pathfinder Today

Eliminate false positives and find real security vulnerabilities in your code. Get started in minutes with AI-powered SAST.

Free and open source • AGPL-3.0 License

Secure your code with confidence

Eliminate false positives and surface real security issues so developers can focus on building features.

Write to us

Send email

Chat with us

Join discussions

Try it now

Get started