zeroclaw-labs/zeroclaw · error
Refusing to transmit sensitive data over non-HTTPS URL: URL
Error message
Refusing to transmit sensitive data over non-HTTPS URL: URL scheme must be https
What it means
A hard security guard in the WhatsApp channel: ensure_https requires the configured API base URL to start with https://, and every network call (post_message, send_interactive_buttons, send_interactive_list, health_check) passes through it. It refuses to transmit tokens and message payloads over plaintext HTTP.
Source
Thrown at crates/zeroclaw-channels/src/whatsapp.rs:160
zeroclaw_api::channel::AttributedApprovalResponse::from_runtime(
ChannelApprovalResponse::Deny,
zeroclaw_api::channel::ApprovalSource::Unreachable,
)
}
Err(_) => {
remove_pending_and_disarm(&token, &mut guard).await;
zeroclaw_api::channel::AttributedApprovalResponse::from_runtime(
ChannelApprovalResponse::Deny,
zeroclaw_api::channel::ApprovalSource::TimedOut,
)
}
};
Ok(attributed)
}
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,
verify_token: String,
/// The alias key under `[channels.whatsapp.<alias>]` this handle is
/// bound to. Used to scope peer-group writes and resolver lookups.
alias: String,
/// Resolves inbound external peers from canonical state at message-time.
/// No cache (see AGENTS.md "ABSOLUTE RULE — SINGLE SOURCE OF TRUTH").
peer_resolver: Arc<dyn Fn() -> Vec<String> + Send + Sync>,
/// Per-channel proxy URL override.
proxy_url: Option<String>,View on GitHub (pinned to 88bb9c8533)
Solutions
- Change base_url to https:// — for local bridges, front them with a TLS-terminating reverse proxy (Caddy/nginx) or a TLS tunnel
- Do not bypass the guard: it protects auth tokens and message content from network sniffing
- Check the URL for a missing scheme, http typo, or stray whitespace before it
Example fix
# before base_url = "http://localhost:3000" # after (TLS-terminating local proxy in front of the bridge) base_url = "https://localhost:8443"
Defensive patterns
Strategy: validation
Validate before calling
fn is_https_url(url: &str) -> bool {
url.trim_start().starts_with("https://")
}
if !is_https_url(&cfg.base_url) {
return Err(anyhow::anyhow!("WhatsApp base_url must use https://"));
} Type guard
fn is_https_url(url: &str) -> bool {
url.trim_start().starts_with("https://")
} Try / catch
Do not catch-and-continue: this is a deliberate security refusal. Let it fail channel startup, fix the URL to https://, and put TLS in front of any local bridge.
Prevention
- Run local WhatsApp bridges behind TLS from day one (Caddy/nginx or a TLS tunnel)
- Validate the base_url scheme at config load time
- Never bypass or downgrade this guard — it protects tokens and message payloads on the wire
When it happens
Trigger: Configuring the WhatsApp API base_url with http:// (e.g., a local bridge at http://localhost:3000) or omitting/mistyping the scheme so it fails the https:// prefix check, then invoking send or health_check.
Common situations: Local development against a plain-HTTP WhatsApp bridge (WaAPI-style); port-forwards or tunnels without TLS; a missing scheme or leading whitespace in the URL.
Related errors
- Refusing to transmit sensitive data over non-HTTPS URL: URL
- {field_name} must use https://, got {url}
- refusing non-HTTPS attachment URL: {url}
- Generated image URL must use HTTPS
- Edge TTS binary_path must be a bare command name without pat
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/4171a1f51775741e.
Report an issue: GitHub.