openai/openai-python · error · InvalidWebhookSignatureError
Webhook timestamp is too new
Error message
Webhook timestamp is too new
What it means
webhook_signature_matches rejects webhooks whose timestamp is further in the future than the tolerance window, indicating a stale signed payload being replayed against a newer context or severe clock skew on the receiver.
Source
Thrown at src/openai/lib/_webhooks.py:37
) -> bool:
"""Validate the replay window and compare the supplied signatures."""
signature_header = get_required_header(headers, "webhook-signature")
timestamp = get_required_header(headers, "webhook-timestamp")
webhook_id = get_required_header(headers, "webhook-id")
# Validate timestamp to prevent replay attacks
try:
timestamp_seconds = int(timestamp)
except ValueError:
raise InvalidWebhookSignatureError("Invalid webhook timestamp format") from None
now = int(time.time())
if now - timestamp_seconds > tolerance:
raise InvalidWebhookSignatureError("Webhook timestamp is too old") from None
if timestamp_seconds > now + tolerance:
raise InvalidWebhookSignatureError("Webhook timestamp is too new") from None
# Extract signatures from v1,<base64> format
# The signature header can have multiple values, separated by spaces.
# Each value is in the format v1,<base64>. We should accept if any match.
signatures: list[str] = []
for part in signature_header.split():
if part.startswith("v1,"):
signatures.append(part[3:])
else:
signatures.append(part)
# Decode the secret if it starts with whsec_
if secret.startswith("whsec_"):
decoded_secret = base64.b64decode(secret[6:])
else:
decoded_secret = secret.encode()
body = payload.decode("utf-8") if isinstance(payload, bytes) else payloadView on GitHub (pinned to 9917c6e28e)
Solutions
- Correct the receiver's system clock via NTP
- Log both the header timestamp and local time when this fires to diagnose skew direction
- If skew is expected in your infra, increase tolerance explicitly rather than disabling verification
Example fix
// n/a (infrastructure fix) # example: widen tolerance only if justified webhook_signature_matches(body, headers, secret, tolerance=600)
Defensive patterns
Strategy: try-catch
Validate before calling
ts = int(headers["webhook-timestamp"])
import time
if ts > time.time() + tolerance:
logger.warning("receiver clock behind sender by %ss", ts - time.time()) Try / catch
try:
ok = webhook_signature_matches(body, headers, secret)
except InvalidWebhookSignatureError as e:
if "too new" in str(e):
return Response(401)
raise Prevention
- Keep receiver clocks synced (chrony/ntp)
- Avoid snapshot-resumed VMs as webhook hosts
- Alert on future-timestamp failures; they indicate skew or tampering
When it happens
Trigger: timestamp_seconds > now + tolerance: receiving host's clock behind the sender, or a forged/manipulated timestamp header.
Common situations: Clock drift on the webhook receiver server; VMs resumed from snapshots with stale clocks; tampered payloads during attack attempts.
Related errors
- Invalid webhook timestamp format
- Webhook timestamp is too old
- The webhook secret must either be set using the env var, OPE
- The given webhook signature does not match the expected sign
AI-assisted analysis of openai/openai-python@9917c6e28e (2026-08-28).
Data as JSON: /api/errors/3055a1c5a0b5231a.
Report an issue: GitHub.