Severity
P0 — remote, unauthenticated message-injection on every Messenger-enabled deployment.
Files
crates/librefang-channels/src/messenger.rs:192-220
Finding
The POST /webhook handler parses the body as JSON and dispatches messages without
checking Meta's required X-Hub-Signature-256 header (HMAC-SHA256 of the raw body
with the app secret). Any internet attacker who learns or guesses the public callback
URL can POST forged Messenger events impersonating arbitrary sender_id values,
triggering agent commands, conversations, and downstream actions. The GET handler
verifies the verify_token query string for the one-time subscription challenge,
but that is unrelated to per-event authentication.
Evidence
// crates/librefang-channels/src/messenger.rs:192-220
.post({
let tx = Arc::clone(&tx);
move |body: axum::extract::Json<serde_json::Value>| {
...
if let Some(entries) = body.0["entry"].as_array() {
for entry in entries {
let msgs = parse_messenger_entry(entry);
Suggested Fix
Read the raw body via Bytes extractor, compute
HMAC-SHA256(app_secret, body_bytes), constant-time compare against the
X-Hub-Signature-256 header (sha256=<hex>), and return 401 on mismatch
before parsing JSON. Reject requests missing the header.
Severity
P0 — remote, unauthenticated message-injection on every Messenger-enabled deployment.
Files
crates/librefang-channels/src/messenger.rs:192-220Finding
The
POST /webhookhandler parses the body as JSON and dispatches messages withoutchecking Meta's required
X-Hub-Signature-256header (HMAC-SHA256 of the raw bodywith the app secret). Any internet attacker who learns or guesses the public callback
URL can POST forged Messenger events impersonating arbitrary
sender_idvalues,triggering agent commands, conversations, and downstream actions. The GET handler
verifies the
verify_tokenquery string for the one-time subscription challenge,but that is unrelated to per-event authentication.
Evidence
Suggested Fix
Read the raw body via
Bytesextractor, computeHMAC-SHA256(app_secret, body_bytes), constant-time compare against theX-Hub-Signature-256header (sha256=<hex>), and return401on mismatchbefore parsing JSON. Reject requests missing the header.