Use COPY for files from your build context or another stage. Use ADD only when you need to download a remote file, and give it a checksum so the build fails if the content changes. Do not pipe a downloaded script straight into a shell inside a RUN step.
What the guidance says
The Docker build guidance says you will mostly want COPY for copying files, including from one stage to another. It says ADD is best for when you need to download a remote artifact, and that ADD has built-in support for checksum validation of the remote resource. It also points to bind mounts for build-context files needed only during a single RUN step, since those do not persist in the image.
The OWASP cheat sheet adds two points for Dockerfile reviews: prefer COPY over ADD, and avoid piping curl output into a shell in RUN instructions.
Why plain downloads are risky
A download in a build is code or data you did not write, fetched at build time. If the server is compromised, the URL is hijacked, or the file at that address is replaced, your image picks up the new content, and nothing in the build notices.
Piping to a shell is worse. A command that fetches a script and runs it immediately gives you no chance to inspect it, and if the connection is cut part way, a half-downloaded script may run.
The safer pattern
ADD --checksum=sha256:PUT_THE_EXPECTED_HASH_HERE \
https://example.com/tool-1.2.3-linux-amd64.tar.gz /tmp/tool.tar.gz
RUN tar -xzf /tmp/tool.tar.gz -C /usr/local/bin && rm /tmp/tool.tar.gz
Replace the placeholder with the hash that the publisher states, ideally taken from a source other than the download host, such as a signed release note. If the downloaded bytes do not match, the build stops.
If you prefer to stay with RUN, download to a file, verify the hash, then use it.
RUN curl -fsSLo /tmp/tool.tgz https://example.com/tool-1.2.3.tgz \
&& echo "EXPECTED_HASH /tmp/tool.tgz" | sha256sum -c - \
&& tar -xzf /tmp/tool.tgz -C /usr/local/bin \
&& rm /tmp/tool.tgz
The fail-on-error flag on curl and the checked hash together mean a bad download breaks the build.
Other habits
- Pin the version in the URL. Avoid addresses that always serve the latest.
- Prefer the package manager when the distribution carries the tool, since it verifies signatures for you.
- Download in a build stage and copy only the result forward, so download tools are not in the final image. See multi-stage builds.
- Record what you fetched. Keep the URL and hash in the repository so changes are reviewed.
- Update hashes on purpose. When you bump a version, update the hash in the same change and review where the new hash came from.
Does ADD do anything else?
It can also unpack local archives, which is one reason reviewers prefer COPY: the behavior is easier to predict. If you need to extract an archive, an explicit tar step is clearer.
What a hash does not do
A checksum shows the file matches the one you expected. It does not show the file is safe. If you copy the hash from the same page as the file, an attacker who changed one changed both. Use an independent source when possible, and scan what you installed.
Safeguard's SBOM and dependency scanning can show what a downloaded tool brought along, and policies and gates can help enforce your rules. Try a free scan.
Quick check
Is ADD with a URL ever the right choice?
Yes, for fetching a remote artifact with a checksum. For local files, use COPY.
Is HTTPS enough to trust a download?
It protects the connection, not the file. If the server or release is compromised, you still receive bad content. A checksum from an independent source helps.
Sources
Last reviewed: 19 October 2026.