← Back to PRs

#7501: feat(hooks): expose rawBody in webhook transform context

by tunamitom open 2026-02-02 22:10 View on GitHub →
gateway size: XS
## Summary This PR adds the raw request body string to the webhook transform context, enabling proper HMAC signature verification in custom transforms. ## Problem Webhook providers (Zoho, GitHub, Stripe, etc.) sign their payloads with HMAC. To verify these signatures, the transform function needs access to the **exact raw body string** that was signed, not the parsed JSON object. Currently, `applyHookMappings` receives only `{ payload, headers, url, path }` - the parsed payload loses the original string representation needed for HMAC verification. ## Solution 1. Modified `readJsonBody()` in `hooks.ts` to return `rawBody` alongside the parsed value 2. Added `rawBody?: string` to `HookMappingContext` type in `hooks-mapping.ts` 3. Pass `rawBody` through to `applyHookMappings()` in `server-http.ts` 4. Support `{{rawBody}}` template expression in transforms ## Usage In a transform script: ```javascript export default async function transform(ctx) { const signature = ctx.headers['x-webhook-signature']; const computed = crypto.createHmac('sha256', secret).update(ctx.rawBody).digest('hex'); if (signature !== computed) { return { action: null }; // reject invalid signature } // ... process valid webhook } ``` Or in template mappings: ```json { "message": "Raw body: {{rawBody}}" } ``` <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR threads the request’s raw JSON body through the hooks pipeline by: - Extending `readJsonBody` to return `{ value, rawBody }`. - Adding `rawBody?: string` to `HookMappingContext` and exposing it in template rendering via `{{rawBody}}`. - Passing the `rawBody` from `server-http` into `applyHookMappings` so transform scripts can do HMAC verification. Overall, it fits cleanly into the existing hooks mapping/transform architecture by enriching the mapping context without changing mapping resolution or dispatch behavior. <h3>Confidence Score: 3/5</h3> - Mostly safe to merge, but the new `rawBody` value is not actually raw due to trimming, which can break intended HMAC verification use-cases. - The change is small and localized to hooks request parsing and mapping context. However, the `.trim()` on the stored `rawBody` is a functional mismatch with the PR’s stated goal (byte-for-byte payload needed for signature verification) and can cause false signature failures depending on provider/payload formatting. - src/gateway/hooks.ts <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs