Replay Protection

Timestamp validation prevents replay attacks on webhooks.

The threat

Without replay protection, an attacker who intercepts a valid webhook could resend it later. The signature would still be valid because the payload and secret haven't changed.

How CueAPI prevents replays

Every webhook signature is bound to a timestamp:

Signed content: "{timestamp}.{payload}"

The timestamp is sent in the X-CueAPI-Timestamp header. When verifying:

  1. Parse the timestamp from the header
  2. Check that |now - timestamp| < tolerance (default: 5 minutes)
  3. If the timestamp is too old or too far in the future, reject the webhook

Tolerance window

The default tolerance is 300 seconds (5 minutes). This allows for:

  • Network latency
  • Clock skew between CueAPI and your server
  • Reasonable processing delays

Replays older than 5 minutes are automatically rejected.

Implementation

python
def verify_webhook(payload, secret, signature, timestamp, tolerance=300):
    # Check timestamp freshness
    ts = int(timestamp)
    if abs(time.time() - ts) > tolerance:
        return False  # Too old — possible replay
 
    # Verify signature (as normal)
    ...

Combining with idempotency

For maximum security, combine replay protection with idempotency checks:

  1. Timestamp check — reject old webhooks (replay protection)
  2. Execution ID check — reject already-processed webhooks (idempotency)

This provides defense-in-depth against both replay attacks and duplicate deliveries.