Skip to content

Commit 26eafda

Browse files
committed
fix(triggers): require a positive signal in Twilio matchEvent routing
Previously an empty MessageStatus/SmsStatus was treated as a status callback, so an ambiguous or partial payload could match twilio_sms_status (or skip twilio_sms_received). Both triggers now require a positive signal — inbound needs status 'received', status callbacks need a non-'received' status — so a payload missing both fields matches neither rather than misrouting.
1 parent e52ddb5 commit 26eafda

2 files changed

Lines changed: 15 additions & 5 deletions

File tree

apps/sim/lib/webhooks/providers/twilio.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,12 @@ describe('twilioHandler', () => {
175175
it('passes through when no triggerId is configured', () => {
176176
expect(match('', inbound)).toBe(true)
177177
})
178+
179+
it('matches neither trigger for an ambiguous payload missing status fields', () => {
180+
const ambiguous = { MessageSid: 'SM1', From: '+1' }
181+
expect(match('twilio_sms_received', ambiguous)).toBe(false)
182+
expect(match('twilio_sms_status', ambiguous)).toBe(false)
183+
})
178184
})
179185

180186
describe('formatInput', () => {

apps/sim/lib/webhooks/providers/twilio.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,21 @@ export const twilioHandler: WebhookProviderHandler = {
2828
/**
2929
* Distinguish an inbound SMS from a delivery status callback so the two
3030
* triggers don't fire on each other's deliveries when they share a URL.
31-
* Twilio reports `SmsStatus: 'received'` for inbound messages; status
32-
* callbacks carry a delivery `MessageStatus` (queued/sent/delivered/…).
31+
* Twilio reports status `received` for inbound messages; delivery callbacks
32+
* carry a non-`received` `MessageStatus` (queued/sent/delivered/…). Each side
33+
* requires a positive signal, so an ambiguous payload missing both fields
34+
* matches neither trigger rather than misrouting.
3335
*/
3436
matchEvent({ body, providerConfig }: EventMatchContext) {
3537
const triggerId = providerConfig.triggerId as string | undefined
3638
if (!triggerId) return true
3739
const b = body as Record<string, unknown>
38-
const status = (((b.MessageStatus as string) || (b.SmsStatus as string)) ?? '').toLowerCase()
39-
const isInbound = status === 'received'
40+
const messageStatus = ((b.MessageStatus as string) ?? '').toLowerCase()
41+
const smsStatus = ((b.SmsStatus as string) ?? '').toLowerCase()
42+
const isInbound = smsStatus === 'received' || messageStatus === 'received'
43+
const isStatusCallback = !isInbound && (messageStatus !== '' || smsStatus !== '')
4044
if (triggerId === 'twilio_sms_received') return isInbound
41-
if (triggerId === 'twilio_sms_status') return !isInbound
45+
if (triggerId === 'twilio_sms_status') return isStatusCallback
4246
return true
4347
},
4448

0 commit comments

Comments
 (0)