GuardAPI Logo
GuardAPI

Fix Insecure Webhooks in Hanami

Insecure webhooks are a critical vulnerability where an application processes incoming HTTP callbacks without verifying their authenticity. In Hanami, failing to validate the cryptographic signature of a payload allows an attacker to spoof events, leading to unauthorized state changes, privilege escalation, or data corruption. You must treat every webhook as untrusted until the HMAC signature is verified against a shared secret.

The Vulnerable Pattern

module Webhooks
  class Stripe < Hanami::Action
    def handle(req, res)
      # VULNERABLE: Blindly trusting the request body
      event_data = req.params[:data]
      user = UserRepo.new.find_by_email(event_data[:email])
      user.update(plan: 'premium')
      res.status = 200
    end
  end
end

The Secure Implementation

The secure implementation introduces three layers of defense. 1. Signature Extraction: It retrieves the HMAC from headers before processing. 2. Raw Body Verification: It calculates the HMAC-SHA256 of the raw request body using a server-side secret; using the raw body is mandatory because parameter parsing can alter the data, breaking the hash. 3. Constant-Time Comparison: It uses Rack::Utils.secure_compare to validate the signature, which protects against timing side-channel attacks that could otherwise leak the secret byte-by-byte.

require 'openssl'

module Webhooks class Stripe < Hanami::Action WEBHOOK_SECRET = ENV.fetch(‘STRIPE_WEBHOOK_SECRET’)

def handle(req, res)
  signature = req.get_header('HTTP_STRIPE_SIGNATURE')
  payload = req.body.read
  req.body.rewind # Ensure body can be read again if needed

  halt 401 unless valid_signature?(signature, payload)

  data = JSON.parse(payload, symbolize_names: true)
  # Proceed with logic
  res.status = 200
rescue JSON::ParserError
  halt 400
end

private

def valid_signature?(signature, payload)
  return false if signature.nil?

  # Extract timestamp and signature from header (Stripe specific example)
  # For generic HMAC: 
  expected = OpenSSL::HMAC.hexdigest('sha256', WEBHOOK_SECRET, payload)
  
  # Use secure_compare to prevent timing attacks
  Rack::Utils.secure_compare(expected, signature)
end

end end

System Alert • ID: 1745
Target: Hanami API
Potential Vulnerability

Your Hanami API might be exposed to Insecure Webhooks

74% of Hanami 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.