Proposal: Standardize Windows Prereq Installs with winget
Use-cases
Atomic Red Team atomics often need external tools before a test can run. Today, Windows prereq setup uses a mix of directInvoke-WebRequest downloads, Chocolatey bootstrapping, vendor installer URLs, ZIP extraction helpers, and a small number of winget installs.
That makes prereq behavior inconsistent across atomics. Contributors have to decide how to download each dependency, users see different install flows for similar tools, and direct URLs can break or drift when vendors move installers.
This would mirror the existing package-manager standardization used by many Linux/macOS atomics, where common dependencies are installed through apt, yum, or brew instead of custom per-atomic download logic.
A standard Windows download/install convention would help users:
- get repeatable prereq setup across Windows atomics
- avoid one-off installer download logic in every YAML file
- reduce direct download URLs when a maintained
wingetpackage exists - avoid bootstrapping another package manager just to install a common tool
- make cleanup more consistent by using
winget uninstallorwinget removewhen an atomic installs a package only for that test - keep direct downloads only for payloads or tools that cannot be installed
through
winget
Proposal
Prefer winget for Windows prereq setup when the dependency has a stable package ID in the Windows Package Manager Community Repository.
Suggested default for installed tools:
winget install --id <Package.Id> --exact --source winget --silent --accept-package-agreements --accept-source-agreementsThe prereq_command should still verify the actual tool needed by the atomic, not only that winget exists. For example:
if (Get-Command curl.exe -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }The get_prereq_command should use winget when available:
winget install --id cURL.cURL --exact --source winget --silent --accept-package-agreements --accept-source-agreementsUse winget download only when the atomic specifically needs an installer file instead of an installed tool. If the atomic only needs the tool available on the system, use winget install.
When an atomic installs a package only for that test, cleanup can remove it with the same package ID:
winget uninstall --id <Package.Id> --exact --source wingetor:
winget remove --id <Package.Id> --exact --source wingetSuggested migration:
| Current pattern | Proposed pattern | Notes |
|---|---|---|
| Direct vendor installer URL for a common Windows tool | winget install --id <Package.Id> --exact |
Prefer the package manager when the package ID is stable. |
| Bootstrap Chocolatey to install one dependency | winget install |
Avoid installing another package manager as prereq setup. |
| Repeated ad hoc ZIP download/extract logic | winget install when package exists |
Keep custom extraction only when the atomic needs a specific archive payload. |
| Direct download of Atomic Red Team payloads | Keep direct repo download or local payload reference | winget is for third-party tools, not ART payload files. |
| Direct download needed for adversary emulation behavior | Keep direct download with hash validation where possible | Some atomics intentionally test download behavior. |
Direct downloads should still be allowed when:
- no reliable
wingetpackage exists - the test needs a specific historical version or exact binary
- the file is an Atomic Red Team payload
- the download behavior is part of what the atomic is testing
- the dependency is portable and should not be installed system-wide
References
Source: redcanaryco/atomic-red-team