Hi! This is a security-hygiene request from a downstream consumer — the Apache Software Foundation's allowlist of approved GitHub Actions.
setup-terraform currently downloads the Terraform release zip and extracts it without verifying its integrity:
|
async function downloadCLI (url) { |
|
core.debug(`Downloading Terraform CLI from ${url}`); |
|
const pathToCLIZip = await tc.downloadTool(url); |
|
|
|
let pathToCLI = ''; |
|
|
|
core.debug('Extracting Terraform CLI zip file'); |
|
if (os.platform().startsWith('win')) { |
|
core.debug(`Terraform CLI Download Path is ${pathToCLIZip}`); |
|
const fixedPathToCLIZip = `${pathToCLIZip}.zip`; |
|
io.mv(pathToCLIZip, fixedPathToCLIZip); |
|
core.debug(`Moved download to ${fixedPathToCLIZip}`); |
|
pathToCLI = await tc.extractZip(fixedPathToCLIZip); |
|
} else { |
|
pathToCLI = await tc.extractZip(pathToCLIZip); |
|
} |
|
|
|
core.debug(`Terraform CLI path is ${pathToCLI}.`); |
|
|
|
if (!pathToCLIZip || !pathToCLI) { |
|
throw new Error(`Unable to download Terraform from ${url}`); |
|
} |
|
|
|
return pathToCLI; |
|
} |
|
|
async function downloadCLI (url) {
core.debug(`Downloading Terraform CLI from ${url}`);
const pathToCLIZip = await tc.downloadTool(url);
...
pathToCLI = await tc.extractZip(pathToCLIZip);
...
}
TLS protects the bytes in transit from releases.hashicorp.com, but the action takes no defense-in-depth step beyond that — a compromised mirror, CDN incident, or any future change to the resolved URL would land an arbitrary binary on every runner that uses the action.
HashiCorp already publishes everything needed to close that gap at each release:
terraform_<version>_SHA256SUMS — SHA256 of every release asset
terraform_<version>_SHA256SUMS.<keyID>.sig — detached PGP signature over the sums file, signed with the HashiCorp release GPG key
Proposed fix
A minimal fix inside downloadCLI:
- After
tc.downloadTool(url) returns the zip path, also fetch terraform_<v>_SHA256SUMS for the same release.
- Find the line for the platform-specific zip filename.
- Hash the downloaded zip with Node's
crypto.createHash('sha256') and compare; fail loudly if it doesn't match.
A stronger fix additionally verifies SHA256SUMS.sig against the HashiCorp public key — @hashicorp/js-releases already knows about the release index, so the signature path is a natural extension.
Downstream impact
The ASF reviews every new commit hash of every action it adds to its allowlist. Our verification script flags every release of setup-terraform because of this missing check — most recently on the v4.0.0 → v4.0.1 bump in apache/infrastructure-actions#836. We're approving 836 because the download shape didn't change between v4.0.0 (already approved) and v4.0.1, but every future bump will need a manual security re-review until the action verifies what it downloads.
Happy to send a PR if it'd help.
Hi! This is a security-hygiene request from a downstream consumer — the Apache Software Foundation's allowlist of approved GitHub Actions.
setup-terraformcurrently downloads the Terraform release zip and extracts it without verifying its integrity:setup-terraform/lib/setup-terraform.js
Lines 37 to 62 in dfe3c3f
TLS protects the bytes in transit from
releases.hashicorp.com, but the action takes no defense-in-depth step beyond that — a compromised mirror, CDN incident, or any future change to the resolved URL would land an arbitrary binary on every runner that uses the action.HashiCorp already publishes everything needed to close that gap at each release:
terraform_<version>_SHA256SUMS— SHA256 of every release assetterraform_<version>_SHA256SUMS.<keyID>.sig— detached PGP signature over the sums file, signed with the HashiCorp release GPG keyProposed fix
A minimal fix inside
downloadCLI:tc.downloadTool(url)returns the zip path, also fetchterraform_<v>_SHA256SUMSfor the same release.crypto.createHash('sha256')and compare; fail loudly if it doesn't match.A stronger fix additionally verifies
SHA256SUMS.sigagainst the HashiCorp public key —@hashicorp/js-releasesalready knows about the release index, so the signature path is a natural extension.Downstream impact
The ASF reviews every new commit hash of every action it adds to its allowlist. Our verification script flags every release of
setup-terraformbecause of this missing check — most recently on the v4.0.0 → v4.0.1 bump in apache/infrastructure-actions#836. We're approving 836 because the download shape didn't change between v4.0.0 (already approved) and v4.0.1, but every future bump will need a manual security re-review until the action verifies what it downloads.Happy to send a PR if it'd help.