Skip to content

Conversation

vaibhav-nanda
Copy link
Contributor

@vaibhav-nanda vaibhav-nanda commented Sep 25, 2025

https://twilio-engineering.atlassian.net/browse/FUNK-2000
The X-Signature is not being sent for extensible webhook right now, although the UI provides an option to add the sharedSecret just like webhooks destination.

Testing

This is tested in staging. The shared secret val is being used to send the required data in x-signature header.
image

  • Added unit tests for new functionality
  • Tested end-to-end using the local server
  • [If destination is already live] Tested for backward compatibility of destination. Note: New required fields are a breaking change.
  • [Segmenters] Tested in the staging environment
  • [Segmenters] [If applicable for this change] Tested for regression with Hadron.

Copy link

codecov bot commented Sep 25, 2025

Codecov Report

❌ Patch coverage is 87.50000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 80.03%. Comparing base (7710428) to head (d0e3291).

Files with missing lines Patch % Lines
...tions/src/destinations/webhook-extensible/index.ts 87.50% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3316   +/-   ##
=======================================
  Coverage   80.03%   80.03%           
=======================================
  Files        1202     1202           
  Lines       22105    22112    +7     
  Branches     4355     4359    +4     
=======================================
+ Hits        17691    17697    +6     
  Misses       3637     3637           
- Partials      777      778    +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@joe-ayoub-segment
Copy link
Contributor

Hi @vaibhav-nanda ping me here when you need this reviewed.

@vaibhav-nanda vaibhav-nanda marked this pull request as ready for review September 30, 2025 08:38
@vaibhav-nanda vaibhav-nanda requested a review from a team as a code owner September 30, 2025 08:38
Comment on lines +34 to +42
if (payload) {
const payloadData = payload.length ? payload[0]['data'] : payload['data']
if (settings.sharedSecret && payloadData) {
const digest = createHmac('sha1', settings.sharedSecret)
.update(JSON.stringify(payloadData), 'utf8')
.digest('hex')
xSignatureHeader = { 'X-Signature': digest }
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @vaibhav-nanda I have a few questions about this:

  1. Do we need the xSignatureHeader to always be present if the customer provides a sharedSecret?

  2. How do you know that you are generating the xSignatureHeader correctly?

  3. This Action implements the performBatch() function. If we send a batch of events then I assume the xSignatureHeader needs to created based off of all the data being sent - is that correct?

  4. Shouldn't the xSignatureHeader value be generated from the actual payload being sent to the destination platform, rather than the input payload values? I can see that the data object gets encoded before it gets sent. if (data) return encodeBody(data, contentType)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @joe-ayoub-segment

  1. Yes, the x-signature header is expected to be present always, if the customer has provided a sharedSecret.

  2. This was confirmed by verifying the header being sent on the destination. The header received on destination was matched with the value calculated using the code on Line 37, and it was the same. This was also confirmed by sending the same request on Actions Webhook destination (it has the same functionality for x-signature header) and it also had the same header as the extensible webhooks.

  3. As per the current implementation in Actions Webhook destination, only the first event in the payload is being used to generate the xSignatureHeader. The same is being followed over here as well.

  4. It has been confirmed by comparing the xSignatureHeader values from Actions webhook and Extensible Webhook destinations. Both are sending out the same headers for the same request to both of them. The xSignatureHeader value is same for both the scenarios.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @vaibhav-nanda,

Regarding 1. Makes sense.

Regarding 2. Makes sense.

Regarding 3 and 4: This doesn't make sense to me. Shouldn't the entire body be used? How will the receiving side know how to check which part of the body was used when it's checking if the request is valid? Because of this I think we should ask @varadarajan-tw to take a look. I'm not qualified ;)!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like for webhook action destination, we call out the signature computation logic in the docs.
https://segment.com/docs/connections/destinations/catalog/actions-webhook/#shared-secret-with-batching. The customer should be able to validate by parsing the body, computing signature and validating it against the the header sent by Segment.

However, the general practice is to compute it for the entire request body. I don't see a standard at Segment but Twilio's signature signing standard seems to be a good one to follow. We can implement this and call this out in our docs so that customers know how to validate.

My only concern with batch request signing is performance when dealing with large payloads. If it doesn't add too much overhead for a batch of 1000 requests, we should consider signing the entire payload.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @varadarajan-tw - makes sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants