From 5c5f567bc870e4c81293a29a6e2a39198664d240 Mon Sep 17 00:00:00 2001 From: HackingGate Date: Thu, 22 Oct 2026 23:46:28 +0900 Subject: [PATCH] A mise lockfile is the manifest no-pinned-release-download asks for, so the rule no longer reads one `mise lock` records each aqua or github tool's artifact as a releases/download URL beside a per-platform checksum that `mise install` verifies, and Renovate's mise manager rewrites the lock with the row it bumps. The pin there is watched; the rule's own message asks for exactly that. A repository that commits its mise.lock was refused on every tool row. `**/mise.lock` joins the set's files.exclude and the repeated list in this repository's override. A corpus test holds the boundary: the same URL line passes in mise.lock, .config/mise/mise.lock and a nested mise.lock, and is still refused in install.sh. no-pinned-versioned-fetch needs no change: a lock row has no curl or wget. Claude-Session: https://claude.ai/code/session_01HM96sKSAyDhLk9smu82u5V --- policy/base/sets.lock.json | 3 ++- policy/base/unmanaged-pins.toml | 7 ++++++- policy/principles.toml | 2 +- tests/base_set_corpus.rs | 25 +++++++++++++++++++++++++ 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/policy/base/sets.lock.json b/policy/base/sets.lock.json index af1f438..4435501 100644 --- a/policy/base/sets.lock.json +++ b/policy/base/sets.lock.json @@ -293,7 +293,8 @@ "policy/**", "README.md", "third_party/**", - "vendor/**" + "vendor/**", + "**/mise.lock" ], "exclude_cfg_test": false, "include": [ diff --git a/policy/base/unmanaged-pins.toml b/policy/base/unmanaged-pins.toml index e7f39e1..fca9d51 100644 --- a/policy/base/unmanaged-pins.toml +++ b/policy/base/unmanaged-pins.toml @@ -128,7 +128,12 @@ Use the package manager, or a manifest entry a dependency bot can read. """ regexp = 'releases/download/v?[0-9]' files.include = ["."] -files.exclude = ["**/tests/**", "**/test/**", "**/*_test.go", "policy/**", "README.md", "third_party/**", "vendor/**"] +# mise.lock is the manifest this message asks for. `mise lock` writes each +# aqua or github tool's artifact as a releases/download URL beside a +# per-platform checksum that `mise install` verifies, and Renovate's mise +# manager rewrites the lock with the row it bumps. The URL there is the +# watched pin, rendered, not the unwatched one. +files.exclude = ["**/tests/**", "**/test/**", "**/*_test.go", "policy/**", "README.md", "third_party/**", "vendor/**", "**/mise.lock"] [rule.no-pinned-versioned-fetch] message = """ diff --git a/policy/principles.toml b/policy/principles.toml index 846ba93..86180f9 100644 --- a/policy/principles.toml +++ b/policy/principles.toml @@ -634,7 +634,7 @@ files.exclude = ["**/tests/**", "**/test/**", "**/*_test.go", "policy/**", "READ # line is its rendering. The set's exclude list is repeated for the reason the # override above gives. [override.no-pinned-release-download] -files.exclude = ["**/tests/**", "**/test/**", "**/*_test.go", "policy/**", "README.md", "third_party/**", "vendor/**", ".github/workflows/release.yml"] +files.exclude = ["**/tests/**", "**/test/**", "**/*_test.go", "policy/**", "README.md", "third_party/**", "vendor/**", "**/mise.lock", ".github/workflows/release.yml"] [override.no-pinned-versioned-fetch] files.exclude = ["**/tests/**", "**/test/**", "**/*_test.go", "policy/**", "README.md", "third_party/**", "vendor/**", ".github/workflows/release.yml"] diff --git a/tests/base_set_corpus.rs b/tests/base_set_corpus.rs index 672b084..2b81b27 100644 --- a/tests/base_set_corpus.rs +++ b/tests/base_set_corpus.rs @@ -607,6 +607,31 @@ fn tracker_references_are_refused_in_configuration_and_source() { } } +#[test] +fn a_mise_lockfile_is_not_read_by_the_release_download_rule() { + // `mise lock` records each tool's artifact as a releases/download URL + // beside a checksum mise verifies, so the lock is the manifest the rule + // asks for. The script path is the control: the same line is refused + // where nothing watches it. + let line = "url = \"https://github.com/gitleaks/gitleaks/releases/download/v8.30.1/gitleaks_8.30.1_linux_arm64.tar.gz\"\n"; + for (path, refused) in [ + ("install.sh", 1), + ("mise.lock", 0), + (".config/mise/mise.lock", 0), + ("tools/mise.lock", 0), + ] { + let case = Case { + set: "unmanaged-pins", + rule: "no-pinned-release-download", + path, + refuses: &[], + allows: &[], + }; + let (code, report) = verdict(&case, line); + assert_eq!(code, refused, "{path}: {report}"); + } +} + #[test] fn a_stylesheet_is_not_read_by_the_code_tracker_rule() { // `solid #000` is the prose-word arm's shape, and no pattern that keeps