GuardAPI Logo
GuardAPI

Fix Insecure Webhooks in Flask

Webhooks are an open door for SSRF, data injection, and logic bypass if you aren't verifying the sender. In Flask, trust nothing. Without cryptographic signature verification, any attacker with your endpoint URL can forge a payload and trigger internal actions. Stop blindly trusting POST requests from the wild.

The Vulnerable Pattern

from flask import Flask, request, jsonify

app = Flask(name)

@app.route(‘/webhook’, methods=[‘POST’]) def insecure_webhook(): # VULNERABLE: No source verification. # Anyone can POST any JSON to this endpoint. data = request.json user_id = data.get(‘user_id’) action = data.get(‘action’)

# Execute privileged logic based on untrusted input
return jsonify({'status': 'processed', 'user': user_id}), 200</code></pre>

The Secure Implementation

The fix implements HMAC (Hash-based Message Authentication Code) verification. 1. Use the raw request body (`request.data`) for hashing, as JSON parsing can vary between systems. 2. Use a shared secret stored in environment variables, never hardcoded. 3. Use `hmac.compare_digest` instead of standard equality operators to mitigate side-channel timing attacks. 4. Always abort with a 401 or 403 if the signature is missing or invalid before any business logic is executed.

import hmac
import hashlib
import os
from flask import Flask, request, abort

app = Flask(name) WEBHOOK_SECRET = os.environ.get(‘WEBHOOK_SECRET’, ‘super-secret-key’).encode()

def verify_signature(payload, signature): if not signature: return False # Compute HMAC SHA256 signature mac = hmac.new(WEBHOOK_SECRET, msg=payload, digestmod=hashlib.sha256) expected_signature = ‘sha256=’ + mac.hexdigest() # Use compare_digest to prevent timing attacks return hmac.compare_digest(expected_signature, signature)

@app.route(‘/webhook’, methods=[‘POST’]) def secure_webhook(): signature = request.headers.get(‘X-Hub-Signature-256’) # Verify signature against raw request body before processing if not verify_signature(request.data, signature): abort(401)

data = request.json
return 'OK', 200</code></pre>
System Alert • ID: 8801
Target: Flask API
Potential Vulnerability

Your Flask API might be exposed to Insecure Webhooks

74% of Flask apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.

RUN FREE SECURITY DIAGNOSTIC
GuardLabs Engine: ONLINE

Free Tier • No Credit Card • Instant Report

Verified by Ghost Labs Security Team

This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.