API Security in Depth · Configuration, Inventory & Secure Operations

Unsafe Consumption of APIs & Webhook Security

Treat third-party APIs and inbound webhooks as untrusted input.

API10 is the mirror image: your service consumes partner APIs and receives webhooks, and trusts them too much. Validate and bound everything you receive (schema, size, redirects, timeouts), use TLS, don't follow redirects blindly, and contain failures with circuit breakers. For inbound webhooks: verify HMAC signatures over the raw body with constant-time comparison, check timestamps to prevent replay (Standard Webhooks: webhook-id, webhook-timestamp, webhook-signature), dedupe by event ID, respond fast and process asynchronously, and re-fetch the resource from the provider's API for critical state.

Inbound webhook checklist

Check Why
Signature over raw body (HMAC / asymmetric) Authenticity + integrity
Timestamp tolerance (e.g. 5 min) Replay protection
Dedupe by event/webhook ID Providers deliver at-least-once
Schema validation + size limits Malformed or malicious payloads
Re-fetch critical resources Don't trust payload state blindly; ordering
Secret rotation (multiple valid secrets) Zero-downtime rotation
Quick 2xx then async processing Avoid provider timeouts and retries storms
def verify(raw: bytes, headers: Mapping[str, str], secrets: list[bytes]) -> None:
    msg_id, ts = headers["webhook-id"], int(headers["webhook-timestamp"])
    if abs(time.time() - ts) > 300:
        raise Unauthorized("stale")
    signed = f"{msg_id}.{ts}.".encode() + raw
    provided = [s.split(",", 1)[1] for s in headers["webhook-signature"].split() if s.startswith("v1,")]
    for secret in secrets:                                  # supports rotation
        expected = base64.b64encode(hmac.new(secret, signed, hashlib.sha256).digest()).decode()
        if any(hmac.compare_digest(expected, p) for p in provided):
            return
    raise Unauthorized("bad signature")

Common pitfalls

  • Verifying signatures over re-serialized JSON instead of raw bytes.
  • Using == for signature comparison.
  • Trusting partner responses without validation or timeouts.

Key points

  • Third-party data is untrusted input
  • Verify, dedupe, then process async
  • Re-fetch authoritative state

Further reading: OWASP API10:2023

Practice questions

Why must webhook signatures be computed over the raw request body?

Answer

Parsing and re-serializing JSON can change whitespace/key order, producing a different byte string and either false failures or a bypassable check.

How do you protect a webhook endpoint against replay attacks?

Answer

Include a signed timestamp and reject old messages, and dedupe by the unique event/message ID.

Open in the app to mark lessons complete, take notes and track your progress.