sdk/api/docker
🐳 Dockerfile

Dockerfile API Reference

Structural analysis of Dockerfiles. No dataflow, no taint. Rules match properties of build instructions: base images, user settings, exposed ports, healthchecks, labels, and more.

How Dockerfile rules differ from Go / Python

Dockerfile rules use a completely separate API: instruction() and missing() from codepathfinder.container_matchers. They do not use flows(), calls(), QueryType, or PropagationPresets. Boolean combinators use all_of / any_of / none_of (not And / Or / Not).

Canonical imports

python
from codepathfinder.container_decorators import dockerfile_rule
from codepathfinder.container_matchers import instruction, missing
from codepathfinder.container_combinators import all_of, any_of, none_of  # optional

@dockerfile_rule decorator

Declares a rule scoped to Dockerfile (and Dockerfile.* variants). The decorator automatically sets file_pattern="Dockerfile*" in metadata.

python
@dockerfile_rule(
    id="DOCKER-SEC-001",              # required
    name="",
    severity="MEDIUM",                # CRITICAL | HIGH | MEDIUM | LOW | INFO
    category="security",
    cwe="",
    cve="",
    tags="",
    message="",
)
def my_rule():
    return instruction(type="FROM", image_tag="latest")
@dockerfile_rule does not accept an owasp parameter (unlike @go_rule and @python_rule). Putting owasp="..." will raise a TypeError.

instruction()

Matches a Dockerfile instruction by type and optional property constraints. Only non-None parameters are applied, so you can compose matches as narrowly as needed.

python
from codepathfinder.container_matchers import instruction

# Base image using the :latest tag
instruction(type="FROM", image_tag="latest")

# FROM without a pinned digest
instruction(type="FROM", missing_digest=True)

# ARG with password-ish name
instruction(type="ARG", arg_name_regex=r"(?i).*password.*")

# EXPOSE with invalid port
instruction(type="EXPOSE", port_greater_than=65535)
instruction(type="EXPOSE", port_less_than=1)

# USER = root
instruction(type="USER", user_name="root")

# HEALTHCHECK too aggressive
instruction(type="HEALTHCHECK", healthcheck_interval_less_than="10s")
Common parameters
typerequired
str
Dockerfile instruction name (FROM, USER, EXPOSE, ARG, RUN, COPY, ADD, HEALTHCHECK, LABEL, CMD, ENTRYPOINT, WORKDIR, STOPSIGNAL, etc.).
base_image
str
FROM: base image name, e.g., "alpine".
image_tag
str
FROM: tag value, e.g., "latest", "3.18".
image_tag_regex
str
FROM: regex applied to the tag.
missing_digest
bool
FROM: matches when the base image has no @sha256: digest pin.
user_name
str
USER: user name, e.g., "root".
user_name_regex
str
USER: regex on user name.
port
int
EXPOSE: exact port number.
port_less_than
int
EXPOSE: port below threshold (for invalid port detection).
port_greater_than
int
EXPOSE: port above threshold.
protocol
str
EXPOSE: "tcp" | "udp".
arg_name
str
ARG: exact name.
arg_name_regex
str
ARG: regex on argument name (useful for secret detection).
copy_from
str
COPY/ADD: --from=stage source.
chown
str
COPY/ADD: --chown= value.
missing_flag
str
COPY/ADD: name of a required flag that is absent, e.g., "chown".
healthcheck_interval_less_than
str
HEALTHCHECK: interval below threshold, e.g., "10s".
healthcheck_timeout_greater_than
str
HEALTHCHECK: timeout above threshold.
healthcheck_retries_greater_than
int
HEALTHCHECK: retries above threshold.
label_key
str
LABEL: key name.
label_value_regex
str
LABEL: regex on the label value.
command_form
str
CMD / ENTRYPOINT: "shell" | "exec".
workdir_not_absolute
bool
WORKDIR: matches when the path is relative.
signal_not_in
list[str]
STOPSIGNAL: matches when signal is NOT in the allowlist.
contains
str
Generic substring match on the raw instruction text.
not_contains
str
Generic: does NOT contain substring.
regex
str
Generic regex against the raw instruction text.
not_regex
str
Generic: does NOT match regex.
validate
callable
Custom Python callable invoked on the parsed instruction for arbitrary validation.

Full signature in codepathfinder/container_matchers.py:24-136.

missing(): absent instruction

Matches when a required instruction is not present in the Dockerfile. Most useful for enforcing hardening baselines (USER, HEALTHCHECK, LABEL metadata).

python
from codepathfinder.container_matchers import missing

missing(instruction="USER")                          # container would run as root
missing(instruction="HEALTHCHECK")                   # no healthcheck defined
missing(instruction="LABEL", label_key="maintainer") # specific label is absent
Signature
instructionrequired
str
Instruction name that must be absent.
label_key
str | None
For LABEL: a specific label key that is absent (when others may be present).
Don't confuse container missing() (from codepathfinder.container_matchers) with qualifier missing() (from codepathfinder.qualifiers). Same name, different module, different purpose.

all_of / any_of / none_of

Boolean combinators for container rules. Import from codepathfinder.container_combinators.

python
from codepathfinder.container_combinators import all_of, any_of, none_of

# Any invalid port range
any_of(
    instruction(type="EXPOSE", port_less_than=1),
    instruction(type="EXPOSE", port_greater_than=65535),
)

# All hardening requirements met (matches if any are missing; combine with negation)
all_of(
    instruction(type="USER", user_name_regex=r"^(?!root$).*"),
    instruction(type="HEALTHCHECK"),
)

# None of the risky patterns
none_of(
    instruction(type="RUN", contains="sudo"),
    instruction(type="RUN", contains="curl | sh"),
)

Complete example: missing USER instruction

Real rule from the registry (DOCKER-SEC-001). Detects Dockerfiles that don't pin a non-root user.

python
from codepathfinder.container_decorators import dockerfile_rule
from codepathfinder.container_matchers import missing


@dockerfile_rule(
    id="DOCKER-SEC-001",
    name="Container Running as Root - Missing USER",
    severity="HIGH",
    cwe="CWE-250",
    category="security",
    tags="docker,dockerfile,container,security,privilege-escalation,root,user,best-practice,hardening,principle-of-least-privilege",
    message=(
        "Dockerfile does not specify USER instruction. Container will run as root by default, "
        "which increases the attack surface if the container is compromised."
    )
)
def missing_user_instruction():
    """Detects Dockerfiles that do not specify a USER instruction."""
    return missing(instruction="USER")