fix(webhook): preserve raw body for Meta webhook HMAC validation
The global express.json() middleware at line 77 was parsing the body
into a JS object before the route-level express.raw() could capture
the raw Buffer. When WHATSAPP_APP_SECRET is set and a signature is
present, crypto.createHmac().update(req.body) received an Object
instead of Buffer, throwing TypeError and crashing the process.
Fix: register app.use('/webhook/whatsapp', express.raw({ type: '*/*' }))
before app.use(express.json()) so the raw body is preserved for HMAC.
Post-deploy verification: all 7 webhook tests pass, pod 0 restarts.
Related: SquareMCP/2026-06-10-twilio-whatsapp-webhook-deployment.md
This commit is contained in:
@@ -22,7 +22,7 @@ spec:
|
|||||||
fsGroup: 1000
|
fsGroup: 1000
|
||||||
containers:
|
containers:
|
||||||
- name: hermes-mcp
|
- name: hermes-mcp
|
||||||
image: localhost:32000/hermes-mcp@sha256:793e7a6e0486b4c117b8ab62a3668ae0f9235b014b02181ce3cb65696a16d96c
|
image: localhost:32000/hermes-mcp@sha256:57be9369be928208bc2e4764fb15162e1339907a4b42669aa995cc3cc24abd94
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
securityContext:
|
securityContext:
|
||||||
allowPrivilegeEscalation: false
|
allowPrivilegeEscalation: false
|
||||||
@@ -147,6 +147,13 @@ spec:
|
|||||||
value: "bf9285c863263d06efbb1b56827d351a"
|
value: "bf9285c863263d06efbb1b56827d351a"
|
||||||
- name: TWILIO_WHATSAPP_NUMBER
|
- name: TWILIO_WHATSAPP_NUMBER
|
||||||
value: "+19547385805"
|
value: "+19547385805"
|
||||||
|
- name: PUBLIC_WEBHOOK_BASE_URL
|
||||||
|
value: "https://hermes.squaremcp.com"
|
||||||
|
- name: WHATSAPP_APP_SECRET
|
||||||
|
value: "04d52724efa5f3ac5eb3f2b673c3d70a"
|
||||||
|
# TODO: set PILOT_CUSTOMER_ID when Lodge Brothers customer is created
|
||||||
|
# - name: PILOT_CUSTOMER_ID
|
||||||
|
# value: ""
|
||||||
- name: WHATSAPP_DEFAULT_ACCESS_TOKEN
|
- name: WHATSAPP_DEFAULT_ACCESS_TOKEN
|
||||||
value: "EAAYG3FLDWzMBRV4qrRvksNnVzCI4wGUvF4R8jjy6pusWBxriRwP9B3ZCRcd3VpDsjoURhJMEQJiNZCcSIJZCcQGsusZANzTpQF9hWrhHgLXUU9tJZCuoEAWTUYA9C29JgQ9BPblpUxEQRKE3p9tZBsl9ChngJy45kXJ9apOYreJclyya0ebgCxZBmndBpCPuAZDZD"
|
value: "EAAYG3FLDWzMBRV4qrRvksNnVzCI4wGUvF4R8jjy6pusWBxriRwP9B3ZCRcd3VpDsjoURhJMEQJiNZCcSIJZCcQGsusZANzTpQF9hWrhHgLXUU9tJZCuoEAWTUYA9C29JgQ9BPblpUxEQRKE3p9tZBsl9ChngJy45kXJ9apOYreJclyya0ebgCxZBmndBpCPuAZDZD"
|
||||||
- name: WA_VERIFY_TOKEN
|
- name: WA_VERIFY_TOKEN
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ app.use(cors({
|
|||||||
allowedHeaders: ['Content-Type', 'mcp-session-id', 'Accept', 'x-api-key', 'Authorization'],
|
allowedHeaders: ['Content-Type', 'mcp-session-id', 'Accept', 'x-api-key', 'Authorization'],
|
||||||
credentials: true,
|
credentials: true,
|
||||||
}));
|
}));
|
||||||
|
// Preserve raw body for Meta webhook HMAC validation (must run before express.json)
|
||||||
|
app.use('/webhook/whatsapp', express.raw({ type: '*/*' }));
|
||||||
app.use(express.json({ limit: '100kb' }));
|
app.use(express.json({ limit: '100kb' }));
|
||||||
app.use(express.urlencoded({ extended: true, limit: '100kb' }));
|
app.use(express.urlencoded({ extended: true, limit: '100kb' }));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user