Remove mutable impls from ecdsa SerializedSignature
What changed, and why it matters
This commit removes the ability for outside code to directly modify the raw bytes of an ECDSA serialized signature object in the rust-bitcoin library. Previously, callers could obtain a mutable reference to the internal byte buffer and change it, which the developers consider meaningless because a signature is supposed to be a fixed cryptographic result. The change makes the type consistent with the taproot signature type, which already did not allow mutation. It is a hardening/correctness change rather than a fix for a known exploitable vulnerability.
Treat as a low-risk API-hardening change. Review downstream code that may have relied on `AsMut`, `BorrowMut`, or `DerefMut` for `SerializedSignature`; such code will fail to compile and must be updated. No immediate security response is indicated unless independent evidence shows that the removed mutable access was exploitable in practice.
Security signals we found
Removal of mutable access to serialized cryptographic data
API hardening to prevent arbitrary mutation of a signature object
Consistency with another signature type (taproot) that lacks mutable references
Evidence from the diff
The patch deletes three mutable trait implementations from bitcoin/src/crypto/ecdsa.rs for the SerializedSignature type: AsMut<[u8]>, BorrowMut<[u8]>, and DerefMut<Target = [u8]>. These impls allowed external code to get &mut [u8] access to the underlying data array and len field, enabling arbitrary byte-level mutation of a supposedly immutable serialized DER signature. Removing them prevents callers from mutating the serialized form after creation and aligns the ECDSA type with the taproot signature type, which lacks such mutable APIs. The commit message frames this as API hardening: mutation of a serialized signature is ‘meaningless’ and undesirable.
Changed components
bitcoin/src/crypto/ecdsa.rsSerializedSignature typeAsMut<[u8]> implBorrowMut<[u8]> implDerefMut implInspect captured patch +0 / −15
diff --git a/bitcoin/src/crypto/ecdsa.rs b/bitcoin/src/crypto/ecdsa.rs
index c87a7321..8610d1c1 100644
--- a/bitcoin/src/crypto/ecdsa.rs
+++ b/bitcoin/src/crypto/ecdsa.rs
@@ -195,11 +195,6 @@ impl AsRef<[u8]> for SerializedSignature {
fn as_ref(&self) -> &[u8] { self }
}
-impl AsMut<[u8]> for SerializedSignature {
- #[inline]
- fn as_mut(&mut self) -> &mut [u8] { self }
-}
-
impl AsRef<PushBytes> for SerializedSignature {
#[inline]
fn as_ref(&self) -> &PushBytes { &<&PushBytes>::from(&self.data)[..self.len()] }
@@ -210,11 +205,6 @@ impl core::borrow::Borrow<[u8]> for SerializedSignature {
fn borrow(&self) -> &[u8] { self }
}
-impl core::borrow::BorrowMut<[u8]> for SerializedSignature {
- #[inline]
- fn borrow_mut(&mut self) -> &mut [u8] { self }
-}
-
impl core::ops::Deref for SerializedSignature {
type Target = [u8];
@@ -222,11 +212,6 @@ impl core::ops::Deref for SerializedSignature {
fn deref(&self) -> &Self::Target { &self.data[..self.len] }
}
-impl core::ops::DerefMut for SerializedSignature {
- #[inline]
- fn deref_mut(&mut self) -> &mut Self::Target { &mut self.data[..self.len] }
-}
-
impl<'a> IntoIterator for &'a SerializedSignature {
type IntoIter = core::slice::Iter<'a, u8>;
type Item = &'a u8;
Why this scored 20/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.