codegen: Exclude very recently released version from candidate for

latest and omitted versions
This commit is contained in:
Taiki Endo
2026-04-05 16:14:59 +09:00
parent 11f5a9921c
commit eab6539ed6
6 changed files with 86 additions and 8 deletions

View File

@@ -10,6 +10,14 @@ Note: In this file, do not use the hard wrap in the middle of a sentence for com
## [Unreleased]
- Introduce [dependency cooldown](https://blog.yossarian.net/2025/11/21/We-should-all-be-using-dependency-cooldowns) when installing with `taiki-e/install-action@<tool_name>`, `tool: <tool_name>@latest`, or `tool: <tool_name>@<omitted_version>` to mitigate the risk of supply chain attacks by default. ([#1666](https://github.com/taiki-e/install-action/pull/1666))
This action without this cooldown already takes a few hours to a few days for new releases to be reflected (as with other common package managers that verify checksums or signatures), so this should not affect most users.
See the ["Security" section in readme](https://github.com/taiki-e/install-action#security) for more details.
- Documentation improvements.
## [2.72.0] - 2026-04-04
- Support `cargo-xwin`. ([#1659](https://github.com/taiki-e/install-action/pull/1659), thanks @daxpedda)

View File

@@ -100,18 +100,28 @@ See the [development guide](DEVELOPMENT.md) for how to add support for new tool.
## Security
The `@v<major>` and `@<tool_name>` tags are updated with each release. To enhance workflow stability and security against supply chain attacks, use the `@v<major>.<minor>.<patch>` tag or their hash to pin the version. Since all releases are immutable, pinning the version in either way should have the same effect.
The `@v<major>` and `@<tool_name>` tags are updated with each release. If you want to enhance workflow stability and security against supply chain attacks, consider using the `@v<major>.<minor>.<patch>` tag or their hash to pin the version and regularly updating with [dependency cooldown]. Since all releases are immutable, pinning the version in either way should have the same effect. Pinning `@<tool_name>` tags by hash is strongly discouraged, as it causes the workflow to reference a [commit that is not present on the repository](https://docs.zizmor.sh/audits/#impostor-commit) when a new version is released.
When installing the tool from GitHub Releases, the tool version that install-action installs with `tool: <tool_name>@latest` or `tool: <tool_name>@<omitted_version>` is associated with the install-action version, so pinning install-action version with the above ways also pins the version of the tool being installed. This also means that if a [dependency cooldown](https://blog.yossarian.net/2025/11/21/We-should-all-be-using-dependency-cooldowns) applies to the action itself, a cooldown of the same duration or a few days longer will apply to the tools installed by that action.
<!-- omit in toc -->
### Security on installation from GitHub Releases
### Security on tool installation
**Tools covered in this section:** Tools in the [supported tools list](TOOLS.md) where column "Where will it be installed from" is "GitHub Releases".
When installing the tool from GitHub Releases, this action will download the tool or its installer from GitHub Releases using HTTPS with tlsv1.2+. This is basically considered to be the same level of security as [the recommended installation of rustup](https://www.rust-lang.org/tools/install).
This action will download the tool or its installer from GitHub Releases using HTTPS with tlsv1.2+. This is basically considered to be the same level of security as [the recommended installation of rustup](https://www.rust-lang.org/tools/install).
Additionally, this action will also verify SHA256 checksums for downloaded files in all tools installed from GitHub Releases. This is enabled by default and can be disabled by setting the `checksum` input option to `false` (strongly discouraged to disable).
Additionally, this action will also verify SHA256 checksums for downloaded files for all tools covered in this section. This is enabled by default and can be disabled by setting the `checksum` input option to `false` (strongly discouraged to disable).
Additionally, we also verify [artifact attestations](https://docs.github.com/en/actions/concepts/security/artifact-attestations) or signature if the tool publishes artifact attestations or distributes signed archives. Verification is done at the stage of getting the checksum, so disabling the checksum will also disable verification.
When installing with `taiki-e/install-action@<tool_name>`, `tool: <tool_name>`, or `tool: <tool_name>@<omitted_version>`, The tool version is reflects upstream releases with a delay of one to a few days (as with other common package managers that verify checksums or signatures). A delay of at least one day is known as [dependency cooldown] and is intended to mitigate the risk of supply chain attacks (the specific cooldown period may be changed in the future). You can bypass the cooldown by explicitly specifying a version. If you want a longer cooldown, consider using the property described below.
When installing with `tool: <tool_name>` or `tool: <tool_name>@<omitted_version>`, the tool version is associated with the install-action version, so pinning install-action version with the `@v<major>.<minor>.<patch>` tag or their hash also pins the version of the tool being installed. This also means that if a [dependency cooldown] applies to the action itself, a cooldown of one to a few days longer will apply to the tools installed by that action.
[dependency cooldown]: https://blog.yossarian.net/2025/11/21/We-should-all-be-using-dependency-cooldowns
<!-- omit in toc -->
### Security on other installation methods
See the linked documentation for information on security when installed using [snap](https://snapcraft.io/docs) or [cargo-binstall](https://github.com/cargo-bins/cargo-binstall#faq).
See the [Supported tools section](#supported-tools) for how to ensure that fallback is not used.

26
manifests/just.json generated
View File

@@ -27,6 +27,32 @@
"1": {
"version": "1.48.1"
},
"1.49.0": {
"x86_64_linux_musl": {
"etag": "0x8DE92D62FFEE2CA",
"hash": "05eb2f068b641b06e5b318796c2e27d4dcca608e65b34329a08c1b9f582611bd"
},
"x86_64_macos": {
"etag": "0x8DE92D6315E20A9",
"hash": "e0b83a9352952ab25e5cf13f6cb03dd1872416e5d89388b56d6ca58f11b0a3a8"
},
"x86_64_windows": {
"etag": "0x8DE92D65DAA4399",
"hash": "657338772efd17a31d67285bb5ed691da87741e44311c0366273c6cb7d913b15"
},
"aarch64_linux_musl": {
"etag": "0x8DE92D633E8329E",
"hash": "993b78f51004248114af22368f69715541542b3c9941c80e02f8ae10eb404ae0"
},
"aarch64_macos": {
"etag": "0x8DE92D61E96BBDE",
"hash": "d21b20df01ec9b9762b0ef08e56ae8dccf3738770edeafa8d2b3a750aee06d78"
},
"aarch64_windows": {
"etag": "0x8DE92D65E1C5B47",
"hash": "e73cd7b3c4fb363f703f99caaa71d4ab114a92205b2ef313212f3b2085d3ee64"
}
},
"1.48": {
"version": "1.48.1"
},

26
manifests/mise.json generated
View File

@@ -36,6 +36,32 @@
"2026.4": {
"version": "2026.4.3"
},
"2026.4.4": {
"x86_64_linux_musl": {
"etag": "0x8DE92B8CD42D7A7",
"hash": "3d746d5a137e63ed88e4e2213a9706a43dff68c995376fabb753a90ec799af18"
},
"x86_64_macos": {
"etag": "0x8DE92B8CF701697",
"hash": "e3fe092643f3e68c3a2be9eef217937f241accb81891332678550c15224627c0"
},
"x86_64_windows": {
"etag": "0x8DE92B8D03C1E31",
"hash": "5c879723f693514f6f8f725270724561cd8ebdf913188839ad1f879900bf5719"
},
"aarch64_linux_musl": {
"etag": "0x8DE92B8CA044A7E",
"hash": "e2da1fd598b4aa347761daf373e51608cbc4465c6b076b60b22cb1ef659cf97e"
},
"aarch64_macos": {
"etag": "0x8DE92B8CEAE639C",
"hash": "22459d2852b716f5dbbdb07173ae0fb28d99b701589f6f6a73d85ac47a497de8"
},
"aarch64_windows": {
"etag": "0x8DE92B8D051630C",
"hash": "6cada4eeeef1a9cd074962a76fa9a6f107b5b791b01839fc3355d3f3b1604c85"
}
},
"2026.4.3": {
"x86_64_linux_musl": {
"etag": "0x8DE918787D0FCD3",

View File

@@ -8,6 +8,7 @@ install-action-manifest-schema = { path = "../manifest-schema" }
anyhow = "1"
flate2 = "1"
fs-err = "3"
jiff = { version = "0.2", default-features = false, features = ["std", "serde"] }
minisign-verify = "0.2"
ring = "0.17"
semver = { version = "1", features = ["serde"] }

View File

@@ -23,6 +23,8 @@ use install_action_internal_codegen::{
use serde::de::DeserializeOwned;
use spdx::expression::{ExprNode, ExpressionReq, Operator};
const DEFAULT_COOLDOWN: u64 = 24;
fn main() {
let args: Vec<_> = env::args().skip(1).collect();
if args.is_empty() || args.iter().any(|arg| arg.starts_with('-')) {
@@ -59,6 +61,7 @@ fn main() {
eprintln!("downloading metadata from {GITHUB_API_START}repos/{repo}");
let repo_info: github::RepoMetadata = download_json(&format!("{GITHUB_API_START}repos/{repo}"));
let before = jiff::Timestamp::now() - Duration::from_hours(DEFAULT_COOLDOWN);
eprintln!("downloading releases from {GITHUB_API_START}repos/{repo}/releases");
let mut releases: github::Releases = vec![];
// GitHub API returns up to 100 results at a time. If the number of releases
@@ -772,17 +775,20 @@ fn main() {
} else if !semver_versions.is_empty() {
let mut prev_version = semver_versions.iter().next().unwrap();
for version in &semver_versions {
if releases[&Reverse(version.clone())].1.published_at > before {
continue; // Exclude very recently released version from candidate for latest and omitted versions.
}
if let Some(crates_io_info) = &crates_io_info {
if let Some(v) = crates_io_info.versions.iter().find(|v| v.num == *version) {
if v.yanked {
continue; // Exclude yanked version from candidate for "latest".
continue; // Exclude yanked version from candidate for latest and omitted versions.
}
} else {
continue; // Exclude version not released on crates.io from candidate for "latest".
continue; // Exclude version not released on crates.io from candidate for latest and omitted versions.
}
}
if base_info.broken.contains(version) {
continue; // Exclude version marked as broken from candidate for "latest".
continue; // Exclude version marked as broken from candidate for latest and omitted versions.
}
if !(version.major == 0 && version.minor == 0) {
manifests.map.insert(
@@ -1249,6 +1255,7 @@ mod github {
pub(crate) struct Release {
pub(crate) tag_name: String,
pub(crate) prerelease: bool,
pub(crate) published_at: jiff::Timestamp,
pub(crate) assets: Vec<ReleaseAsset>,
}