commit 65eb3825d7f932535fba7fdb563108c7ff19e205
parent 265d1fbb21ec1ae7b17af2c554b60530b99be8da
Author: triesap <tyson@radroots.org>
Date: Sun, 14 Jun 2026 22:29:23 -0700
trade: prevent unchecked canonical draft deserialization
Diffstat:
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/crates/trade/src/listing/draft.rs b/crates/trade/src/listing/draft.rs
@@ -37,7 +37,7 @@ impl RadrootsListingDraftDocumentV1 {
}
}
-#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[derive(Clone, Debug)]
pub struct RadrootsCanonicalListingDraft {
listing: RadrootsListing,
@@ -266,6 +266,21 @@ mod tests {
assert_eq!(document.listing.product.title, "Coffee");
}
+ #[cfg(feature = "serde_json")]
+ #[test]
+ fn draft_document_deserializes_as_untrusted_input() {
+ let json = serde_json::to_string(&RadrootsListingDraftDocumentV1::new(listing()))
+ .expect("serialize document");
+
+ let document: RadrootsListingDraftDocumentV1 =
+ serde_json::from_str(&json).expect("deserialize document");
+ let canonical =
+ canonicalize_listing_draft(&seller_actor(), document).expect("canonical draft");
+
+ assert_eq!(canonical.seller_pubkey().as_str(), SELLER);
+ assert_eq!(canonical.listing().product.title, "Coffee");
+ }
+
#[test]
fn canonical_draft_carries_seller_listing_and_addresses() {
let seller_pubkey = RadrootsPublicKey::parse(SELLER).expect("seller");