From 96619dec063628255292782d251902c8adda46d4 Mon Sep 17 00:00:00 2001 From: dhruv8sh Date: Wed, 16 Sep 2026 10:32:49 +0530 Subject: [PATCH 1/2] Reject placeholder partner pull tokens on startup reject_placeholder_secrets checked ec.partners[].api_token but never ts_pull_token, and the placeholder list didn't include the literal values trusted-server.example.toml actually ships. An operator who copied the template verbatim could deploy with a template string as the live pull-sync bearer token. Signed-off-by: dhruv8sh --- crates/trusted-server-core/src/settings.rs | 91 ++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/crates/trusted-server-core/src/settings.rs b/crates/trusted-server-core/src/settings.rs index f57714dcc..48560bc57 100644 --- a/crates/trusted-server-core/src/settings.rs +++ b/crates/trusted-server-core/src/settings.rs @@ -450,6 +450,8 @@ impl EcPartner { "sharedid-internal-token-32-bytes", "inttest-api-key-1-32-bytes-minimum", "inttest2-api-key-2-32-bytes-minimum", + "partner_api_token", + "partner_ts_pull_token", ]; /// Returns `true` if `api_token` matches a known placeholder value @@ -3089,6 +3091,16 @@ impl Settings { { insecure_fields.push(format!("ec.partners[{}].api_token", partner.source_domain)); } + if partner + .ts_pull_token + .as_ref() + .is_some_and(|token| EcPartner::is_placeholder_api_token(token.expose())) + { + insecure_fields.push(format!( + "ec.partners[{}].ts_pull_token", + partner.source_domain + )); + } } for handler in &self.handlers { if Handler::is_placeholder_password(handler.password.expose()) { @@ -5406,6 +5418,85 @@ source_domain = "partner.example.com" ); } + fn test_partner_with_pull_token(ts_pull_token: &str) -> EcPartner { + EcPartner { + name: "Test Partner".to_owned(), + source_domain: "partner.example.com".to_owned(), + openrtb_atype: EcPartner::default_openrtb_atype(), + bidstream_enabled: false, + api_token: None, + batch_rate_limit: EcPartner::default_batch_rate_limit(), + pull_sync_enabled: true, + pull_sync_url: Some("https://partner.example.com/sync".to_owned()), + pull_sync_allowed_domains: vec!["partner.example.com".to_owned()], + pull_sync_ttl_sec: EcPartner::default_pull_sync_ttl_sec(), + pull_sync_rate_limit: EcPartner::default_pull_sync_rate_limit(), + ts_pull_token: Some(Redacted::new(ts_pull_token.to_owned())), + } + } + + #[test] + fn reject_placeholder_secrets_includes_partner_pull_tokens() { + let mut settings = + Settings::from_toml(&crate_test_settings_str()).expect("should parse test settings"); + settings.publisher.proxy_secret = Redacted::new("unit-test-proxy-secret".to_owned()); + settings.ec.passphrase = Redacted::new("test-secret-key-32-bytes-minimum".to_owned()); + settings.ec.partners = vec![test_partner_with_pull_token("partner_ts_pull_token")]; + + let err = settings + .reject_placeholder_secrets() + .expect_err("should reject placeholder partner pull token"); + assert!( + format!("{err:?}").contains("ec.partners[partner.example.com].ts_pull_token"), + "error should mention the partner pull token field" + ); + } + + #[test] + fn reject_placeholder_secrets_allows_realistic_partner_pull_token() { + let mut settings = + Settings::from_toml(&crate_test_settings_str()).expect("should parse test settings"); + settings.publisher.proxy_secret = Redacted::new("unit-test-proxy-secret".to_owned()); + settings.ec.passphrase = Redacted::new("test-secret-key-32-bytes-minimum".to_owned()); + settings.ec.partners = vec![test_partner_with_pull_token( + "unit-test-realistic-pull-sync-token-32-bytes-min", + )]; + + settings + .reject_placeholder_secrets() + .expect("should accept a realistic partner pull token"); + } + + /// Guards against the placeholder lists drifting away from the example config + /// Example value shipped in `trusted-server.example.toml` must be recognized + /// as a placeholder + #[test] + fn example_toml_partner_secret_examples_are_recognized_placeholders() { + const EXAMPLE_TOML: &str = include_str!("../../../trusted-server.example.toml"); + const EXAMPLE_PARTNER_KEYS: &[&str] = &["api_token", "ts_pull_token"]; + let pattern = format!( + r#"(?m)^\s*#?\s*(?:{})\s*=\s*"([^"]+)""#, + EXAMPLE_PARTNER_KEYS.join("|") + ); + let example_value = + Regex::new(&pattern).expect("should compile example partner secret regex"); + + let mut checked_any = false; + for capture in example_value.captures_iter(EXAMPLE_TOML) { + checked_any = true; + let value = &capture[1]; + assert!( + EcPartner::is_placeholder_api_token(value), + "example config partner secret '{value}' should be a recognized placeholder \ + — add it to EcPartner::API_TOKEN_PLACEHOLDERS" + ); + } + assert!( + checked_any, + "should have found at least one partner secret example value in the template" + ); + } + #[test] fn is_unusable_store_id_rejects_placeholders_empty_and_padded_values() { for placeholder in RequestSigning::STORE_ID_PLACEHOLDERS { From 57eab4aa28d886736714975f2899952e0b9d04f3 Mon Sep 17 00:00:00 2001 From: dhruv8sh Date: Tue, 22 Sep 2026 01:22:04 +0530 Subject: [PATCH 2/2] Fix placeholder partner secret check to compare resolved values, not key names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit partner_api_token and partner_ts_pull_token are secret-store key names shipped as examples in trusted-server.example.toml, not resolved secret values — reject_placeholder_secrets runs after secret resolution and only ever sees resolved values, matching every other secret field in the template. Removes the two key-name entries from EcPartner::API_TOKEN_PLACEHOLDERS, retargets the affected test at an existing value placeholder, and drops the drift-guard test that asserted the incorrect invariant. Signed-off-by: dhruv8sh --- crates/trusted-server-core/src/settings.rs | 39 +++------------------- 1 file changed, 5 insertions(+), 34 deletions(-) diff --git a/crates/trusted-server-core/src/settings.rs b/crates/trusted-server-core/src/settings.rs index 48560bc57..47f614387 100644 --- a/crates/trusted-server-core/src/settings.rs +++ b/crates/trusted-server-core/src/settings.rs @@ -443,15 +443,14 @@ pub struct EcPartner { } impl EcPartner { - /// Known partner API token placeholders that must not be used in deployments. + /// Known partner secret placeholders (`api_token` and `ts_pull_token`) that + /// must not be used in deployments. pub const API_TOKEN_PLACEHOLDERS: &[&str] = &[ "partner-api-token-32-bytes-minimum", "replace-with-partner-api-token-32-bytes-minimum", "sharedid-internal-token-32-bytes", "inttest-api-key-1-32-bytes-minimum", "inttest2-api-key-2-32-bytes-minimum", - "partner_api_token", - "partner_ts_pull_token", ]; /// Returns `true` if `api_token` matches a known placeholder value @@ -5441,7 +5440,9 @@ source_domain = "partner.example.com" Settings::from_toml(&crate_test_settings_str()).expect("should parse test settings"); settings.publisher.proxy_secret = Redacted::new("unit-test-proxy-secret".to_owned()); settings.ec.passphrase = Redacted::new("test-secret-key-32-bytes-minimum".to_owned()); - settings.ec.partners = vec![test_partner_with_pull_token("partner_ts_pull_token")]; + settings.ec.partners = vec![test_partner_with_pull_token( + "partner-api-token-32-bytes-minimum", + )]; let err = settings .reject_placeholder_secrets() @@ -5467,36 +5468,6 @@ source_domain = "partner.example.com" .expect("should accept a realistic partner pull token"); } - /// Guards against the placeholder lists drifting away from the example config - /// Example value shipped in `trusted-server.example.toml` must be recognized - /// as a placeholder - #[test] - fn example_toml_partner_secret_examples_are_recognized_placeholders() { - const EXAMPLE_TOML: &str = include_str!("../../../trusted-server.example.toml"); - const EXAMPLE_PARTNER_KEYS: &[&str] = &["api_token", "ts_pull_token"]; - let pattern = format!( - r#"(?m)^\s*#?\s*(?:{})\s*=\s*"([^"]+)""#, - EXAMPLE_PARTNER_KEYS.join("|") - ); - let example_value = - Regex::new(&pattern).expect("should compile example partner secret regex"); - - let mut checked_any = false; - for capture in example_value.captures_iter(EXAMPLE_TOML) { - checked_any = true; - let value = &capture[1]; - assert!( - EcPartner::is_placeholder_api_token(value), - "example config partner secret '{value}' should be a recognized placeholder \ - — add it to EcPartner::API_TOKEN_PLACEHOLDERS" - ); - } - assert!( - checked_any, - "should have found at least one partner secret example value in the template" - ); - } - #[test] fn is_unusable_store_id_rejects_placeholders_empty_and_padded_values() { for placeholder in RequestSigning::STORE_ID_PLACEHOLDERS {