Invoke-WebRequest (or its alias iwr)
by setting $ProgressPreference = 'SilentlyContinue'.
| Property | Value |
|---|---|
| Severity | Style |
| Category | Style |
| Default | Enabled |
| Auto-fix | Yes (--fix --fix-unsafe) |
Description
PowerShell’sInvoke-WebRequest renders a per-response progress bar by default.
On Windows containers this collapses download throughput by an order of magnitude
because the host cannot render the bar and the cmdlet stalls waiting for terminal
updates. Microsoft’s official Windows container guidance is to set
$ProgressPreference = 'SilentlyContinue' before any Invoke-WebRequest call.
The rule fires whenever a RUN invokes Invoke-WebRequest or iwr without a
preceding $ProgressPreference = 'SilentlyContinue' assignment. Detection
does not depend on the stage’s default shell — Invoke-WebRequest is a
PowerShell-unique cmdlet, so finding it is itself the shell signal. That way the
rule catches both SHELL-based PowerShell stages and one-off powershell -Command
wrappers embedded inside bash stages.
Why this matters
On Windows Server Core images specifically, users have reportedInvoke-WebRequest downloads taking minutes where a curl or the same call
with $ProgressPreference = 'SilentlyContinue' takes seconds. The progress bar
is pure noise in a non-interactive build step.
Examples
Before (violation)
After (fixed with --fix --fix-unsafe)
Already clean (no violation)
Explicit wrapper (violation)
Fix behavior
The fix adapts to where the PowerShell script lives:SHELLwith bare-Command: appends a new array element"$ProgressPreference = 'SilentlyContinue';"to theSHELLinstruction.SHELLwith an existing prelude: appends the assignment to the existing prelude string, inserting a;separator if missing.- No
SHELLin a PowerShell-by-default stage: inserts a newSHELLinstruction after theFROM. - Explicit
powershell -Command/pwsh -Commandwrapper: zero-width insertion at the start of the inner script. RUN <<EOFheredoc body (PowerShell stages only): inserts the assignment on a new line at the start of the heredoc body.
FixSuggestion safety — it requires --fix-unsafe to apply. A
same-SHELL-scope suppression prevents duplicate SHELL edits when multiple RUNs
in the same stage violate.
Interaction with other rules
tally/powershell/prefer-shell-instruction(priority 95): when it converts repeatedpowershell -Commandwrappers to aSHELLinstruction, its prelude already contains$ProgressPreference = 'SilentlyContinue'. The combined--fix --fix-unsaferun letsprefer-shell-instructionwin;progress-preference’s edit is dropped as overlapping.tally/powershell/error-action-preference(priority 96): both rules edit theSHELLinstruction with zero-width insertions before the closing]. When both are enabled and both trigger, both apply — the resultingSHELLcarries two complementary array elements, each with its own preamble.tally/prefer-run-heredoc(priority 100): structural conversion to heredoc runs after the preference is set and carries it into the heredoc body.
References
$ProgressPreference— Microsoft Learn: controls how PowerShell renders progress reports. Default isContinue;SilentlyContinuesuppresses the per-response bar.Invoke-WebRequest— Microsoft Learn: cmdlet reference documenting the progress-rendering behavior.- Optimize Windows Dockerfiles
— Microsoft Learn: Windows-container-specific Dockerfile guidance, including
the
$ProgressPreferencerecommendation.