Skip to main content

ServiceNow AVR Setup

Organizations: Setup guide for ServiceNow Application Vulnerability Response

Updated this week

Note: This setup guide is intended for use with ServiceNow Application Vulnerability Response. If you intend to set up this integration for ServiceNow Vulnerability Response, please refer to this setup guide.

Note: This integration is only available for Enterprise programs.

Configure OAuth

Note: If you have configured an Application Registry before, you can skip this section.

  1. Navigate to System OAuth > Application Registry in your ServiceNow settings.

  2. Click New to create a new Application Registry.

  3. Click Create an OAuth API endpoint for external clients​

  4. Enter these values for these fields:

    • Name: HackerOne

    • Client ID: This is auto-generated. Copy this value; you'll need this later when setting up the OAuth connection.

    • Client Secret: Enter a secret key. You'll need this key again later in the process when setting up the OAuth connection.

  5. Click Submit.

Create a Scripted REST API

  1. Navigate to System Web Services > Scripted REST APIs.

  2. Click New to create a new Scripted REST service:

  3. Enter these values for these fields:

    1. Name: HackerOne

    2. API ID: hackerone

    3. Default ACLs: vulnerability_integration_svc

  4. Click Submit and then open the newly created API.

Create Vulnerability API

  1. Under the Resources tab, click New.

  2. Enter these values for these fields:

    1. Name: Create Vulnerability

    2. HTTP Method: POST

    3. Relative path: /create_vulnerability_avr

  3. Add the following script to process incoming vulnerability data:

    (function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
    try {
    let request_body;
    try {
    request_body = JSON.parse(request.body.dataString);
    } catch (error) {
    response.setStatus(400);
    response.setBody({ error: "Invalid JSON payload" });
    return;
    }
    let date = new Date(request_body.submission_date_y_m_d);
    let year = date.getFullYear();
    /** CONFIGURATION */
    const vul_table = "sn_vul_app_vul_entry";
    const vul_item_table = "sn_vul_app_vulnerable_item";
    const vul_source = "HackerOne";
    const vul_entry_id = "H1-" + year + "-" + request_body.report_id.toString();
    /** HELPER FUNCTIONS */
    function mapCVSSAttackVector(letter) {
    const mappings = {
    N: "NETWORK",
    A: "ADJACENT",
    L: "LOCAL",
    P: "PHYSICAL",
    };
    return mappings[letter] || "";
    }
    function mapCVSSScore(letter) {
    const mappings = {
    N: "NONE",
    L: "LOW",
    H: "HIGH",
    R: "REQUIRED",
    U: "UNCHANGED",
    C: "CHANGED",
    };
    return mappings[letter] || "";
    }
    /** MAIN */
    let vul_entry = new GlideRecord(vul_table);
    let cwe_entry = new GlideRecord("sn_vul_cwe");
    const cvss_components = [
    request_body.cvss_calculation_method,
    `AV:${request_body.cvss_attack_vector}`,
    `AC:${request_body.cvss_attack_complexity}`,
    `PR:${request_body.cvss_privileges_required}`,
    `UI:${request_body.cvss_user_interaction}`,
    `S:${request_body.cvss_scope}`,
    `C:${request_body.cvss_confidentiality}`,
    `I:${request_body.cvss_integrity}`,
    `A:${request_body.cvss_availability}`,
    ];
    const cvss_vector_string = cvss_components.join("/");
    if (!vul_entry.get("id", vul_entry_id)) {
    vul_entry.initialize();
    vul_entry.setValue("id", vul_entry_id);
    vul_entry.setValue("source_severity", parseInt(request_body.severity_number));
    vul_entry.setValue("source", vul_source);
    vul_entry.setValue("threat", request_body.details);
    if (request_body.cvss_calculation_method.includes("CVSS:3.1") || request_body.cvss_calculation_method.includes("CVSS:3.0")) {
    vul_entry.setValue("v3_attack_vector", mapCVSSAttackVector(request_body.cvss_attack_vector));
    vul_entry.setValue("v3_attack_complexity", mapCVSSScore(request_body.cvss_attack_complexity));
    vul_entry.setValue("v3_privileges_required", mapCVSSScore(request_body.cvss_privileges_required));
    vul_entry.setValue("v3_user_interaction", mapCVSSScore(request_body.cvss_user_interaction));
    vul_entry.setValue("v3_scope_change", mapCVSSScore(request_body.cvss_scope));
    vul_entry.setValue("v3_confidentiality_impact", mapCVSSScore(request_body.cvss_confidentiality));
    vul_entry.setValue("v3_integrity_impact", mapCVSSScore(request_body.cvss_integrity));
    vul_entry.setValue("v3_availability_impact", mapCVSSScore(request_body.cvss_availability));
    vul_entry.setValue("cvss_base_score", request_body.cvss_score);
    vul_entry.setValue("cvss_vector", cvss_vector_string);
    }
    if (request_body.cwe && cwe_entry.get("cwe_id", request_body.cwe)) {
    vul_entry.setValue("cwe_id", cwe_entry.sys_id);
    }
    vul_entry.insert();
    }
    let vul_item = new GlideRecord(vul_item_table);
    vul_item.initialize();
    if (!vul_item.get('vulnerability', vul_entry.sys_id)) {
    vul_item.setValue('source', vul_source);
    vul_item.setValue('vulnerability', vul_entry.sys_id);
    vul_item.setValue('technical_details', request_body.details.substring(0, 1000));
    vul_item.setValue('scan_type', 'manual')
    vul_item.insert();
    }
    response.setStatus(201);
    response.setBody({
    table_name: vul_item_table,
    sys_id: vul_item.sys_id || false,
    external_id: vul_item.number || false,
    link: vul_item.sys_id ? gs.getProperty("glide.servlet.uri") + vul_item.getLink() : false,
    });
    } catch (error) {
    response.setStatus(500);
    response.setBody({ error: "Server error", details: error.toString() });
    }
    })(request, response);
  4. Click Submit.

  5. Copy the Resource path of the newly created resource and save it for use later

Setup Severity Map

  1. Navigate to Vulnerability Response > Normalized Severity Maps

  2. To ensure accurate severity representation, use the following severity mapping between HackerOne and ServiceNow:

Configure on HackerOne

To set up the integration on HackerOne:

  1. To access integrations, go to Engagements, click the kebab menu for the program you’re interested in, then click Settings.

  2. Scroll down to Automation > Integrations.

  3. Click Connect with ServiceNow.

  4. Click Set up new integration to start the setup process.

  5. Click on New Authentication to set up the connection to ServiceNow

  6. Authenticate your ServiceNow instance by entering information into these fields:

    1. ServiceNow Instance URL: Enter the full URL to your ServiceNow instance, for example, it could be: https://my-instance.service-now.com/

    2. Client ID & Client Secret: Enter the Client ID and Client secret from step 4 in Configure OAuth.

  7. Click Create, and in the popup, click Allow.

  8. Click Next. Enter the URLs of the scripted resources you have created before and click Next.

  9. (Optional) Select which actions in HackerOne you'd like to post to ServiceNow in the Select HackerOne to ServiceNow events window. You can choose from:

    1. Comments: When someone comments on a report, post an update on the associated ServiceNow item.

    2. State changes: When someone changes the state of a report, post an update on the associated ServiceNow item.

    3. Rewards: When someone awards or suggests a bounty and/or bonus, post an update on the associated ServiceNow item.

    4. Show Bounty Award: Show the amount when a bounty is awarded or suggested (this also requires Rewards to be enabled).

    5. Assignee changes: When someone assigns a user/group to a report, post an update on the associated ServiceNow item.

    6. Disclosure: Post an update on the associated ServiceNow item when disclosure is requested or a report becomes public.

    7. Synchronize attachments: Synchronize attachments linked with reports and comments to the associated ServiceNow item.

  10. Copy the HackerOne ServiceNow Listener URL and save it for use when configuring outgoing requests.

  11. Enable the integration after finishing the setup wizard.

Configuring Outgoing Requests

After configuring incoming requests, you’ll need to configure outgoing requests in ServiceNow enabling you to post comments from ServiceNow to HackerOne. You’ll need to use Outbound REST Messages and Business Rules in the configuration process.

To configure posting comments from ServiceNow to HackerOne:

  1. Navigate to: System Web Services > Outbound > REST Message.

  2. Click New to create a new Outbound REST Message.

  3. Enter these values for these fields:

    • Name: HackerOne

    • Endpoint: The Public ServiceNow URL. This is found in the configuration wizard on the HackerOne platform.

    • Authentication Type: No authentication

  4. Click Submit.

  5. Reopen the HackerOne outbound REST message you just created.

  6. Click New to add a new HTTP Method.

  7. Enter these values for these fields:

    • Name: New Comment

    • HTTP Method: POST

    • Authentication Type: Inherit from parent

  8. Enter this in the Content field in the HTTP Request tab:

    {
    "event_name": "new_comment",
    "message": "${message}",
    "sys_id": "${sys_id}",
    "element_id": "${element_id}"
    }
  9. Add these two HTTP Headers on the same HTTP Request tab:

    • Accept: application/json

    • Content-Type: application/json

  10. Click Submit.

  11. Navigate to System Definition > Business Rules.

  12. Click New to create a new business rule.

  13. Enter these values for these fields:

    • Name: Add Comment

    • Table: Journal Entry [sys_journal_field]

    • Advanced: Make sure the box is checked

  14. Enter these values for these fields on the When to run tab.

    1. When: async

    2. Insert: Make sure the box is checked

    3. Filter Conditions:

      1. Value is not empty: AND :

      2. Name : is : sn_vul_vulnerable_item

  15. Enter this script in the Advanced tab:

    (function executeRule(current, previous /*null when async*/) {
    try {
    var vulnItem = new GlideRecord('sn_vul_vulnerable_item');
    if (!vulnItem.get(current.element_id))
    return;

    // Check if the vulnerable item source is HackerOne
    if (vulnItem.source != 'HackerOne')
    return;

    var r = new sn_ws.RESTMessageV2('HackerOne', 'New Comment');
    var encoded_message = GlideStringUtil.base64Encode(current.value.toString());

    r.setStringParameterNoEscape('message', encoded_message);
    r.setStringParameterNoEscape('sys_id', current.sys_id);
    r.setStringParameterNoEscape('element_id', current.element_id);

    r.execute();
    } catch (ex) {
    gs.error("HackerOne webhook error: " + ex.message);
    }
    })(current, previous);
  16. Click Submit.

Make sure that the arguments for RESTMessageV2 match the name you gave to the Outbound REST Message.

You're all set! Now that you've finished setting up the ServiceNow integration, you can create a vulnerable item right from your HackerOne report.

Did this answer your question?