CVE-2025-58359 Overview
ZF FROST is a Rust implementation of FROST (Flexible Round-Optimised Schnorr Threshold signatures) maintained by the Zcash Foundation. CVE-2025-58359 affects versions 2.0.0 through 2.1.0 of the frost-core crate. The frost_core::keys::refresh module silently ignores attempts to change min_signers when refreshing shares. Participants who believe they have lowered the signing threshold retain the original threshold, and the refreshed shares remain usable alongside the original threshold, weakening the security of participant shares. The issue is fixed in version 2.2.0.
Critical Impact
A participant that refreshes shares with a smaller min_signers value gains no threshold reduction, but signing remains possible under the original threshold, potentially reducing the security guarantees of the refreshed key material.
Affected Products
- ZF FROST frost-core version 2.0.0
- ZF FROST frost-core versions 2.0.x through 2.1.0
- Downstream crates depending on the vulnerable frost-core refresh module
Discovery Timeline
- 2025-09-05 - CVE-2025-58359 published to NVD
- 2026-06-17 - Last updated in NVD database
Technical Details for CVE-2025-58359
Vulnerability Analysis
FROST is a threshold Schnorr signature scheme where a group of n participants can sign a message provided that at least min_signers (the threshold t) cooperate. The frost_core::keys::refresh module allows participants to rotate their shares while preserving the same underlying group key. The API accepts a min_signers parameter, which users could reasonably assume would update the operational threshold for the refreshed shares.
In versions 2.0.0 through 2.1.0, the refresh routine does not enforce or update the threshold parameter. Passing a smaller min_signers value produces refreshed shares that still bind to the original threshold. Signing attempts using the smaller threshold fail, but signing using the original threshold continues to succeed with the refreshed shares. As a result, both the old and refreshed share sets can be used to sign under the original threshold, undermining the intended isolation between share generations and weakening protection of individual participant shares. This class of weakness is tracked as [CWE-325: Missing Cryptographic Step].
Root Cause
The root cause is missing input validation on the min_signers argument in the refresh flow. The refresh module never rejects an inconsistent threshold nor propagates the new value into the derived share structures. Documentation also failed to communicate that threshold changes are unsupported by refresh, leading to user assumptions inconsistent with the implementation.
Attack Vector
Exploitation requires a legitimate participant with low privileges to invoke the refresh workflow with a smaller min_signers value, either accidentally or intentionally. Because the original threshold remains valid against the refreshed shares, any adversary that later obtains a sufficient subset of shares matching the original threshold can forge signatures. The impact is limited to confidentiality and integrity of the threshold key material for participants that performed the erroneous refresh.
// Patch excerpt from frost-core: refresh: validate min_signers (#908)
// Source: https://github.com/ZcashFoundation/frost/commit/379ef689c733b3d9c80fd409071d4f3af4dafed2
/// `round1_packages` maps the identifier of each other participant to the
/// [`round1::Package`] they sent to the current participant (the owner of
/// `secret_package`). These identifiers must come from whatever mapping the
/// participant has between communication channels and participants, i.e. they
/// must have assurance that the [`round1::Package`] came from the participant
/// with that identifier.
See the GitHub commit 379ef68 for the full fix that adds validation of min_signers during refresh.
Detection Methods for CVE-2025-58359
Indicators of Compromise
- Presence of frost-core versions 2.0.0 through 2.1.0 in Cargo.lock or dependency manifests.
- Application logs showing calls to frost_core::keys::refresh with a min_signers value different from the original threshold.
- Signing operations that succeed with shares from different refresh generations under the same threshold.
Detection Strategies
- Perform software composition analysis on Rust projects and container images to enumerate frost-core versions across builds and artifacts.
- Audit source code for invocations of the frost_core::keys::refresh module and verify that the caller-supplied min_signers matches the original group threshold.
- Review key management runbooks and ceremony logs to identify prior refresh operations performed with mismatched thresholds.
Monitoring Recommendations
- Instrument threshold-signing services to record the generation and threshold associated with each refresh, and alert on drift.
- Track dependency updates in CI/CD pipelines and fail builds pinned to frost-core < 2.2.0.
- Monitor signer coordinator services for anomalous signing sessions that combine shares from multiple refresh generations.
How to Mitigate CVE-2025-58359
Immediate Actions Required
- Upgrade frost-core and dependent crates to version 2.2.0 or later across all environments.
- Inventory any prior refresh operations that attempted to change min_signers and treat the associated shares as potentially weakened.
- Rotate group keys where refresh was previously invoked with an inconsistent threshold, rather than relying on refresh alone.
Patch Information
The fix is available in frost-core v2.2.0. Details of the input validation change are described in GHSA-wgq8-vr6r-mqxm and implemented in commit 379ef68. Version 2.2.0 rejects refresh calls whose min_signers value does not match the original threshold.
Workarounds
- Do not call frost_core::keys::refresh with a min_signers value different from the group's original threshold until upgrading.
- Wrap the refresh API in a project-local helper that asserts the requested threshold equals the current threshold and rejects mismatches.
- If a threshold change is required, perform a full distributed key generation (DKG) with the new threshold rather than using refresh.
# Update the pinned frost-core version and rebuild
cargo update -p frost-core --precise 2.2.0
cargo tree -i frost-core # verify no transitive dependency pulls in <2.2.0
cargo build --release
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.