fix(config): resolve trust hash collision for same-name directories#8628
fix(config): resolve trust hash collision for same-name directories#8628
Conversation
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses a subtle but critical bug in how trust hash and monorepo marker files were named, which could lead to hash collisions and compromise the paranoid mode's trust verification. The issue stemmed from Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
Greptile SummaryThis PR fixes a trust-hash filename collision in Key changes:
Confidence Score: 4/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[mise trust path] --> B[trust_path: hash path filename]
B --> C["hashed_path = ~/.mise/trusted-configs/dir-file-HASH"]
C --> D[write symlink at hashed_path]
D --> E{paranoid mode?}
E -- yes --> F["with_appended_extension(hashed_path, 'hash')"]
F --> G["writes ~/.mise/trusted-configs/dir-file-HASH.hash"]
E -- no --> Z[done]
H[mise untrust path] --> I[trust_path]
I --> J[remove hashed_path if exists]
J --> K["with_appended_extension(hashed_path, 'hash') → remove .hash file"]
K --> L["with_appended_extension(hashed_path, 'monorepo') → remove .monorepo file"]
M[is_trusted path] --> N{paranoid?}
N -- yes --> O["trust_file_hash: with_appended_extension(trust_path, 'hash')"]
O --> P[read stored hash, compare with current file hash]
N -- no --> Q{monorepo walk?}
Q -- yes --> R["with_appended_extension(trust_path dir, 'monorepo') exists?"]
R -- yes --> S[trusted]
R -- no --> T[walk to parent dir]
Last reviewed commit: e09b622 |
8abad7f to
58121ba
Compare
There was a problem hiding this comment.
Code Review
This pull request correctly fixes a hash collision bug by introducing a with_appended_extension helper function to append extensions to filenames instead of replacing them. The change is applied consistently across all relevant locations for handling trust hashes and monorepo markers. The addition of a unit test for the new helper function is a great way to ensure its correctness. I have one suggestion to make the new helper function more robust.
|
|
||
| /// Appends an extension to a path without replacing existing dots in the filename. | ||
| /// Unlike `Path::with_extension`, this preserves the full filename. | ||
| /// e.g. "foo-bar.toml-abc123" + "hash" → "foo-bar.toml-abc123.hash" | ||
| /// | ||
| /// NOTE: This changes the filename convention for .hash and .monorepo files. |
There was a problem hiding this comment.
While the current implementation is correct for its usage context, it could be made more robust and idiomatic by operating on the OsString of the whole path. This avoids the unwrap() on file_name(), which could panic if the function is ever called with a path that has no filename component (e.g., / or . or ..).
| /// Appends an extension to a path without replacing existing dots in the filename. | |
| /// Unlike `Path::with_extension`, this preserves the full filename. | |
| /// e.g. "foo-bar.toml-abc123" + "hash" → "foo-bar.toml-abc123.hash" | |
| /// | |
| /// NOTE: This changes the filename convention for .hash and .monorepo files. | |
| fn with_appended_extension(path: &Path, ext: &str) -> PathBuf { | |
| let mut os_string = path.as_os_str().to_owned(); | |
| os_string.push("."); | |
| os_string.push(ext); | |
| PathBuf::from(os_string) | |
| } |
PathBuf::with_extension("hash") replaces everything after the last dot
in the trust filename. Since hashed filenames contain dots (e.g.
"infra-mise.toml-a1b2c3d4"), this causes all configs with the same
parent directory leaf name to share a single hash file, silently
breaking paranoid mode trust verification and monorepo markers.
Replace with_extension() with a helper that appends the extension to
the full filename instead of replacing.
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
58121ba to
e09b622
Compare
### 🐛 Bug Fixes - **(config)** resolve trust hash collision for same-name directories by @tdragon in [#8628](#8628) - **(docs)** fix width of tools table by @himkt in [#8625](#8625) - **(docs)** prevent homepage hero atmosphere overflow by @nygmaaa in [#8642](#8642) - **(doctor)** detect PATH ordering issues when mise is activated by @jdx in [#8585](#8585) - **(git)** use origin as remote name by @bentinata in [#8626](#8626) - **(installer)** normalize current version before comparison by @tak848 in [#8649](#8649) - **(lockfile)** Resolve symlink when updating lockfiles by @chancez in [#8589](#8589) - **(python)** verify checksums for precompiled binary downloads by @malept in [#8593](#8593) - **(rust)** resolve relative CARGO_HOME/RUSTUP_HOME to absolute paths by @simonepri in [#8604](#8604) - **(task)** correctly resolve task name for _default files with extensions by @youta1119 in [#8646](#8646) - **(tasks)** global file tasks not properly marked as such by @roele in [#8618](#8618) - **(tasks)** handle broken pipe in table print and task completion output by @vmaleze in [#8608](#8608) - use dark/light logo variants in README for GitHub dark mode by @jdx in [#8656](#8656) - failing rebuild of runtime symlinks for shared tools by @roele in [#8647](#8647) - add spaces around current element operator in flutter version_expr by @roele in [#8616](#8616) - complete task arguments correctly by @KevSlashNull in [#8601](#8601) ### 📚 Documentation - switch body font to DM Sans and darken dark mode background by @jdx in [6e3ad34](6e3ad34) - use Cormorant Garamond for headers and Roc Grotesk for body text by @jdx in [010812a](010812a) - resolve chaotic heading hierarchy in task-arguments.md by @muzimuzhi in [#8644](#8644) ### 🧪 Testing - fix test_java and mark as slow by @roele in [#8634](#8634) ### 📦️ Dependency Updates - update docker/dockerfile:1 docker digest to 4a43a54 by @renovate[bot] in [#8657](#8657) - update ghcr.io/jdx/mise:alpine docker digest to 2584470 by @renovate[bot] in [#8658](#8658) ### 📦 Registry - add viteplus (npm:vite-plus) by @risu729 in [#8594](#8594) - remove backend.options for podman by @roele in [#8633](#8633) - add pi.dev coding agent by @dector in [#8635](#8635) - add ormolu ([github:tweag/ormolu](https://github.com/tweag/ormolu)) by @3w36zj6 in [#8617](#8617) - use version_expr for dart and sort versions by @roele in [#8631](#8631) ### New Contributors - @bentinata made their first contribution in [#8626](#8626) - @tdragon made their first contribution in [#8628](#8628) - @nygmaaa made their first contribution in [#8642](#8642) - @youta1119 made their first contribution in [#8646](#8646) - @chancez made their first contribution in [#8589](#8589) - @dector made their first contribution in [#8635](#8635) - @tak848 made their first contribution in [#8649](#8649) ## 📦 Aqua Registry Updates #### New Packages (5) - [`acsandmann/rift`](https://github.com/acsandmann/rift) - [`alltuner/mise-completions-sync`](https://github.com/alltuner/mise-completions-sync) - [`berbicanes/apiark`](https://github.com/berbicanes/apiark) - [`gitlab.com/graphviz/graphviz`](https://github.com/gitlab.com/graphviz/graphviz) - [`jorgelbg/pinentry-touchid`](https://github.com/jorgelbg/pinentry-touchid) #### Updated Packages (7) - [`UpCloudLtd/upcloud-cli`](https://github.com/UpCloudLtd/upcloud-cli) - [`aquaproj/registry-tool`](https://github.com/aquaproj/registry-tool) - [`go-swagger/go-swagger`](https://github.com/go-swagger/go-swagger) - [`gopinath-langote/1build`](https://github.com/gopinath-langote/1build) - [`sassman/t-rec-rs`](https://github.com/sassman/t-rec-rs) - [`sharkdp/fd`](https://github.com/sharkdp/fd) - [`temporalio/cli`](https://github.com/temporalio/cli)
Summary
PathBuf::with_extension("hash")replaces everything after the last.in the trust filename, but hashed filenames contain dots (e.g.infra-mise.toml-a1b2c3d4)/projectA/infra/mise.tomland/projectB/infra/mise.tomlproduceinfra-mise.hash), silently breaking paranoid mode trust verification.monorepoextension)with_extension()with a helper that appends the extension to the full filename instead of replacing ituntrust()to also remove.hashand.monoreposidecar files, preventing stale trust state in paranoid modeRelated: #4499
Note: Existing
.hashand.monorepofiles from prior versions use a different filename convention and will be silently ignored after upgrade. Previously trusted configs will need a one-timemise trustafter upgrading. This is acceptable since the old files were unreliable due to the collision bug.Test plan
with_extensionproduces identical paths for different configswith_appended_extensionhelpercargo testpasses (532 tests)cargo clippyclean🤖 Generated with Claude Code