{"record":{"id":"aab209b97c6be56a","repo":"Hmbown/CodeWhale","slug":"fleet-alert-url-from-name-must-use-https","errorCode":null,"errorMessage":"fleet alert URL from {name} must use https","messagePattern":"fleet alert URL from (.+?) must use https","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/fleet/alerts.rs","lineNumber":507,"sourceCode":"        .ok_or_else(|| anyhow!(\"fleet alert secret {name} is not configured\"))\n}\n\nfn required_https_url<R>(resolver: &R, name: &str) -> Result<String>\nwhere\n    R: FleetAlertSecretResolver,\n{\n    let url = resolver\n        .resolve(name)\n        .ok_or_else(|| anyhow!(\"fleet alert URL {name} is not configured\"))?;\n    validate_https_alert_url(name, &url)?;\n    Ok(url)\n}\n\nfn validate_https_alert_url(name: &str, url: &str) -> Result<()> {\n    let parsed = reqwest::Url::parse(url)\n        .with_context(|| format!(\"fleet alert URL from {name} is not a valid URL\"))?;\n    if parsed.scheme() != \"https\" {\n        return Err(anyhow!(\"fleet alert URL from {name} must use https\"));\n    }\n    Ok(())\n}\n\nfn short_reason(reason: &str) -> String {\n    let trimmed = reason.trim();\n    if trimmed.len() <= 240 {\n        return trimmed.to_string();\n    }\n    let prefix: String = trimmed.chars().take(237).collect();\n    format!(\"{prefix}...\")\n}\n\nfn default_pagerduty_severity() -> String {\n    \"error\".to_string()\n}\n\n#[cfg(test)]","sourceCodeStart":489,"sourceCodeEnd":525,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/fleet/alerts.rs#L489-L525","documentation":"required_https_url() validates every Webhook alert URL with reqwest::Url::parse and then rejects any scheme other than https. This is a deliberate hardening step so alert payloads (which include run ids, status, and failure reasons) are never sent over plaintext HTTP where they could be read or tampered with. The error names the env var the URL came from.","triggerScenarios":"Setting the Webhook adapter's url_env to an http:// URL (e.g. a local test listener like http://127.0.0.1:9000/hook) and dispatching with dry_run=false; also URLs whose scheme parses oddly (e.g. 'localhost:8080/x' parses scheme 'localhost').","commonSituations":"Pointing alerts at a local dev receiver over plain HTTP; copying an internal http endpoint from docs; env vars provisioned by platforms that hand out http URLs by default; typos like missing '//' after https: are caught by the earlier parse error instead.","solutions":["Change the env var's value to an https:// URL (put a TLS terminator in front of local test receivers, e.g. an ngrok/local reverse proxy).","Double-check the scheme spelling and that the value parses as an absolute URL — 'example.com/hook' without a scheme fails earlier with the not-a-valid-URL context error.","For local testing keep dry_run=true, which validates config shape without sending.","If you must target plain HTTP internally, that is intentionally unsupported — file the alert through a different mechanism rather than weakening the check."],"exampleFix":"# before\n$ export ALERT_HOOK_URL=\"http://127.0.0.1:9000/fleet\"   # -> must use https\n\n# after\n$ export ALERT_HOOK_URL=\"https://hooks.internal.example.com/fleet\"","handlingStrategy":"validation","validationCode":"fn webhook_urls_are_https(cfg: &FleetAlertConfig) -> Result<(), String> {\n    for (name, adapter) in &cfg.adapters {\n        if let FleetAlertAdapterConfig::Webhook { url_env, .. } = adapter {\n            if let Ok(url) = std::env::var(url_env) {\n                if reqwest::Url::parse(&url).map(|u| u.scheme() != \"https\").unwrap_or(true) {\n                    return Err(format!(\"adapter '{name}': {url_env} must be an https:// URL\"));\n                }\n            }\n        }\n    }\n    Ok(())\n}\n","typeGuard":"fn is_https_url(s: &str) -> bool {\n    reqwest::Url::parse(s).map(|u| u.scheme() == \"https\").unwrap_or(false)\n}\n","tryCatchPattern":"Err(e) if e.to_string().contains(\"must use https\") => {\n    // value of the named env var is http:// — fix the env var; do not catch-and-send-over-http\n}\n","preventionTips":["Never point alert webhooks at http:// endpoints; front local receivers with TLS.","Validate url_env values with Url::parse at deploy time, not at first alert.","Watch for scheme-less values like 'hooks.example.com/x' — they fail earlier as invalid URLs.","Include the https requirement in the runbook next to each *_env variable."],"tags":["fleet","alerts","webhook","https","url-validation","security"],"backgroundTag":"https-url-required","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}