Note: This setup guide is intended for use with ServiceNow Vulnerability Response. If you intend to set up this integration for ServiceNow Application 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.
Navigate to System OAuth > Application Registry in your ServiceNow settings.
Click New to create a new Application Registry.
Click Create an OAuth API endpoint for external clients
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.
Click Submit.
Create a Scripted REST API
Navigate to System Web Services > Scripted REST APIs.
Click New to create a new Scripted REST service:
Enter these values for these fields:
Name: HackerOne
API ID: hackerone
Click Submit and then open the newly created API.
Under the Resources tab, click New.
Enter these values for these fields:
Add the following script to process incoming vulnerability data:
(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
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_third_party_entry";
const vul_item_table = "sn_vul_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", 3);
vul_entry.setValue("source", vul_source);
vul_entry.setValue("summary", request_body.details);
vul_entry.setValue("name", request_body.title);
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("v3_base_score", request_body.cvss_score);
vul_entry.setValue("v3_vector_string", 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("external_id", request_body.report_id.toString())) {
vul_item.source = vul_source;
vul_item.setValue("vulnerability", vul_entry.sys_id);
vul_item.external_id = request_body.report_id.toString();
vul_item.insert();
}
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,
});
})(request, response);Click Submit.
Copy the Resource path of the newly created resource and save it for use later
Setup Severity Map
Navigate to Vulnerability Response > Normalized Severity Maps
To ensure accurate severity representation, use the following severity mapping between HackerOne and ServiceNow:
Configure on HackerOne
To set up the integration on HackerOne:
To access integrations, go to Engagements, click the kebab menu for the program you’re interested in, then click Settings.
Scroll down to Automation > Integrations.
Click Connect with ServiceNow.
Click Set up new integration to start the setup process.
Click on New Authentication to set up the connection to ServiceNow
Authenticate your ServiceNow instance by entering information into these fields:
ServiceNow Instance URL: Enter the full URL to your ServiceNow instance, for example, it could be: https://my-instance.service-now.com/
Client ID & Client Secret: Enter the Client ID and Client secret from step 4 in Configure OAuth.
Click Create and in the popup click Allow.
Click Next. Enter the create vulnerability URL of the scripted resource you have created before and click Next.
Select Synchronize attachments if you want to upload attachments to the Vulnerable Item and click Finish.
Enable the integration after finishing the setup wizard.
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.