What changed, and why it matters
This commit fixes a design bug in a Rust Bitcoin library. The library claimed a certain internal trait called Tag was 'sealed' (meaning only the library authors could add new types that satisfy it), but it actually was not sealed. The commit properly seals it so outside users cannot create new Tag types. This is a defensive API-correctness change, not a fix for an active security vulnerability. It prevents future misuse rather than closing an exploitable hole.
No urgent action required. Treat as a normal API-correctness improvement. Reviewers may want to confirm no other 'sealed' traits in the crate have the same documentation/implementation mismatch, and verify that downstream crates do not rely on implementing Tag themselves.
Security signals we found
Trait sealing mismatch between documentation and implementation
Prevents arbitrary user-defined types from satisfying the Tag trait
Defensive API-hardening change with no direct exploit path visible in the diff
Evidence from the diff
The Tag trait in primitives/src/script/tag.rs was documented as sealed but had no actual sealing mechanism. The commit adds a private sealed::Sealed trait and makes Tag: sealed::Sealed, then implements Sealed only for the existing concrete tag types (RedeemScriptTag, ScriptSigTag, ScriptPubKeyTag, SignetBlockScriptTag, TapScriptTag, WitnessScriptTag). This prevents downstream crates from implementing Tag for arbitrary types, preserving the intended closed set of script tags and avoiding potential misuse of generic Script<Tag> APIs.
Changed components
primitives/src/script/tag.rsbitcoin_primitives::script::Tag traitbitcoin_primitives::script::sealed::Sealed traitInspect captured patch +13 / −3
diff --git a/primitives/api/all-features.txt b/primitives/api/all-features.txt
index 08d337fa..2a961024 100644
--- a/primitives/api/all-features.txt
+++ b/primitives/api/all-features.txt
@@ -3540,7 +3540,7 @@ pub fn bitcoin_primitives::script::PushBytesErrorReport::input_len(&self) -> usi
impl bitcoin_primitives::script::PushBytesErrorReport for core::convert::Infallible
pub fn core::convert::Infallible::input_len(&self) -> usize
pub trait bitcoin_primitives::script::ScriptHashableTag: bitcoin_primitives::script::sealed::Sealed
-pub trait bitcoin_primitives::script::Tag
+pub trait bitcoin_primitives::script::Tag: bitcoin_primitives::script::tag::sealed::Sealed
pub type bitcoin_primitives::script::RedeemScript = bitcoin_primitives::script::Script<bitcoin_primitives::script::RedeemScriptTag>
pub type bitcoin_primitives::script::RedeemScriptBuf = bitcoin_primitives::script::ScriptBuf<bitcoin_primitives::script::RedeemScriptTag>
pub type bitcoin_primitives::script::ScriptPubKey = bitcoin_primitives::script::Script<bitcoin_primitives::script::ScriptPubKeyTag>
diff --git a/primitives/api/alloc-only.txt b/primitives/api/alloc-only.txt
index e3cb82c0..b06496de 100644
--- a/primitives/api/alloc-only.txt
+++ b/primitives/api/alloc-only.txt
@@ -3377,7 +3377,7 @@ pub fn bitcoin_primitives::script::PushBytesErrorReport::input_len(&self) -> usi
impl bitcoin_primitives::script::PushBytesErrorReport for core::convert::Infallible
pub fn core::convert::Infallible::input_len(&self) -> usize
pub trait bitcoin_primitives::script::ScriptHashableTag: bitcoin_primitives::script::sealed::Sealed
-pub trait bitcoin_primitives::script::Tag
+pub trait bitcoin_primitives::script::Tag: bitcoin_primitives::script::tag::sealed::Sealed
pub type bitcoin_primitives::script::RedeemScript = bitcoin_primitives::script::Script<bitcoin_primitives::script::RedeemScriptTag>
pub type bitcoin_primitives::script::RedeemScriptBuf = bitcoin_primitives::script::ScriptBuf<bitcoin_primitives::script::RedeemScriptTag>
pub type bitcoin_primitives::script::ScriptPubKey = bitcoin_primitives::script::Script<bitcoin_primitives::script::ScriptPubKeyTag>
diff --git a/primitives/src/script/tag.rs b/primitives/src/script/tag.rs
index 31d96adb..37a89e73 100644
--- a/primitives/src/script/tag.rs
+++ b/primitives/src/script/tag.rs
@@ -6,7 +6,17 @@
//! in Bitcoin transactions.
/// Sealed trait representing a type of script.
-pub trait Tag {}
+pub trait Tag: sealed::Sealed {}
+
+mod sealed {
+ pub trait Sealed {}
+ impl Sealed for super::RedeemScriptTag {}
+ impl Sealed for super::ScriptSigTag {}
+ impl Sealed for super::ScriptPubKeyTag {}
+ impl Sealed for super::SignetBlockScriptTag {}
+ impl Sealed for super::TapScriptTag {}
+ impl Sealed for super::WitnessScriptTag {}
+}
/// A P2SH redeem script.
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
Why this scored 18/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.