HackerOne
HackerOne integration allows users to fetch reports by using the fetch incidents capability. It also provides commands to retrieve all the reports and programs.
Vulnerability Management · HackerOne
Details
| ID | HackerOne |
|---|---|
| Provider | HackerOne |
| Category | Vulnerability Management |
| From Version | 6.0.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
HackerOne integration allows users to fetch reports by using the fetch incidents capability. It also provides commands to retrieve all the reports and programs.
This integration was integrated and tested with API version v1 of HackerOne.
Advanced Filter
Theadvanced_filter parameter used both in the hackerone-report-list command and in the integration configuration, is used to filter results based on attribute values.
The general filtering syntax is as follows:
{"attribute": "value1, value2"}
attributeis the name of the attribute that the filter will be applied against.valueis the value being checked for. You can specify multiple values as a comma-separated list for the attributes that are accepting the multiple values according to the API document.- To specify multiple filters, use the comma ( , ) to separate them
(for example,{"attribute1": "value1, value2", "attribute2" : "value3, value4"}).
To get the detailed information regarding the valid attributes for filtering user can refer to the HackerOne API documentation.
Configure HackerOne in Cortex
| Parameter | Description | Required |
|---|---|---|
| Server URL | Server URL to connect to HackerOne. | True |
| Username | The username of the user. | True |
| Maximum number of incidents per fetch | The maximum limit is 100. | False |
| First fetch time interval | Date or relative timestamp to start fetching incidents from. Formats accepted: 2 minutes, 2 hours, 2 days, 2 weeks, 2 months, 2 years, yyyy-mm-dd, yyyy-mm-ddTHH:MM:SSZ, etc |
False |
| Program Handle | Fetches reports based on the specified program handle. Supports comma separated values. Note: To get program handle, use the “hackerone-program-list” command. |
True |
| State | Fetches reports based on the specified report state. Note: Supports comma separated values. |
False |
| Severity | Fetches reports based on severity ratings of the report. Note: Supports comma separated values. |
False |
| Advanced Filters | By providing advanced filters users can get specific reports according to their requirements. Supports JSON format. Note: This will take higher precedence over “Program Handle”, “State” and “Severity”. Format accepted: {“filter[attribute1][]”: “value1, value2”, “filter[attribute2]” : “value3”} For example: {“filter[closed_at__gt]” : “2020-10-26T10:48:16.834Z”, “filter[state][]” : “new, triaged”} To know more visit: https://api.hackerone.com/customer-resources/#reports-get-all-reports. |
False |
| Use system proxy settings | False | |
| Trust any certificate (not secure) | False | |
| Incident type | False | |
| Fetch incidents | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
hackerone-report-list
Retrieves all the reports based on program handle and provided arguments.
Base Command
hackerone-report-list
Input
| Argument Name | Description | Required |
|---|---|---|
| program_handle | The program handle to fetch the reports based on the specified handle. Users can get the list of the program_handle by executing the “hackerone-program-list” command. Note: Supports comma separated values. |
Required |
| sort_by | Sort the reports based on the attributes provided. Possible values: swag_awarded_at, bounty_awarded_at, last_reporter_activity_at, first_program_activity_at, last_program_activity_at, triaged_at, created_at, closed_at, last_public_activity_at, last_activity_at, disclosed_at. Note: The default sort order for an attribute is descending. Prefix the attributes with a hyphen to sort in ascending order. Supports comma separated values. Example: -last_reporter_activity_at, created_at. |
Optional |
| page_size | The number of reports to retrieve per page. Default value is 50. Note: Possible values are between 1 and 100. |
Optional |
| page_number | Page number to retrieve the reports from the specified page. Default value is 1. | Optional |
| advanced_filter | By providing advanced filters, users can get specific reports according to their requirements. Supports JSON format. Note: This will take higher precedence over “program_handle”, “filter_by_keyword”, “state” and “severity”. Format accepted: {“filter[attribute1][]”: “value1, value2”, “filter[attribute2]” : “value3”} For example: {“filter[closed_at__gt]”:”2020-10-26T10:48:16.834Z”,”filter[state][]”:”new, triaged”}. |
Optional |
| filter_by_keyword | The keyword filter to retrieve the reports by title and keywords. | Optional |
| state | The state filter to retrieve the reports by current report state. Possible values: new, pending-program-review, triaged, needs-more-info, resolved, not-applicable, informative, duplicate, spam, retesting. Note: Supports comma separated values. |
Optional |
| severity | The severity filter to retrieve the reports by the severity ratings. Possible values: none, low, medium, high, critical. Note: Supports comma separated values. |
Optional |
| limit | Number of reports to retrieve. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| HackerOne.Report.id | String | The unique ID of the report. |
| HackerOne.Report.type | String | The type of the object of HackerOne. |
| HackerOne.Report.attributes.title | String | The title of the report. |
| HackerOne.Report.attributes.state | String | The state of the Report. It can be new, pending-program-review, triaged, needs-more-info, resolved, not-applicable, informative, duplicate, spam or retesting. |
| HackerOne.Report.attributes.created_at | Date | The date and time the object was created. Formatted according to ISO 8601. |
| HackerOne.Report.attributes.vulnerability_information | String | Detailed information about the vulnerability including the steps to reproduce as well as supporting material and references. |
| HackerOne.Report.attributes.triaged_at | Date | The date and time the object was triaged. Formatted according to ISO 8601. |
| HackerOne.Report.attributes.closed_at | Date | The date and time the object was closed. Formatted according to ISO 8601. |
| HackerOne.Report.attributes.last_reporter_activity_at | String | The date and time that the most recent reporter activity was posted on the report. Formatted according to ISO 8601. |
| HackerOne.Report.attributes.first_program_activity_at | String | The date and time that the first program activity was posted on the report. Formatted according to ISO 8601. |
| HackerOne.Report.attributes.last_program_activity_at | String | The date and time that the most recent program activity was posted on the report. Formatted according to ISO 8601. |
| HackerOne.Report.attributes.bounty_awarded_at | String | The date and time that the most recent bounty was awarded on the report. Formatted according to ISO 8601. |
| HackerOne.Report.attributes.swag_awarded_at | String | The date and time that the most recent swag was awarded on the report. Formatted according to ISO 8601. |
| HackerOne.Report.attributes.disclosed_at | String | The date and time the report was disclosed. Formatted according to ISO 8601. |
| HackerOne.Report.attributes.reporter_agreed_on_going_public_at | String | The date and time the reporter agreed for the public disclosure. Formatted according to ISO 8601. |
| HackerOne.Report.attributes.last_public_activity_at | String | The date and time that the most recent public activity was posted on the report. Formatted according to ISO 8601. |
| HackerOne.Report.attributes.last_activity_at | String | The date and time that the most recent activity was posted on the report. Formatted according to ISO 8601. |
| HackerOne.Report.attributes.source | String | A free-form string defining the source of the report for tracking purposes. For example, “detectify”, “rapid7” or “jira”. |
| HackerOne.Report.attributes.timer_bounty_awarded_elapsed_time | Number | The total number of seconds that have elapsed between when the timer started and when it stopped ticking. The timer does not take weekends into account. If the field is null and the corresponding miss_at field is set, it means the timer is still counting. |
| HackerOne.Report.attributes.timer_bounty_awarded_miss_at | Date | The date and time the system expects the program to have awarded a bounty by. The field is null when the system does not expect the report to receive a bounty at the time. |
| HackerOne.Report.attributes.timer_first_program_response_miss_at | Date | The date and time the system expects the program to have posted an initial public comment to the report by. |
| HackerOne.Report.attributes.timer_first_program_response_elapsed_time | Number | The total number of seconds that have elapsed between when the timer started and when it stopped ticking. The timer does not take weekends into account. If the field is null and the corresponding miss_at field is set, it means the timer is still counting. |
| HackerOne.Report.attributes.timer_report_resolved_miss_at | Date | The date and time the system expects the program to have closed the report by. The field is null when the report seems blocked by the reporter. |
| HackerOne.Report.attributes.timer_report_resolved_elapsed_time | Number | The total number of seconds that have elapsed between when the timer started and when it stopped ticking. The timer does not take weekends into account. If the field is null and the corresponding miss_at field is set, it means the timer is still counting. |
| HackerOne.Report.attributes.timer_report_triage_miss_at | Date | The date and time the system expects the program to have triaged the report by. The field is null when the system does not expect the report to be triaged at the time. |
| HackerOne.Report.attributes.timer_report_triage_elapsed_time | Number | The total number of seconds that have elapsed between when the timer started and when it stopped ticking. The timer does not take weekends into account. If the field is null and the corresponding miss_at field is set, it means the timer is still counting. |
| HackerOne.Report.relationships.reporter.data.id | String | The unique ID of the reporter. |
| HackerOne.Report.relationships.reporter.data.type | String | The type of the object of HackerOne. |
| HackerOne.Report.relationships.reporter.data.attributes.username | String | The username of the reporter. |
| HackerOne.Report.relationships.reporter.data.attributes.name | String | The name of the reporter. |
| HackerOne.Report.data.relationships.reporter.data.attributes.disabled | Boolean | Indicates if the reporter is disabled. |
| HackerOne.Report.data.relationships.reporter.data.attributes.created_at | String | The date and time the object was created. Formatted according to ISO 8601. |
| HackerOne.Report.data.relationships.reporter.data.attributes.profile_picture.62x62 | String | URL of the profile photo of a reporter of size 62x62. |
| HackerOne.Report.data.relationships.reporter.data.attributes.profile_picture.82x82 | String | URL of the profile photo of a reporter of size 82x82. |
| HackerOne.Report.data.relationships.reporter.data.attributes.profile_picture.110x110 | String | URL of the profile photo of a reporter of size 110x110. |
| HackerOne.Report.data.relationships.reporter.data.attributes.profile_picture.260x260 | String | URL of the profile photo of a reporter of size 260x260. |
| HackerOne.Report.data.relationships.reporter.data.attributes.bio | String | The reporter’s biography, as provided by the reporter. |
| HackerOne.Report.data.relationships.reporter.data.attributes.reputation | Number | The reputation of the reporter. |
| HackerOne.Report.data.relationships.reporter.data.attributes.signal | Number | The signal of the reporter. This number ranges from -10 to 7. The closer to 7, the higher the average submission quality of the reporter. |
| HackerOne.Report.data.relationships.reporter.data.attributes.impact | Number | The impact of the reporter. This number ranges from 0 to 50. The closer to 50, the higher the average severity of the reporter’s reports is. |
| HackerOne.Report.data.relationships.reporter.data.attributes.website | String | The reporter’s website, as provided by the reporter. |
| HackerOne.Report.data.relationships.reporter.data.attributes.location | String | The reporter’s location, as provided by the reporter. |
| HackerOne.Report.data.relationships.reporter.data.attributes.hackerone_triager | Boolean | Indicates if the reporter is a hackerone triager. |
| HackerOne.Report.data.relationships.program.data.id | String | The unique ID of the program. |
| HackerOne.Report.data.relationships.program.data.type | String | The type of the object of HackerOne. |
| HackerOne.Report.data.relationships.program.data.attributes.handle | String | The handle of the program. |
| HackerOne.Report.data.relationships.program.data.attributes.created_at | String | The date and time the object was created. Formatted according to ISO 8601. |
| HackerOne.Report.data.relationships.program.data.attributes.updated_at | String | The date and time the object was updated. Formatted according to ISO 8601. |
| HackerOne.Report.data.relationships.severity.data.id | String | The unique ID of the severity. |
| HackerOne.Report.data.relationships.severity.data.type | String | The type of the severity of HackerOne. |
| HackerOne.Report.data.relationships.severity.data.attributes.rating | String | The qualitative rating of the severity. |
| HackerOne.Report.data.relationships.severity.data.attributes.author_type | String | The involved party that provided the severity. |
| HackerOne.Report.data.relationships.severity.data.attributes.user_id | Number | The unique id of the user who created the object. |
| HackerOne.Report.data.relationships.severity.data.attributes.created_at | String | The date and time the object was created. Formatted according to ISO 8601. |
| HackerOne.Report.data.relationships.severity.data.attributes.score | Number | The vulnerability score calculated from the Common Vulnerability Scoring System (CVSS). |
| HackerOne.Report.data.relationships.severity.data.attributes.attack_complexity | String | A CVSS metric that describes the conditions beyond the attacker’s control that must exist in order to exploit the vulnerability. |
| HackerOne.Report.data.relationships.severity.data.attributes.attack_vector | String | A CVSS metric that reflects the context by which vulnerability exploitation is possible. |
| HackerOne.Report.data.relationships.severity.data.attributes.availability | String | A CVSS metric that measures the availability of the impacted component resulting from a successfully exploited vulnerability. |
| HackerOne.Report.data.relationships.severity.data.attributes.confidentiality | String | A CVSS metric that measures the impact to the confidentiality of the information resources managed by a software component due to a successfully exploited vulnerability. |
| HackerOne.Report.data.relationships.severity.data.attributes.integrity | String | A CVSS metric that measures the impact to the integrity of a successfully exploited vulnerability. |
| HackerOne.Report.data.relationships.severity.data.attributes.privileges_required | String | A CVSS metric that describes the level of privileges an attacker must possess before successfully exploiting the vulnerability. |
| HackerOne.Report.data.relationships.severity.data.attributes.user_interaction | String | A CVSS metric that captures the requirement for a user, other than the attacker, to participate in the successful compromise of the vulnerability component. |
| HackerOne.Report.data.relationships.severity.data.attributes.scope | String | A CVSS metric that determines if a successful attack impacts a component other than the vulnerable component. |
| HackerOne.Report.data.relationships.weakness.data.id | String | The unique ID of the weakness. |
| HackerOne.Report.data.relationships.weakness.data.type | String | The type of the object of HackerOne. |
| HackerOne.Report.data.relationships.weakness.data.attributes.name | String | The name of the weakness. |
| HackerOne.Report.data.relationships.weakness.data.attributes.description | String | The raw description of the weakness. |
| HackerOne.Report.data.relationships.weakness.data.attributes.external_id | String | The weakness’ external reference to CWE or CAPEC. |
| HackerOne.Report.data.relationships.weakness.data.attributes.created_at | String | The date and time the object was created. Formatted according to ISO 8601. |
| HackerOne.Report.data.relationships.custom_field_values.data.id | String | The unique ID of the custom field value. |
| HackerOne.Report.data.relationships.custom_field_values.data.type | String | The type of the object of HackerOne. |
| HackerOne.Report.data.relationships.custom_field_values.data.attributes.value | String | The attribute’s value. |
| HackerOne.Report.data.relationships.custom_field_values.data.attributes.created_at | String | The date and time the object was created. Formatted according to ISO 8601. |
| HackerOne.Report.data.relationships.custom_field_values.data.attributes.updated_at | String | The date and time the object was updated. Formatted according to ISO 8601. |
| HackerOne.Report.data.relationships.custom_field_values.data.relationships.custom_field_attribute.data.id | String | The unique ID of the custom field attribute. |
| HackerOne.Report.data.relationships.custom_field_values.data.relationships.custom_field_attribute.data.type | String | The type of the object of HackerOne. |
| HackerOne.Report.data.relationships.custom_field_values.data.relationships.custom_field_attribute.data.attributes.field_type | String | The type of custom field. |
| HackerOne.Report.data.relationships.custom_field_values.data.relationships.custom_field_attribute.data.attributes.label | String | The attribute’s label. |
| HackerOne.Report.data.relationships.custom_field_values.data.relationships.custom_field_attribute.data.attributes.internal | Boolean | Internal or public custom field. |
| HackerOne.Report.data.relationships.custom_field_values.data.relationships.custom_field_attribute.data.attributes.required | Boolean | Whether the field is required or not. |
| HackerOne.Report.data.relationships.custom_field_values.data.relationships.custom_field_attribute.data.attributes.error_message | String | A custom error message when the regex validation fails. |
| HackerOne.Report.data.relationships.custom_field_values.data.relationships.custom_field_attribute.data.attributes.helper_text | String | The helper text for custom_field_attribute. |
| HackerOne.Report.data.relationships.custom_field_values.data.relationships.custom_field_attribute.data.attributes.configuration | String | An optional configuration for the attribute’s type. |
| HackerOne.Report.data.relationships.custom_field_values.data.relationships.custom_field_attribute.data.attributes.checkbox_text | String | The text shown with a checkbox field. |
| HackerOne.Report.data.relationships.custom_field_values.data.relationships.custom_field_attribute.data.attributes.regex | String | A regex used to validate the input for a text field. |
| HackerOne.Report.data.relationships.custom_field_values.data.relationships.custom_field_attribute.data.attributes.created_at | String | The date and time the object was created. Formatted according to ISO 8601. |
| HackerOne.Report.data.relationships.custom_field_values.data.relationships.custom_field_attribute.data.attributes.updated_at | String | The date and time the object was updated. Formatted according to ISO 8601. |
| HackerOne.Report.data.relationships.custom_field_values.data.relationships.custom_field_attribute.data.attributes.archived_at | String | The date and time the object was archived. Formatted according to ISO 8601. |
| HackerOne.Report.data.relationships.assignee.data.id | String | The unique ID of the user. |
| HackerOne.Report.data.relationships.assignee.data.type | String | The type of the object of HackerOne. |
| HackerOne.Report.data.relationships.assignee.data.attributes.name | Unknown | The name of the assignee. |
| HackerOne.Report.data.relationships.assignee.data.attributes.created_at | String | The date and time the object was created. Formatted according to ISO 8601. |
| HackerOne.Report.data.relationships.assignee.data.attributes.permissions | String | The permissions of the group/user. Possible values are reward_management, program_management, user_management, and report_management. |
| HackerOne.Report.data.relationships.assignee.data.attributes.username | String | The username of the assignee. |
| HackerOne.Report.data.relationships.assignee.data.attributes.disabled | Boolean | Indicates if the assignee is disabled. |
| HackerOne.Report.data.relationships.assignee.data.attributes.profile_picture.62x62 | String | URL of the profile photo of the assignee of size 62x62. |
| HackerOne.Report.data.relationships.assignee.data.attributes.profile_picture.82x82 | String | URL of the profile photo of the assignee of size 82x82. |
| HackerOne.Report.data.relationships.assignee.data.attributes.profile_picture.110x110 | String | URL of the profile photo of the assignee of size 110x110. |
| HackerOne.Report.data.relationships.assignee.data.attributes.profile_picture.260x260 | String | URL of the profile photo of the assignee of size 260x260. |
| HackerOne.Report.data.relationships.assignee.data.attributes.signal | Number | The signal of the assignee. The number ranges from -10 to 7. The closer to 7, the higher the average submission quality of the user. |
| HackerOne.Report.data.relationships.assignee.data.attributes.impact | Number | The impact of the assignee. This number ranges from 0 to 50. The closer to 50, the higher the average severity of the user’s reports is. |
| HackerOne.Report.data.relationships.assignee.data.attributes.reputation | Number | The reputation of the assignee. |
| HackerOne.Report.data.relationships.assignee.data.attributes.bio | String | The assignee’s biography, as provided by the assignee. |
| HackerOne.Report.data.relationships.assignee.data.attributes.website | String | The assignee’s website, as provided by the assignee. |
| HackerOne.Report.data.relationships.assignee.data.attributes.location | String | The assignee’s location, as provided by the assignee. |
| HackerOne.Report.data.relationships.assignee.data.attributes.hackerone_triager | Boolean | Indicates if the assignee is a hackerone triager. |
| HackerOne.Report.data.relationships.structured_scope.data.id | String | The unique ID of the scope. |
| HackerOne.Report.data.relationships.structured_scope.data.type | String | The type of the HackerOne object. |
| HackerOne.Report.data.relationships.structured_scope.data.attributes.asset_type | String | The type of the asset. |
| HackerOne.Report.data.relationships.structured_scope.data.attributes.asset_identifier | String | The identifier of the asset. |
| HackerOne.Report.data.relationships.structured_scope.data.attributes.eligible_for_bounty | Boolean | If the asset is eligible for a bounty. |
| HackerOne.Report.data.relationships.structured_scope.data.attributes.eligible_for_submission | Boolean | If the asset is eligible for a submission. |
| HackerOne.Report.data.relationships.structured_scope.data.attributes.instruction | String | The raw instruction of the asset provided by the program. |
| HackerOne.Report.data.relationships.structured_scope.data.attributes.max_severity | String | The qualitative rating of the maximum severity allowed on this asset. |
| HackerOne.Report.data.relationships.structured_scope.data.attributes.created_at | Date | The date and time the object was created. Formatted according to ISO 8601. |
| HackerOne.Report.data.relationships.structured_scope.data.attributes.updated_at | Date | The date and time the object was updated. Formatted according to ISO 8601. |
| HackerOne.Report.data.relationships.structured_scope.data.attributes.reference | String | The customer defined reference identifier or tag of the asset. |
| HackerOne.Report.data.relationships.bounties.data.id | String | The unique ID of the bounty. |
| HackerOne.Report.data.relationships.bounties.data.type | String | The type of the HackerOne object. |
| HackerOne.Report.data.relationships.bounties.data.attributes.created_at | Date | The date and time the object was created. Formatted according to ISO 8601. |
| HackerOne.Report.data.relationships.bounties.data.attributes.amount | String | Amount in USD. |
| HackerOne.Report.data.relationships.bounties.data.attributes.bonus_amount | String | Bonus amount in USD. |
| HackerOne.Report.data.relationships.bounties.data.attributes.awarded_amount | String | Amount in awarded currency. |
| HackerOne.Report.data.relationships.bounties.data.attributes.awarded_bonus_amount | String | Bonus amount in awarded currency. |
| HackerOne.Report.data.relationships.bounties.data.attributes.awarded_currency | String | The currency used to award the bounty and bonus. |
Command Example
!hackerone-report-list program_handle=something_h1b page_size=2
Context Example
{
"HackerOne": {
"Report": [
{
"attributes": {
"created_at": "2021-08-10T07:17:41.923Z",
"first_program_activity_at": "2021-08-10T07:17:42.048Z",
"last_activity_at": "2021-08-10T07:17:42.048Z",
"last_program_activity_at": "2021-08-10T07:17:42.048Z",
"last_public_activity_at": "2021-08-10T07:17:42.048Z",
"last_reporter_activity_at": "2021-08-10T07:17:42.048Z",
"state": "new",
"title": "Do not use depreciated function isSecure",
"vulnerability_information": "## Summary:\nThe depreciated function isSecure is not compatible with for SSL verification.\n\n## Impact\n\nSSL verification will fail regardless of certificate authenticity."
},
"id": "1297733",
"relationships": {
"custom_field_values": {
"data": [
{
"attributes": {
"created_at": "2021-08-10T07:17:41.929Z",
"updated_at": "2021-08-10T07:17:41.929Z",
"value": "true"
},
"id": "198319",
"relationships": {
"custom_field_attribute": {
"data": {
"attributes": {
"checkbox_text": "Yes",
"created_at": "2021-08-10T07:14:39.477Z",
"field_type": "Checkbox",
"helper_text": "Is the report urgent in need to be resolved?",
"internal": false,
"label": "Urgent",
"required": false,
"updated_at": "2021-08-10T07:14:39.477Z"
},
"id": "1362",
"type": "custom-field-attribute"
}
}
},
"type": "custom-field-value"
}
]
},
"program": {
"data": {
"attributes": {
"created_at": "2021-08-09T13:39:20.342Z",
"handle": "something_h1b",
"updated_at": "2021-08-10T09:29:56.853Z"
},
"id": "53994",
"type": "program"
}
},
"reporter": {
"data": {
"attributes": {
"created_at": "2021-08-02T09:27:56.324Z",
"disabled": false,
"hackerone_triager": false,
"name": "Jahnvi",
"profile_picture": {
"110x110": "/assets/avatars/default-71a302d706457f3d3a31eb30fa3e73e6cf0b1d677b8fa218eaeaffd67ae97918.png",
"260x260": "/assets/avatars/default-71a302d706457f3d3a31eb30fa3e73e6cf0b1d677b8fa218eaeaffd67ae97918.png",
"62x62": "/assets/avatars/default-71a302d706457f3d3a31eb30fa3e73e6cf0b1d677b8fa218eaeaffd67ae97918.png",
"82x82": "/assets/avatars/default-71a302d706457f3d3a31eb30fa3e73e6cf0b1d677b8fa218eaeaffd67ae97918.png"
},
"username": "jahnvi_crest"
},
"id": "1878386",
"type": "user"
}
},
"severity": {
"data": {
"attributes": {
"attack_complexity": "high",
"attack_vector": "adjacent",
"author_type": "User",
"availability": "none",
"confidentiality": "high",
"created_at": "2021-08-10T07:17:41.970Z",
"integrity": "low",
"privileges_required": "high",
"rating": "medium",
"scope": "changed",
"score": 6.2,
"user_id": 1878386,
"user_interaction": "none"
},
"id": "1185951",
"type": "severity"
}
},
"weakness": {
"data": {
"attributes": {
"created_at": "2017-01-05T01:51:19.000Z",
"description": "The program calls a function that can never be guaranteed to work safely.",
"external_id": "cwe-242",
"name": "Use of Inherently Dangerous Function"
},
"id": "20",
"type": "weakness"
}
}
},
"type": "report"
},
{
"attributes": {
"closed_at": "2021-08-10T07:11:12.110Z",
"created_at": "2021-08-10T07:09:28.496Z",
"first_program_activity_at": "2021-08-10T07:09:28.603Z",
"last_activity_at": "2021-08-17T07:36:10.504Z",
"last_program_activity_at": "2021-08-10T07:11:37.062Z",
"last_public_activity_at": "2021-08-10T07:11:37.062Z",
"last_reporter_activity_at": "2021-08-10T07:11:37.062Z",
"state": "resolved",
"timer_first_program_response_elapsed_time": 103,
"title": "SQL injection vulnerability in user signup form",
"vulnerability_information": "## Summary:\n[add summary of the vulnerability]\n\n## Steps To Reproduce:\n[add details for how we can reproduce the issue]\n\n 1. [add step]\n 1. [add step]\n 1. [add step]\n\n## Supporting Material/References:\n[list any additional material (e.g. screenshots, logs, etc.)]\n\n * [attachment / reference]\n\n## Impact\n\nCan query for all users in db"
},
"id": "1297727",
"relationships": {
"assignee": {
"data": {
"attributes": {
"created_at": "2021-08-09T13:39:21.016Z",
"name": "Standard",
"permissions": [
"report_management",
"reward_management"
]
},
"id": "112937",
"type": "group"
}
},
"program": {
"data": {
"attributes": {
"created_at": "2021-08-09T13:39:20.342Z",
"handle": "something_h1b",
"updated_at": "2021-08-10T09:29:56.853Z"
},
"id": "53994",
"type": "program"
}
},
"reporter": {
"data": {
"attributes": {
"created_at": "2021-08-02T09:27:56.324Z",
"disabled": false,
"hackerone_triager": false,
"name": "Jahnvi",
"profile_picture": {
"110x110": "/assets/avatars/default-71a302d706457f3d3a31eb30fa3e73e6cf0b1d677b8fa218eaeaffd67ae97918.png",
"260x260": "/assets/avatars/default-71a302d706457f3d3a31eb30fa3e73e6cf0b1d677b8fa218eaeaffd67ae97918.png",
"62x62": "/assets/avatars/default-71a302d706457f3d3a31eb30fa3e73e6cf0b1d677b8fa218eaeaffd67ae97918.png",
"82x82": "/assets/avatars/default-71a302d706457f3d3a31eb30fa3e73e6cf0b1d677b8fa218eaeaffd67ae97918.png"
},
"username": "jahnvi_crest"
},
"id": "1878386",
"type": "user"
}
},
"severity": {
"data": {
"attributes": {
"author_type": "User",
"created_at": "2021-08-10T07:09:28.534Z",
"rating": "low",
"user_id": 1878386
},
"id": "1185942",
"type": "severity"
}
},
"weakness": {
"data": {
"attributes": {
"created_at": "2017-01-05T01:51:19.000Z",
"description": "The software constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component.",
"external_id": "cwe-89",
"name": "SQL Injection"
},
"id": "67",
"type": "weakness"
}
}
},
"type": "report"
}
]
}
}
Human Readable Output
Report(s)
Report ID Reporter Username Title State Severity Created At Vulnerability Information 1297733 jahnvi_crest Do not use depreciated function isSecure new medium 2021-08-10T07:17:41.923Z ## Summary:
The depreciated function isSecure is not compatible with for SSL verification.
## Impact
SSL verification will fail regardless of certificate authenticity.1297727 jahnvi_crest SQL injection vulnerability in user signup form resolved low 2021-08-10T07:09:28.496Z ## Summary:
[add summary of the vulnerability]
## Steps To Reproduce:
[add details for how we can reproduce the issue]
1. [add step]
1. [add step]
1. [add step]
## Supporting Material/References:
[list any additional material (e.g. screenshots, logs, etc.)]
* [attachment / reference]
## Impact
Can query for all users in db
hackerone-program-list
Retrieves information about the programs in which the user is a member.
Base Command
hackerone-program-list
Input
| Argument Name | Description | Required |
|---|---|---|
| page_size | The number of programs to retrieve per page. Default value is 50. Note: Possible values are between 1 and 100. |
Optional |
| page_number | Page number to retrieve the programs from the specified page. Default value is 1. | Optional |
| limit | Number of programs to retrieve. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| HackerOne.Program.id | String | The unique ID of the program. |
| HackerOne.Program.type | String | The type of the object of HackerOne. |
| HackerOne.Program.attributes.handle | String | The handle of the program. |
| HackerOne.Program.attributes.policy | String | The policy of the program. |
| HackerOne.Program.attributes.created_at | Date | The date and time the object was created. Formatted according to ISO 8601. |
| HackerOne.Program.attributes.updated_at | Date | The date and time the object was updated. Formatted according to ISO 8601. |
Command Example
!hackerone-program-list page_size=2
Context Example
{
"HackerOne": {
"Program": [
{
"attributes": {
"created_at": "2021-08-09T13:39:20.342Z",
"handle": "something_h1b",
"policy": "# What we are looking for\r\nWe want to proactively discover and remediate security vulnerabilities on our digital assets\r\n\r\nThe vulnerabilities identified in the HackerOne reports will be classified by the degree of risk as well as the impact they present to the host system, this includes the amount and type of data exposed, privilege level obtained, the proportion of systems or users affected.\r\n\r\n# What is a Bug Bounty Program?\r\nsomething\u2019s Bug Bounty Program (BBP) is an initiative driven and managed by the something Information Security team. \r\n\r\n* Security researchers are encouraged to report any behavior impacting the information security posture of something\u2019 products and services. If you are performing research, please use your own accounts and do not interact with other people\u2019s accounts or data.\r\n* Document your findings thoroughly, providing steps to reproduce and send your report to us. Reports with complete vulnerability details, including screenshots or video, are essential for a quick response. If the report is not detailed enough to reproduce the issue, the issue will not be eligible for a reward.\r\n *Reference HackerOne guidance on writing quality reports:\r\n * https://docs.hackerone.com/hackers/quality-reports.html \r\n * https://www.hacker101.com/sessions/good_reports\r\n\r\n* We will contact you to confirm that we\u2019ve received your report and trace your steps to reproduce your research.\r\n* We will work with the affected teams to validate the report.\r\n* We will issue bounty awards for eligible findings. To be eligible for rewards, reports must comply with all parts of this policy and you must be the first to report the issue to us. You must be 18 or older to be eligible for an award.\r\n* We will notify you of remediation and may reach out for questions or clarification. You must be available to provide additional information if needed by us to reproduce and investigate the report.\r\n\r\n\r\n# Response Targets\r\nWe will make a best effort to meet the following response targets for hackers participating in our program:\r\n\r\n* Time to first response (from report submit) - 1 business days\r\n* Time to triage (from report submit) - 2 business days \r\n* Time to bounty (from triage) - 10 business days\r\n\r\nWe\u2019ll try to keep you informed about our progress throughout the process.\r\n\r\n# Program Rules\r\n* Do not try to further pivot into the network by using a vulnerability. The rules around Remote Code Execution (RCE), SQL Injection (SQLi), and FileUpload vulnerabilities are listed below.\r\n* Do not try to exploit service providers we use, prohibited actions include, but are not limited to bruteforcing login credentials of Domain Registrars, DNS Hosting Companies, Email Providers and/or others. The Firm does not authorize you to perform any actions to any property/system/service/data not listed below.\r\n* If you encounter Personally Identifiable Information (PII) contact us immediately. Do not proceed with access and immediately purge any local information, if applicable.\r\n* Please limit any automated scanning to 60 requests per second. Aggressive testing that causes service degradation will be grounds for removal from the program.\r\n\r\n* Submit one vulnerability per- report, unless you need to chain vulnerabilities to provide impact.\r\n* When duplicates occur, we only award the first report that was received (provided that it can be fully reproduced).\r\n* Multiple vulnerabilities caused by one underlying issue will be awarded one bounty.\r\n* Social engineering (e.g. phishing, vishing, smishing) is prohibited.\r\n* Make a good faith effort to avoid privacy violations, destruction of data, and interruption or degradation of our service. Only interact with accounts you own or with the explicit permission of the account holder.\r\n\r\n# Disclosure Policy\r\n* As this is a private program, please do not discuss this program or any vulnerabilities (even resolved ones) outside of the program without express consent from the organization.\r\n* Follow HackerOne's [disclosure guidelines](https://www.hackerone.com/disclosure-guidelines).\r\n\r\n\r\n# How To Create Accounts\r\n* Go to our Website\r\n* Register \r\n* use @hackerone.com email address\r\n* Only use accounts you're authorised to access\r\n\r\n# Rewards\r\nOur rewards are based on severity per the Common Vulnerability Scoring Standard (CVSS). Please note these are general guidelines, and that reward decisions are up to the discretion of something.\r\n\r\n#Out of scope vulnerabilities\r\n\r\n\r\n***Note: 0-day vulnerabilities may be reported 30 days after initial publication. We have a team dedicated to tracking these issues; hosts identified by this team and internally ticketed will not be eligible for bounty.***\r\n\r\nThe following issues are considered out of scope:\r\n \r\n When reporting vulnerabilities, please consider (1) attack scenario / exploitability, and (2) security impact of the bug. The following issues are considered out of scope:\r\n\r\n* Disruption of our service (DoS, DDoS).\r\n* PII - do not collect any personally identifiable information - including credit card information, addresses and phone numbers from other customers\r\n* Reports from automated tools or scans\r\n* Social engineering of employees or contractors\r\n* For the time being we are making all vulnerabilities in Flash files out of scope\r\n* Reports affecting outdated browsers\r\n* Known vulnerabilities on deprecated assets not currently covered by CloudFlare.\r\n* Missing security best practices and controls (rate-limiting/throttling, lack of CSRF protection, lack of security headers, missing flags on cookies, descriptive errors, server/technology disclosure - without clear and working exploit)\r\n* Lack of crossdomain.xml, p3p.xml, robots.txt or any other policy files and/or wildcard presence/misconfigurations in these\r\n* Use of a known-vulnerable libraries or frameworks - for example an outdated JQuery or AngularJS (without clear and working exploit)\r\n* Self-exploitation (cookie reuse, self cookie-bomb, self denial-of-service etc.)\r\n* Self Cross-site Scripting vulnerabilities without evidence on how the vulnerability can be used to attack another user\r\n* Lack of HTTPS\r\n* Reports about insecure SSL / TLS configuration\r\n* Password complexityrequirements, account/email enumeration, or any report that discusses how you can learn whether a given username or email address is easy to guess\r\n* Presence/Lack of autocomplete attribute on web forms/password managers\r\n* Server Banner Disclosure/Technology used Disclosure\r\n* Full Path Disclosure\r\n* IP Address Disclosure\r\n* CSRF on logout or insignificant functionalities\r\n* Publicly accessible login panels\r\n* Clickjacking\r\n* CSS Injection attacks (Unless it gives you ability to read anti-CSRF tokens or other sensitive information)\r\n* Tabnabbing\r\n* Host Header Injection (Unless it givesyou access to interim proxies)\r\n* Cache Poisoning\r\n* Reflective File Download\r\n* Cookie scoped to parent domain or anything related to the path misconfiguration and improperly scoped\r\n* Private IP/Hostname disclosures or real IP disclosures for services using CDN\r\n* Open ports which do not lead directly to a vulnerability\r\n* Weak Certificate Hash Algorithm\r\n* Any physical/wireless attempt against our property or data centers\r\n\r\n# Safe Harbor \r\nThis policy is designed to be compatible with common vulnerability disclosure good practice. It does not give you permission to act in any manner that is inconsistent with the law, or which might cause us to be in breach of any of its legal obligations, including but not limited to:\r\n\r\n* The General Data Protection Regulation 2016/679 (GDPR) andthe Data Protection Act 2018\r\n\r\nWe affirm that we will not seek prosecution of any security researcher who reports any security vulnerability on a service or system, where the researcher has acted in good faith and in accordance with this disclosure policy.\r\n\r\nsomething cannot authorize any activity on third-party products or guarantee they won\u2019t pursue legal action against you. We aren\u2019t responsible for your liability from actions performed on third parties.\r\n\r\nThank you for helping keep us and our users safe!\r\n\n",
"updated_at": "2021-08-10T09:29:56.853Z"
},
"id": "53994",
"type": "program"
},
{
"attributes": {
"created_at": "2021-08-09T13:41:35.764Z",
"handle": "checker_program_h1b",
"policy": "# What we are looking for\r\nWe want to proactively discover and remediate security vulnerabilities on our digital assets\r\n\r\nThe vulnerabilities identified in the HackerOne reports will be classified by the degree of risk as well as the impact they present to the host system, this includes the amount and type of data exposed, privilege level obtained, the proportion of systems or users affected.\r\n\r\n# What is a Bug Bounty Program?\r\nchecker_program\u2019s Bug Bounty Program (BBP) is an initiative driven and managed by the checker_program Information Security team. \r\n\r\n* Security researchers are encouraged to report any behavior impacting the information security posture of checker_program\u2019 products and services. If you are performing research, please use your own accounts and do not interact with other people\u2019s accounts or data.\r\n* Document your findings thoroughly, providing steps to reproduce and send your report to us. Reports with complete vulnerability details, including screenshots or video, are essential for a quick response. If the report is not detailed enough to reproduce the issue, the issue will not be eligible for a reward.\r\n *Reference HackerOne guidance on writing quality reports:\r\n * https://docs.hackerone.com/hackers/quality-reports.html \r\n * https://www.hacker101.com/sessions/good_reports\r\n\r\n* We will contact you to confirm that we\u2019ve received your report and trace your steps to reproduce your research.\r\n* We will work with the affected teams to validate the report.\r\n* We will issue bounty awards for eligible findings. To be eligible for rewards, reports must comply with all parts of this policy and you must be the first to report the issue to us. You must be 18 or older to be eligible for an award.\r\n* We will notify you of remediation and may reach out for questions or clarification. You must be available to provide additional information if needed by us to reproduce and investigate the report.\r\n\r\n\r\n# Response Targets\r\nWe will make a best effort to meet the following response targets for hackers participating in our program:\r\n\r\n* Time to first response (from report submit) - 1 business days\r\n* Time to triage (from report submit) - 2 business days \r\n* Time to bounty (from triage) - 10 business days\r\n\r\nWe\u2019ll try to keep you informed about our progress throughout the process.\r\n\r\n# Program Rules\r\n* Do not try to further pivot into the network by using a vulnerability. The rules around Remote Code Execution (RCE), SQL Injection (SQLi), and FileUpload vulnerabilities are listed below.\r\n* Do not try to exploit service providers we use, prohibited actions include, but are not limited to bruteforcing login credentials of Domain Registrars, DNS Hosting Companies, Email Providers and/or others. The Firm does not authorize you to perform any actions to any property/system/service/data not listed below.\r\n* If you encounter Personally Identifiable Information (PII) contact us immediately. Do not proceed with access and immediately purge any local information, if applicable.\r\n* Please limit any automated scanning to 60 requests per second. Aggressive testing that causes service degradation will be grounds for removal from the program.\r\n\r\n* Submit one vulnerability per- report, unless you need to chain vulnerabilities to provide impact.\r\n* When duplicates occur, we only award the first report that was received (provided that it can be fully reproduced).\r\n* Multiple vulnerabilities caused by one underlying issue will be awarded one bounty.\r\n* Social engineering (e.g. phishing, vishing, smishing) is prohibited.\r\n* Make a good faith effort to avoid privacy violations, destruction of data, and interruption or degradation of our service. Only interact with accounts you own or with the explicit permission of the account holder.\r\n\r\n# Disclosure Policy\r\n* As this is a private program, please do not discuss this program or any vulnerabilities (even resolved ones) outside of the program without express consent from the organization.\r\n* Follow HackerOne's [disclosure guidelines](https://www.hackerone.com/disclosure-guidelines).\r\n\r\n\r\n# How To Create Accounts\r\n* Go to our Website\r\n* Register \r\n* use @hackerone.com email address\r\n* Only use accounts you're authorised to access\r\n\r\n# Rewards\r\nOur rewards are based on severity per the Common Vulnerability Scoring Standard (CVSS). Please note these are general guidelines, and that reward decisions are up to the discretion of checker_program.\r\n\r\n#Out of scope vulnerabilities\r\n\r\n\r\n***Note: 0-day vulnerabilities may be reported 30 days after initial publication. We have a team dedicated to tracking these issues; hosts identified by this team and internally ticketed will not be eligible for bounty.***\r\n\r\nThe following issues are considered out of scope:\r\n \r\n When reporting vulnerabilities, please consider (1) attack scenario / exploitability, and (2) security impact of the bug. The following issues are considered out of scope:\r\n\r\n* Disruption of our service (DoS, DDoS).\r\n* PII - do not collect any personally identifiable information - including credit card information, addresses and phone numbers from other customers\r\n* Reports from automated tools or scans\r\n* Social engineering of employees or contractors\r\n* For the time being we are making all vulnerabilities in Flash files out of scope\r\n* Reports affecting outdated browsers\r\n* Known vulnerabilities on deprecated assets not currently covered by CloudFlare.\r\n* Missing security best practices and controls (rate-limiting/throttling, lack of CSRF protection, lack of security headers, missing flags on cookies, descriptive errors, server/technology disclosure - without clear and working exploit)\r\n* Lack of crossdomain.xml, p3p.xml, robots.txt or any other policy files and/or wildcard presence/misconfigurations in these\r\n* Use of a known-vulnerable libraries or frameworks - for example an outdated JQuery or AngularJS (without clear and working exploit)\r\n* Self-exploitation (cookie reuse, self cookie-bomb, self denial-of-service etc.)\r\n* Self Cross-site Scripting vulnerabilities without evidence on how the vulnerability can be used to attack another user\r\n* Lack of HTTPS\r\n* Reports about insecure SSL / TLS configuration\r\n* Password complexityrequirements, account/email enumeration, or any report that discusses how you can learn whether a given username or email address is easy to guess\r\n* Presence/Lack of autocomplete attribute on web forms/password managers\r\n* Server Banner Disclosure/Technology used Disclosure\r\n* Full Path Disclosure\r\n* IP Address Disclosure\r\n* CSRF on logout or insignificant functionalities\r\n* Publicly accessible login panels\r\n* Clickjacking\r\n* CSS Injection attacks (Unless it gives you ability to read anti-CSRF tokens or other sensitive information)\r\n* Tabnabbing\r\n* Host Header Injection (Unless it givesyou access to interim proxies)\r\n* Cache Poisoning\r\n* Reflective File Download\r\n* Cookie scoped to parent domain or anything related to the path misconfiguration and improperly scoped\r\n* Private IP/Hostname disclosures or real IP disclosures for services using CDN\r\n* Open ports which do not lead directly to a vulnerability\r\n* Weak Certificate Hash Algorithm\r\n* Any physical/wireless attempt against our property or data centers\r\n\r\n# Safe Harbor \r\nThis policy is designed to be compatible with common vulnerability disclosure good practice. It does not give you permission to act in any manner that is inconsistent with the law, or which might cause us to be in breach of any of its legal obligations, including but not limited to:\r\n\r\n* The General Data Protection Regulation 2016/679 (GDPR) andthe Data Protection Act 2018\r\n\r\nWe affirm that we will not seek prosecution of any security researcher who reports any security vulnerability on a service or system, where the researcher has acted in good faith and in accordance with this disclosure policy.\r\n\r\nchecker_program cannot authorize any activity on third-party products or guarantee they won\u2019t pursue legal action against you. We aren\u2019t responsible for your liability from actions performed on third parties.\r\n\r\nThank you for helping keep us and our users safe!\r\n\r\n",
"updated_at": "2021-08-10T09:29:56.984Z"
},
"id": "53996",
"type": "program"
}
]
}
}
Human Readable Output
Program(s)
Program ID Handle Created At Updated At 53994 something_h1b 2021-08-09T13:39:20.342Z 2021-08-10T09:29:56.853Z 53996 checker_program_h1b 2021-08-09T13:41:35.764Z 2021-08-10T09:29:56.984Z
Configuration parameters
url— Server URL (required)username— Username (required)max_fetch— Maximum number of incidents per fetchfirst_fetch— First fetch time intervalprogram_handle— Program Handlestate— Stateseverity— Severityfilter_by— Advanced Filtersproxy— Use system proxy settingsinsecure— Trust any certificate (not secure)incidentType— Incident typeincidentFetchInterval— Incidents Fetch IntervalisFetch— Fetch incidents
Commands (2)
-
hackerone-program-listRetrieves information about the programs in which the user is a member.
-
hackerone-report-listRetrieves all the reports based on program handle and provided arguments.
import traceback from collections.abc import Callable from typing import Any import demistomock as demisto # noqa: F401 import urllib3 from CommonServerPython import * # noqa: F401 from CommonServerUserPython import * # noqa # Disable insecure warnings urllib3.disable_warnings() """ CONSTANTS """ DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ" # ISO8601 format with UTC, default in XSOAR URL_SUFFIX = {"REPORTS": "reports", "PROGRAMS": "me/programs"} API_VERSION = "v1" BASE_URL = "https://api.hackerone.com" DEFAULT_MAX_FETCH = "15" DEFAULT_FIRST_FETCH = "3 days" INT32 = 2147483647 LOWER_BOUND = 1 MAXIMUM_PAGE_SIZE = 100 MAXIMUM_LIMIT = 1000 DEFAULT_PAGE_SIZE = 50 HTTP_ERROR = { 401: "Unauthenticated. Check the configured Username and API Key.", 403: "Forbidden. Verify the URL.", 404: "Please verify the value of Program Handle as well as the value of the URL. " "\n Or the URL is not reachable. Please try again later.", 500: "The server encountered an internal error for HackerOne and was unable to complete your request.", } MESSAGES = { "COMMON_ERROR_MESSAGE": "Unable to retrieve the data based on arguments.", "PAGE_SIZE": "{} is an invalid value for page size. Page size must be between 1 and 100.", "PAGE_NUMBER": "{} is an invalid value for page number. Page number must be between 1 and int32.", "NO_RECORDS_FOUND": "No {} were found for the given argument(s).", "PROGRAM_HANDLE": "Program Handle is invalid. It should not be empty.", "INVALID_MAX_FETCH": "{} is an invalid value for Maximum number of incidents per fetch. It must be between 1 and 100.", "INVALID_FIRST_FETCH": "{} is an invalid value for 'First fetch time interval'. " "It should be a valid date or relative timestamp. " "For example: '2 days', '2 months' or of the format 'yyyy-mm-dd', 'yyyy-mm-ddTHH:MM:SSZ'", "FILTER": "Please provide filter in a valid JSON format. Format accepted- ' " '{"attribute1" : "value1, value2" , "attribute2" : "value3, value4"} \'.', "INVALID_POSITIVE_INT": "{} is an invalid value for {}. It must be between {} and {}.", "INVALID_ARGUMENT": "Limit argument cannot be given with 'page_size' or 'page_number' argument.", } """ CLIENT CLASS """ class Client(BaseClient): """Client class to interact with the service API.""" def __init__( self, base_url: str, verify: bool, proxy: bool, auth: tuple, max_fetch: Optional[int], first_fetch: str, program_handle: List, severity: str, state: str, filters: str, ): self.max_fetch = max_fetch self.first_fetch = first_fetch self.program_handle = program_handle self.severity = severity self.state = state self.filters = filters super().__init__(base_url=base_url, verify=verify, proxy=proxy, auth=auth) def report_list(self, params: dict) -> dict: """ Returns response :type params: ``Dict`` :param params: Query Parameters to be passed. :return: API response :rtype: ``Dict`` """ return self._http_request( method="GET", url_suffix=URL_SUFFIX["REPORTS"], params=params, error_handler=self.exception_handler ) def program_list(self, params: dict) -> dict: """ Returns response :type params: ``Dict`` :param params: Query Parameters to be passed. :return: API response :rtype: ``Dict`` """ return self._http_request( method="GET", url_suffix=URL_SUFFIX["PROGRAMS"], params=params, error_handler=self.exception_handler ) @staticmethod def exception_handler(response: requests.models.Response): """ Handle error in the response and display error message based on status code. :type response: ``requests.models.Response`` :param response: response from API. :raises: raise DemistoException based on status code of response. """ if response.headers.get("Content-Type") and ("text/html" in response.headers["Content-Type"]): raise DemistoException(MESSAGES["COMMON_ERROR_MESSAGE"]) err_msg = None if response.status_code == 401: err_msg = HTTP_ERROR[401] elif response.status_code >= 500: err_msg = HTTP_ERROR[500] elif response.status_code == 404: err_msg = HTTP_ERROR[404] elif response.status_code == 403: err_msg = HTTP_ERROR[403] else: # Parse json error response errors = response.json().get("errors", []) if not errors: raise DemistoException(MESSAGES["COMMON_ERROR_MESSAGE"]) for error in errors: msg = error.get("detail", error.get("title", MESSAGES["COMMON_ERROR_MESSAGE"])) if err_msg: err_msg = f"{err_msg}\n{msg}" else: err_msg = msg raise DemistoException(err_msg) """ HELPER FUNCTIONS """ def remove_duplicates(data) -> List: """ Remove duplicates from list :type data: ``List`` :param data: list of response :return: list of unique response :rtype: ``List`` """ cleaned_list = [] # type: ignore for entry in data: if entry not in cleaned_list: cleaned_list.append(entry) return cleaned_list def prepare_filter_by_arguments(program_handle, severity, state, filters) -> dict[str, Any]: """ Prepares params for the filters provided by user :type program_handle: ``List`` :param program_handle: The program handle provided by the user. :type severity: ``Any`` :param severity: Severity level provided by user. :type state: ``Any`` :param state: State provided by user. :type filters: ``str`` :param filters: The advanced_filter argument provided by the user. :return: Parameters related to the filters. :rtype: ``Dict[str, Any]`` """ params = {"filter[program][]": program_handle, "filter[severity][]": severity, "filter[state][]": state} if not filters: return params filters = json.loads(filters) for key, value in filters.items(): key, value = key.strip(), value.strip() if not key or not value: continue if "[]" in key: params[key] = argToList(value) else: params[key] = value return params def validate_fetch_incidents_parameters(max_fetch: Optional[int], program_handle: List, filters: str): """ Validates fetch incident parameters, raise ValueError on invalid arguments. :type max_fetch: ``int`` :param max_fetch: Maximum number of incidents per fetch provided by user. :type program_handle: ``List`` :param program_handle: The program handle provided by the user. :type filters: ``str`` :param filters: The advanced_filter argument provided by the user. """ if not 0 < max_fetch <= 100: # type:ignore raise ValueError(MESSAGES["INVALID_MAX_FETCH"].format(max_fetch)) if not program_handle: raise ValueError(MESSAGES["PROGRAM_HANDLE"]) if filters: try: json.loads(filters) except (json.JSONDecodeError, json.decoder.JSONDecodeError, AttributeError): raise ValueError(MESSAGES["FILTER"]) def prepare_fetch_incidents_parameters( max_fetch, time_to_fetch, program_handle, severity, state, filters, page ) -> dict[str, Any]: """ Prepare fetch incidents params :type max_fetch: ``int`` :param max_fetch: Maximum number of incidents per fetch provided by user. :type time_to_fetch: ``str`` :param time_to_fetch: Date or relative timestamp to start fetching incidents from. :type program_handle: ``List`` :param program_handle: The program handle provided by the user. :type severity: ``str`` :param severity: Severity level provided by user. :type state: ``str`` :param state: State provided by user. :type filters: ``str`` :param filters: The advanced_filter argument provided by the user. :type page: ``str`` :param page: Page number to retrieve next records. """ fetch_params: dict[str, Any] = {"page[size]": max_fetch, "sort": "reports.created_at", "page[number]": page} fetch_params.update(prepare_filter_by_arguments(program_handle, severity, state, filters)) fetch_params["filter[created_at__gt]"] = arg_to_datetime(time_to_fetch).isoformat()[:-6] # type:ignore return assign_params(**fetch_params) def validate_report_list_args(args): """ Validates all report list arguments, raise ValueError on invalid arguments. :type args: ``Dict[str, str]`` :param args: The command arguments provided by the user. """ filters = args.get("advanced_filter", "") if filters: try: json.loads(filters) except (json.JSONDecodeError, json.decoder.JSONDecodeError, AttributeError): raise ValueError(MESSAGES["FILTER"]) def prepare_report_list_args(args: dict[str, Any]) -> dict[str, Any]: """ Preapare params for hackerone-report-list command. :type args: ``Dict[str, str]`` :param args: The command arguments provided by the user. :return: Parameters to send in request :rtype: ``Dict[str, Any]`` """ params: dict[str, Any] = {"filter[keyword]": args.get("filter_by_keyword")} sort_by = argToList(args.get("sort_by", "")) if sort_by: params["sort"] = [ "reports." + sort_value[1:] if sort_value.startswith("-") else "-reports." + sort_value for sort_value in sort_by ] program_handle = argToList(args.get("program_handle", "")) state = argToList(args.get("state", "")) severity = argToList(args.get("severity", "")) filters = args.get("advanced_filter", "") params.update(prepare_filter_by_arguments(program_handle, severity, state, filters)) return assign_params(**params) def prepare_hr_for_programs(results: List[dict[str, Any]]) -> str: """ Parse and convert the programs in response into human-readable markdown string. :type results: ``List[Dict[str, Any]]`` :param results: Details of programs. :return: Human Readable string containing programs. :rtype: ``str`` """ programs_hr = [] for res in results: hr = {"Program ID": res.get("id")} attributes = res.get("attributes", {}) hr["Handle"] = attributes.get("handle") hr["Created At"] = attributes.get("created_at") hr["Updated At"] = attributes.get("updated_at") programs_hr.append(hr) return tableToMarkdown( "Program(s)", programs_hr, headers=["Program ID", "Handle", "Created At", "Updated At"], removeNull=True ) def prepare_hr_for_reports(results: List[dict[str, Any]]) -> str: """ Parse and convert the reports in response into human-readable markdown string. :type results: ``List[Dict[str, Any]]`` :param results: Details of reports. :return: Human Readable string containing reports. :rtype: ``str`` """ reports_hr = [] for res in results: hr = {"Report ID": res.get("id")} relationships = res.get("relationships", {}) attributes = res.get("attributes", {}) hr["Title"] = attributes.get("title") hr["State"] = attributes.get("state") severity = relationships.get("severity", {}).get("data", {}).get("attributes", {}) hr["Severity"] = severity.get("rating", "") hr["Created At"] = attributes.get("created_at") hr["Vulnerability Information"] = attributes.get("vulnerability_information") reporter = relationships.get("reporter", {}) relationship_data = reporter.get("data", {}) inner_attributes = relationship_data.get("attributes", {}) hr["Reporter Username"] = inner_attributes.get("username") reports_hr.append(hr) return tableToMarkdown( "Report(s)", reports_hr, headers=["Report ID", "Reporter Username", "Title", "State", "Severity", "Created At", "Vulnerability Information"], removeNull=True, ) def get_and_validate_positive_int_argument( args: dict, argument_name: str, lower_bound: int = 1, upper_bound: Optional[int] = None ) -> Optional[int]: """ Extracts int argument from Demisto arguments. If argument exists, validates that: - lower_bound <= argument's value. - argument's value <= maximum_bound if maximum_bound is not None. Args: args (Dict): Demisto arguments. argument_name (str): The name of the argument to extract. lower_bound (int): Lower number bound of the argument value. upper_bound (Optional[int]): Maximum number bound of the argument value, if given. Returns: - (int): If argument exists and is between 'lower_bound' and 'maximum_bound', returns argument. - (None): If argument does not exist, returns None. - (Exception): If argument exists and is lower than 'lower_bound' or higher than 'maximum_bound' (if 'maximum_bound' exists), raises DemistoException. """ argument_value = arg_to_number(args.get(argument_name), arg_name=argument_name) if argument_value is None: return None if not lower_bound <= argument_value <= upper_bound: # type:ignore raise ValueError(MESSAGES["INVALID_POSITIVE_INT"].format(argument_value, argument_name, lower_bound, upper_bound)) return argument_value def get_page_and_limit_args(args: dict): """ Receives demisto argument, and extract the relevant arguments for limits and paging: 'page_number', 'page_size', 'limit'. Follows the logic: - 'limit' argument cannot be specified with 'page' or 'page_size' argument. - 'page_size' argument is within its expected lower/upper bounds. - If 'limit' is not given, and 'page_size' is, sets 'limit' value to 'page_size' value. - If 'limit' is not given, and 'page_size' is not given, sets 'limit' value to 'DEFAULT_PAGE_SIZE' value. Args: args (Dict): Demisto argument. Returns: - (int, int): 'page', 'limit' extracted, or their default values used. - (DemistoException): If arguments don't follow the expected logic mentioned. """ page = get_and_validate_positive_int_argument(args, "page_number", lower_bound=LOWER_BOUND, upper_bound=INT32) page_size = get_and_validate_positive_int_argument(args, "page_size", lower_bound=LOWER_BOUND, upper_bound=MAXIMUM_PAGE_SIZE) limit = get_and_validate_positive_int_argument(args, "limit", lower_bound=LOWER_BOUND, upper_bound=MAXIMUM_LIMIT) if limit and (page_size or page): raise ValueError(MESSAGES["INVALID_ARGUMENT"]) if not limit and page_size: limit = page_size if not limit: limit = DEFAULT_PAGE_SIZE if not page: page = LOWER_BOUND return page, limit """ COMMAND FUNCTIONS """ def test_module(client: Client) -> str: """Tests API connectivity and authentication' Returning 'ok' indicates that the integration works like it is supposed to. Connection to the service is successful. Raises: exceptions if something goes wrong. Args: client: client to use Returns: 'ok' if test passed, anything else will fail the test. """ if demisto.params().get("isFetch"): fetch_incidents(client, {}) else: client.program_list(params={"page[size]": 1}) return "ok" def fetch_incidents( client: Client, last_run: dict, ) -> tuple[dict, list]: """Fetches incidents from HackerOne. :type client: ``Client`` :param client: client to use :type last_run: ``Dict[str, str]`` :param last_run: Last run returned by function demisto.getLastRun :type params: ``Dict[str, str]`` :param params: Arguments for fetch-incident. :rtype: ``Tuple`` :return: tuple of dictionary of next run and list of fetched incidents """ validate_fetch_incidents_parameters(client.max_fetch, client.program_handle, client.filters) time_to_fetch = last_run.get("next_created_at", client.first_fetch) max_fetch = client.max_fetch if client.max_fetch else int(DEFAULT_MAX_FETCH) # After one run we get a duplicate of the first incident, add one to reach the limit if last_run.get("next_created_at") and max_fetch < 100: max_fetch += 1 fetch_params = prepare_fetch_incidents_parameters( max_fetch, time_to_fetch, client.program_handle, client.severity, client.state, client.filters, 1 ) response = client.report_list(params=fetch_params) results = response.get("data", []) next_run = last_run if not results: return next_run, [] previous_report_ids = last_run.get("report_ids", []) new_report_ids = [] incidents = [] for result in results: if result.get("id") not in previous_report_ids: new_report_ids.append(result.get("id")) incidents.append( { "name": result.get("attributes", {}).get("title", ""), "occurred": result.get("attributes", {}).get("created_at"), "rawJSON": json.dumps(result), } ) next_report_ids = new_report_ids created_at_last_report = results[-1].get("attributes", {}).get("created_at") if created_at_last_report == time_to_fetch: next_report_ids = previous_report_ids + new_report_ids next_run = {"next_created_at": created_at_last_report, "report_ids": next_report_ids} return next_run, incidents def hackerone_program_list_command(client: Client, args: dict[str, str]) -> CommandResults: """ Retrieves detailed information of all the programs that the user is a member of. :type client: ``Client`` :param client: Client object to be used. :type args: ``Dict[str, str]`` :param args: The command arguments provided by the user. :return: Standard command result. :rtype: ``CommandResults`` """ page, limit = get_page_and_limit_args(args) raw_responses = [] outputs = [] count = limit while limit > 0: page_size = min(limit, 100) params: dict[str, Any] = {"page[size]": page_size, "page[number]": page} raw_response = client.program_list(params=params) program_list = raw_response.get("data", []) if not program_list: break raw_responses.append(raw_response) outputs.extend(program_list) limit -= 100 page += 1 response = remove_duplicates(raw_responses[:count]) result = remove_duplicates(outputs[:count]) # Returning if data is empty or not present if not result: return CommandResults(readable_output=MESSAGES["NO_RECORDS_FOUND"].format("programs")) # Creating the Human Readable hr_response = prepare_hr_for_programs(result) # Creating the Context data context_data = remove_empty_elements(result) return CommandResults( outputs_prefix="HackerOne.Program", outputs_key_field="id", outputs=context_data, readable_output=hr_response, raw_response=response, ) def hackerone_report_list_command(client: Client, args: dict[str, str]) -> CommandResults: """ Retrieves list with detailed information of all the reports. :type client: ``Client`` :param client: Client object to be used. :type args: ``Dict[str, str]`` :param args: The command arguments provided by the user. :return: Standard command result. :rtype: ``CommandResults`` """ validate_report_list_args(args) params = prepare_report_list_args(args) page, limit = get_page_and_limit_args(args) raw_responses = [] outputs = [] count = limit while limit > 0: page_size = min(limit, 100) params["page[size]"] = (page_size,) params["page[number]"] = page raw_response = client.report_list(params=params) report_list = raw_response.get("data", []) if not report_list: break raw_responses.append(raw_response) outputs.extend(report_list) limit -= 100 page += 1 response = remove_duplicates(raw_responses[:count]) result = remove_duplicates(outputs[:count]) # Returning if data is empty or not present if not result: return CommandResults(readable_output=MESSAGES["NO_RECORDS_FOUND"].format("reports")) # Creating the Human Readable hr_response = prepare_hr_for_reports(result) # Creating the Context data context_data = remove_empty_elements(result) return CommandResults( outputs_prefix="HackerOne.Report", outputs_key_field="id", outputs=context_data, readable_output=hr_response, raw_response=response, ) def main(): """main function, parses params and runs command functions""" # Commands dictionary commands: dict[str, Callable] = { "hackerone-report-list": hackerone_report_list_command, "hackerone-program-list": hackerone_program_list_command, } params = demisto.params() verify_certificate = not params.get("insecure", False) proxy = params.get("proxy", False) url = urljoin(params.get("url", BASE_URL), API_VERSION) credentials = params.get("username", {}) username = credentials.get("identifier").strip() password = credentials.get("password") command = demisto.command() demisto.debug(f"[HackerOne] Command being called is {command}") max_fetch = arg_to_number(params.get("max_fetch") if params.get("max_fetch").strip() else DEFAULT_MAX_FETCH) # type:ignore first_fetch = params.get("first_fetch") if params.get("first_fetch").strip() else DEFAULT_FIRST_FETCH program_handle = argToList(params.get("program_handle", "")) severity = params.get("severity", "") state = params.get("state", "") filters = params.get("filter_by", "").strip() try: client = Client( base_url=url, verify=verify_certificate, proxy=proxy, auth=(username, password), max_fetch=max_fetch, first_fetch=first_fetch, program_handle=program_handle, severity=severity, state=state, filters=filters, ) if command == "test-module": # This is the call made when pressing the integration Test button. return_results(test_module(client)) elif command == "fetch-incidents": last_run = demisto.getLastRun() next_run, incidents = fetch_incidents(client, last_run) demisto.incidents(incidents) demisto.setLastRun(next_run) elif command in commands: args = {key: value.strip() for key, value in demisto.args().items()} return_results(commands[command](client, args)) except Exception as e: demisto.error(traceback.format_exc()) # print the traceback return_error(f"Failed to execute {command} command.\nError:\n{e!s}") if __name__ in ("__main__", "__builtin__", "builtins"): # pragma: no cover main()