Either use Wget or Curl but not both.Documentation Index
Fetch the complete documentation index at: https://tally.wharflab.com/llms.txt
Use this file to discover all available pages before exploring further.
| Property | Value |
|---|---|
| Severity | Warning |
| Category | Best Practice |
| Default | Enabled |
| Auto-fix | Yes (--fix --fix-unsafe; AI AutoFix fallback) |
Description
Don’t install two tools that have the same effect. Using bothwget and curl in a Dockerfile adds unnecessary cruft to the image. Pick one and use
it consistently.
The rule fires when both tools are present in the Dockerfile in any combination: both invoked, both installed, or one installed while the other is
invoked. Installing the second tool is itself the offense — even if you never call it, it still inflates the image.
Examples
Problematic code
Correct code
Auto-fix
The rule rewrites offending commands to the tool it picks as the winner for the Dockerfile. Rewriting is bidirectional:curl → wget or
wget → curl. All fixes are unsafe (FixUnsafe) and require --fix --fix-unsafe.
How the winning tool is chosen (auto mode)
Auto mode uses usage-based heuristics, not tool-install flags. The winner — and therefore the direction of the rewrite — is decided in this order:- Used without explicit install wins. If exactly one of
curl/wgetis used without being explicitly installed by the Dockerfile (e.g., it comes from the base image), that tool wins and the other one is rewritten. Installing the tool you already get “for free” is the thing DL4001 is pushing back on. - Most invocations wins. If both tools are in the same install category (both installed, or both used-without-install), the tool with more total invocations across the Dockerfile wins.
- First seen wins. If invocation counts tie, the tool whose first use appears earlier in the Dockerfile wins.
- Rewrite each invocation. Tally doesn’t try to translate
curlflags into the equivalentwgetflags argument-by-argument — that’s a fragile game with many edge cases. Instead, each offending command is read as a single HTTP action (“download this URL into this file”, “download this URL and pipe it intotar”, etc.), and the replacement is produced from scratch using whichever target tool was chosen. What matters for a Docker image build is the outcome — which bytes end up where, which errors fail the build — and that’s what the rewrite preserves. When a command is too elaborate to reinterpret this way (non-HTTP features, shell interpolation, custom scripting), tally falls back to the AI AutoFix path, which additionally requires an ACP-capable agent configured in the top-level[ai]section. - Clean up what’s left. After all the invocation rewrites are applied, tally re-reads the resulting Dockerfile and removes anything
that exists only to serve the evicted tool:
- the tool’s entry in install commands (dropped from the package list, or the whole install RUN if it only installed that one tool),
- COPY heredocs that write the tool’s config file (
.curlrc/.wgetrc//etc/wgetrc), ENVbindings that point at those config paths (CURL_HOME,WGETRC,WGETHOSTS),- any annotation comments tally itself added when it inserted the config.
tally/sort-packages reorders the install
line or tally/prefer-curl-config inserts a .curlrc heredoc, those edits are already applied by the time cleanup runs, so the cleanup
sees the finished state and does the right thing instead of fighting anyone for the same source range.
The rule refuses to attach a sync fix when the preferred tool already appears in the same RUN (for example curl ... || wget ...).
On Windows stages the replacement is emitted with a .exe suffix (curl.exe, wget.exe); on Linux stages the bare tool name is used.
Deterministic rewrite examples
When the AI AutoFix fallback is used
Examples where deterministic lowering cannot preserve Dockerfile-relevant behavior and the rule falls back to AI AutoFix:Configuration
fix-preference
- Type:
string - Allowed values:
"auto","curl","wget" - Default:
"auto"
"auto"(default): pick the winner using the usage-based heuristics described in the Auto-fix section above (used-without-install → invocation count → first seen)."curl": always report and rewritewgetcalls tocurl, regardless of usage or install state."wget": always report and rewritecurlcalls towget, regardless of usage or install state.
"auto".