Webhooks

How to use Outgoing Webhooks

Webhooks are based on system events, so each webhook delivery will be for a single event resource. Events are versioned and the schema for the data attribute is static within an API version. Note that the data attribute of an event resource is different from the data JSON keys that wrap API resources.

Make sure that your API token uses version 2021-10-28 or later to receive the event data attribute. You can specify the API version on the API credentials page.

Using the Outgoing Webhooks documentation

Webhook Documentation

You will find information about the different parts of the request:

  • What triggers the webhook to make a request
  • Header parameters
  • Request body schema
  • Notes on the expected response
  • Payload examples for the event (on the right sidebar)

Getting Started

Setup an Outgoing Webhook integration

To create a new Outgoing Webhook endpoint:

  1. Go to the Settings tab for your program and click Integrations.

    For a program, go to the Settings tab and click Integrations

    The Integrations page is displayed.

  2. In Outgoing Webhooks, click Add integration.

    In Outgoing Webhooks, click Add integration

    The Outgoing webhooks page is displayed.

  3. Click Add webhook.

    Click Add webhook

    The Add webhook page is displayed.

  4. Specify the following information:

    • Name: Provide a name for the webhook.
    • URL: Provide the consumer URL of the webhook. This URL will be provided by your internal team.
    • Triggering Events: Select the desired events that will trigger a webhook. For example, when a submission is created.

    Specify webhook name, URL, and triggering events

  5. Click Add & enable webhook.

    Click Add webhook

    The webhook is created and displays the Edit webhook page.

    The webhook instance is saved and displays on the Outgoing webhook page.

    The webhook instance is created and displays on the Outgoing webhook page

Viewing Recent Deliveries

Within the Outgoing webhooks integration, you can view past deliveries (failed or successful). This page will provide request headers, request bodies, and response data. Click Recent Deliveries to view the past deliveries.

Click Recent Deliveries to view the past deliveries

Example Use Case

  1. Submission’s severity is updated to P1
  2. Webhook consumer receives submission.updated webhook request
  3. Webhook consumer looks at change data to see Submission’s severity was updated to P1
  4. Webhook consumer creates an urgent Jira ticket and sends a Slack message for investigation

Validating the Signature

GitHub reference

  1. On the Outgoing webhooks page, click the Edit icon under Actions.

    On the Outgoing webhooks page, click the Edit icon under Actions

    The Edit webhook page is displayed.

  2. Copy the secret code.

    Copy the secret code

  3. Store the secret securely in your application and use it to verify the webhook request.

Ruby Example

Replace the values where applicable.

require 'openssl'
require 'rack'

# Secret from Outgoing Webhooks integration settings page in Crowdcontrol
secret = "replace with your integration's secret"

# Raw digest from the request header `X-Bugcrowd-Digest`
raw_digest = "replace with the digest from the `X-Bugcrowd-Digest` header"

# Raw body from the request - can use "copy to clipboard" from the deliveries page
raw_body = "replace with your webhook's body"

# Separate the timestamp
at_time = raw_digest.split(';').first.tr('timestamp=', '')

# Separate the digest string
digest = raw_digest.split(';').last

# Generate a new signature
signature = 'sha256=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), secret, (raw_body + at_time))

# Compare the new signature with the digest from the request
Rack::Utils.secure_compare(signature, digest)

# _To avoid timing attacks, always use `secure_compare` (which performs comparisons in constant time) instead of an equality operator like `=`._

Python Example

Replace the values where applicable.

import hmac
import json

secret = "replace with your integration's secret"
raw_digest = "replace with the digest from the `X-Bugcrowd-Digest` header"

# To get the raw body into the correct format from a non-compacted server, you need to specify compact formatting when dumping it to JSON:
# raw_body = json.dumps(payload, separators=(',', ':'))
# Alternatively can copy from the deliveries page
raw_body = "replace with your webhook's body"

digest = raw_digest.split(';')[1]
at_time = raw_digest.split(';')[0].split('=')[1]
signature = 'sha256=' + hmac.new(secret.encode('utf8'), (raw_body + at_time).encode('utf8'), digestmod='SHA256').digest().hex()
hmac.compare_digest(digest, signature)