Significant-Gravitas/AutoGPT · error · HTTPException
Invalid webhook signature
Error message
Invalid webhook signature
What it means
The ingress endpoint calls webhook_manager.verify_signature(webhook, request) to check the provider's request-signature scheme (HMAC, RSA, etc.). Any non-HTTPException failure from verification — bad signature, missing signature header, malformed payload digest — is logged and converted to HTTP 403 'Invalid webhook signature'. A 403 (not 404) is deliberate: at this point the webhook's existence is already proven to the sender, so concealment adds nothing, and 403 correctly tells the sender its credentials for signing are wrong.
Source
Thrown at autogpt_platform/backend/backend/api/features/integrations/router.py:734
if webhook.credentials_id
else None
)
except NotFoundError as e:
logger.warning(f"Webhook payload received for unknown webhook #{webhook_id}")
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
# Run provider signature verification (no-op for providers whose protocol
# has no signing scheme). 403 on failure; not 404 — that would leak
# webhook existence.
try:
await webhook_manager.verify_signature(webhook, request)
except HTTPException:
raise
except Exception:
logger.exception(
f"Signature verification failed for webhook #{webhook_id} ({provider.value})"
)
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Invalid webhook signature",
)
payload, event_type = await webhook_manager.validate_payload(
webhook, request, credentials
)
logger.debug(
f"Validated {provider.value} {webhook.webhook_type} {event_type} event "
f"with payload {payload}"
)
webhook_event = WebhookEvent(
provider=provider,
webhook_id=webhook_id,
event_type=event_type,
payload=payload,
)View on GitHub (pinned to 9c8bb5550f)
Solutions
- Replay the exact raw request body with the correct signature header computed over the untouched bytes (signature is computed on the raw body, not parsed JSON).
- If the secret rotated, re-register the webhook so a fresh secret is configured at the provider and stored server-side.
- Ensure any proxy in front of the backend passes the body through byte-identical and forwards the signature headers.
- Check backend logs: the logger.exception line 'Signature verification failed for webhook #{id}' includes the underlying exception with the precise reason.
Example fix
# before (unsigned test call)
curl -X POST https://api.example.com/integrations/github/webhooks/$ID/webhook -d '{"foo":1}'
# after (sign the raw body)
BODY=$(cat event.json)
SIG=$(python -c "import hmac,hashlib,sys;print(hmac.new(b'$SECRET',sys.stdin.buffer.read(),hashlib.sha256).hexdigest())" <<<"$BODY")
curl -X POST https://api.example.com/integrations/github/webhooks/$ID/webhook \
-H "X-Hub-Signature-256: sha256=$SIG" \
-H "Content-Type: application/json" \
-d "$BODY" Defensive patterns
Strategy: try-catch
Validate before calling
# Pre-flight: compute the signature the way the provider will import hmac, hashlib sig = "sha256=" + hmac.new(secret, raw_body_bytes, hashlib.sha256).hexdigest() assert sig == sent_header # self-check before relying on the receiver
Try / catch
# Only sane for test harnesses sending ingress traffic
resp = await client.post(ingress_url, content=raw, headers=sig_headers)
try:
resp.raise_for_status()
except httpx.HTTPStatusError as e:
if e.response.status_code == 403:
raise SignatureMisconfigured(ingress_url) from e # fix secret/transport, don't retry
raise Prevention
- Sign the exact raw bytes of the body; never re-serialize parsed JSON for signature computation.
- Keep proxies from rewriting the request body (disable modification/normalization).
- Re-register the webhook whenever its secret rotates so both sides agree.
When it happens
Trigger: Provider sends the event without the expected signature header (X-Hub-Signature-256 for GitHub, X-Signature-Ed25519 for Slack, X-Signature for Compass, etc.); the shared secret rotated and AutoGPT still verifies with the old one; a proxy/load balancer re-encodes or truncates the raw body so the digest doesn't match; manual curl testing without computing a signature.
Common situations: Testing ingress locally with plain curl; secret rotation on the provider side; reverse proxy (nginx/Cloudflare) modifying the body (e.g. chunked re-encoding) breaking HMAC; clock/lag between webhook registration and provider config propagation.
Related errors
- Webhook not configured
- Invalid signature
- The ChatGPT verification link is invalid. Close this window
- job belongs to a different user
- url must point at a trusted frontend origin.
AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14).
Data as JSON: /api/errors/cc6f6bf611da5439.
Report an issue: GitHub.