From 9044f988de2ec78fc2374840b52d0551b5dbc396 Mon Sep 17 00:00:00 2001 From: Doug Markiewicz <53265380+doug-markiewicz@users.noreply.github.com> Date: Thu, 24 Jul 2025 16:41:47 -0400 Subject: [PATCH 1/2] Create burp suite custom integration --- burp-suite/README.md | 58 ++++ burp-suite/config.json | 1 + burp-suite/custom-integration-burp.star | 383 ++++++++++++++++++++++++ 3 files changed, 442 insertions(+) create mode 100644 burp-suite/README.md create mode 100644 burp-suite/config.json create mode 100644 burp-suite/custom-integration-burp.star diff --git a/burp-suite/README.md b/burp-suite/README.md new file mode 100644 index 0000000..1a8f00d --- /dev/null +++ b/burp-suite/README.md @@ -0,0 +1,58 @@ +# Custom Integration: Burp Suite DAST + +## runZero requirements + +- Superuser access to the [Custom Integrations configuration](https://console.runzero.com/custom-integrations) in runZero. + +## Burp Suite DAST requirements + +- API key with appropriate permissions. +- Burp Suite API URL (e.g. `https://:8443/graphql/v1`). + +## Steps + +### Burp Suite DAST configuration + +1. Create an API user for Burp Suite and copy the API key. + a. Login to the Burp Suite web console. + b. Navigate to Team > Add a new user + c. Enter a Name, Username and Email + d. For **Choose a login type**, select API key + e. Select the **Scan viewers** and **Sites maintainers** roles. +2. Note down the API URL: `https://:8443/graphql/v1`. + +### runZero configuration + +1. (OPTIONAL) - Make any necessary changes to the script to align with your environment. + - Set the BURP_API_URL variable in the integration script. + - If appropriate, modify GraphQL queries to fetch additional data points. + - If updating GraphQL queries, update build functions to include additional data points. +2. [Create the Credential for the Custom Integration](https://console.runzero.com/credentials). + - Select the type `Custom Integration Script Secrets`. + - For the `access_key`, enter a random value or leave the field blank. This attribute will not be used. + - For the `access_secret`, input your Burp Suite API key. +3. [Create the Custom Integration](https://console.runzero.com/custom-integrations/new). + - Add a Name and Icon for the integration (e.g., "burp"). + - Upload an image file for the Burp Suite icon. + - Download a Burp Suite icon from their [website](https://portswigger.net) or [social media](https://www.linkedin.com/company/portswigger/). + - Resize selected icon to be 256px by 256px + - Upload resized icon file + - Toggle `Enable custom integration script` to input the finalized script. + - Click `Validate` to ensure it has valid syntax. + - Click `Save` to create the Custom Integration. +4. [Create the Custom Integration task](https://console.runzero.com/ingest/custom/). + - Select the Credential and Custom Integration created in steps 2 and 3. + - Update the task schedule to recur at the desired timeframes. + - Select the Explorer you'd like the Custom Integration to run from. + - Click `Save` to kick off the first task. + +### What's next? + +- You will see the task kick off on the [tasks](https://console.runzero.com/tasks) page like any other integration. +- The task will update the existing assets with the data pulled from the Custom Integration source. +- The task will create new assets for when there are no existing assets that meet merge criteria (e.g hostname). +- You can search for assets enriched by this custom integration with the runZero search `custom_integration:burp`. + +### Additional Resources + +- [Burp Suite DAST API documentation](https://portswigger.net/burp/documentation/dast/user-guide/api-documentation/graphql-api/getting-started) \ No newline at end of file diff --git a/burp-suite/config.json b/burp-suite/config.json new file mode 100644 index 0000000..7bd553e --- /dev/null +++ b/burp-suite/config.json @@ -0,0 +1 @@ +{ "name": "Burp Suite DAST", "type": "inbound" } \ No newline at end of file diff --git a/burp-suite/custom-integration-burp.star b/burp-suite/custom-integration-burp.star new file mode 100644 index 0000000..3199328 --- /dev/null +++ b/burp-suite/custom-integration-burp.star @@ -0,0 +1,383 @@ +load('runzero.types', 'ImportAsset', 'NetworkInterface', 'Software', 'Vulnerability') +load('json', json_encode='encode', json_decode='decode') +load('net', 'ip_address') +load('http', http_post='post', http_get='get', 'url_encode') +load('uuid', 'new_uuid') + +# Sets the Burp Suite GraphQL API endpoint +BURP_API_URL = 'https://:8443/graphql/v1' + +# Sets the number of scans to check for issues. Using '1' will only pull the most recent scan. +SCAN_LIMIT = 1 + +# Sets the timeout for HTTP requests +HTTP_TIMEOUT = 300 + +# Sets the page size when pulling issue serial numbers +ISSUE_PAGE_SIZE = 1000 + +# GraphQL query to pull the site tree from Burp +QUERY_SITE_TREE = """ +query GetSiteTree { + site_tree { + sites { + id + name + parent_id + ephemeral + scope_v2 { + start_urls + out_of_scope_url_prefixes + } + } + } +} +""" +# GraphQL query to pull scan IDs for for a given site +QUERY_SCANS = """ +query GetScans($siteId: ID!, $limit: Int!) { + scans(site_id: $siteId, limit: $limit) { + id + } +} +""" + +# GraphQL query to pull issue serial numbers for given scan ID +QUERY_SCAN_ISSUES = """ +query GetScan($scanId: ID!, $start: Int!, $count: Int!) { + scan(id: $scanId) { + issues(start:$start, count:$count) { + serial_number + severity + } + } +} +""" + +# GraphQL query to pull issue details for a given scan ID and issue serial number +QUERY_ISSUE = """ +query getIssue($scanId: ID!, $serialNumber: ID!) { + issue(scan_id: $scanId, serial_number: $serialNumber) { + issue_type { + type_index + name + description_html + remediation_html + vulnerability_classifications_html + references_html + } + display_confidence + serial_number + remediation_html + description_html + confidence + severity + path + origin + evidence { + ... on Request { + request_index + request_count + request_segments { + ... on DataSegment { + data_html + } + ... on HighlightSegment { + highlight_html + } + ... on SnipSegment { + snip_length + } + } + } + ... on Response { + response_index + response_count + response_segments { + ... on DataSegment { + data_html + } + ... on HighlightSegment { + highlight_html + } + } + } + } + } +} +""" + +# Sets Burp risk ratings to numeric values that runZero can interpret +RISK_RANK_MAP = { + "critical": 4, + "high": 3, + "medium": 2, + "low": 1, +} +RISK_SCORE_MAP = { + "critical": 10, + "high": 7, + "medium": 5, + "low": 2, +} + +# Fetches the site tree from Burp +def get_sites(token): + print('fetching site tree from ' + BURP_API_URL) + headers = {'Content-Type':'application/json','Authorization': token} + body = {'query': QUERY_SITE_TREE} + resp = http_post(BURP_API_URL, headers=headers, body=bytes(json_encode(body)), timeout=300) + + if resp.status_code != 200: + print('failed to fetch site tree ' + '(' + resp.status_code + ')') + + resp_json = json_decode(resp.body) + + resp_err = resp_json.get('errors', []) + if resp_err: + for m in resp_err: + print('error: ', m.get('message', '')) + return None + + return resp_json.get('data').get('site_tree', {}).get('sites', []) + +# Fetches scan IDs for a given site +def get_scans(token, site_id, site_name): + print('fetching scan data for ' + site_name + ' (' + 'site_id: ' + site_id + ')') + headers = {'Content-Type':'application/json','Authorization': token} + body = {'query': QUERY_SCANS, 'variables':{'siteId': site_id, 'limit': SCAN_LIMIT}} + + resp = http_post(BURP_API_URL, headers=headers, body=bytes(json_encode(body)), timeout=HTTP_TIMEOUT) + if resp.status_code != 200: + print('failed to fetch scan data for ' + site_name + ' (' + resp.status_code + ')') + + resp_json = json_decode(resp.body) + + resp_err = resp_json.get('errors', []) + if resp_err: + for m in resp_err: + print('error fetching scan data for ' + site_name + ' (' + m.get('message', '') + ')') + return None + + return resp_json.get('data').get('scans', []) + +# Fetches the serial numbers of each issue from a given scan ID +def get_issue_serial_numbers(token, scan_id, start=0, count=1000): + headers = {'Content-Type':'application/json','Authorization': token} + body = {'query': QUERY_SCAN_ISSUES, 'variables':{'scanId': scan_id, 'start': start, 'count': count}} + resp = http_post(BURP_API_URL, headers=headers, body=bytes(json_encode(body)), timeout=HTTP_TIMEOUT) + + if resp.status_code != 200: + print('failed to fetch serial numbers for scan ID ' + scan_id + ' (' + resp.status_code + ')') + + resp_json = json_decode(resp.body) + + resp_err = resp_json.get('errors', []) + if resp_err: + for m in resp_err: + print('error fetching serial numbers for scan ID ' + scan_id + ' (' + m.get('message', '') + ')') + return None + + return resp_json.get('data', {}).get('scan', {}).get('issues', []) + +def get_issue(token, scan_id, serial_number): + headers = {'Content-Type':'application/json','Authorization': token} + body = {'query': QUERY_ISSUE, 'variables':{'scanId': scan_id, 'serialNumber': serial_number}} + resp = http_post(BURP_API_URL, headers=headers, body=bytes(json_encode(body)), timeout=HTTP_TIMEOUT) + + if resp.status_code != 200: + print('failed to fetch issue details for serial number ' + serial_number + ' (' + resp.status_code + ')') + + resp_json = json_decode(resp.body) + + resp_err = resp_json.get('errors', []) + if resp_err: + for m in resp_err: + print('error fetching issue details for serial number ' + serial_number + ' (' + m.get('message', '') + ')') + return None + + return resp_json.get('data', {}).get('issue', {}) + +# Builds asset records for importing into runZero +def build_assets(sites, token): + assets = [] + network = build_network_interface() + for s in sites: + scans = [] + scan_ids = [] + issue_serial_numbers = [] + issues = [] + + site_id = s.get('id', '') + site_name = s.get('name', '') + parent_id = s.get('parent_id', '') + ephemeral = s.get('ephemeral', '') + + scans = get_scans(token, site_id, site_name) + if scans: + for sid in scans: + scan_id = sid.get('id', '') + scan_ids.append(sid.get('id')) + issue_serial_numbers = get_issue_serial_numbers(token, scan_id) + if issue_serial_numbers: + for i in issue_serial_numbers: + serial_number = i.get('serial_number', '') + issue_details = get_issue(token, scan_id, serial_number) + if issue_details: + issues.append(issue_details) + + if issues: + vulnerabilities = build_vulnerabilities(site_id, site_name, issues) + else: + vulnerabilities = None + + # Create string of scan IDs + scan_ids_string = ', '.join(scan_ids) + + # Create string of serial numbers + serial_numbers = [item['serial_number'] for item in issue_serial_numbers] + serial_numbers_string = ", ".join(serial_numbers) + + assets.append( + ImportAsset( + id=site_id, + hostnames=[site_name], + networkInterfaces=[network], + vulnerabilities=vulnerabilities, + customAttributes={ + 'ephemeral': ephemeral, + 'lastSeenScanIds': scan_ids_string, + 'lastSeenIssueSerialNumbers': serial_numbers_string, + 'siteId': site_id, + 'siteName': site_name, + 'parentId': parent_id + + } + ) + ) + return assets + +# Build runZero network interface placeholder. Burp does not collect IP address or mac address. +def build_network_interface(): + return NetworkInterface(ipv4Addresses=[ip_address('127.0.0.1')]) + +# Build vulnerability records to include in asset import +def build_vulnerabilities(site_id, site_name, issues): + print('fetching vulnerability details for ' + site_name + ' (' + 'site_id: ' + site_id + ')') + vulns = [] + vulnerability_count = 0 + for i in issues: + confidence = i.get('confidence', '') + description = clean_html_tags(i.get('issue_type', {}).get('description_html', '')) + name = i.get('issue_type', {}).get('name', '') + origin = i.get('origin', '') + remediation = clean_html_tags(i.get('issue_type', {}).get('remediation_html', '')) + serial_number = i.get('serial_number', '') + type_index = i.get('issue_type', {}).get('type_index', '') + + severity = i.get('severity', '').lower() + if severity in RISK_RANK_MAP: + risk_rank = RISK_RANK_MAP[severity] + score = RISK_SCORE_MAP[severity] + else: + risk_rank = 0 + score = 0 + + evidence = i.get('evidence', []) + if evidence: + for item in evidence: + if 'request_segments' in item: + request_count = item['request_count'] + request_segments = [] + for segment in item['request_segments']: + if 'data_html' in segment: + request_segments.append(segment['data_html']) + elif 'highlight_html' in segment: + request_segments.append(segment['highlight_html']) + else: + continue + elif 'response_segments' in item: + response_count = item['response_count'] + response_segments = '' + for segment in item['response_segments']: + if 'data_html' in segment: + response_segments += segment['data_html'] + response_segments += '\n\n' + elif 'highlight_html' in segment: + response_segments += segment['highlight_html'] + response_segments += '\n\n' + else: + continue + else: + print('no evidence available for issue serial number ' + serial_number) + evidence_request_count = '' + evidence_request_segments = '' + evidence_request_is_trunc = '' + evidence_response_count = '' + evidence_response_segments = '' + evidence_response_is_trunc = '' + + vulns.append( + Vulnerability( + id=str(new_uuid()), + name=name, + description=str(description), + solution=str(remediation), + riskScore=float(score), + riskRank=risk_rank, + severityScore=float(score), + severityRank=risk_rank, + serviceAddress="127.0.0.1", + customAttributes={ + 'confidence': confidence, + 'evidenceRequestCount': request_count, + 'evidenceRequestSegments': request_segments, + 'evidenceResponseCount': response_count, + 'evidenceResponseSegments': response_segments, + 'origin': origin, + 'serial_number': serial_number, + 'type_index': type_index + } + ) + ) + vulnerability_count += 1 + + print('fetched ' + str(vulnerability_count) + ' vulnerabilities for site ' + site_name) + return vulns + +# Replace HTML tags added by Burp +# Note: runZero uses markdown to format vulnerability description and solution attributes. +def clean_html_tags(content): + + if not content: + return content + + # Replace paragraph tags + content = content.replace('

', '') + content = content.replace('

', '\n\n') + + # Replace list tags + content = content.replace('
    ', '') + content = content.replace('
', '') + content = content.replace('
  • ', '\n- ') + + # Replace bold tags with a backtick. Text between backticks will appear in a code block. + content = content.replace('', '`') + content = content.replace('', '`') + + return content + +def main(**kwargs): + # kwargs!! + token = kwargs['access_secret'] + + # get site tree + sites = get_sites(token) + if not sites: + print('no sites were retrieved') + return None + + # build asset import + imported_assets = build_assets(sites, token) + + return imported_assets \ No newline at end of file From 614de38828397f6d10eedad307bfe4d6efc3b940 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 24 Jul 2025 21:07:07 +0000 Subject: [PATCH 2/2] Auto: update integrations JSON and README --- README.md | 1 + docs/integrations.json | 118 ++++++++++++++++++++++------------------- 2 files changed, 63 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index d2a8631..d6eeb10 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ If you need help setting up a custom integration, you can create an [issue](http ## Import to runZero - [Automox](https://github.com/runZeroInc/runzero-custom-integrations/blob/main/automox/) +- [Burp Suite DAST](https://github.com/runZeroInc/runzero-custom-integrations/blob/main/burp-suite/) - [Carbon Black](https://github.com/runZeroInc/runzero-custom-integrations/blob/main/carbon-black/) - [Cisco-ISE](https://github.com/runZeroInc/runzero-custom-integrations/blob/main/cisco-ise/) - [Cortex XDR](https://github.com/runZeroInc/runzero-custom-integrations/blob/main/cortex-xdr/) diff --git a/docs/integrations.json b/docs/integrations.json index c323ab8..aa4f386 100644 --- a/docs/integrations.json +++ b/docs/integrations.json @@ -1,24 +1,30 @@ { - "lastUpdated": "2025-06-02T21:09:20.457960Z", - "totalIntegrations": 20, + "lastUpdated": "2025-07-24T21:07:07.265701Z", + "totalIntegrations": 21, "integrationDetails": [ { - "name": "Carbon Black", + "name": "NinjaOne", "type": "inbound", - "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/carbon-black/README.md", - "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/carbon-black/custom-integration-carbon-black.star" + "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/ninjaone/README.md", + "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/ninjaone/custom-integration-ninjaone.star" }, { - "name": "Device42", + "name": "Lima Charlie", "type": "inbound", - "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/device42/README.md", - "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/device42/custom-integration-device42.star" + "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/lima-charlie/README.md", + "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/lima-charlie/custom-integration-lima-charlie.star" }, { - "name": "Kandji", + "name": "Carbon Black", "type": "inbound", - "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/kandji/README.md", - "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/kandji/custom-integration-kandji.star" + "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/carbon-black/README.md", + "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/carbon-black/custom-integration-carbon-black.star" + }, + { + "name": "Automox", + "type": "inbound", + "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/automox/README.md", + "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/automox/custom-integration-automox.star" }, { "name": "Sumo Logic", @@ -27,16 +33,10 @@ "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/sumo-logic/custom-integration-sumo.star" }, { - "name": "Lima Charlie", - "type": "inbound", - "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/lima-charlie/README.md", - "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/lima-charlie/custom-integration-lima-charlie.star" - }, - { - "name": "Stairwell", + "name": "Burp Suite DAST", "type": "inbound", - "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/stairwell/README.md", - "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/stairwell/custom-integration-stairwell.star" + "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/burp-suite/README.md", + "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/burp-suite/custom-integration-burp.star" }, { "name": "Digital Ocean", @@ -45,64 +45,64 @@ "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/digital-ocean/custom-integration-digital-ocean.star" }, { - "name": "Snipe-IT", + "name": "Cisco-ISE", "type": "inbound", - "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/snipe-it/README.md", - "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/snipe-it/snipeit.star" + "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/cisco-ise/README.md", + "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/cisco-ise/custom_integration_cisco-ise.star" }, { - "name": "Cortex XDR", - "type": "inbound", - "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/cortex-xdr/README.md", - "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/cortex-xdr/custom-integration-cortex-xdr.star" + "name": "runZero Vunerability Workflow", + "type": "outbound", + "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/vulnerability-workflow/README.md", + "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/vulnerability-workflow/custom-integration-vulnerability-workflow.star" }, { - "name": "runZero Task Sync", + "name": "Stairwell", "type": "inbound", - "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/task-sync/README.md", - "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/task-sync/custom-integration-task-sync.star" + "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/stairwell/README.md", + "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/stairwell/custom-integration-stairwell.star" }, { - "name": "NinjaOne", + "name": "Manage Engine Endpoint Central", "type": "inbound", - "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/ninjaone/README.md", - "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/ninjaone/custom-integration-ninjaone.star" + "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/manage-engine-endpoint-central/README.md", + "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/manage-engine-endpoint-central/custom-integration-endpoint-central.star" }, { - "name": "runZero Vulnerability Workflow", - "type": "outbound", - "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/vulnerability-workflow/README.md", - "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/vulnerability-workflow/custom-integration-vulnerability-workflow.star" + "name": "JAMF", + "type": "inbound", + "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/jamf/README.md", + "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/jamf/custom-integration-jamf.star" }, { - "name": "Netskope", + "name": "runZero Task Sync", "type": "inbound", - "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/netskope/README.md", - "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/netskope/custom-integration-netskope.star" + "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/task-sync/README.md", + "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/task-sync/custom-integration-task-sync.star" }, { - "name": "JAMF", + "name": "Snipe-IT", "type": "inbound", - "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/jamf/README.md", - "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/jamf/custom-integration-jamf.star" + "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/snipe-it/README.md", + "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/snipe-it/snipeit.star" }, { - "name": "Manage Engine Endpoint Central", + "name": "Drata", "type": "inbound", - "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/manage-engine-endpoint-central/README.md", - "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/manage-engine-endpoint-central/custom-integration-endpoint-central.star" + "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/drata/README.md", + "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/drata/custom-integration-drata.star" }, { - "name": "Cisco-ISE", + "name": "Netskope", "type": "inbound", - "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/cisco-ise/README.md", - "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/cisco-ise/custom_integration_cisco-ise.star" + "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/netskope/README.md", + "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/netskope/custom-integration-netskope.star" }, { - "name": "Automox", + "name": "Cortex XDR", "type": "inbound", - "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/automox/README.md", - "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/automox/custom-integration-automox.star" + "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/cortex-xdr/README.md", + "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/cortex-xdr/custom-integration-cortex-xdr.star" }, { "name": "Extreme Networks CloudIQ", @@ -117,10 +117,16 @@ "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/tanium/custom-integration-tanium.star" }, { - "name": "Drata", + "name": "Device42", "type": "inbound", - "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/drata/README.md", - "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/drata/custom-integration-drata.star" + "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/device42/README.md", + "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/device42/custom-integration-device42.star" + }, + { + "name": "Kandji", + "type": "inbound", + "readme": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/kandji/README.md", + "integration": "https://github.com/runZeroInc/runzero-custom-integrations/blob/main/kandji/custom-integration-kandji.star" } ] -} +} \ No newline at end of file