fix(#2164): address argus review — Option<String> secret + stale hook cleanup
Two issues flagged by argus in PR #2388 review: 1. Empty-key fallback: when load_or_generate() failed, webhook_secret was String::new(). An attacker knowing this could forge deliveries with a valid HMAC of the empty key. Fix: change to Option<String>; on None, skip hook registration entirely and return 503 from /webhook/* handlers (rather than 401 with a misleadingly-verifiable empty-key HMAC). 2. Stale hook cleanup: on upgrade from old code, old loopback hooks (http://127.0.0.1:.../webhook/knowledge, .../webhook/config-pr) were left alongside the new domain-URL hook. Fix: during ensure_webhook / ensure_config_pr_webhook, after listing hooks, delete any that end with our path suffix but point at a different base URL. clippy + nix fmt clean.
This commit is contained in:
parent
79a29873e3
commit
7b1b1d9db8
5 changed files with 84 additions and 12 deletions
|
|
@ -306,11 +306,14 @@ async fn cmd_serve(
|
|||
// Webhook HMAC secret: load from state dir or generate on first run.
|
||||
// Used by both the webhook handlers (verification) and the Forgejo
|
||||
// hook registrations (so Forgejo signs deliveries with the same key).
|
||||
let webhook_secret = match hive_c0re::webhook_secret::load_or_generate() {
|
||||
Ok(s) => s,
|
||||
let webhook_secret: Option<String> = match hive_c0re::webhook_secret::load_or_generate() {
|
||||
Ok(s) => Some(s),
|
||||
Err(e) => {
|
||||
tracing::warn!(error = ?e, "webhook secret load/generate failed; webhooks will not verify HMAC");
|
||||
String::new()
|
||||
tracing::error!(
|
||||
error = ?e,
|
||||
"webhook secret load/generate failed; /webhook/* endpoints disabled and hooks not registered"
|
||||
);
|
||||
None
|
||||
}
|
||||
};
|
||||
// Webhook setup: ensure Forgejo webhooks are registered for both
|
||||
|
|
@ -319,9 +322,14 @@ async fn cmd_serve(
|
|||
// forge::ensure_all so the core token + repos + org are present.
|
||||
// URLs use the public hive domain (HYPERHIVE_HIVE_DOMAIN) so Forgejo
|
||||
// delivers through the gateway, bypassing the SSRF loopback guard.
|
||||
// No-op when the core token or domain are absent.
|
||||
// No-op when the core token or domain are absent, or when the HMAC
|
||||
// secret is unavailable (load failure).
|
||||
let webhook_secret_reg = webhook_secret.clone();
|
||||
tokio::spawn(async move {
|
||||
let Some(webhook_secret_reg) = webhook_secret_reg else {
|
||||
tracing::debug!("webhook secret unavailable; skipping hook registration");
|
||||
return;
|
||||
};
|
||||
let Some(token) = forge::core_token() else {
|
||||
return;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue