From 32ec67f8bfacc3a44b2cfe08ca492903dcc73e82 Mon Sep 17 00:00:00 2001 From: M3gA-Mind Date: Fri, 23 Oct 2026 08:53:23 +0530 Subject: [PATCH] test(failure): pin that provider detail scrubs a key the provider echoes extract_provider_error_detail runs the quoted provider message through sanitize_api_error, and that detail is shown to users. No test covered a provider echoing the rejected key back in its error message. Pin it for OpenAI- and Anthropic-shaped keys. --- crates/tinyinference-llm/src/failure_tests.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/crates/tinyinference-llm/src/failure_tests.rs b/crates/tinyinference-llm/src/failure_tests.rs index 1d806c1..b30c585 100644 --- a/crates/tinyinference-llm/src/failure_tests.rs +++ b/crates/tinyinference-llm/src/failure_tests.rs @@ -407,6 +407,21 @@ fn extract_provider_error_detail_pulls_openai_message() { assert!(detail.contains("gpt-5.5")); } +#[test] +fn extract_provider_error_detail_scrubs_a_key_the_provider_echoes() { + // The detail is quoted to the user, and providers echo a rejected key in + // it. Synthetic keys, built at runtime so no key-shaped literal is committed. + let body = "AbCdEf0123456789".repeat(2); + for key in [format!("sk-proj-{body}"), format!("sk-ant-api03-{body}")] { + let raw = format!( + r#"someprovider API error (422 Unprocessable Entity): {{"error":{{"message":"bad parameter for key {key}"}}}}"# + ); + let detail = extract_provider_error_detail(&raw).expect("expected JSON message"); + assert!(detail.contains("bad parameter"), "got: {detail}"); + assert!(!detail.contains(&body), "key leaked: {detail}"); + } +} + #[test] fn extract_provider_error_detail_returns_none_for_transport_errors() { // Plain transport failure — no provider JSON body to quote. Surfacing