Skip to content

Messenger webhook accepts unsigned POST bodies — full inbound message spoofing #3438

Description

@houko

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/channelsMessaging channel adaptersbugSomething isn't workinghas-prA pull request has been linked to this issuesecuritySecurity issuesseverity/criticalRemote-exploitable, data loss, or production-blocking

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions