GuardAPI Logo
GuardAPI
GuardAPI Logo GuardAPI

Fix Insecure Webhooks in AdonisJS

Webhooks are high-value targets for spoofing and replay attacks. In AdonisJS, if you process incoming webhooks without cryptographic verification, you're effectively exposing internal logic to the public internet. Attackers can forge events, manipulate data, or trigger unintended side effects by simply POSTing a JSON payload to your endpoint. To secure this, you must implement HMAC signature verification using the raw request body.

The Vulnerable Pattern

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

export default class WebhooksController { public async handle({ request, response }: HttpContextContract) { // DANGER: Blindly trusting the parsed body const payload = request.all()

if (payload.type === 'payment.succeeded') {
  // This logic can be triggered by anyone with the URL
  await fulfillOrder(payload.data.orderId)
}

return response.ok({ status: 'success' })

} }

The Secure Implementation

The secure implementation relies on three critical security principles. First, we use `request.raw()` because standard body parsers can modify the spacing or key order of JSON, which invalidates the HMAC. Second, we generate a local hash using a shared secret and the SHA-256 algorithm. Third, we use `crypto.timingSafeEqual` to compare the signatures; standard string comparison (`===`) is vulnerable to timing attacks where an attacker can determine the correct signature one character at a time by measuring the response latency.

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import crypto from 'crypto'
import Env from '@ioc:Adonis/Core/Env'

export default class WebhooksController { public async handle({ request, response }: HttpContextContract) { const signature = request.header(‘X-Webhook-Signature’) const secret = Env.get(‘WEBHOOK_SECRET’) const rawBody = request.raw() // Essential: use the unparsed body

if (!signature || !rawBody) {
  return response.unauthorized('Missing signature')
}

const hmac = crypto.createHmac('sha256', secret)
const expectedSignature = hmac.update(rawBody).digest('hex')

// Prevent timing attacks with timingSafeEqual
const isValid = crypto.timingSafeEqual(
  Buffer.from(signature),
  Buffer.from(expectedSignature)
)

if (!isValid) {
  return response.badRequest('Invalid signature')
}

const payload = JSON.parse(rawBody)
// Process verified payload...
return response.ok({ status: 'verified' })

} }

System Alert • ID: 6623
Target: AdonisJS API
Potential Vulnerability

Your AdonisJS API might be exposed to Insecure Webhooks

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