feat(vfox): add provenance metadata to lockfile for tool plugins#8544
feat(vfox): add provenance metadata to lockfile for tool plugins#8544
Conversation
Add VerifiedAttestation enum to represent the type of attestation that was successfully verified (GithubAttestations, Slsa, Cosign). Re-export VerifiedAttestation and InstallResult from vfox crate lib so they are accessible to the main mise backend code. Add test-attestation plugin fixture and snapshot test, plus 5 unit tests for PreInstallAttestation validation helpers. Assisted-By: claude-sonnet-4.6 via OpenCode
…gh InstallResult Change verify() to return Result<Option<VerifiedAttestation>> instead of Result<()>, tracking the highest-priority attestation that was successfully verified (GitHub > SLSA > Cosign). Add verified_attestation field to InstallResult so callers can inspect what was verified. Assisted-By: claude-sonnet-4.6 via OpenCode
After a vfox plugin install, convert the VerifiedAttestation returned by verify() into a ProvenanceType and record it in the tool version's lock_platforms entry. Before install, capture the expected provenance from the lockfile and enforce it afterwards using discriminant comparison, raising a downgrade-attack error if the verification result does not match what was previously locked. Assisted-By: claude-sonnet-4.6 via OpenCode
Add pre_install_provenance_for_platform() to the Vfox crate, which extracts the highest-priority attestation type declared by a plugin for a target platform without performing actual verification. Override resolve_lock_info() in VfoxBackend to call this method and include the provenance type in the PlatformInfo written to the lockfile during `mise lock`. Assisted-By: claude-sonnet-4.6 via OpenCode
Update the vfox backend docs to mention GitHub artifact attestation support and provenance recording in the lockfile, noting that this applies to tool plugins only (not backend plugins). Add vfox to the full-support tier in mise-lock.md and note all backends with provenance support (aqua, github, vfox tool plugins, core:ruby, core:zig). Add a sync comment on ProvenanceType pointing to VerifiedAttestation in the vfox crate. Assisted-By: claude-sonnet-4.6 via OpenCode
…ement Add an e2e test that verifies: 1. `mise lock` writes a URL for a vfox tool (vfox:version-fox/vfox-cmake) 2. Injecting provenance into the lockfile and attempting install fails with a downgrade attack error when the plugin does not perform attestation verification The test uses the awk-injection pattern from the aqua provenance test, avoiding any real sigstore verification. Assisted-By: claude-sonnet-4.6 via OpenCode
SLSA provenance_path from vfox plugins is a local filesystem path that
is only valid during the install session. Using format!("file://{}",
path) produced malformed URIs for relative/Windows paths and stored
ephemeral data in the lockfile. Change to url: None to match how the
github and aqua backends handle SLSA provenance at lock-time.
Also simplify the e2e test AWK script by removing the broken section
tracking logic (in_section was set and immediately reset on the same
line due to rule ordering). Since we always generate a fresh lockfile
before injection, there are no pre-existing provenance lines to remove.
Assisted-By: claude-sonnet-4.6 via OpenCode
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 significantly enhances the supply-chain security of 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
|
There was a problem hiding this comment.
Code Review
This pull request introduces comprehensive support for attestation verification in vfox tool plugins, allowing mise to verify GitHub artifact attestations, SLSA provenance, and Cosign signatures. The changes include adding a new VerifiedAttestation enum to represent different verification types, updating the InstallResult to store the verified attestation, and modifying the verify function to return the highest-priority successful attestation. A new pre_install_provenance_for_platform function was added to retrieve attestation information without full installation. The vfox backend now integrates with mise's lockfile system to record and enforce provenance, preventing downgrade attacks by comparing expected lockfile provenance with actual verification results. New Lua plugin files and Rust tests were added to demonstrate and validate the attestation functionality, alongside updates to documentation reflecting the enhanced security features.
Greptile SummaryThis PR wires Key changes:
Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant MiseCore as mise core
participant VfoxBackend as VfoxBackend
participant VfoxCrate as vfox crate
participant Plugin as Lua Plugin
Note over User,Plugin: mise install (install_version_)
User->>MiseCore: mise install
MiseCore->>VfoxBackend: install_version_(ctx, tv)
VfoxBackend->>VfoxBackend: extract locked_provenance from tv (take)
VfoxBackend->>VfoxCrate: install(sdk, version, path)
VfoxCrate->>Plugin: PreInstall(ctx)
Plugin-->>VfoxCrate: PreInstall { url, attestation }
VfoxCrate->>VfoxCrate: download(url)
VfoxCrate->>VfoxCrate: verify(pre_install, file) → Option<VerifiedAttestation>
VfoxCrate->>VfoxCrate: extract(file, install_dir)
VfoxCrate-->>VfoxBackend: InstallResult { sha256, verified_attestation }
VfoxBackend->>VfoxBackend: verified_attestation_to_provenance()
VfoxBackend->>VfoxBackend: write provenance to tv.lock_platforms
VfoxBackend->>VfoxBackend: compare got vs locked_provenance (discriminant check)
alt Provenance mismatch
VfoxBackend-->>MiseCore: Err("downgrade attack")
else Match or no expectation
VfoxBackend-->>MiseCore: Ok(tv with provenance)
end
Note over User,Plugin: mise lock (resolve_lock_info)
User->>MiseCore: mise lock
MiseCore->>VfoxBackend: resolve_lock_info(tv, target)
VfoxBackend->>VfoxCrate: pre_install_provenance_for_platform(sdk, version, os, arch)
VfoxCrate->>Plugin: PreInstallForPlatform(ctx)
Plugin-->>VfoxCrate: PreInstall { url, attestation }
VfoxCrate->>VfoxCrate: attestation_to_verified(attestation)
VfoxCrate-->>VfoxBackend: (url, Option<VerifiedAttestation>)
VfoxBackend->>VfoxBackend: verified_attestation_to_provenance()
VfoxBackend-->>MiseCore: PlatformInfo { url, provenance }
MiseCore-->>User: writes mise.lock
Last reviewed commit: 28a5456 |
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Backend plugins use backend_install and have no PreInstall hook. Calling pre_install_provenance_for_platform on one would fail with a Lua error. Add an early return with PlatformInfo::default(), matching the is_backend_plugin() guard already present in install_version_(). Note: get_tarball_url has the same pre-existing issue but is not addressed here to keep this PR scoped. Assisted-By: claude-sonnet-4.6 via OpenCode
Assisted-By: claude-sonnet-4.6 via OpenCode
vfox tool plugins provide version + URL + provenance in the lockfile but do not populate checksum or size fields. Move from Full support to its own Partial support line to accurately reflect this. Assisted-By: claude-sonnet-4.6 via OpenCode
Assisted-By: claude-sonnet-4.6 via OpenCode
…nce_for_platform Assisted-By: claude-sonnet-4.6 via OpenCode
Minisign is intentionally absent (not just 'excluded') because vfox plugins do not produce Minisign signatures. The updated comment explains why the subset exists and gives clear guidance for extending both enums. Assisted-By: claude-sonnet-4.6 via OpenCode
…mments All three attestation verifications always execute — none short-circuits the others. The priority ordering only controls which variant is recorded in 'verified'. Updated inline comments to make this distinction explicit so readers aren't misled into thinking early verification prevents later ones from running. Assisted-By: claude-sonnet-4.6 via OpenCode
…ping The same mise→vfox OS/arch name mapping was duplicated in get_tarball_url and resolve_lock_info. Extracted into a private to_vfox_platform() helper on VfoxBackend. Assisted-By: claude-sonnet-4.6 via OpenCode
validate_github_artifact_attestation_params handles both directions but only the owner-without-repo direction was tested. Add the mirror case. Assisted-By: claude-sonnet-4.6 via OpenCode
The previous message said 'Enable the corresponding verification setting' which is guidance for aqua/github backends where the user controls attestation flags. For vfox, attestation is declared entirely by the plugin — there is no user-facing setting. The updated message directs the user to update the lockfile or investigate the plugin change. Assisted-By: claude-sonnet-4.6 via OpenCode
…sult The SLSA guard condition only exempts GithubAttestations, so a prior Cosign result is intentionally overwritten. Make this explicit. Assisted-By: claude-sonnet-4.6 via OpenCode
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
If install fails, tv is discarded via ?, so the taken value is never observed. A future refactor that recovers from install errors would need to restore locked_provenance to tv before retrying. Assisted-By: claude-sonnet-4.6 via OpenCode
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
### 🚀 Features - **(github)** use release latest endpoint to get latest release by @roele in [#8516](#8516) - **(install)** add shared and system install directories by @jdx in [#8581](#8581) - **(vfox)** add provenance metadata to lockfile for tool plugins by @malept in [#8544](#8544) ### 🐛 Bug Fixes - **(aqua)** expose main binary when files field is empty and symlink_bins is enabled by @AlexanderTheGrey in [#8550](#8550) - **(env)** redact secrets in `mise set` listing and task-specific env by @jdx in [#8583](#8583) - **(prepare)** install config tools before running prepare steps by @jdx in [#8582](#8582) - **(task)** allow ctrl-c to interrupt tool downloads during `mise run` by @jdx in [#8571](#8571) - **(tasks)** add file task header parser support for spaces around = by @roele in [#8574](#8574) ### 📚 Documentation - **(task)** add property description for interactive by @roele in [#8562](#8562) - add missing `</bold>` closing tag by @muzimuzhi in [#8564](#8564) - rebrand site with new chef logo and warm culinary palette by @jdx in [#8587](#8587) ### 📦️ Dependency Updates - update ghcr.io/jdx/mise:alpine docker digest to de4657e by @renovate[bot] in [#8577](#8577) - update ghcr.io/jdx/mise:copr docker digest to eef29a2 by @renovate[bot] in [#8578](#8578) - update ghcr.io/jdx/mise:rpm docker digest to 5a96587 by @renovate[bot] in [#8580](#8580) - update ghcr.io/jdx/mise:deb docker digest to 464cf7c by @renovate[bot] in [#8579](#8579) ### 📦 Registry - fix flatc version test mismatch by @jdx in [#8588](#8588) ### Chore - **(registry)** skip spark test-tool by @jdx in [#8572](#8572) ### New Contributors - @AlexanderTheGrey made their first contribution in [#8550](#8550) ## 📦 Aqua Registry Updates #### New Packages (6) - [`bahdotsh/mdterm`](https://github.com/bahdotsh/mdterm) - [`callumalpass/mdbase-lsp`](https://github.com/callumalpass/mdbase-lsp) - [`facebook/ktfmt`](https://github.com/facebook/ktfmt) - [`gurgeous/tennis`](https://github.com/gurgeous/tennis) - [`tektoncd/pipelines-as-code`](https://github.com/tektoncd/pipelines-as-code) - [`weedonandscott/trolley`](https://github.com/weedonandscott/trolley) #### Updated Packages (2) - [`apple/container`](https://github.com/apple/container) - [`cocogitto/cocogitto`](https://github.com/cocogitto/cocogitto)
…#8544) # Summary - Wire `PreInstallAttestation` (returned by vfox tool plugin `PreInstall` hooks) through to `PlatformInfo.provenance` in `mise.lock`, covering both `mise install` and `mise lock` - Brings vfox tool plugins to parity with aqua and github backends for supply-chain provenance tracking and downgrade-attack detection - Does not apply to vfox backend plugins (they use `backend_install`, which has no `PreInstall` hook) ## Details - **`VerifiedAttestation` enum** in vfox crate: `GithubAttestations`, `Slsa`, `Cosign` — represents the highest-priority attestation that was successfully verified (GitHub > SLSA > Cosign) - **`verify()` return type** changed from `Result<()>` to `Result<Option<VerifiedAttestation>>`; threaded through `InstallResult` so callers can inspect what was verified - **Provenance recording + enforcement** in `install_version_()`: records `ProvenanceType` in lockfile after install, and raises a "downgrade attack" error on subsequent installs if the lockfile expected provenance that wasn't verified - **`resolve_lock_info()` override**: calls new `pre_install_provenance_for_platform()` to populate provenance in the lockfile during `mise lock`. This trusts the plugin's declared attestation fields (e.g. `github_owner`/`github_repo`, `slsa_provenance_path`) to infer provenance type without running actual sigstore/cosign verification — consistent with how `mise lock` works for other backends (query plugin metadata, don't verify signatures). Actual verification only runs during `mise install` - **SLSA URL handling**: uses `url: None` for vfox SLSA provenance (matching github/aqua backends) since the local filesystem path to the downloaded provenance file is ephemeral - **Crate boundary**: `VerifiedAttestation` (attestation verification mechanics) lives in the `vfox` crate, while `ProvenanceType` (lockfile schema) lives in `mise` core. The `verified_attestation_to_provenance()` bridge in `src/backend/vfox.rs` maps between the two, keeping the vfox crate independent of mise's lockfile format - **Docs**: updated vfox.md security bullet and mise-lock.md backend support matrix to note provenance support for `aqua`, `github`, `vfox` (tool plugins only), `core:ruby` (precompiled), `core:zig` (install-time) ## Test plan - [x] 6 unit tests for `PreInstallAttestation` validation (GitHub owner/repo, cosign key/sig, SLSA min-level/provenance-path) - [x] Snapshot test for `attestation` plugin fixture - [x] Unit test for `verified_attestation_to_provenance()` conversion - [x] E2E test: `mise lock` writes URL for vfox tool, injected provenance triggers downgrade-attack error on `mise install` - [x] All existing tests pass (`cargo test`, vfox crate tests, lints) 🤖 Generated with the assistance of OpenCode (claude-sonnet-4.6). --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
### 🚀 Features - **(github)** use release latest endpoint to get latest release by @roele in [jdx#8516](jdx#8516) - **(install)** add shared and system install directories by @jdx in [jdx#8581](jdx#8581) - **(vfox)** add provenance metadata to lockfile for tool plugins by @malept in [jdx#8544](jdx#8544) ### 🐛 Bug Fixes - **(aqua)** expose main binary when files field is empty and symlink_bins is enabled by @AlexanderTheGrey in [jdx#8550](jdx#8550) - **(env)** redact secrets in `mise set` listing and task-specific env by @jdx in [jdx#8583](jdx#8583) - **(prepare)** install config tools before running prepare steps by @jdx in [jdx#8582](jdx#8582) - **(task)** allow ctrl-c to interrupt tool downloads during `mise run` by @jdx in [jdx#8571](jdx#8571) - **(tasks)** add file task header parser support for spaces around = by @roele in [jdx#8574](jdx#8574) ### 📚 Documentation - **(task)** add property description for interactive by @roele in [jdx#8562](jdx#8562) - add missing `</bold>` closing tag by @muzimuzhi in [jdx#8564](jdx#8564) - rebrand site with new chef logo and warm culinary palette by @jdx in [jdx#8587](jdx#8587) ### 📦️ Dependency Updates - update ghcr.io/jdx/mise:alpine docker digest to de4657e by @renovate[bot] in [jdx#8577](jdx#8577) - update ghcr.io/jdx/mise:copr docker digest to eef29a2 by @renovate[bot] in [jdx#8578](jdx#8578) - update ghcr.io/jdx/mise:rpm docker digest to 5a96587 by @renovate[bot] in [jdx#8580](jdx#8580) - update ghcr.io/jdx/mise:deb docker digest to 464cf7c by @renovate[bot] in [jdx#8579](jdx#8579) ### 📦 Registry - fix flatc version test mismatch by @jdx in [jdx#8588](jdx#8588) ### Chore - **(registry)** skip spark test-tool by @jdx in [jdx#8572](jdx#8572) ### New Contributors - @AlexanderTheGrey made their first contribution in [jdx#8550](jdx#8550) ## 📦 Aqua Registry Updates #### New Packages (6) - [`bahdotsh/mdterm`](https://github.com/bahdotsh/mdterm) - [`callumalpass/mdbase-lsp`](https://github.com/callumalpass/mdbase-lsp) - [`facebook/ktfmt`](https://github.com/facebook/ktfmt) - [`gurgeous/tennis`](https://github.com/gurgeous/tennis) - [`tektoncd/pipelines-as-code`](https://github.com/tektoncd/pipelines-as-code) - [`weedonandscott/trolley`](https://github.com/weedonandscott/trolley) #### Updated Packages (2) - [`apple/container`](https://github.com/apple/container) - [`cocogitto/cocogitto`](https://github.com/cocogitto/cocogitto)
Summary
PreInstallAttestation(returned by vfox tool pluginPreInstallhooks) through toPlatformInfo.provenanceinmise.lock, covering bothmise installandmise lockbackend_install, which has noPreInstallhook)Details
VerifiedAttestationenum in vfox crate:GithubAttestations,Slsa,Cosign— represents the highest-priority attestation that was successfully verified (GitHub > SLSA > Cosign)verify()return type changed fromResult<()>toResult<Option<VerifiedAttestation>>; threaded throughInstallResultso callers can inspect what was verifiedinstall_version_(): recordsProvenanceTypein lockfile after install, and raises a "downgrade attack" error on subsequent installs if the lockfile expected provenance that wasn't verifiedresolve_lock_info()override: calls newpre_install_provenance_for_platform()to populate provenance in the lockfile duringmise lock. This trusts the plugin's declared attestation fields (e.g.github_owner/github_repo,slsa_provenance_path) to infer provenance type without running actual sigstore/cosign verification — consistent with howmise lockworks for other backends (query plugin metadata, don't verify signatures). Actual verification only runs duringmise installurl: Nonefor vfox SLSA provenance (matching github/aqua backends) since the local filesystem path to the downloaded provenance file is ephemeralVerifiedAttestation(attestation verification mechanics) lives in thevfoxcrate, whileProvenanceType(lockfile schema) lives inmisecore. Theverified_attestation_to_provenance()bridge insrc/backend/vfox.rsmaps between the two, keeping the vfox crate independent of mise's lockfile formataqua,github,vfox(tool plugins only),core:ruby(precompiled),core:zig(install-time)Test plan
PreInstallAttestationvalidation (GitHub owner/repo, cosign key/sig, SLSA min-level/provenance-path)attestationplugin fixtureverified_attestation_to_provenance()conversionmise lockwrites URL for vfox tool, injected provenance triggers downgrade-attack error onmise installcargo test, vfox crate tests, lints)🤖 Generated with the assistance of OpenCode (claude-sonnet-4.6).