diff --git a/src/channels/qq.rs b/src/channels/qq.rs index 70dc20d..7373512 100644 --- a/src/channels/qq.rs +++ b/src/channels/qq.rs @@ -11,6 +11,13 @@ use uuid::Uuid; const QQ_API_BASE: &str = "https://api.sgroup.qq.com"; const QQ_AUTH_URL: &str = "https://bots.qq.com/app/getAppAccessToken"; +fn ensure_https(url: &str) -> anyhow::Result<()> { + if !url.starts_with("https://") { + anyhow::bail!("Refusing to transmit sensitive data over non-HTTPS URL: URL scheme must be https"); + } + Ok(()) +} + /// Deduplication set capacity — evict half of entries when full. const DEDUP_CAPACITY: usize = 10_000; @@ -196,6 +203,8 @@ impl Channel for QQChannel { ) }; + ensure_https(&url)?; + let resp = self .http_client() .post(&url) diff --git a/src/channels/whatsapp.rs b/src/channels/whatsapp.rs index c6e5baa..040474e 100644 --- a/src/channels/whatsapp.rs +++ b/src/channels/whatsapp.rs @@ -8,6 +8,13 @@ use uuid::Uuid; /// Messages are received via the gateway's `/whatsapp` webhook endpoint. /// The `listen` method here is a no-op placeholder; actual message handling /// happens in the gateway when Meta sends webhook events. +fn ensure_https(url: &str) -> anyhow::Result<()> { + if !url.starts_with("https://") { + anyhow::bail!("Refusing to transmit sensitive data over non-HTTPS URL: URL scheme must be https"); + } + Ok(()) +} + pub struct WhatsAppChannel { access_token: String, endpoint_id: String, @@ -165,6 +172,8 @@ impl Channel for WhatsAppChannel { } }); + ensure_https(&url)?; + let resp = self .http_client() .post(&url) @@ -203,6 +212,10 @@ impl Channel for WhatsAppChannel { // Check if we can reach the WhatsApp API let url = format!("https://graph.facebook.com/v18.0/{}", self.endpoint_id); + if ensure_https(&url).is_err() { + return false; + } + self.http_client() .get(&url) .bearer_auth(&self.access_token) diff --git a/src/tools/composio.rs b/src/tools/composio.rs index bfa5a0d..0add428 100644 --- a/src/tools/composio.rs +++ b/src/tools/composio.rs @@ -19,6 +19,13 @@ use std::sync::Arc; const COMPOSIO_API_BASE_V2: &str = "https://backend.composio.dev/api/v2"; const COMPOSIO_API_BASE_V3: &str = "https://backend.composio.dev/api/v3"; +fn ensure_https(url: &str) -> anyhow::Result<()> { + if !url.starts_with("https://") { + anyhow::bail!("Refusing to transmit sensitive data over non-HTTPS URL: URL scheme must be https"); + } + Ok(()) +} + /// A tool that proxies actions to the Composio managed tool platform. pub struct ComposioTool { api_key: String, @@ -177,6 +184,8 @@ impl ComposioTool { connected_account_ref, ); + ensure_https(&url)?; + let resp = self .client() .post(&url)