fix(telegram): preserve polling after secret-blocked updates (#1353)

* fix(telegram): preserve polling after secret-blocked updates

* style(telegram): simplify polling leak-scan guard

* style(telegram): satisfy clippy for poll leak guard
This commit is contained in:
Nige
2026-03-18 11:33:45 -07:00
committed by GitHub
parent bedc71ebdc
commit 33a2dd2c78
+39 -2
View File
@@ -492,8 +492,16 @@ impl near::agent::channel_host::Host for ChannelStoreData {
tracing::debug!(body = %truncated, "Response body");
}
// Leak detection on response body (best-effort)
if let Ok(body_str) = std::str::from_utf8(&body) {
// Leak detection on response body (best-effort).
//
// Telegram `getUpdates` is special: it is inbound polling data, so
// user-pasted secrets can legitimately appear in the response body.
// Those messages are still checked later by the inbound message
// safety layer before they reach the LLM, so we allow the polling
// response to continue here to avoid poisoning the offset state.
if let Ok(body_str) = std::str::from_utf8(&body)
&& !should_skip_response_leak_scan(&url)
{
leak_detector
.scan_and_clean(body_str)
.map_err(|e| format!("Potential secret leak in response: {}", e))?;
@@ -3122,6 +3130,19 @@ fn extract_host_from_url(url: &str) -> Option<String> {
})
}
fn should_skip_response_leak_scan(url: &str) -> bool {
url::Url::parse(url).is_ok_and(|parsed| {
matches!(parsed.scheme(), "http" | "https")
&& parsed
.host_str()
.is_some_and(|host| host.eq_ignore_ascii_case("api.telegram.org"))
&& parsed
.path_segments()
.and_then(|segments| segments.rev().find(|segment| !segment.is_empty()))
.is_some_and(|segment| segment == "getUpdates")
})
}
/// Pre-resolve host credentials for all HTTP capability mappings.
///
/// Called once per callback (in async context, before spawn_blocking) so the
@@ -4386,6 +4407,22 @@ mod tests {
assert_eq!(store.redact_credentials(input), input);
}
#[test]
fn test_should_skip_response_leak_scan_only_for_telegram_getupdates() {
use super::should_skip_response_leak_scan;
assert!(should_skip_response_leak_scan(
"https://api.telegram.org/bot123/getUpdates?offset=1"
));
assert!(!should_skip_response_leak_scan(
"https://api.telegram.org/bot123/sendMessage"
));
assert!(!should_skip_response_leak_scan(
"https://api.example.com/getUpdates"
));
assert!(!should_skip_response_leak_scan("not a url"));
}
/// Verify that WASM HTTP host functions work using a dedicated
/// current-thread runtime inside spawn_blocking.
#[tokio::test]