From 1d78ab46205866ed23633b0e59aa0b6e9bcc4c13 Mon Sep 17 00:00:00 2001 From: Ismael Hajy Date: Fri, 10 Jul 2026 19:14:54 +0200 Subject: [PATCH] fix(xds): reject a zero cert refresh_interval The file-watcher certificate provider's duration deserializer already rejects negative refresh intervals, but a refresh_interval of "0s" was accepted and parsed to 'Duration::ZERO'. 'tokio::time::interval(ZERO)' then panics inside the spawned refresh task, silently killing certificate rotation while provider construction still succeeds. Extend the existing guard to reject zero as well as negative durations, so the misconfiguration surfaces as a clear bootstrap error (matching grpc-java's `refreshInterval > 0` check; grpc-go coerces 0 to its default instead). --- .../src/xds/cert_provider/file_watcher.rs | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/tonic-xds/src/xds/cert_provider/file_watcher.rs b/tonic-xds/src/xds/cert_provider/file_watcher.rs index 7bb0fe97a..67c90ff97 100644 --- a/tonic-xds/src/xds/cert_provider/file_watcher.rs +++ b/tonic-xds/src/xds/cert_provider/file_watcher.rs @@ -69,9 +69,9 @@ where let secs: f64 = num .parse() .map_err(|_| serde::de::Error::custom(format!("invalid duration number: '{num}'")))?; - if secs < 0.0 { + if secs <= 0.0 { return Err(serde::de::Error::custom(format!( - "invalid duration '{s}': must not be negative" + "invalid duration '{s}': must be greater than 0" ))); } Ok(Some(Duration::from_secs_f64(secs))) @@ -399,16 +399,19 @@ mod tests { } #[test] - fn parse_refresh_interval_negative() { - let err = serde_json::from_value::( + fn parse_refresh_interval_must_be_greater_than_zero() { + for v in [ + serde_json::json!({"refresh_interval":"0s"}), serde_json::json!({"refresh_interval": "-1s"}), - ); - assert!(err.is_err()); - assert!( - err.unwrap_err() - .to_string() - .contains("must not be negative") - ); + ] { + let err = serde_json::from_value::(v); + assert!(err.is_err()); + assert!( + err.unwrap_err() + .to_string() + .contains("must be greater than 0") + ); + } } #[tokio::test]