From 2004e7c2996966d6ecf2086758bea268936d7e34 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Fri, 17 Apr 2026 12:06:37 -0400 Subject: [PATCH 1/5] chore: CON-1710 Reject missing subnet type when checking canister sig delegations --- rs/certification/src/lib.rs | 12 ++++++------ rs/certification/src/tests.rs | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/rs/certification/src/lib.rs b/rs/certification/src/lib.rs index 35455ea385fe..14ad43b3b1a3 100644 --- a/rs/certification/src/lib.rs +++ b/rs/certification/src/lib.rs @@ -161,12 +161,12 @@ pub fn verify_certified_data_with_cache_for_canister_sig( ) -> Result { let (time, delegation_info) = verify_certified_data_internal(certificate, canister_id, root_pk, certified_data, true)?; - if let Some(info) = delegation_info - && info.subnet_type.as_deref() == Some("cloud_engine") - { - return Err(CertificateValidationError::UntrustedDelegationSubnet( - info.subnet_id, - )); + if let Some(info) = delegation_info { + if info.subnet_type.is_none() || info.subnet_type.as_deref() == Some("cloud_engine") { + return Err(CertificateValidationError::UntrustedDelegationSubnet( + info.subnet_id, + )); + } } Ok(time) } diff --git a/rs/certification/src/tests.rs b/rs/certification/src/tests.rs index 7fd41badb695..680106dff9f7 100644 --- a/rs/certification/src/tests.rs +++ b/rs/certification/src/tests.rs @@ -1146,6 +1146,42 @@ fn should_reject_cloud_engine_delegation_via_canister_sig_path() { ); } +#[test] +fn should_reject_missing_subnet_type_delegation_via_canister_sig_path() { + let rng = &mut reproducible_rng(); + let subnet_id = subnet_id(42); + let cid = canister_id(1); + let certified_data = random_certified_data(); + + let (_cert, root_pk, cbor) = CertificateBuilder::new_with_rng( + CanisterData { + canister_id: cid, + certified_data: certified_data.clone(), + }, + rng, + ) + .with_delegation( + CertificateBuilder::new_with_rng( + SubnetData { + subnet_id, + canister_id_ranges: vec![(canister_id(0), canister_id(10))], + }, + rng, + ) + ) + .build(); + + assert_matches!( + verify_certified_data_with_cache_for_canister_sig( + &cbor, + &cid, + &root_pk, + certified_data.as_bytes(), + ), + Err(CertificateValidationError::UntrustedDelegationSubnet(_)) + ); +} + #[test] fn should_accept_delegation_with_non_cloud_engine_type() { let rng = &mut reproducible_rng(); From 3ce84b4be9dfb84440fca74e75c2be66238caa74 Mon Sep 17 00:00:00 2001 From: IDX GitHub Automation Date: Fri, 17 Apr 2026 16:11:51 +0000 Subject: [PATCH 2/5] Automatically fixing code for linting and formatting issues --- rs/certification/src/tests.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/rs/certification/src/tests.rs b/rs/certification/src/tests.rs index 680106dff9f7..800f746b95c6 100644 --- a/rs/certification/src/tests.rs +++ b/rs/certification/src/tests.rs @@ -1160,15 +1160,13 @@ fn should_reject_missing_subnet_type_delegation_via_canister_sig_path() { }, rng, ) - .with_delegation( - CertificateBuilder::new_with_rng( - SubnetData { - subnet_id, - canister_id_ranges: vec![(canister_id(0), canister_id(10))], - }, - rng, - ) - ) + .with_delegation(CertificateBuilder::new_with_rng( + SubnetData { + subnet_id, + canister_id_ranges: vec![(canister_id(0), canister_id(10))], + }, + rng, + )) .build(); assert_matches!( From f8adf9cc39d383eae9657962b2b275e677203d69 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Mon, 20 Apr 2026 09:26:55 -0400 Subject: [PATCH 3/5] Fix the clippy --- rs/certification/src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rs/certification/src/lib.rs b/rs/certification/src/lib.rs index 14ad43b3b1a3..b24cc9b390cd 100644 --- a/rs/certification/src/lib.rs +++ b/rs/certification/src/lib.rs @@ -161,12 +161,12 @@ pub fn verify_certified_data_with_cache_for_canister_sig( ) -> Result { let (time, delegation_info) = verify_certified_data_internal(certificate, canister_id, root_pk, certified_data, true)?; - if let Some(info) = delegation_info { - if info.subnet_type.is_none() || info.subnet_type.as_deref() == Some("cloud_engine") { - return Err(CertificateValidationError::UntrustedDelegationSubnet( - info.subnet_id, - )); - } + if let Some(info) = delegation_info + && (info.subnet_type.is_none() || info.subnet_type.as_deref() == Some("cloud_engine")) + { + return Err(CertificateValidationError::UntrustedDelegationSubnet( + info.subnet_id, + )); } Ok(time) } From 4c383500827de3773562fdc20eee696399fc3289 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Mon, 20 Apr 2026 10:07:57 -0400 Subject: [PATCH 4/5] Include the subnet type in the iccsa test helper --- rs/crypto/iccsa/test_utils/src/lib.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/rs/crypto/iccsa/test_utils/src/lib.rs b/rs/crypto/iccsa/test_utils/src/lib.rs index 958e8b972f63..4d748336e33f 100644 --- a/rs/crypto/iccsa/test_utils/src/lib.rs +++ b/rs/crypto/iccsa/test_utils/src/lib.rs @@ -55,13 +55,16 @@ fn conditionally_add_delegation_cert( rng: &mut R, ) -> CertificateBuilder { if with_delegation { - cert_builder.with_delegation(CertificateBuilder::new_with_rng( - CertificateData::SubnetData { - subnet_id: subnet_id(123), - canister_id_ranges: vec![(canister_id(0), canister_id(10))], - }, - rng, - )) + cert_builder.with_delegation( + CertificateBuilder::new_with_rng( + CertificateData::SubnetData { + subnet_id: subnet_id(123), + canister_id_ranges: vec![(canister_id(0), canister_id(10))], + }, + rng, + ) + .with_subnet_type("application"), + ) } else { cert_builder } From aa1bc880aa5af59e0ab7b7eb392dfa103cd261cf Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Tue, 21 Apr 2026 14:26:35 -0400 Subject: [PATCH 5/5] Nicer --- rs/certification/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rs/certification/src/lib.rs b/rs/certification/src/lib.rs index b24cc9b390cd..bbe117e6e235 100644 --- a/rs/certification/src/lib.rs +++ b/rs/certification/src/lib.rs @@ -162,7 +162,7 @@ pub fn verify_certified_data_with_cache_for_canister_sig( let (time, delegation_info) = verify_certified_data_internal(certificate, canister_id, root_pk, certified_data, true)?; if let Some(info) = delegation_info - && (info.subnet_type.is_none() || info.subnet_type.as_deref() == Some("cloud_engine")) + && matches!(info.subnet_type.as_deref(), None | Some("cloud_engine")) { return Err(CertificateValidationError::UntrustedDelegationSubnet( info.subnet_id,