Skip to content

VNX-DOCKER-004: Dockerfile ADD downloads a remote source without a checksum

Reports a Dockerfile ADD that downloads an http(s) URL or a git repository with no --checksum, in every ADD form; git sources pinned to a full commit are not reported.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-DOCKER-004
Severity Medium
SARIF level warning
Kind oci
Languages Dockerfile
CWE CWE-829, CWE-494
CAPEC CAPEC-185
ATT&CK T1195.002
CWSS vector CWSS:1.0/TI:M/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C
Tags docker supply-chain integrity container
Source internal/sast/rules/vnx-docker-004.rego

Overview

This rule detects ADD instructions in Dockerfiles that download content directly from an HTTP or HTTPS URL (e.g., ADD https://example.com/tool.tar.gz /usr/local/). While Docker’s ADD instruction supports URL downloads, it performs no checksum or signature verification of the downloaded content, the build silently accepts whatever bytes the server returns. This creates a supply chain attack vector where a compromised server, a DNS hijack, or a BGP rerouting can substitute malicious content without any build-time detection. This maps to CWE-829 (Inclusion of Functionality from Untrusted Control Sphere).

Why This Matters

When ADD fetches from a URL, the Docker daemon connects to that URL at build time and copies the response body into the image layer. There is no built-in mechanism to verify:

  • That the content is the same as when you last built the image
  • That the server has not been compromised between builds
  • That the URL has not been redirected to a malicious host

This is exactly the attack surface exploited in the 2020 SolarWinds attack and the Codecov supply chain breach: a trusted URL serves tampered content that is incorporated into builds without triggering any alerts. CAPEC-185 (Malicious Software Update) and MITRE ATT&CK T1195.002 (Compromise Software Supply Chain) document this class of attack.

The Docker documentation itself discourages using ADD with URLs, explicitly recommending curl or wget with checksum verification instead.

What Gets Flagged

The rule reports ADD instructions whose source is remote (http://, https://, git://, ssh:// or git@host:) and that carry no --checksum=. Flags before the source, lowercase instructions, the JSON form, a source on a continuation line and ONBUILD ADD are all handled.

# FLAGGED
ADD https://github.com/example/tool/releases/download/v1.4.0/tool-linux-amd64 /usr/local/bin/tool
ADD --chmod=755 http://downloads.example.com/agent/install.sh /opt/agent/install.sh
ADD ["https://example.com/config/app.yaml", "/etc/app/app.yaml"]
ADD https://github.com/example/plugins.git#main /src/plugins
ADD --link \
    https://storage.example.com/models/classifier-v3.onnx \
    /models/classifier.onnx
ARG TINI_URL=https://github.com/krallin/tini/releases/download/v0.19.0/tini
ADD ${TINI_URL} /tini

Not reported: ADD --checksum=sha256:..., a git source pinned to a 40-character commit, local sources (VNX-DOCKER-006), a source held in a variable with no ARG default, RUN curl/wget downloads, ADD text in comments, labels, strings and heredocs, test and .devcontainer images.

Remediation

  1. Replace ADD <url> with a RUN step using curl or wget that downloads the file and immediately verifies its SHA-256 checksum. Obtain the expected checksum from the tool vendor’s release page and embed it directly in the Dockerfile.

    # SAFE: download and verify checksum before use
    FROM debian:12-slim
    
    RUN set -eux; \
        curl -fsSL https://example.com/myapp-v1.2.tar.gz -o /tmp/myapp.tar.gz; \
        echo "a1b2c3d4e5f6...expectedhash  /tmp/myapp.tar.gz" | sha256sum -c -; \
        tar -xzf /tmp/myapp.tar.gz -C /opt/myapp/; \
        rm /tmp/myapp.tar.gz
  2. Prefer GPG signature verification where available. For tools that publish a .asc or .sig alongside their release artifacts, verify the GPG signature instead of (or in addition to) the SHA-256 hash. This adds a trust anchor that a checksum alone does not provide.

    # SAFE: GPG signature verification
    FROM debian:12-slim
    
    RUN set -eux; \
        gpg --keyserver keys.openpgp.org --recv-keys ABCDEF1234567890; \
        curl -fsSL https://example.com/myapp-v1.2.tar.gz -o /tmp/myapp.tar.gz; \
        curl -fsSL https://example.com/myapp-v1.2.tar.gz.asc -o /tmp/myapp.tar.gz.asc; \
        gpg --verify /tmp/myapp.tar.gz.asc /tmp/myapp.tar.gz; \
        tar -xzf /tmp/myapp.tar.gz -C /opt/myapp/
  3. Copy files from a build context or a verified prior stage. If the tool is versioned and regularly updated, consider vendoring its binary into your repository or fetching it in a dedicated CI job that validates the checksum before making it available to Dockerfile builds.

    # SAFE: multi-stage build, tool verified and copied from a trusted earlier stage
    FROM debian:12-slim AS downloader
    RUN curl -fsSL https://example.com/tool -o /tool \
        && echo "expectedhash  /tool" | sha256sum -c -
    
    FROM gcr.io/distroless/static-debian12
    COPY --from=downloader /tool /usr/local/bin/tool
  4. Use BuildKit with --checksum (Docker 24.0+). Newer versions of Docker BuildKit support a --checksum option on ADD for URL sources, allowing you to specify an expected SHA-256 digest directly in the ADD instruction.

    # SAFE: ADD with explicit checksum (BuildKit 24.0+)
    # syntax=docker/dockerfile:1
    ADD --checksum=sha256:a1b2c3... https://example.com/myapp.tar.gz /opt/myapp/

References

Suppressing this rule

Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):

# nosec vnx-docker-004
// nosec vnx-docker-004

Or record an ignore rule: vulnetix ignore add --rule vnx-docker-004 --reason "...". See Suppressing findings.

Edit this pageSources: cli/internal/sast/rules/vnx-docker-004.rego, cli/internal/sast/docs/vnx-docker-004.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.