diff --git a/docs/assets/images/Product_Hierarchy_Overview.png b/docs/assets/images/Product_Hierarchy_Overview.png index a0502462f98..3a6b683a328 100644 Binary files a/docs/assets/images/Product_Hierarchy_Overview.png and b/docs/assets/images/Product_Hierarchy_Overview.png differ diff --git a/docs/assets/images/Product_Hierarchy_Overview_2.png b/docs/assets/images/Product_Hierarchy_Overview_2.png index cb4b3b8514b..20760513bbb 100644 Binary files a/docs/assets/images/Product_Hierarchy_Overview_2.png and b/docs/assets/images/Product_Hierarchy_Overview_2.png differ diff --git a/docs/content/get_started/about/OS__new_user_checklist.md b/docs/content/get_started/about/OS__new_user_checklist.md index ebf29ec20f8..cf977048319 100644 --- a/docs/content/get_started/about/OS__new_user_checklist.md +++ b/docs/content/get_started/about/OS__new_user_checklist.md @@ -23,6 +23,6 @@ This is the essence of DefectDojo - import security data, organize it, and prese All of these features can be automated, and because DefectDojo can handle over 200 tools (at time of writing) you should be all set to create a functional security inventory of your entire organizational output. ### Open-Source Features -- Does your organization use Jira? Learn how to use our [Jira integration](/issue_tracking/jira/jira_guide/) to create Jira tickets from the data you ingest. +- Does your organization use Jira? Learn how to use our [Jira integration](/issue_tracking/jira/os__jira_guide/) to create Jira tickets from the data you ingest. - Are you expecting to share DefectDojo with many users in your organization? Check out our guides to [user management](/admin/user_management/about_perms_and_roles/) and set up role-based access control (RBAC). - Ready to dive into automation? Learn how to use the [DefectDojo API](/import_data/import_scan_files/api_pipeline_modelling/) to automatically import new data, and build a robust CI/CD pipeline. \ No newline at end of file diff --git a/docs/content/get_started/about/faq.md b/docs/content/get_started/about/faq.md index 7c6593f6c6a..ab14697cec4 100644 --- a/docs/content/get_started/about/faq.md +++ b/docs/content/get_started/about/faq.md @@ -21,7 +21,7 @@ DefectDojo is meant to be the central source of truth for your organization's se - Allowing users to identify duplicate findings across scans and tools, minimizing alert fatigue. - Enforcing SLAs on vulnerabilities, ensuring that your organization handles each Finding within an appropriate timeframe. -- Sending tickets to [Jira](/issue_tracking/jira/jira_guide/), ServiceNow or other Project Tracking software, allowing your development team to integrate issue remediation into their standard release process without requiring them to learn another project management tool. +- [Sending tickets](/issue_tracking/intro/intro/) to Jira, ServiceNow or other Project Tracking software, allowing your development team to integrate issue remediation into their standard release process without requiring them to learn another project management tool. - Integrating into automated [CI/CD pipelines](/import_data/import_scan_files/api_pipeline_modelling/) to automatically ingest report data from repositories, even down to the branch level. - Creating [reports](/metrics_reports/reports/using_the_report_builder/) on any set of vulnerabilities or software context, to quickly share scan results or status updates with stakeholders. - Establishing acceptance and mitigation workflows, supporting formal risk-management tracking. @@ -129,6 +129,6 @@ DefectDojo Pro users also have access to [executive-level Metrics dashboards](/g ### How can I integrate a project management tool with DefectDojo? -In both Pro and Open-Source editions of DefectDojo, Findings in DefectDojo can be pushed to Jira as Issues, which allows you to integrate issue remediation with your development team. We have a [complete guide to Jira](/issue_tracking/jira/jira_guide/) written which describes the process in detail. +In both Pro and Open-Source editions of DefectDojo, Findings in DefectDojo can be pushed to Jira as Issues, which allows you to integrate issue remediation with your development team. DefectDojo Pro adds support for [Additional Project Tracking Integrations](/issue_tracking/intro/intro/)**: ServiceNow, Azure DevOps, GitHub and GitLab. \ No newline at end of file diff --git a/docs/content/issue_tracking/jira/jira_guide.md b/docs/content/issue_tracking/jira/OS__jira_guide.md similarity index 72% rename from docs/content/issue_tracking/jira/jira_guide.md rename to docs/content/issue_tracking/jira/OS__jira_guide.md index 9fcd50530be..a9dca184057 100644 --- a/docs/content/issue_tracking/jira/jira_guide.md +++ b/docs/content/issue_tracking/jira/OS__jira_guide.md @@ -1,9 +1,8 @@ --- title: "📋 Jira Integration Guide" description: "Work with the Jira integration" -weight: 1 -aliases: - - /en/share_your_findings/jira_guide +weight: 2 +audience: opensource --- DefectDojo's Jira integration can be used to push Finding data to one or more Jira Spaces. By doing so, you can integrate DefectDojo into your standard development workflow. Here are some examples of how this can work: @@ -19,11 +18,11 @@ Setting Up Jira requires the following steps: ## Step 1: Connect a Jira Instance -Connecting a Jira Instance is the first step to take when setting up DefectDojo’s Jira integration. Please note Jira Service Management is currently not supported. +Connecting a Jira Instance is the first step to take when setting up DefectDojo's Jira integration. Please note Jira Service Management is currently not supported. #### Required information from Jira -Atlassian uses different ways of authentication between Jira Cloud and Jira Data Center. +Atlassian uses different methods of authentication between Jira Cloud and Jira Data Center. for **Jira Cloud**, you will need: * a Jira URL, i.e. https://yourcompany.atlassian.net/ @@ -35,7 +34,6 @@ for **Jira Data Center (or Server)**, you will need: * a Jira URL, i.e. https://jira.yourcompany.com * an account with permissions to create and update issues in your Jira instance. This can be: * A standard **username / password** combination - * A **emailaddress / Personal Access Token** combination (not supported in Defect Dojo Open-Source) Optionally, you can map: * Jira Transitions to trigger Re-Opening and Closing Findings @@ -43,45 +41,7 @@ Optionally, you can map: Multiple Jira Spaces can be handled by a single Jira Instance connection, as long as the Jira account / token used by DefectDojo has permission to create Issues in the associated Jira Space. -### Add a Jira Instance (Pro UI) - -1. If you have not already done so, navigate to the System Settings page and check the box on **Enable Jira Integration**. - -2. Navigate to the **Enterprise Settings \> Jira Instances \> + New Jira Instance** page from the DefectDojo sidebar. - -![image](images/jira-instance-beta.png) - -3. Select a **Configuration Name** for this Jira Instance to use in DefectDojo. This name is simply a label for the Instance connection in DefectDojo, and does not need to be related to any Jira data. - -4. Select the URL for your company’s Jira instance \- likely similar to `https://**yourcompany**.atlassian.net` if you’re using a Jira Cloud installation. - -5. Enter an appropriate authetication method in the Username / Password fields for Jira: - * For standard **username / password Jira authentication**, enter a Jira Username and corresponding Password in these fields. - * For authentication with a **user's API token (Jira Cloud)** enter the Username with the corresponding **API token** in the password field. - * For authentication with a Jira **Personal Access Token (aka PAT, used in Jira Data Center and Jira Server only)**, enter the PAT in the password field. Username is not used for authentication with a Jira PAT, but the field is still required in this form, so you can use a placeholder value here to identify your PAT. - -Note that the user associated with this connection have permission to create Issues and access data in your Jira instance. - -6. You will need to provide values for an Epic Name ID, Re-open Transition ID and Close Transition ID. These values can be changed later. While logged into Jira, you can access these values from the following URLs: -- **Epic Name ID**: visit `https:///rest/api/2/field` and search for Epic Name. Copy the number out of `number` and paste it here. If you do not have an Epic Name ID associated with your Space in Jira (due to using a Team-Managed Space, for example), enter 0 on this field. -- **Re-open Transition ID**: visit `https:///rest/api/latest/issue//transitions?expand-transitions.fields` to find the ID for your Jira instance. Paste it in the Reopen Transition ID field. -- **Close Transition ID**: Visit `https:///rest/api/latest/issue//transitions?expand-transitions.fields` to find the ID for your Jira instance. Paste it in the Close Transition ID field. - -7. Select the Default issue type which you want to create Issues as in Jira. The options for this are **Bug, Task, Story** and **Epic** (which are standard Jira issue types) as well as **Spike** and **Security**, which are custom issue types. If you have a different Issue Type which you want to use, please contact [support@defectdojo.com](mailto:support@defectdojo.com) for assistance. - -8. Select your Issue Template, which will determine the Issue Description when Issues are created in Jira. - -The two types are: -- **Jira\_full**, which will include all Finding information in Jira Issues -- **Jira\_limited**, which will include a smaller amount of Finding information and metadata. - -If you leave this field blank, it will default to **Jira\_full.** If you need a different kind of template, Pro users can reach out to [support@defectdojo.com](mailto:support@defectdojo.com) - -9. If you wish, enter the name of a Jira Resolution which will change the status of a Finding to Accepted or to False Positive (when the Resolution is triggered on the Issue). - -The form can be submitted from here. If you wish, you can further customize your Jira integration under Optional Fields. Clicking this button will allow you to apply generic text to Jira Issues or change the mapping of Jira Severity Mappings. - -### Add a Jira Instance (Classic UI / Open-Source) +### Add a Jira Instance 1. If you have not already done so, navigate to the System Settings page and check the box on **Enable Jira Integration**. You will need to do this before the ⚙️ **Configuration \> JIRA** option shows up on the sidebar. ​ @@ -93,13 +53,13 @@ The form can be submitted from here. If you wish, you can further customize you #### Add Jira Configuration (Express) -The Express method allows for a quicker method of linking a Space. Use the Express method if you simply want to connect a Jira Space quickly, and you aren’t dealing with a complex Jira workflow. +The Express method allows for a quicker method of linking a Space. Use the Express method if you simply want to connect a Jira Space quickly, and you aren't dealing with a complex Jira workflow. ![image](images/Connect_DefectDojo_to_Jira_2.png) 1. Select a name for this Jira Configuration to use in DefectDojo. This name is simply a label for the Instance connection in DefectDojo, and does not need to be related to any Jira data. ​ -2. Select the URL for your company’s Jira instance \- likely similar to `https://**yourcompany**.atlassian.net` if you’re using a Jira Cloud installation. +2. Select the URL for your company's Jira instance \- likely similar to `https://**yourcompany**.atlassian.net` if you're using a Jira Cloud installation. ​ 3. Enter an appropriate authetication method in the Username / Password fields for Jira: * For standard **username / password Jira authentication**, enter a Jira Username and corresponding Password in these fields. @@ -115,15 +75,15 @@ The two types are: If you leave this field blank, it will default to **Jira\_full.** -6. Select one or more Jira Resolution types which will change the status of a Finding to Accepted (when the Resolution is triggered on the Issue). If you don’t wish to use this automation, you can leave the field blank. +6. Select one or more Jira Resolution types which will change the status of a Finding to Accepted (when the Resolution is triggered on the Issue). If you don't wish to use this automation, you can leave the field blank. ​ -7. Select one or more Jira Resolution types which will change the status of a Finding to False Positive (when the Resolution is triggered on the Issue). If you don’t wish to use this automation, you can leave the field blank. +7. Select one or more Jira Resolution types which will change the status of a Finding to False Positive (when the Resolution is triggered on the Issue). If you don't wish to use this automation, you can leave the field blank. ​ 8. Decide whether you wish to send SLA Notifications as a comment on a Jira issue. ​ 9. Decide whether you wish to automatically sync Findings with Jira. If this is enabled, Jira Issues will automatically be kept in sync with the related Findings. If this is not enabled, you will need to manually push any changes made to a Finding after the Issue has been created in Jira. ​ -10. Select your Issue key. In Jira, this is the string associated with an Issue (e.g. the word **‘EXAMPLE’** in an issue called **EXAMPLE\-123**). If you don’t know your issue key, create a new Issue in the Jira Space. In the screenshot below, we can see that the issue key on our Jira Space is **DEF**. +10. Select your Issue key. In Jira, this is the string associated with an Issue (e.g. the word **'EXAMPLE'** in an issue called **EXAMPLE\-123**). If you don't know your issue key, create a new Issue in the Jira Space. In the screenshot below, we can see that the issue key on our Jira Space is **DEF**. ​ ![image](images/Connect_DefectDojo_to_Jira_3.png) ​ @@ -157,65 +117,7 @@ Comments (in Jira) and Notes (in DefectDojo) can be kept in sync. This setting c Each Product or Engagement in DefectDojo has its own settings which govern how Findings are converted to JIRA Issues. From here, you can decide the associated Jira Space and set the default behaviour for creating Issues, Epics, Labels and other JIRA metadata. -### Add Jira to a Product or Engagement (Pro UI) - -You can find this page by clicking the Gear menu on a Product or Engagement - ⚙️ and opening the Jira Space Settings page. - -![image](images/jira-project-settings.png) - -#### Jira Instance - -If you have multiple instances of Jira set up, for separate products or teams within your organization, you can indicate which Jira Space you want DefectDojo to create Issues in. Select a Space from the drop\-down menu. - -If this menu doesn't list any Jira instances, confirm that those Space are connected in your global Jira Configuration for DefectDojo \- yourcompany.defectdojo.com/jira. - -#### Project key - -This is the key of the Space that you want to use with DefectDojo. The Space Key for a given Space can be found in the URL. (This was previously referred to as a **Jira Project Key**, but as of Sepetember 2025, this is now referred to in Jira as the **Space Key**). - -![image](images/Add_a_Connected_Jira_Project_to_a_Product_3.png) - -#### Issue template - -Here you can determine how much DefectDojo metadata you want to send to Jira. Select one of two options: - -* **jira\_full**: Issues will track all of the parameters from DefectDojo \- a full Description, CVE, Severity, etc. Useful if you need complete Finding context in Jira (for example, if someone is working on this Issue who doesn't have access to DefectDojo). - -Here is an example of a **jira\_full** Issue: -​ -![image](images/Add_a_Connected_Jira_Project_to_a_Product_4.png) - -* **Jira\_limited:** Issues will only track the DefectDojo link, the Product/Engagement/Test links, the Reporter and Environment fields. All other fields are tracked in DefectDojo only. Useful if you don't require full Finding context in Jira (for example, if someone is working on this Issue who mainly works in DefectDojo, and doesn't need the full picture in JIRA as well.) - -​Here is an example of a **jira\_limited** Issue: - -![image](images/Add_a_Connected_Jira_Project_to_a_Product_5.png) - -#### Component - -If you manage your Jira Space using Components, you can assign the appropriate Component for DefectDojo here. - -**Custom fields** - -If you don’t need to use Custom Fields with DefectDojo issues, you can leave this field as ‘null’. - -However, if your Jira Space Settings **require you** to use Custom Fields on new Issues, you will need to hard-code these mappings. - -Note that DefectDojo cannot send any Issue\-specific metadata as Custom Fields, only a default value. This section should only be set up if your Jira Space **requires that these Custom Fields exist** in every Issue in your Space. - -Follow **[this guide](#custom-fields-in-jira)** to get started working with Custom Fields. - -**Jira labels** - -Select the relevant labels that you want the Issue to be created with in Jira, e.g. **DefectDojo**, **YourProductName..** - -![image](images/Add_a_Connected_Jira_Project_to_a_Product_6.png) - -#### Default assignee - -The name of the default assignee in Jira. If left blank, DefectDojo will follow the default behaviour in your Jira Space when creating Issues. - -### Add Jira to a Product or Engagement (Classic UI / Open-Source) +### Add Jira to a Product or Engagement In the Classic UI, you can find Jira settings by opening the Edit Product or Edit Engagement form. "**📝 Edit**" button under **Settings** on the page: @@ -261,7 +163,7 @@ If you manage your Jira Space using Components, you can assign the appropriate C **Custom fields** -If you don’t need to use Custom Fields with DefectDojo issues, you can leave this field as ‘null’. +If you don't need to use Custom Fields with DefectDojo issues, you can leave this field as 'null'. However, if your Jira Space Settings **require you** to use Custom Fields on new Issues, you will need to hard\-code these mappings. @@ -314,7 +216,7 @@ If enabled, Jira comments will populate on the associated Finding in DefectDojo, #### Send SLA Notifications As Comments -If enabled, any Issue which breaches DefectDojo’s Service Level Agreement rules will have comments added to the Jira issue indicating this. These comments will be posted daily until the Issue is resolved. +If enabled, any Issue which breaches DefectDojo's Service Level Agreement rules will have comments added to the Jira issue indicating this. These comments will be posted daily until the Issue is resolved. Service Level Agreements can be configured under **Configuration \> SLA Configuration** in DefectDojo and assigned to each Product. @@ -360,7 +262,7 @@ DefectDojo's Jira Webhook only accepts requests from the Jira API. Once you have one or more Issues created from DefectDojo Findings, you can test the Webhook by adding a Comment to one of those Findings. The Comment should be received by the Jira webhook as a note. -If this doesn’t work correctly, it could be due to a Firewall issue on your Jira instance blocking the Webhook. +If this doesn't work correctly, it could be due to a Firewall issue on your Jira instance blocking the Webhook. * DefectDojo's Firewall Rules include a checkbox for **Jira Cloud,** which needs to be enabled before DefectDojo can receive Webhook messages from Jira. @@ -370,7 +272,7 @@ If this doesn’t work correctly, it could be due to a Firewall issue on your Ji In order to test that the Jira integration is working properly, you can add a new blank Finding to the Product associated with Jira in DefectDojo. **Product \> Findings \> Add New Finding.** -Add whatever title severity and description you wish, and then click “Finished”. The Finding should appear as an Issue in Jira with all of the relevant metadata. +Add whatever title severity and description you wish, and then click "Finished". The Finding should appear as an Issue in Jira with all of the relevant metadata. If Jira Issues are not being created correctly, check your Notifications for error codes. @@ -382,7 +284,7 @@ In order to test the Jira webhooks, add a Note to a Finding which also exists in If the webhooks are configured correctly, you should see the Note in Jira as a Comment on the issue. -If this doesn’t work correctly, it could be due to a Firewall issue on your Jira instance blocking the Webhook. +If this doesn't work correctly, it could be due to a Firewall issue on your Jira instance blocking the Webhook. * DefectDojo's Firewall Rules include a checkbox for **Jira Cloud,** which needs to be enabled before DefectDojo can receive Webhook messages from Jira. @@ -390,7 +292,7 @@ If this doesn’t work correctly, it could be due to a Firewall issue on your Ji Jira integrations can be removed from your instance only if no related Issues have been created. If Issues have been created, there is no way to completely remove a Jira Instance from DefectDojo. -However, you can disable your Jira integration by disabling it at the Product level. From the **Edit Product** form (Classic UI) or from the **Jira Product Settings** (Pro UI) you can uncheck the "Enable Connection With Jira Space" option. This will not delete or change any existing Jira tickets created by DefectDojo, but will disable any further updates. +However, you can disable your Jira integration by disabling it at the Product level. From the **Edit Product** form you can uncheck the "Enable Connection With Jira Space" option. This will not delete or change any existing Jira tickets created by DefectDojo, but will disable any further updates. # Pushing Findings To Jira @@ -454,7 +356,7 @@ DefectDojo's built\-in Jira Issue Types (**Bug, Task, Story** and **Epic)** are Some Jira configurations require additional custom fields to be accounted for before an issue can be created. This process will allow you to account for these custom fields in your DefectDojo \-\> Jira integration, ensuring that issues are created successfully. These custom fields will be added to any API calls sent from DefectDojo to a linked Jira instance. -If you don’t already use Custom Fields in Jira, there is no need to follow this process. +If you don't already use Custom Fields in Jira, there is no need to follow this process. 1. Recording the names of your Custom Fields in Jira (**Jira UI**) 2. Determine the Key values for the new Custom Fields (Jira Field Spec Endpoint) @@ -485,46 +387,46 @@ Here is an example of a Field Spec URL: The API will return a long string of JSON, which should be formatted into readable text (using a code editor, browser extension or ). -The JSON returned from this URL will contain all of your Jira custom fields, most of which are irrelevant to DefectDojo and have values of `“Null”`. Each object in this API response corresponds to a different field in Jira. You will need to search for the objects that have `“name”` attributes which match the names of each Custom Field you created in the Jira UI, and then note the value of their “key” attribute. +The JSON returned from this URL will contain all of your Jira custom fields, most of which are irrelevant to DefectDojo and have values of `"Null"`. Each object in this API response corresponds to a different field in Jira. You will need to search for the objects that have `"name"` attributes which match the names of each Custom Field you created in the Jira UI, and then note the value of their "key" attribute. ![image](images/Using_Custom_Fields.png) -Once you’ve found the matching object in the JSON output, you can determine the “key” value \- in this case, it's `customfield_10050`. +Once you've found the matching object in the JSON output, you can determine the "key" value \- in this case, it's `customfield_10050`. Jira generates different key values for each Custom Field, but these key values do not change once created. If you create another Custom Field in the future, it will have a new key value. **Expanding our Custom Field list:** -* “DefectDojo Custom URL Field” \= customfield\_10050 -* “Another example of a Custom Field” \= customfield\_12345 +* "DefectDojo Custom URL Field" \= customfield\_10050 +* "Another example of a Custom Field" \= customfield\_12345 * ... #### Step 3 \- Finding the Custom Fields on a Jira Issue -Locate an Issue in Jira that contains the Custom Fields which you recorded in Step 2\. Copy the Issue Key for the title (should look similar to “`EXAMPLE-123`”) and navigate to the following URL: +Locate an Issue in Jira that contains the Custom Fields which you recorded in Step 2\. Copy the Issue Key for the title (should look similar to "`EXAMPLE-123`") and navigate to the following URL: `https://yourcompany-example.atlassian.net/rest/api/2/issue/EXAMPLE-123` This will return another string of JSON. -As before, API output will contain lots of `customfield_##` object parameters with `null` values \- these are custom fields that Jira adds by default, which aren’t relevant to this issue. It will also contain `customfield_##` values that match the Custom Field Key values that you found in the previous step. Unlike with the Field Spec output, you won’t see names identifying any of these custom fields, which is why you needed to record the key values in Step 2\. +As before, API output will contain lots of `customfield_##` object parameters with `null` values \- these are custom fields that Jira adds by default, which aren't relevant to this issue. It will also contain `customfield_##` values that match the Custom Field Key values that you found in the previous step. Unlike with the Field Spec output, you won't see names identifying any of these custom fields, which is why you needed to record the key values in Step 2\. ![image](images/Using_Custom_Fields_2.png) **Example:** -We know that `customfield_10050` represents the DefectDojo Custom URL Field because we recorded it in Step 2\. We can now see that `customfield_10050` contains a value of `“https://google.com”` in the `EXAMPLE-123` issue. +We know that `customfield_10050` represents the DefectDojo Custom URL Field because we recorded it in Step 2\. We can now see that `customfield_10050` contains a value of `"https://google.com"` in the `EXAMPLE-123` issue. #### Step 4 \- Creating a JSON Field Reference from each Jira Custom Field Key -You’ll now need to take the value of each of the Custom Fields from your list and store them in a JSON object (to use as a reference). You can ignore any Custom Fields that don’t correspond to your list. +You'll now need to take the value of each of the Custom Fields from your list and store them in a JSON object (to use as a reference). You can ignore any Custom Fields that don't correspond to your list. -This JSON object will contain all of the default values for new Jira Issues. We recommend using names that are easy for your team to recognize as ‘default’ values that need to be changed: ‘`change-me.com`’, ‘`Change this paragraph.`’ etc. +This JSON object will contain all of the default values for new Jira Issues. We recommend using names that are easy for your team to recognize as 'default' values that need to be changed: '`change-me.com`', '`Change this paragraph.`' etc. **Example:** -From step 3, we now know that Jira expects a URL string for "`customfield_10050`”. We can use this to build our example JSON object. +From step 3, we now know that Jira expects a URL string for "`customfield_10050`". We can use this to build our example JSON object. -Say we had also located a DefectDojo\-related short text field, which we identified as "`customfield_67890`”. We would look at this field in our second API output, look at the associated value, and reference the stored value in our example JSON object as well. +Say we had also located a DefectDojo\-related short text field, which we identified as "`customfield_67890`". We would look at this field in our second API output, look at the associated value, and reference the stored value in our example JSON object as well. ​ Your JSON object will start to look like this as you add more Custom Fields to it. @@ -539,7 +441,7 @@ Repeat this process until all of the DefectDojo\-relevant custom fields from Jir #### Data types \& Jira Syntax -Some fields, such as Date fields, may relate to multiple custom fields in Jira. If that is the case, you’ll need to add both fields to your JSON Field Reference. +Some fields, such as Date fields, may relate to multiple custom fields in Jira. If that is the case, you'll need to add both fields to your JSON Field Reference. ``` "customfield_10040": "1970-01-01", @@ -557,7 +459,7 @@ Other fields, such as the Label field, may be tracked as a list of strings \- pl ], ``` -Other custom fields may contain additional, contextual information that should be removed from the Field Reference. For example, the Custom Multichoice Field contains an extra block in the API output, which you’ll need to remove, as this block stores the current value of the field. +Other custom fields may contain additional, contextual information that should be removed from the Field Reference. For example, the Custom Multichoice Field contains an extra block in the API output, which you'll need to remove, as this block stores the current value of the field. * you should remove the extra object from this field: @@ -642,10 +544,10 @@ You can now add these custom fields to the associated DefectDojo Product, in the * Navigate to Edit Product \- defectdojo.com/product/ID/edit . * Navigate to Custom fields and paste the JSON Field Reference as plain text in the Custom Fields box. -* Click ‘Submit’. +* Click 'Submit'. #### Step 6 \- Testing your Jira Custom Fields from a new Finding: -Now, when you create a new Finding in the Jira\-associated Product, Jira will automatically create all of these Custom Fields in Jira according to the JSON block contained within. These Custom Fields will be created with the default (“change\-me\-please”, etc.) values. +Now, when you create a new Finding in the Jira\-associated Product, Jira will automatically create all of these Custom Fields in Jira according to the JSON block contained within. These Custom Fields will be created with the default ("change\-me\-please", etc.) values. -Within the Product on DefectDojo, navigate to the Findings \> Add New Finding page. Make sure the Finding is both Active and Verified to ensure that it pushes to Jira, and then confirm on the Jira side that the Custom Fields are successfully created without any inconsistencies. \ No newline at end of file +Within the Product on DefectDojo, navigate to the Findings \> Add New Finding page. Make sure the Finding is both Active and Verified to ensure that it pushes to Jira, and then confirm on the Jira side that the Custom Fields are successfully created without any inconsistencies. diff --git a/docs/content/issue_tracking/jira/PRO__jira_guide.md b/docs/content/issue_tracking/jira/PRO__jira_guide.md new file mode 100644 index 00000000000..6fe271f367a --- /dev/null +++ b/docs/content/issue_tracking/jira/PRO__jira_guide.md @@ -0,0 +1,562 @@ +--- +title: "📋 Jira Integration Guide" +description: "Work with the Jira integration" +weight: 1 +audience: pro +aliases: + - /en/share_your_findings/jira_guide +--- +DefectDojo's Jira integration can be used to push Finding data to one or more Jira Spaces. By doing so, you can integrate DefectDojo into your standard development workflow. Here are some examples of how this can work: + +* The AppSec team can selectively push Findings to a Jira Space used by developers, so that issue remediation can be appropriately prioritized alongside regular development. Developers on this board don't need to access DefectDojo - they can keep all their work in one place. +* DefectDojo can push ALL Findings to a bidirectional Jira Space which the AppSec team uses, which allows them to split up issue validation. This board keeps in sync with DefectDojo and allows for complex remediation workflows. +* DefectDojo can selectively push Findings from separate Products &/or Engagements to separate Jira Spaces, to keep things in their proper context. + +# Setting Up Jira +Setting Up Jira requires the following steps: +1. Connect a Jira Instance, either with a username / password or an API token. Multiple instances can be linked. +2. Add that Jira Instance to one or more Products or Engagements within DefectDojo. +3. If you wish to use bidirectional sync, create a Jira Webhook which will send updates to DefectDojo. + +## Step 1: Connect a Jira Instance + +Connecting a Jira Instance is the first step to take when setting up DefectDojo's Jira integration. Please note Jira Service Management is currently not supported. + +#### Required information from Jira + +Atlassian uses different ways of authentication between Jira Cloud and Jira Data Center. + +for **Jira Cloud**, you will need: +* a Jira URL, i.e. https://yourcompany.atlassian.net/ +* an account with permissions to create and update issues in your Jira instance. This can be: + * A standard **username / password** combination + * A **username / API Token** combination + +for **Jira Data Center (or Server)**, you will need: +* a Jira URL, i.e. https://jira.yourcompany.com +* an account with permissions to create and update issues in your Jira instance. This can be: + * A standard **username / password** combination + * A **emailaddress / Personal Access Token** combination + +Optionally, you can map: +* Jira Transitions to trigger Re-Opening and Closing Findings +* Jira Resolutions which can apply Risk Acceptance and False Positive statuses to Findings (optional) + +Multiple Jira Spaces can be handled by a single Jira Instance connection, as long as the Jira account / token used by DefectDojo has permission to create Issues in the associated Jira Space. + +### Add a Jira Instance + +1. If you have not already done so, navigate to the System Settings page and check the box on **Enable Jira Integration**. + +2. Navigate to the **Enterprise Settings \> Jira Instances \> + New Jira Instance** page from the DefectDojo sidebar. + +![image](images/jira-instance-beta.png) + +3. Select a **Configuration Name** for this Jira Instance to use in DefectDojo. This name is simply a label for the Instance connection in DefectDojo, and does not need to be related to any Jira data. + +4. Select the URL for your company's Jira instance \- likely similar to `https://**yourcompany**.atlassian.net` if you're using a Jira Cloud installation. + +5. Enter an appropriate authentication method in the Username / Password fields for Jira: + * For standard **username / password Jira authentication**, enter a Jira Username and corresponding Password in these fields. + * For authentication with a **user's API token (Jira Cloud)** enter the Username with the corresponding **API token** in the password field. + * For authentication with a Jira **Personal Access Token (aka PAT, used in Jira Data Center and Jira Server only)**, enter the PAT in the password field. Username is not used for authentication with a Jira PAT, but the field is still required in this form, so you can use a placeholder value here to identify your PAT. + +Note that the user associated with this connection must have permission to create Issues and access data in your Jira instance. + +6. You will need to provide values for an Epic Name ID, Re-open Transition ID and Close Transition ID. These values can be changed later. While logged into Jira, you can access these values from the following URLs: +- **Epic Name ID**: visit `https:///rest/api/2/field` and search for Epic Name. Copy the number out of `number` and paste it here. If you do not have an Epic Name ID associated with your Space in Jira (due to using a Team-Managed Space, for example), enter 0 on this field. +- **Re-open Transition ID**: visit `https:///rest/api/latest/issue//transitions?expand-transitions.fields` to find the ID for your Jira instance. Paste it in the Reopen Transition ID field. +- **Close Transition ID**: Visit `https:///rest/api/latest/issue//transitions?expand-transitions.fields` to find the ID for your Jira instance. Paste it in the Close Transition ID field. + +7. Select the Default issue type which you want to create Issues as in Jira. The options for this are **Bug, Task, Story** and **Epic** (which are standard Jira issue types) as well as **Spike** and **Security**, which are custom issue types. If you have a different Issue Type which you want to use, please contact [support@defectdojo.com](mailto:support@defectdojo.com) for assistance. + +8. Select your Issue Template, which will determine the Issue Description when Issues are created in Jira. + +The two types are: +- **Jira\_full**, which will include all Finding information in Jira Issues +- **Jira\_limited**, which will include a smaller amount of Finding information and metadata. + +If you leave this field blank, it will default to **Jira\_full.** If you need a different kind of template, reach out to [support@defectdojo.com](mailto:support@defectdojo.com). + +9. If you wish, enter the name of a Jira Resolution which will change the status of a Finding to Accepted or to False Positive (when the Resolution is triggered on the Issue). + +The form can be submitted from here. If you wish, you can further customize your Jira integration under Optional Fields. Clicking this button will allow you to apply generic text to Jira Issues or change the mapping of Jira Severity Mappings. + +## Step 2: Connect a Product or Engagement to Jira + +Each Product or Engagement in DefectDojo has its own settings which govern how Findings are converted to JIRA Issues. From here, you can decide the associated Jira Space and set the default behaviour for creating Issues, Epics, Labels and other JIRA metadata. + +### Add Jira to a Product + +You can find this page by clicking the Gear menu on a Product ⚙️ and opening the **Jira Project Settings** page. + +![image](images/jira-project-settings.png) + +#### Jira Instance + +If you have multiple instances of Jira set up, for separate products or teams within your organization, you can indicate which Jira Space you want DefectDojo to create Issues in. Select a Space from the drop\-down menu. + +If this menu doesn't list any Jira instances, confirm that those Spaces are connected in your global Jira Configuration for DefectDojo \- yourcompany.defectdojo.com/jira. + +#### Project key + +This is the key of the Space that you want to use with DefectDojo. The Space Key for a given Space can be found in the URL. (This was previously referred to as a **Jira Project Key**, but as of September 2025, this is now referred to in Jira as the **Space Key**). + +![image](images/Add_a_Connected_Jira_Project_to_a_Product_3.png) + +#### Epic Issue Type Name + +The name of the Epic issue type in Jira. This defaults to "Epic" but can be changed if your Jira instance uses a different name. + +#### Issue template + +Here you can determine how much DefectDojo metadata you want to send to Jira. Select one of two options: + +* **jira\_full**: Issues will track all of the parameters from DefectDojo \- a full Description, CVE, Severity, etc. Useful if you need complete Finding context in Jira (for example, if someone is working on this Issue who doesn't have access to DefectDojo). + +Here is an example of a **jira\_full** Issue: +​ +![image](images/Add_a_Connected_Jira_Project_to_a_Product_4.png) + +* **Jira\_limited:** Issues will only track the DefectDojo link, the Product/Engagement/Test links, the Reporter and Environment fields. All other fields are tracked in DefectDojo only. Useful if you don't require full Finding context in Jira (for example, if someone is working on this Issue who mainly works in DefectDojo, and doesn't need the full picture in JIRA as well.) + +​Here is an example of a **jira\_limited** Issue: + +![image](images/Add_a_Connected_Jira_Project_to_a_Product_5.png) + +#### Component + +If you manage your Jira Space using Components, you can assign the appropriate Component for DefectDojo here. + +#### Custom fields + +If you don't need to use Custom Fields with DefectDojo issues, you can leave this field as 'null'. + +However, if your Jira Space Settings **require you** to use Custom Fields on new Issues, you will need to hard-code these mappings. + +Note that DefectDojo cannot send any Issue\-specific metadata as Custom Fields, only a default value. This section should only be set up if your Jira Space **requires that these Custom Fields exist** in every Issue in your Space. + +Follow **[this guide](#custom-fields-in-jira)** to get started working with Custom Fields. + +#### Jira labels + +Select the relevant labels that you want the Issue to be created with in Jira, e.g. **DefectDojo**, **YourProductName..** + +![image](images/Add_a_Connected_Jira_Project_to_a_Product_6.png) + +#### Default assignee + +The name of the default assignee in Jira. If left blank, DefectDojo will follow the default behaviour in your Jira Space when creating Issues. + +### Jira Project Settings + +#### Enabled + +This toggle controls whether DefectDojo pushes Findings to Jira for this Product. Disabling this will not delete or change any existing Jira tickets created by DefectDojo, but will prevent any further updates or new Issue creation. + +Jira integrations can be removed from your instance only if no related Issues have been created. If Issues have been created, there is no way to completely remove a Jira Instance from DefectDojo. + +#### Add Vulnerability Id as a Jira label + +This allows you to add the Vulnerability ID data as a Jira Label automatically. Vulnerability IDs are added to Findings from individual security tools \- these may be Common Vulnerabilities and Exposures (CVE) IDs or a different format, specific to the tool reporting the Finding. + +#### Push All Issues + +If checked, DefectDojo will automatically push any Active and Verified Findings to Jira as Issues. If left unchecked, all Findings will need to be pushed to Jira manually (individually or via bulk push). + +When this setting is enabled, Jira Issues will continue to sync with DefectDojo even if the Finding's status changes. + +#### Enable Engagement Epic Mapping + +In DefectDojo, Engagements represent a collection of work. Each Engagement contains one or more tests, which contain one or more Findings which need to be mitigated. Epics in Jira work in a similar way, and this checkbox allows you to push Engagements to Jira as Epics. + +* An Engagement in DefectDojo \- note the three findings listed at the bottom. +​ +![image](images/Add_a_Connected_Jira_Project_to_a_Product_8.png) +* How the same Engagement becomes an Epic when pushed to JIRA \- the Engagement's Findings are also pushed, and live inside the Engagement as Child Issues. + +![image](images/Add_a_Connected_Jira_Project_to_a_Product_9.png) + +#### Push Notes + +If enabled, Jira comments will populate on the associated Finding in DefectDojo, under Notes, and vice versa; Notes on Findings will be added to the associated Jira Issue as Comments. + +#### Send SLA Notifications As Comments + +If enabled, any Issue which breaches DefectDojo's Service Level Agreement rules will have comments added to the Jira issue indicating this. These comments will be posted daily until the Issue is resolved. + +Service Level Agreements can be configured under **Configuration \> SLA Configuration** in DefectDojo and assigned to each Product. + +#### Send Risk Acceptance Expiration Notifications As Comment + +If enabled, any Issue where the associated DefectDojo Risk Acceptance expires will have a comment added to the Jira issue indicating this. These comments will be posted daily until the Issue is resolved. + +### Engagement-Level Jira Settings + +By default, Engagements **inherit Jira settings from their Product**. However, you can override the Jira settings for individual Engagements. + +To access Engagement-level Jira settings, click the Gear menu ⚙️ on an Engagement and open the **Jira Project Settings** page. + +From here, you can uncheck **Inherit from Product** and provide Engagement-specific values for: **Project Key**, **Issue Template, Custom Fields, Jira Labels, Default Assignee**, and other settings. + +Note that once an Engagement has its own Jira project assigned, it can no longer inherit from the Product. + +![image](images/Creating_Issues_in_Jira_5.png) + +## Step 3: Configure Bidirectional Sync: Jira Webhook + +The Jira integration allows for bidirectional sync via webhook. DefectDojo receives Jira notifications at a unique address, which can allow for Jira comments to be received on Findings, or for Findings to be resolved via Jira depending on your configuration. + +### Locating your Jira Webhook URL + +Your Jira Webhook is located on the System Settings form under **Jira Integration Settings**: **Enterprise Settings \> System Settings** from the sidebar. + +![image](images/Configuring_the_Jira_DefectDojo_Webhook.png) + +### Creating the Jira Webhook + +1. Visit `**https:// \ /plugins/servlet/webhooks**` +2. Click 'Create a Webhook'. +3. For the field labeled 'URL' enter: `https:// \<**YOUR DOJO DOMAIN**\> /jira/webhook/ \<**YOUR GENERATED WEBHOOK SECRET**\>`. The Web Hook Secret is listed under the Jira Integration Settings as listed above. +4. Under 'Comments' enable 'Created'. Under Issue enable 'Updated'. +5. Make sure your JIRA instance trusts the SSL certificate used by your DefectDojo instance. For JIRA Cloud DefectDojo must use [a valid SSL/TLS certificate, signed by a globally trusted certificate authority](https://developer.atlassian.com/cloud/jira/platform/deprecation-notice-registering-webhooks-with-non-secure-urls/) + +Note that you do not need to create a Secret within Jira to use this webhook. The Secret is built into DefectDojo's URL, so simply adding the complete URL to the Jira Webhook form is sufficient. + +DefectDojo's Jira Webhook only accepts requests from the Jira API. + +#### Testing the Webhook + +Once you have one or more Issues created from DefectDojo Findings, you can test the Webhook by adding a Comment to one of those Findings. The Comment should be received by the Jira webhook as a note. + +If this doesn't work correctly, it could be due to a Firewall issue on your Jira instance blocking the Webhook. + +* DefectDojo's Firewall Rules include a checkbox for **Jira Cloud,** which needs to be enabled before DefectDojo can receive Webhook messages from Jira. + +## Testing the Jira integration + +#### Test 1: Do Findings successfully push to Jira? + +In order to test that the Jira integration is working properly, you can add a new blank Finding to the Product associated with Jira in DefectDojo. **Product \> Findings \> Add New Finding.** + +Add whatever title severity and description you wish, and then click "Finished". The Finding should appear as an Issue in Jira with all of the relevant metadata. + +If Jira Issues are not being created correctly, check your Notifications for error codes. + +* Confirm that the Jira User associated with DefectDojo's Jira Configuration has permission to create and update issues on that particular Jira Space. + +#### Test 2: Jira Webhooks send to DefectDojo + +In order to test the Jira webhooks, add a Note to a Finding which also exists in JIRA as an Issue (for example, the test issue in the section above). + +If the webhooks are configured correctly, you should see the Note in Jira as a Comment on the issue. + +If this doesn't work correctly, it could be due to a Firewall issue on your Jira instance blocking the Webhook. + +* DefectDojo's Firewall Rules include a checkbox for **Jira Cloud,** which needs to be enabled before DefectDojo can receive Webhook messages from Jira. + +## Disconnecting from Jira + +Jira integrations can be removed from your instance only if no related Issues have been created. If Issues have been created, there is no way to completely remove a Jira Instance from DefectDojo. + +However, you can disable your Jira integration by disabling it at the Product level. From the **Jira Project Settings** page (accessible via the ⚙️ Gear menu on a Product), uncheck the **Enabled** toggle. This will not delete or change any existing Jira tickets created by DefectDojo, but will disable any further updates. + +# Pushing Findings To Jira + +A Product with a JIRA mapping can push Findings to Jira as Issues using several methods. You can push Findings individually, in bulk, as Finding Groups, or automatically. + +## Push a Single Finding + +1. Open the Finding you want to push. +2. Click the **☰ Finding Menu** and select **Push to Jira**. +3. Confirm the push when prompted. DefectDojo will create a Jira Issue and link it to the Finding. + +Once the Issue is created, DefectDojo will display a link to the Jira Issue on the Finding page. + +![image](images/Creating_Issues_in_Jira_2.png) + +You can also check the **Push to Jira** checkbox when editing a Finding via the **Edit Finding** form. When the Finding is saved, it will be pushed to Jira. + +### Updating a Linked Jira Issue + +If a Finding already has a linked Jira Issue, selecting **Push to Jira** again will update the existing Jira Issue with any changes made in DefectDojo. If **Push All Issues** is enabled on the Product, this syncing happens automatically. + +### Unlinking a Finding from Jira + +To remove the association between a Finding and its Jira Issue, click the **☰ Finding Menu** and select **Unlink From Jira**. This removes the link in DefectDojo but does not delete the Jira Issue itself. + +## Bulk Push Findings + +You can push multiple Findings to Jira at once using the Bulk Update form: + +1. From a Findings list, select the Findings you want to push using the checkboxes. +2. Open the **Bulk Update** form. +3. Under **Jira Settings**, check the **Push to Jira** checkbox. +4. Click **Submit**. + +The selected Findings will be queued for Jira push. DefectDojo will display a confirmation message indicating how many Findings were queued. + +## Push Engagements as Epics + +If **Enable Engagement Epic Mapping** is turned on in your Jira Project Settings, you can push an Engagement to Jira as an Epic. The Engagement's Findings will be pushed as Child Issues within that Epic. + +To push an Engagement as an Epic: + +1. Open the Engagement you want to push. +2. Click the **☰ Engagement Menu** and select **Push to Jira**. +3. Optionally, provide an **Epic Name** (defaults to the Engagement name if left blank) and an **Epic Priority**. +4. Check **Push to Jira (Create Epic)** and submit the form. + +## Push Finding Groups as Jira Issues + +If you have Finding Groups enabled, you can push a Group of Findings to Jira as a single Issue rather than separate Issues for each Finding. + +To push a Finding Group: + +1. Open the Finding Group. +2. Click the **☰ Finding Group Menu** and select **Push to Jira**, or check the **Push to Jira** checkbox when editing the Finding Group. + +The Jira Issue associated with a Finding Group must be deleted directly from the Jira instance if removal is needed. + +### Automatically Create and Push Finding Groups + +With **Push All Issues** enabled on the Product, and a **Group By** option selected on import: + +As long as the Finding Groups are being created successfully, the Finding Group is what will automatically push to Jira as an Issue, not the individual Findings. + +![image](images/Creating_Issues_in_Jira_4.png) + +## Automatic Push Behaviour + +DefectDojo can automatically push Findings and updates to Jira in several scenarios: + +### Push All Issues + +When the **Push All Issues** setting is enabled on a Product's Jira Project Settings, DefectDojo will automatically create Jira Issues for all Active and Verified Findings. This includes Findings created via scan import. Once a Jira Issue is created, it will continue to sync with DefectDojo even if the Finding's status changes. + +### Auto-Sync on Status Changes + +When **Push All Issues** or the system-level **Finding Jira Sync** setting is enabled, DefectDojo will automatically update linked Jira Issues when certain actions are taken on Findings: + +* **Request Review** \- A comment is added to the linked Jira Issue (or the Finding Group's Jira Issue if the Finding belongs to a group). +* **Clear Review** \- A comment is added to the linked Jira Issue. +* **Close Finding** \- The linked Jira Issue is updated to reflect the closure. If **Push Notes** is enabled, a comment is also added. + +## Jira Comments and Notes + +When **Push Notes** is enabled in the Jira Project Settings: + +* If a comment is added to a Jira Issue, the same comment will be added to the Finding, under the **Notes** section. +* Likewise, if a Note is added to a Finding, the Note will be added to the Jira issue as a comment. + +## Jira Status Changes + +The Jira Instance configuration has entries for two Jira Transitions which will trigger a status change on a Finding. + +* When the **'Close' Transition** is performed on Jira, the associated Finding will also Close, and become marked as **Inactive** and **Mitigated** on DefectDojo. DefectDojo will record this change on the Finding page under the **Mitigated By** heading. +​ +![image](images/Creating_Issues_in_Jira_3.png) + +* When the **'Reopen' Transition** is performed on the Jira Issue, the associated Finding will be set as **Active** on DefectDojo, and will lose its **Mitigated** status. + +# Custom Fields in Jira + +DefectDojo does not currently support passing any Issue\-specific information into these Custom Fields \- these fields will need to be updated manually in Jira after the issue is created. Each Custom Field will only be created from DefectDojo with a default value. + + Jira Cloud now allows you to create a default Custom Field value directly in\-app. [See Atlassian's documentation on Custom Fields](https://support.atlassian.com/jira-cloud-administration/docs/configure-a-custom-field/) for more information on how to configure this. + +DefectDojo's built\-in Jira Issue Types (**Bug, Task, Story** and **Epic)** are set up to work 'out of the box'. Data fields in DefectDojo will automatically map to the corresponding fields in Jira. By default, DefectDojo will assign Priority, Labels and a Reporter to any new Issue it creates. + +Some Jira configurations require additional custom fields to be accounted for before an issue can be created. This process will allow you to account for these custom fields in your DefectDojo \-\> Jira integration, ensuring that issues are created successfully. These custom fields will be added to any API calls sent from DefectDojo to a linked Jira instance. + +If you don't already use Custom Fields in Jira, there is no need to follow this process. + +1. Recording the names of your Custom Fields in Jira (**Jira UI**) +2. Determine the Key values for the new Custom Fields (Jira Field Spec Endpoint) +3. Locate the acceptable data for each Custom Field, using the Key values as a reference (Jira Issue Endpoint) +4. Create a Field Reference JSON block to track all of the Custom Field Keys and acceptable data (Jira Issue Endpoint) +5. Store the JSON block in the associated DefectDojo Product, to allow Custom Fields to be created from Jira (DefectDojo UI) +6. Test your work and ensure that all required data is flowing from Jira properly + +#### Step 1: Record the names of your Custom Fields in Jira + +Jira supports a variety of different Context Fields, including Date Pickers, Custom Labels, Radio Buttons. Each of these Context Fields will have a different Key value that can be found in the Jira API. + +Write down the names of each required Custom Field, as you will need to search through the Jira API to find them in the next step. + +**Example of a Custom Field list (your Custom Field names will be different):** + +* DefectDojo Custom URL Field +* Another example of a Custom Field +* ... + +#### Step 2: Finding your Jira Custom Field Key Values + +Start this process by navigating to the Field Spec URL for your entire Jira instance. + +Here is an example of a Field Spec URL: + +`https://yourcompany-example.atlassian.net/rest/api/2/field` + +The API will return a long string of JSON, which should be formatted into readable text (using a code editor, browser extension or ). + +The JSON returned from this URL will contain all of your Jira custom fields, most of which are irrelevant to DefectDojo and have values of `"Null"`. Each object in this API response corresponds to a different field in Jira. You will need to search for the objects that have `"name"` attributes which match the names of each Custom Field you created in the Jira UI, and then note the value of their "key" attribute. + +![image](images/Using_Custom_Fields.png) + +Once you've found the matching object in the JSON output, you can determine the "key" value \- in this case, it's `customfield_10050`. + +Jira generates different key values for each Custom Field, but these key values do not change once created. If you create another Custom Field in the future, it will have a new key value. + +**Expanding our Custom Field list:** + +* "DefectDojo Custom URL Field" \= customfield\_10050 +* "Another example of a Custom Field" \= customfield\_12345 +* ... + +#### Step 3 \- Finding the Custom Fields on a Jira Issue + +Locate an Issue in Jira that contains the Custom Fields which you recorded in Step 2\. Copy the Issue Key for the title (should look similar to "`EXAMPLE-123`") and navigate to the following URL: + +`https://yourcompany-example.atlassian.net/rest/api/2/issue/EXAMPLE-123` + +This will return another string of JSON. + +As before, API output will contain lots of `customfield_##` object parameters with `null` values \- these are custom fields that Jira adds by default, which aren't relevant to this issue. It will also contain `customfield_##` values that match the Custom Field Key values that you found in the previous step. Unlike with the Field Spec output, you won't see names identifying any of these custom fields, which is why you needed to record the key values in Step 2\. + +![image](images/Using_Custom_Fields_2.png) + +**Example:** +We know that `customfield_10050` represents the DefectDojo Custom URL Field because we recorded it in Step 2\. We can now see that `customfield_10050` contains a value of `"https://google.com"` in the `EXAMPLE-123` issue. + +#### Step 4 \- Creating a JSON Field Reference from each Jira Custom Field Key + +You'll now need to take the value of each of the Custom Fields from your list and store them in a JSON object (to use as a reference). You can ignore any Custom Fields that don't correspond to your list. + +This JSON object will contain all of the default values for new Jira Issues. We recommend using names that are easy for your team to recognize as 'default' values that need to be changed: '`change-me.com`', '`Change this paragraph.`' etc. + +**Example:** + +From step 3, we now know that Jira expects a URL string for "`customfield_10050`". We can use this to build our example JSON object. + +Say we had also located a DefectDojo\-related short text field, which we identified as "`customfield_67890`". We would look at this field in our second API output, look at the associated value, and reference the stored value in our example JSON object as well. +​ +Your JSON object will start to look like this as you add more Custom Fields to it. + +``` +{ + "customfield_10050": "https://change-me.com", + "customfield_67890": "This is the short text custom field." +} +``` + +Repeat this process until all of the DefectDojo\-relevant custom fields from Jira have been added to your JSON Field Reference. + +#### Data types \& Jira Syntax + +Some fields, such as Date fields, may relate to multiple custom fields in Jira. If that is the case, you'll need to add both fields to your JSON Field Reference. + +``` + "customfield_10040": "1970-01-01", + "customfield_10041": "1970-01-01T03:30:00.000+0200", +``` + +Other fields, such as the Label field, may be tracked as a list of strings \- please make sure your JSON Field Reference uses a format that matches API output from Jira. + +``` +// a list of custom labels on a Jira object + "customfield_10042": [ + "custom-label-one", + "this-is-default", + "change-me-please" + ], +``` + +Other custom fields may contain additional, contextual information that should be removed from the Field Reference. For example, the Custom Multichoice Field contains an extra block in the API output, which you'll need to remove, as this block stores the current value of the field. + +* you should remove the extra object from this field: + +``` +"customfield_10047": [ + { + "value": "A" + }, + { + "self": "example.url...", + "value": "C", + "id": "example ID" + } +] +``` +* instead, you can shorten this to the following and disregard the second part: + +``` +"customfield_10047": [ + { + "value": "A" + } +] +``` + +#### Example Completed Field Reference + +Here is a complete JSON Field Reference, with in\-line comments explaining what each custom field pertains to. This is meant as an all\-encompassing example. Your JSON will contain different key values and data points depending on the Custom Values you want to use during issue creation. + +``` +{ + "customfield_10050": "https://change-me.com", + + "customfield_10049": "This is a short text custom field", + +// two different fields, but both correspond to the same custom date attribute + "customfield_10040": "1970-01-01", + "customfield_10041": "1970-01-01T03:30:00.000+0200", + +// a list of custom labels on a Jira object + "customfield_10042": [ + "custom-label-one", + "this-is-default", + "change-me-please" + ], + +// custom number field + "customfield_10043": 0, + +// custom paragraph field + "customfield_10044": "This is a very long winded way to say CHANGE ME PLEASE", + +// custom radio button field + "customfield_10045": { + "value": "radio button option" + }, + +// custom multichoice field + "customfield_10047": [ + { + "value": "A" + } + ], + +// custom checkbox field + "customfield_10039": [ + { + "value": "A" + } + ], + +// custom select list (singlechoice) field + "customfield_10048": { + "value": "1" + } +} +``` + +#### Step 5 \- Adding the Custom Fields to a DefectDojo Product + +You can now add these custom fields to the associated DefectDojo Product, in the Jira Project Settings page (accessible via the ⚙️ Gear menu on the Product). Paste the JSON Field Reference as plain text in the **Custom Fields** box and save. + +#### Step 6 \- Testing your Jira Custom Fields from a new Finding: + +Now, when you create a new Finding in the Jira\-associated Product, Jira will automatically create all of these Custom Fields in Jira according to the JSON block contained within. These Custom Fields will be created with the default ("change\-me\-please", etc.) values. + +Within the Product on DefectDojo, navigate to the Findings \> Add New Finding page. Make sure the Finding is both Active and Verified to ensure that it pushes to Jira, and then confirm on the Jira side that the Custom Fields are successfully created without any inconsistencies. diff --git a/docs/content/issue_tracking/jira/troubleshooting_jira.md b/docs/content/issue_tracking/jira/troubleshooting_jira.md index 131bc4fbbe8..552c70f9eed 100644 --- a/docs/content/issue_tracking/jira/troubleshooting_jira.md +++ b/docs/content/issue_tracking/jira/troubleshooting_jira.md @@ -65,7 +65,7 @@ Using the 'Push To Jira' workflow triggers an asynchronous process, however an I Common reasons issues are not created: * The Default Issue Type you have selected is not usable with the Jira Space -* Issues in the Space have required attributes that prevent them from being created via DefectDojo (see our guide to [Custom Fields](../jira_guide/#custom-fields-in-jira)) +* Issues in the Space have required attributes that prevent them from being created via DefectDojo (which can be handled via Custom Fields in Jira) ## Error: Product Misconfigured or no permissions in Jira? @@ -77,11 +77,11 @@ This error message can appear when attempting to add a created Jira configuratio ## Changes made to Jira issues are not updating Findings in DefectDojo -* Start by confirming that the [DefectDojo webhook receiver](../jira_guide/#step-3-configure-bidirectional-sync-jira-webhook) is configured correctly and can successfully receive updates. +* Start by confirming that the DefectDojo webhook receiver is configured correctly and can successfully receive updates. * Ensure the SSL certificate used by Defect Dojo is trusted by JIRA. For JIRA Cloud you must use [a valid SSL/TLS certificate, signed by a globally trusted certificate authority](https://developer.atlassian.com/cloud/jira/platform/deprecation-notice-registering-webhooks-with-non-secure-urls/) -* If you're trying to push status changes, confirm that Jira transition mappings are set up correctly (Reopen / Close [Transition IDs](../jira_guide/#step-3-configure-bidirectional-sync-jira-webhook)). +* If you're trying to push status changes, confirm that Jira transition mappings are set up correctly (Reopen / Close Transition IDs). * [Test](https://support.atlassian.com/jira/kb/testing-webhooks-in-jira-cloud/) your JIRA webhook using a public endpoint such as Pipedream or Beeceptor: diff --git a/docs/content/releases/pro/changelog.md b/docs/content/releases/pro/changelog.md index b15a105c203..4caa1e784f5 100644 --- a/docs/content/releases/pro/changelog.md +++ b/docs/content/releases/pro/changelog.md @@ -12,6 +12,30 @@ For Open Source release notes, please see the [Releases page on GitHub](https:// ## Mar 2026: v2.56 +### Mar 30, 2026: v2.56.4 + +* **(Deduplication)** Fixed an issue where cross-tool deduplication could silently fail to match duplicates when findings were imported across different scan tools. +* **(Pro UI)** Audit Log table now supports global search and query parameter–based filtering. +* **(Pro UI)** Improved page load performance for large listing tables (Findings, Endpoints, etc.) by reducing unnecessary computation during pagination. + +### Mar 23, 2026: v2.56.3 + +* **(MFA)** All authenticated users can now access their own MFA settings page, regardless of role. +* **(Pro UI)** Alerts table now uses server-side filtering, sorting, and pagination for improved performance. +* **(Pro UI)** Removed the deprecated Credentials section from System Settings. +* **(Pro UI)** Fixed boolean filters on the Product Types table for the Critical and Key Asset columns. +* **(Pro UI)** Fixed a filter alignment issue on the Engagements table. +* **(Pro UI)** Standardized the Test field label to "Title" across all screens. +* **(Rules Engine)** Fixed a timeout (502 error) that could occur when previewing rules against a large number of Findings. + +### Mar 16, 2026: v2.56.2 + +* **(API)** Added pagination limit enforcement and deprecation warnings for unpaginated API requests. +* **(Jira)** Custom field values are now properly encoded and decoded as JSON, with validation errors shown for invalid input. +* **(Pro UI)** The New Risk Acceptance form now pre-fills the expiration date using the system default number of days. +* **(Pro UI)** Improved handling of Group membership and permissions in the UI. +* **(SBOM)** SBOM imports are now processed asynchronously, improving upload responsiveness for large files. + ### Mar 12, 2026: v2.56.1 * **(Pro UI)** Finding Groups can now be filtered by computed status: resolved, active, or risk-accepted. diff --git a/docs/content/supported_tools/parsers/file/sarif.md b/docs/content/supported_tools/parsers/file/sarif.md index b6c1ee62eab..f544eb6f5eb 100644 --- a/docs/content/supported_tools/parsers/file/sarif.md +++ b/docs/content/supported_tools/parsers/file/sarif.md @@ -6,15 +6,38 @@ OASIS Static Analysis Results Interchange Format (SARIF). SARIF is supported by many tools. More details about the format here: -SARIF parser customizes the Test_Type with data from the report. -For example, a report with `Dockle` as a driver name will produce a Test with a Test_Type named `Dockle Scan (SARIF)` +Current implementation will aggregate all the findings in the SARIF file into a single report. -Current implementation is limited and will aggregate all the findings in the SARIF file in one single report. +## How Test Types Are Determined -##### Support for de-duplication (fingerprinting) +Unlike most parsers in DefectDojo, the SARIF parser has a **report-defined Test Type**. When you import a SARIF file with `scan_type=SARIF`, DefectDojo reads the tool name from within the SARIF file at `runs[].tool.driver.name` and uses it to construct the Test Type name. -SARIF parser take into account data for fingerprinting. It's base on `fingerprints` and `partialFingerprints` properties. -It's possible to activate de-duplication based on this data by customizing settings. +The naming pattern is: **`{tool name} ({scan_type})`** + +For example: + +| Tool | `runs[].tool.driver.name` value | Resulting Test Type | +|------|-------------------------------|---------------------| +| Semgrep | `semgrep` | `semgrep (SARIF)` | +| Trivy | `Trivy Scan` | `Trivy Scan (SARIF)` | +| Dockle | `Dockle` | `Dockle Scan (SARIF)` | +| MobSF | `mobsfscan` | `mobsfscan (SARIF)` | + +This means that even though all of these tools produce SARIF output and are imported with `scan_type=SARIF`, each tool will create a **distinct Test Type** in DefectDojo. For more information on how report-defined Test Types work, see **[Test Types](/asset_modelling/hierarchy/product_hierarchy#test-types)**. + +## Reimporting SARIF Results + +When using the `/api/v2/reimport-scan/` endpoint, DefectDojo needs to match incoming results to an existing Test. Understanding how this matching works is important when multiple SARIF-based tools are reporting into the same Engagement. + +### One Tool Per Test + +Each Test in DefectDojo represents results from a single tool. SARIF results from different tools (e.g. Semgrep, Trivy, MobSF) cannot be combined into the same Test, even though they share the same `scan_type=SARIF`. DefectDojo enforces this by validating that the tool name inside the SARIF file matches the existing Test's Test Type on reimport. + +This constraint is what makes reimport's comparison logic reliable: when a Finding is absent from a new report, DefectDojo can safely assume it has been resolved. If results from multiple tools were mixed in a single Test, DefectDojo would not be able to distinguish between a resolved Finding and a Finding that simply isn't covered by the current tool. + +## Support for Deduplication (Fingerprinting) + +The SARIF parser takes into account data for fingerprinting, based on the `fingerprints` and `partialFingerprints` properties in the SARIF file. It's possible to activate deduplication based on this data by customizing settings: ```Python # in your settings.py file @@ -25,7 +48,7 @@ DEDUPLICATION_ALGORITHM_PER_PARSER["SARIF"] = DEDUPE_ALGO_UNIQUE_ID_FROM_TOOL_OR Sample SARIF scans can be found [here](https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans/sarif). ### Default Deduplication Hashcode Fields -By default, DefectDojo identifies duplicate Findings using these [hashcode fields](https://docs.defectdojo.com/en/working_with_findings/finding_deduplication/about_deduplication/): +By default, DefectDojo identifies duplicate Findings using these [hashcode fields](/triage_findings/finding_deduplication/about_deduplication): - title - cwe diff --git a/docs/package-lock.json b/docs/package-lock.json index 2c86e0d3d7c..39caf2b63d8 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -2632,9 +2632,9 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -3939,9 +3939,9 @@ } }, "node_modules/purgecss/node_modules/brace-expansion": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.3.tgz", - "integrity": "sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -4618,9 +4618,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", - "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", + "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", "license": "ISC", "bin": { "yaml": "bin.mjs" diff --git a/dojo/finding/helper.py b/dojo/finding/helper.py index 3c13d69a252..ba11567869b 100644 --- a/dojo/finding/helper.py +++ b/dojo/finding/helper.py @@ -723,11 +723,18 @@ def bulk_clear_finding_m2m(finding_qs): # Remove tags with proper count maintenance bulk_remove_all_tags(Finding, finding_ids) - # Auto-discover and delete remaining (non-tag) M2M through tables - for m2m_field in Finding._meta.many_to_many: - if hasattr(m2m_field, "tag_options"): + # Auto-discover and delete M2M through tables — both forward (Finding._meta.many_to_many) + # and reverse (other models with ManyToManyField pointing to Finding, e.g. Finding_Group.findings). + # Forward M2M fields use field.remote_field.through, reverse use field.through. + m2m_through_models = set() + for field_info in Finding._meta.get_fields(): + if hasattr(field_info, "tag_options"): continue - through_model = m2m_field.remote_field.through + through = getattr(field_info, "through", None) or getattr(getattr(field_info, "remote_field", None), "through", None) + if through is not None: + m2m_through_models.add(through) + + for through_model in m2m_through_models: # Find the FK column that points to Finding fk_column = None for field in through_model._meta.get_fields(): diff --git a/dojo/importers/default_reimporter.py b/dojo/importers/default_reimporter.py index 03cfd7ef635..efeaa252eb8 100644 --- a/dojo/importers/default_reimporter.py +++ b/dojo/importers/default_reimporter.py @@ -1,4 +1,5 @@ import logging +from itertools import batched from django.conf import settings from django.core.files.uploadedfile import TemporaryUploadedFile @@ -31,6 +32,9 @@ logger = logging.getLogger(__name__) deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") +# Bound IN-list size when bulk-loading status fields for close_old_findings. +_CLOSE_OLD_FINDINGS_STATUS_FIELDS_CHUNK = 1000 + class DefaultReImporterOptions(ImporterOptions): def validate_test( @@ -412,6 +416,7 @@ def process_findings( finding = self.finding_post_processing( finding, unsaved_finding, + is_matched_finding=bool(matched_findings), ) # all data is already saved on the finding, we only need to trigger post processing in batches push_to_jira = self.push_to_jira and ((not self.findings_groups_enabled or not self.group_by) or not finding_will_be_grouped) @@ -469,6 +474,44 @@ def process_findings( return self.new_items, self.reactivated_items, self.to_mitigate, self.untouched + def _sync_close_old_finding_status_fields(self, findings: list[Finding]) -> None: + """ + Refresh false_p, risk_accepted, and out_of_scope from the DB for each finding. + + These can change during reimport (e.g. false positive) while the in-memory instances + are stale. Per-finding refresh_from_db in close_old_findings was added in + https://github.com/DefectDojo/django-DefectDojo/pull/12291. A naive refresh per + finding issues one SELECT each; we batch one query per chunk of primary keys and fall + back to refresh_from_db only when needed. + + This really should be fixed differently, but for now we at least optimize it to be done in bulk. + """ + findings_without_pk = [f for f in findings if f.pk is None] + findings_with_pk = [f for f in findings if f.pk is not None] + + for finding in findings_without_pk: + finding.refresh_from_db(fields=["false_p", "risk_accepted", "out_of_scope"]) + + for chunk in batched(findings_with_pk, _CLOSE_OLD_FINDINGS_STATUS_FIELDS_CHUNK, strict=False): + ids = [f.pk for f in chunk] + fresh_by_id = { + row["id"]: row + for row in Finding.objects.filter(pk__in=ids).values( + "id", + "false_p", + "risk_accepted", + "out_of_scope", + ) + } + for finding in chunk: + row = fresh_by_id.get(finding.pk) + if row is not None: + finding.false_p = row["false_p"] + finding.risk_accepted = row["risk_accepted"] + finding.out_of_scope = row["out_of_scope"] + else: + finding.refresh_from_db(fields=["false_p", "risk_accepted", "out_of_scope"]) + def close_old_findings( self, findings: list[Finding], @@ -482,17 +525,17 @@ def close_old_findings( if self.close_old_findings_toggle is False: return [] logger.debug("REIMPORT_SCAN: Closing findings no longer present in scan report") + # Get any status changes that could have occurred earlier in the process + # for special statuses only. + # An example of such is a finding being reported as false positive, and + # reimport makes this change in the database. However, the findings here + # are calculated based from the original values before the reimport, so + # any updates made during reimport are discarded without first getting the + # state of the finding as it stands at this moment (django-DefectDojo #12291). + self._sync_close_old_finding_status_fields(findings) # Determine if pushing to jira or if the finding groups are enabled mitigated_findings = [] for finding in findings: - # Get any status changes that could have occurred earlier in the process - # for special statuses only. - # An example of such is a finding being reported as false positive, and - # reimport makes this change in the database. However, the findings here - # are calculated based from the original values before the reimport, so - # any updates made during reimport are discarded without first getting the - # state of the finding as it stands at this moment - finding.refresh_from_db(fields=["false_p", "risk_accepted", "out_of_scope"]) # Ensure the finding is not already closed if not finding.mitigated or not finding.is_mitigated: logger.debug("mitigating finding: %i:%s", finding.id, finding) @@ -931,6 +974,8 @@ def finding_post_processing( self, finding: Finding, finding_from_report: Finding, + *, + is_matched_finding: bool = False, ) -> Finding: """ Save all associated objects to the finding after it has been saved @@ -949,19 +994,22 @@ def finding_post_processing( for endpoint in self.endpoints_to_add: key = self.endpoint_manager.record_endpoint(endpoint) self.endpoint_manager.record_status_for_create(finding, key) - # Parsers shouldn't use the tags field, and use unsaved_tags instead. - # Merge any tags set by parser into unsaved_tags - tags_from_parser = finding_from_report.tags if isinstance(finding_from_report.tags, list) else [] - unsaved_tags_from_parser = finding_from_report.unsaved_tags if isinstance(finding_from_report.unsaved_tags, list) else [] - merged_tags = unsaved_tags_from_parser + tags_from_parser - if merged_tags: - finding_from_report.unsaved_tags = merged_tags - if finding_from_report.unsaved_tags: - cleaned_tags = clean_tags(finding_from_report.unsaved_tags) - if isinstance(cleaned_tags, list): - finding.tags.add(*cleaned_tags) - elif isinstance(cleaned_tags, str): - finding.tags.add(cleaned_tags) + # For matched/existing findings, do not update tags from the report, + # consistent with how other fields are handled on reimport. + if not is_matched_finding: + # Parsers shouldn't use the tags field, and use unsaved_tags instead. + # Merge any tags set by parser into unsaved_tags + tags_from_parser = finding_from_report.tags if isinstance(finding_from_report.tags, list) else [] + unsaved_tags_from_parser = finding_from_report.unsaved_tags if isinstance(finding_from_report.unsaved_tags, list) else [] + merged_tags = unsaved_tags_from_parser + tags_from_parser + if merged_tags: + finding_from_report.unsaved_tags = merged_tags + if finding_from_report.unsaved_tags: + cleaned_tags = clean_tags(finding_from_report.unsaved_tags) + if isinstance(cleaned_tags, list): + finding.tags.add(*cleaned_tags) + elif isinstance(cleaned_tags, str): + finding.tags.add(cleaned_tags) # Process any files if finding_from_report.unsaved_files: finding.unsaved_files = finding_from_report.unsaved_files diff --git a/dojo/management/commands/migrate_endpoints_to_locations.py b/dojo/management/commands/migrate_endpoints_to_locations.py index d30fa121d3b..25c739abb0a 100644 --- a/dojo/management/commands/migrate_endpoints_to_locations.py +++ b/dojo/management/commands/migrate_endpoints_to_locations.py @@ -11,6 +11,9 @@ logger = logging.getLogger(__name__) +# Chunk size for DB cursor and progress report +CHUNK_SIZE = 1000 + class Command(BaseCommand): @@ -88,10 +91,31 @@ def _associate_location_with_findings(self, endpoint: Endpoint, location: Locati location.associate_with_product(product) def handle(self, *args, **options): - # Start off with the endpoint objects - it should everything we need - for endpoint in Endpoint.objects.all().iterator(): - # Get the URL object first - location = self._endpoint_to_url(endpoint) - # Associate the URL with the findings associated with the Findings - # the association to a finding will also apply to a product automatically - self._associate_location_with_findings(endpoint, location) + # Allow endpoints to work with V3/Locations enabled + with Endpoint.allow_endpoint_init(): + # Progress counter + i = 0 + # Start off with the endpoint objects - it should contain everything we need + queryset = Endpoint.objects.all() + # Grab the total count so we can communicate progress + endpoint_count = queryset.count() + + # Process each endpoint + for i, endpoint in enumerate(queryset.iterator(chunk_size=CHUNK_SIZE), 1): + # Progress report every chunk + if not i % CHUNK_SIZE: + self.stdout.write( + self.style.SUCCESS( + f"Migrated {i}/{endpoint_count} endpoints...", + ), + ) + # Get the URL object first + location = self._endpoint_to_url(endpoint) + # Associate the URL with the findings associated with the Findings + # the association to a finding will also apply to a product automatically + self._associate_location_with_findings(endpoint, location) + self.stdout.write( + self.style.SUCCESS( + f"Migrated {i} total endpoints.", + ), + ) diff --git a/dojo/middleware.py b/dojo/middleware.py index 8d274202f90..231846a4efe 100644 --- a/dojo/middleware.py +++ b/dojo/middleware.py @@ -326,6 +326,7 @@ def _trigger_async_index_update(self, model_groups): # Import here to avoid circular import from django.conf import settings # noqa: PLC0415 circular import + from dojo.celery_dispatch import dojo_dispatch_task # noqa: PLC0415 circular import from dojo.tasks import update_watson_search_index_for_model # noqa: PLC0415 circular import # Create tasks per model type, chunking large lists into configurable batches @@ -337,4 +338,4 @@ def _trigger_async_index_update(self, model_groups): # Create tasks for each batch and log each one for i, batch in enumerate(batches, 1): logger.debug(f"AsyncSearchContextMiddleware: Triggering batch {i}/{len(batches)} for {model_name}: {len(batch)} instances") - update_watson_search_index_for_model(model_name, batch) + dojo_dispatch_task(update_watson_search_index_for_model, model_name, batch) diff --git a/dojo/tools/aws_inspector2/parser.py b/dojo/tools/aws_inspector2/parser.py index 0b95d842c38..2174d06e977 100644 --- a/dojo/tools/aws_inspector2/parser.py +++ b/dojo/tools/aws_inspector2/parser.py @@ -1,3 +1,4 @@ +import contextlib import json from datetime import UTC, datetime @@ -114,6 +115,7 @@ def get_cvss_details(self, finding: Finding, raw_finding: dict) -> Finding: def get_package_vulnerability(self, finding: Finding, raw_finding: dict) -> Finding: vulnerability_details = raw_finding.get("packageVulnerabilityDetails", {}) + vulnerable_packages = vulnerability_details.get("vulnerablePackages", []) vulnerability_packages_descriptions = "\n".join( [ ( @@ -123,14 +125,40 @@ def get_package_vulnerability(self, finding: Finding, raw_finding: dict) -> Find f"\tfixed version: {vulnerability_package.get('fixedInVersion', 'N/A')}\n" f"\tremediation: {vulnerability_package.get('remediation', 'N/A')}\n" ) - for vulnerability_package in vulnerability_details.get("vulnerablePackages", []) + for vulnerability_package in vulnerable_packages ], ) if (vulnerability_id := vulnerability_details.get("vulnerabilityId", None)) is not None: finding.unsaved_vulnerability_ids = [vulnerability_id] vulnerability_source = vulnerability_details.get("source") vulnerability_source_url = vulnerability_details.get("sourceUrl") - # populate fields + # component name/version/file_path from the first vulnerable package + if vulnerable_packages: + finding.component_name = vulnerable_packages[0].get("name") + finding.component_version = vulnerable_packages[0].get("version") + finding.file_path = vulnerable_packages[0].get("filePath") + if settings.V3_FEATURE_LOCATIONS and finding.component_name: + finding.unsaved_locations.append( + LocationData.dependency( + name=finding.component_name, + version=finding.component_version or "", + file_path=finding.file_path or "", + ), + ) + # reference URLs from the advisory + reference_urls = vulnerability_details.get("referenceUrls", []) + if reference_urls: + finding.references = "\n".join(reference_urls) + # publish date from when the vendor first created the advisory + if vendor_created_at := vulnerability_details.get("vendorCreatedAt"): + with contextlib.suppress(ValueError): + finding.publish_date = date_parser.parse(vendor_created_at).date() + # CVSS v3 base score from the vendor-supplied CVSS entries + for cvss_entry in vulnerability_details.get("cvss", []): + if str(cvss_entry.get("version", "")).startswith("3") and cvss_entry.get("baseScore") is not None: + finding.cvssv3_score = float(cvss_entry["baseScore"]) + break + # populate description fields if vulnerability_source is not None and vulnerability_source_url is not None: finding.url = vulnerability_source_url finding.description += ( @@ -149,8 +177,8 @@ def get_code_vulnerability(self, finding: Finding, raw_finding: dict) -> Finding file_path_info = raw_finding.get("filePath", {}) file_name = file_path_info.get("fileName", "N/A") file_path = file_path_info.get("filePath", "N/A") - start_line = file_path_info.get("startLine", "N/A") - end_line = file_path_info.get("endLine", "N/A") + start_line = file_path_info.get("startLine", None) + end_line = file_path_info.get("endLine", None) detector_tags = ", ".join(raw_finding.get("detectorTags", [])) reference_urls = ", ".join(raw_finding.get("referenceUrls", [])) rule_id = raw_finding.get("ruleId", "N/A") @@ -162,6 +190,10 @@ def get_code_vulnerability(self, finding: Finding, raw_finding: dict) -> Finding finding.sast_source_file_path = f"{file_path}{file_name}" finding.line = start_line finding.sast_source_line = start_line + if start_line is None: + start_line = "N/A" + if end_line is None: + end_line = "N/A" finding.description += ( "\n**Additional info**\n" f"CWEs: {string_cwes}\n" @@ -270,9 +302,9 @@ def process_endpoints(self, finding: Finding, raw_finding: dict) -> Finding: endpoints.append(Endpoint(host=endpoint_host)) finding.impact = "\n".join(impact) if settings.V3_FEATURE_LOCATIONS: - finding.unsaved_locations = endpoints + finding.unsaved_locations.extend(endpoints) else: # TODO: Delete this after the move to Locations - finding.unsaved_endpoints = endpoints + finding.unsaved_endpoints.extend(endpoints) return finding diff --git a/dojo/url/api/views.py b/dojo/url/api/views.py index 816e30b60a5..caebd867bec 100644 --- a/dojo/url/api/views.py +++ b/dojo/url/api/views.py @@ -36,3 +36,6 @@ def get_queryset(self) -> QuerySet[URL]: return URL.objects.annotate( active_findings=Coalesce(active_finding_subquery, Value(0)), ) + + def perform_destroy(self, instance): + instance.location.delete() diff --git a/dojo/utils_cascade_delete.py b/dojo/utils_cascade_delete.py index b8c0ee4af66..044c45a539e 100644 --- a/dojo/utils_cascade_delete.py +++ b/dojo/utils_cascade_delete.py @@ -159,27 +159,32 @@ def cascade_delete_related_objects(from_model, instance_pk_query, skip_relations bulk_remove_all_tags(from_model, instance_pk_query) - for m2m_field in from_model._meta.many_to_many: - # Skip tag fields — handled by bulk_remove_all_tags above - if hasattr(m2m_field, "tag_options"): - continue - # Skip if caller already cleaned M2M for this model - if from_model in skip_m2m_for: - continue - through_model = m2m_field.remote_field.through - fk_column = None - for field in through_model._meta.get_fields(): - if hasattr(field, "related_model") and field.related_model is from_model: - fk_column = field.column - break - if fk_column: - filterspec_m2m = {f"{fk_column}__in": models.Subquery(instance_pk_query)} - m2m_count = execute_delete_sql(through_model.objects.filter(**filterspec_m2m)) - if m2m_count: - logger.debug( - "cascade_delete: cleared %d rows from M2M %s", - m2m_count, through_model._meta.db_table, - ) + # Clear all M2M through tables — both forward (from_model._meta.many_to_many) + # and reverse (other models with ManyToManyField pointing to from_model). + # Forward M2M fields use field.remote_field.through, reverse use field.through. + if from_model not in skip_m2m_for: + m2m_through_models = set() + for field_info in from_model._meta.get_fields(): + if hasattr(field_info, "tag_options"): + continue + through = getattr(field_info, "through", None) or getattr(getattr(field_info, "remote_field", None), "through", None) + if through is not None: + m2m_through_models.add(through) + + for through_model in m2m_through_models: + fk_column = None + for field in through_model._meta.get_fields(): + if hasattr(field, "related_model") and field.related_model is from_model: + fk_column = field.column + break + if fk_column: + filterspec_m2m = {f"{fk_column}__in": models.Subquery(instance_pk_query)} + m2m_count = execute_delete_sql(through_model.objects.filter(**filterspec_m2m)) + if m2m_count: + logger.debug( + "cascade_delete: cleared %d rows from M2M %s", + m2m_count, through_model._meta.db_table, + ) # At level 0, do NOT delete root records — the caller handles that # (e.g. via ORM obj.delete() to fire Django signals). diff --git a/scripts/update_performance_test_counts.py b/scripts/update_performance_test_counts.py index f9fd077e0e8..77a2e629e11 100644 --- a/scripts/update_performance_test_counts.py +++ b/scripts/update_performance_test_counts.py @@ -422,6 +422,8 @@ def _extract_call_span(method_content: str, call_name: str) -> tuple[int, int] | "reimport1_async_tasks": "expected_num_async_tasks2", "reimport2_queries": "expected_num_queries3", "reimport2_async_tasks": "expected_num_async_tasks3", + "reimport3_queries": "expected_num_queries4", + "reimport3_async_tasks": "expected_num_async_tasks4", } param_map_deduplication = { "first_import_queries": "expected_num_queries1", diff --git a/unittests/scans/aws_inspector2/aws_inspector2_package_vuln_metadata.json b/unittests/scans/aws_inspector2/aws_inspector2_package_vuln_metadata.json new file mode 100644 index 00000000000..a8fdb2a07c2 --- /dev/null +++ b/unittests/scans/aws_inspector2/aws_inspector2_package_vuln_metadata.json @@ -0,0 +1,3340 @@ +{ + "findings": [ + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000001", + "awsAccountId": "123456789016", + "type": "PACKAGE_VULNERABILITY", + "description": "Due to the design of the name constraint checking algorithm, the processing time of some inputs scale non-linearly with respect to the size of the certificate. This affects programs which validate arbitrary certificate chains.", + "title": "CVE-2025-58187 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "HIGH", + "firstObservedAt": "2025-12-26 14:21:44.742000+01:00", + "lastObservedAt": "2026-03-13 22:38:57.161000+01:00", + "updatedAt": "2026-03-13 22:38:57.161000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789014:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789015:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "stack name", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234568", + "lambda:createdBy": "DeployUser", + "owner_email": "user2@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 7.5, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 7.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-58187", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.25.3", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 7.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-58187", + "vendorSeverity": "HIGH", + "vendorCreatedAt": "2025-10-30 00:16:19+01:00", + "vendorUpdatedAt": "2026-01-29 17:02:27+01:00", + "referenceUrls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-58187", + "https://groups.google.com/g/golang-announce/c/4Emdl2iQ_bI" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.00013 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000002", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "Requests is a HTTP library. Due to a URL parsing issue, Requests releases prior to 2.32.4 may leak .netrc credentials to third parties for specific maliciously-crafted URLs. Users should upgrade to version 2.32.4 to receive a fix. For older versions of Requests, use of the .netrc file can be disabled with `trust_env=False` on one's Requests Session.", + "title": "CVE-2024-47081 - requests", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "MEDIUM", + "firstObservedAt": "2025-06-10 23:43:07.201000+02:00", + "lastObservedAt": "2026-03-07 23:40:17.655000+01:00", + "updatedAt": "2026-03-07 23:40:17.655000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user2@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 5.3, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 5.3, + "scoringVector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:N/A:N", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2024-47081", + "vulnerablePackages": [ + { + "name": "requests", + "version": "2.32.0", + "epoch": 0, + "packageManager": "PYTHON", + "filePath": "python/requests-2.32.0.dist-info/METADATA", + "fixedInVersion": "2.32.4", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12" + }, + { + "name": "requests", + "version": "2.32.0", + "epoch": 0, + "packageManager": "PYTHON", + "filePath": "requirements.txt", + "fixedInVersion": "2.32.4" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 5.3, + "scoringVector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:N/A:N", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2024-47081", + "vendorSeverity": "MEDIUM", + "vendorCreatedAt": "2025-06-09 20:15:24+02:00", + "vendorUpdatedAt": "2025-06-12 18:06:47+02:00", + "referenceUrls": [ + "https://seclists.org/fulldisclosure/2025/Jun/2", + "https://nvd.nist.gov/vuln/detail/CVE-2024-47081", + "https://github.com/psf/requests/commit/96ba401c1296ab1dda74a2365ef36d88f7d144ef", + "https://github.com/psf/requests/pull/6965", + "https://github.com/psf/requests/security/advisories/GHSA-9hjg-9r4m-mvj7" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.00154 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000003", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "The net/url package does not set a limit on the number of query parameters in a query. While the maximum size of query parameters in URLs is generally limited by the maximum request header size, the net/http.Request.ParseForm method can parse large URL-encoded forms. Parsing a large form containing many unique query parameters can cause excessive memory consumption.", + "title": "CVE-2025-61726 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "HIGH", + "firstObservedAt": "2026-01-29 22:42:51.151000+01:00", + "lastObservedAt": "2026-03-07 23:40:17.700000+01:00", + "updatedAt": "2026-03-07 23:40:17.700000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 7.5, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 7.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-61726", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.25.6", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 7.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-61726", + "vendorSeverity": "HIGH", + "vendorCreatedAt": "2026-01-28 21:16:09+01:00", + "vendorUpdatedAt": "2026-02-06 19:47:34+01:00", + "referenceUrls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-61726", + "https://groups.google.com/g/golang-announce/c/Vd2tYVM8eUc" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.00032 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000004", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "Expr is an expression language and expression evaluation for Go. Prior to version 1.17.7, several builtin functions in Expr, including `flatten`, `min`, `max`, `mean`, and `median`, perform recursive traversal over user-provided data structures without enforcing a maximum recursion depth. If the evaluation environment contains deeply nested or cyclic data structures, these functions may recurse indefinitely until exceed the Go runtime stack limit. This results in a stack overflow panic, causing the host application to crash. While exploitability depends on whether an attacker can influence or inject cyclic or pathologically deep data into the evaluation environment, this behavior represents a denial-of-service (DoS) risk and affects overall library robustness. Instead of returning a recoverable evaluation error, the process may terminate unexpectedly. In affected versions, evaluation of expressions that invoke certain builtin functions on untrusted or insufficiently validated data structures can lead to a pro", + "title": "CVE-2025-68156 - github.com/expr-lang/expr", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "HIGH", + "firstObservedAt": "2025-12-26 14:21:44.662000+01:00", + "lastObservedAt": "2026-03-07 23:40:17.764000+01:00", + "updatedAt": "2026-03-07 23:40:17.764000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 7.5, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 7.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-68156", + "vulnerablePackages": [ + { + "name": "github.com/expr-lang/expr", + "version": "v1.17.6", + "epoch": 0, + "packageManager": "GO", + "filePath": "extensions/collector", + "fixedInVersion": "1.17.7", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 7.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-68156", + "vendorSeverity": "HIGH", + "vendorCreatedAt": "2025-12-16 20:16:00+01:00", + "vendorUpdatedAt": "2026-03-05 20:56:33+01:00", + "referenceUrls": [ + "https://github.com/expr-lang/expr/pull/870", + "https://nvd.nist.gov/vuln/detail/CVE-2025-68156", + "https://github.com/expr-lang/expr/security/advisories/GHSA-cfpf-hrx2-8rv6" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.00085 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000005", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "The Parse function permits values other than IPv6 addresses to be included in square brackets within the host component of a URL. RFC 3986 permits IPv6 addresses to be included within the host component, enclosed within square brackets. For example: \"http://[::1]/\". IPv4 addresses and hostnames must not appear within square brackets. Parse did not enforce this requirement.", + "title": "CVE-2025-47912 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "MEDIUM", + "firstObservedAt": "2025-12-26 14:21:44.742000+01:00", + "lastObservedAt": "2026-03-13 22:38:57.160000+01:00", + "updatedAt": "2026-03-13 22:38:57.160000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 5.3, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 5.3, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-47912", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.25.2", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 5.3, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-47912", + "vendorSeverity": "MEDIUM", + "vendorCreatedAt": "2025-10-30 00:16:18+01:00", + "vendorUpdatedAt": "2026-01-29 14:57:18+01:00", + "referenceUrls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-47912", + "https://groups.google.com/g/golang-announce/c/4Emdl2iQ_bI" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.00023 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000006", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "Within HostnameError.Error(), when constructing an error string, there is no limit to the number of hosts that will be printed out. Furthermore, the error string is constructed by repeated string concatenation, leading to quadratic runtime. Therefore, a certificate provided by a malicious actor can result in excessive resource consumption.", + "title": "CVE-2025-61729 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "HIGH", + "firstObservedAt": "2025-12-26 14:21:44.741000+01:00", + "lastObservedAt": "2026-02-18 13:40:45.341000+01:00", + "updatedAt": "2026-02-18 13:40:45.341000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 7.5, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 7.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-61729", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.25.5", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 7.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-61729", + "vendorSeverity": "HIGH", + "vendorCreatedAt": "2025-12-02 20:15:51+01:00", + "vendorUpdatedAt": "2025-12-19 19:25:28+01:00", + "referenceUrls": [ + "https://groups.google.com/g/golang-announce/c/8FJoBkPddm4", + "https://nvd.nist.gov/vuln/detail/CVE-2025-61729" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.00017 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000007", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "During the TLS 1.3 handshake if multiple messages are sent in records that span encryption level boundaries (for instance the Client Hello and Encrypted Extensions messages), the subsequent messages may be processed before the encryption level changes. This can cause some minor information disclosure if a network-local attacker can inject messages during the handshake.", + "title": "CVE-2025-61730 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "MEDIUM", + "firstObservedAt": "2026-01-29 22:42:51.149000+01:00", + "lastObservedAt": "2026-03-07 23:40:17.699000+01:00", + "updatedAt": "2026-03-07 23:40:17.699000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 5.3, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 5.3, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-61730", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.25.6", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 5.3, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-61730", + "vendorSeverity": "MEDIUM", + "vendorCreatedAt": "2026-01-28 21:16:09+01:00", + "vendorUpdatedAt": "2026-02-03 21:36:41+01:00", + "referenceUrls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-61730", + "https://groups.google.com/g/golang-announce/c/Vd2tYVM8eUc" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 7e-05 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000008", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "Validating certificate chains which contain DSA public keys can cause programs to panic, due to a interface cast that assumes they implement the Equal method. This affects programs which validate arbitrary certificate chains.", + "title": "CVE-2025-58188 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "HIGH", + "firstObservedAt": "2025-12-26 14:21:44.743000+01:00", + "lastObservedAt": "2026-03-13 22:38:57.161000+01:00", + "updatedAt": "2026-03-13 22:38:57.161000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 7.5, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 7.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-58188", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.25.2", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 7.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-58188", + "vendorSeverity": "HIGH", + "vendorCreatedAt": "2025-10-30 00:16:19+01:00", + "vendorUpdatedAt": "2026-01-29 16:55:11+01:00", + "referenceUrls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-58188", + "https://groups.google.com/g/golang-announce/c/4Emdl2iQ_bI" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 7e-05 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000009", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "On Unix platforms, when listing the contents of a directory using File.ReadDir or File.Readdir the returned FileInfo could reference a file outside of the Root in which the File was opened. The impact of this escape is limited to reading metadata provided by lstat from arbitrary locations on the filesystem without permitting reading or writing files outside the root.", + "title": "CVE-2026-27139 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "LOW", + "firstObservedAt": "2026-03-07 23:40:17.699000+01:00", + "lastObservedAt": "2026-03-13 22:38:57.160000+01:00", + "updatedAt": "2026-03-13 22:38:57.160000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 2.5, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 2.5, + "scoringVector": "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2026-27139", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.26.1", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 2.5, + "scoringVector": "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2026-27139", + "vendorSeverity": "LOW", + "vendorCreatedAt": "2026-03-06 23:16:01+01:00", + "vendorUpdatedAt": "2026-03-09 16:15:57+01:00", + "referenceUrls": [ + "https://groups.google.com/g/golang-announce/c/EdhZqrQ98hk", + "https://nvd.nist.gov/vuln/detail/CVE-2026-27139" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 5e-05 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/0000000000000000000000000000000a", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "archive/zip uses a super-linear file name indexing algorithm that is invoked the first time a file in an archive is opened. This can lead to a denial of service when consuming a maliciously constructed ZIP archive.", + "title": "CVE-2025-61728 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "MEDIUM", + "firstObservedAt": "2026-01-29 22:42:51.148000+01:00", + "lastObservedAt": "2026-03-13 22:38:57.159000+01:00", + "updatedAt": "2026-03-13 22:38:57.159000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 6.5, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 6.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-61728", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.25.6", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 6.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-61728", + "vendorSeverity": "MEDIUM", + "vendorCreatedAt": "2026-01-28 21:16:09+01:00", + "vendorUpdatedAt": "2026-02-06 19:45:10+01:00", + "referenceUrls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-61728", + "https://groups.google.com/g/golang-announce/c/Vd2tYVM8eUc" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.00022 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/0000000000000000000000000000000b", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "url.Parse insufficiently validated the host/authority component and accepted some invalid URLs.", + "title": "CVE-2026-25679 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "HIGH", + "firstObservedAt": "2026-03-07 23:40:17.699000+01:00", + "lastObservedAt": "2026-03-13 22:38:57.160000+01:00", + "updatedAt": "2026-03-13 22:38:57.160000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 7.5, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 7.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2026-25679", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.26.1", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 7.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2026-25679", + "vendorSeverity": "HIGH", + "vendorCreatedAt": "2026-03-06 23:16:00+01:00", + "vendorUpdatedAt": "2026-03-10 19:18:37+01:00", + "referenceUrls": [ + "https://groups.google.com/g/golang-announce/c/EdhZqrQ98hk", + "https://nvd.nist.gov/vuln/detail/CVE-2026-25679" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.00072 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/0000000000000000000000000000000c", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "OpenTelemetry-Go is the Go implementation of OpenTelemetry. The OpenTelemetry Go SDK in version v1.20.0-1.39.0 is vulnerable to Path Hijacking (Untrusted Search Paths) on macOS/Darwin systems. The resource detection code in sdk/resource/host_id.go executes the ioreg system command using a search path. An attacker with the ability to locally modify the PATH environment variable can achieve Arbitrary Code Execution (ACE) within the context of the application. A fix was released with v1.40.0.", + "title": "CVE-2026-24051 - go.opentelemetry.io/otel/sdk", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "HIGH", + "firstObservedAt": "2026-02-20 22:48:50.875000+01:00", + "lastObservedAt": "2026-03-07 23:40:17.764000+01:00", + "updatedAt": "2026-03-07 23:40:17.764000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 7.0, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 7.0, + "scoringVector": "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2026-24051", + "vulnerablePackages": [ + { + "name": "go.opentelemetry.io/otel/sdk", + "version": "v1.38.0", + "epoch": 0, + "packageManager": "GO", + "filePath": "extensions/collector", + "fixedInVersion": "1.40.0", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 7.0, + "scoringVector": "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2026-24051", + "vendorSeverity": "HIGH", + "vendorCreatedAt": "2026-02-03 00:16:07+01:00", + "vendorUpdatedAt": "2026-02-27 21:32:10+01:00", + "referenceUrls": [ + "https://github.com/open-telemetry/opentelemetry-go/security/advisories/GHSA-9h8m-3fm2-qjrq", + "https://github.com/open-telemetry/opentelemetry-go/commit/d45961bcda453fcbdb6469c22d6e88a1f9970a53", + "https://nvd.nist.gov/vuln/detail/CVE-2026-24051" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 7e-05 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/0000000000000000000000000000000d", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "Despite HTTP headers having a default limit of 1MB, the number of cookies that can be parsed does not have a limit. By sending a lot of very small cookies such as \"a=;\", an attacker can make an HTTP server allocate a large amount of structs, causing large memory consumption.", + "title": "CVE-2025-58186 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "MEDIUM", + "firstObservedAt": "2025-12-26 14:21:44.745000+01:00", + "lastObservedAt": "2026-03-13 22:38:57.161000+01:00", + "updatedAt": "2026-03-13 22:38:57.161000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 5.3, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 5.3, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-58186", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.25.2", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 5.3, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-58186", + "vendorSeverity": "MEDIUM", + "vendorCreatedAt": "2025-10-30 00:16:19+01:00", + "vendorUpdatedAt": "2025-11-04 23:16:33+01:00", + "referenceUrls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-58186", + "https://groups.google.com/g/golang-announce/c/4Emdl2iQ_bI" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.00029 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/0000000000000000000000000000000e", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "Parsing a maliciously crafted DER payload could allocate large amounts of memory, causing memory exhaustion.", + "title": "CVE-2025-58185 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "MEDIUM", + "firstObservedAt": "2025-12-26 14:21:44.743000+01:00", + "lastObservedAt": "2026-03-13 22:38:57.161000+01:00", + "updatedAt": "2026-03-13 22:38:57.161000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 5.3, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 5.3, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-58185", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.25.2", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 5.3, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-58185", + "vendorSeverity": "MEDIUM", + "vendorCreatedAt": "2025-10-30 00:16:19+01:00", + "vendorUpdatedAt": "2026-02-06 21:26:41+01:00", + "referenceUrls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-58185", + "https://groups.google.com/g/golang-announce/c/4Emdl2iQ_bI" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.00024 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/0000000000000000000000000000000f", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "Actions which insert URLs into the content attribute of HTML meta tags are not escaped. This can allow XSS if the meta tag also has an http-equiv attribute with the value \"refresh\". A new GODEBUG setting has been added, htmlmetacontenturlescape, which can be used to disable escaping URLs in actions in the meta content attribute which follow \"url=\" by setting htmlmetacontenturlescape=0.", + "title": "CVE-2026-27142 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "HIGH", + "firstObservedAt": "2026-03-07 23:40:17.699000+01:00", + "lastObservedAt": "2026-03-13 22:38:57.161000+01:00", + "updatedAt": "2026-03-13 22:38:57.161000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 7.5, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 7.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2026-27142", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.26.1", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 7.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2026-27142", + "vendorSeverity": "HIGH", + "vendorCreatedAt": "2026-03-06 23:16:01+01:00", + "vendorUpdatedAt": "2026-03-10 19:18:44+01:00", + "referenceUrls": [ + "https://groups.google.com/g/golang-announce/c/EdhZqrQ98hk", + "https://nvd.nist.gov/vuln/detail/CVE-2026-27142" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.00061 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000010", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "During session resumption in crypto/tls, if the underlying Config has its ClientCAs or RootCAs fields mutated between the initial handshake and the resumed handshake, the resumed handshake may succeed when it should have failed. This may happen when a user calls Config.Clone and mutates the returned Config, or uses Config.GetConfigForClient. This can cause a client to resume a session with a server that it would not have resumed with during the initial handshake, or cause a server to resume a session with a client that it would not have resumed with during the initial handshake.", + "title": "CVE-2025-68121 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "CRITICAL", + "firstObservedAt": "2026-02-06 23:49:39.109000+01:00", + "lastObservedAt": "2026-03-13 22:38:57.160000+01:00", + "updatedAt": "2026-03-13 22:38:57.160000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 10.0, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 10.0, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-68121", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.26.0-rc.3", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 10.0, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-68121", + "vendorSeverity": "CRITICAL", + "vendorCreatedAt": "2026-02-05 19:16:10+01:00", + "vendorUpdatedAt": "2026-02-20 18:25:50+01:00", + "referenceUrls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-68121", + "https://groups.google.com/g/golang-announce/c/K09ubi9FQFk" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.0001 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000011", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "Black is the uncompromising Python code formatter. Prior to 26.3.1, Black writes a cache file, the name of which is computed from various formatting options. The value of the --python-cell-magics option was placed in the filename without sanitization, which allowed an attacker who controls the value of this argument to write cache files to arbitrary file system locations. Fixed in Black 26.3.1.", + "title": "CVE-2026-32274 - black", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "HIGH", + "firstObservedAt": "2026-03-13 22:38:57.193000+01:00", + "lastObservedAt": "2026-03-13 22:38:57.193000+01:00", + "updatedAt": "2026-03-13 22:38:57.193000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2026-32274", + "vulnerablePackages": [ + { + "name": "black", + "version": "24.10.0", + "epoch": 0, + "packageManager": "PYTHON", + "filePath": "requirements-dev.txt", + "fixedInVersion": "26.3.1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 8.7, + "scoringVector": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X", + "version": "4.0", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2026-32274", + "vendorSeverity": "HIGH", + "vendorCreatedAt": "2026-03-12 21:16:06+01:00", + "vendorUpdatedAt": "2026-03-12 22:07:53+01:00", + "referenceUrls": [ + "https://github.com/psf/black/releases/tag/26.3.1", + "https://github.com/psf/black/security/advisories/GHSA-3936-cmfr-pm3m", + "https://nvd.nist.gov/vuln/detail/CVE-2026-32274", + "https://github.com/psf/black/commit/4937fe6cf241139ddbfc16b0bdbb5b422798909d", + "https://github.com/psf/black/pull/5038" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "YES", + "exploitabilityDetails": { + "lastKnownExploitAt": "2026-03-12 22:34:42+01:00" + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000012", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "If the PATH environment variable contains paths which are executables (rather than just directories), passing certain strings to LookPath (\"\", \".\", and \"..\"), can result in the binaries listed in the PATH being unexpectedly returned.", + "title": "CVE-2025-47906 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "MEDIUM", + "firstObservedAt": "2025-12-26 14:21:44.744000+01:00", + "lastObservedAt": "2026-03-07 23:40:17.699000+01:00", + "updatedAt": "2026-03-07 23:40:17.699000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 6.5, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 6.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:L", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-47906", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.24.6", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 6.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:L", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-47906", + "vendorSeverity": "MEDIUM", + "vendorCreatedAt": "2025-09-18 21:15:37+02:00", + "vendorUpdatedAt": "2026-01-27 20:56:17+01:00", + "referenceUrls": [ + "https://groups.google.com/g/golang-announce/c/x5MKroML2yM", + "https://nvd.nist.gov/vuln/detail/CVE-2025-47906" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.00028 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000013", + "awsAccountId": "123456789012", + "type": "CODE_VULNERABILITY", + "description": "User-provided inputs must be sanitized before they are logged. An attacker can use unsanitized input to break a log's integrity, forge log entries, or bypass log monitors.", + "title": "CWE-117,93 - Log injection", + "remediation": { + "recommendation": { + "text": "You have a log statement that might use unsanitized input originating from HTTP requests or AWS Lambda sources. Depending on the context, this could result in:\n\n1. A log injection attack that breaks log integrity, forges log entries, or bypasses monitors that use the logs. To increase the security of your code, sanitize your inputs before logging them. [Learn more](https://cwe.mitre.org/data/definitions/117.html)\n\n2. A sensitive information leak that exposes users' credentials, private information, or identifying information to an attacker. To preserve privacy in your code, redact sensitive user information before logging it. [Learn more](https://cwe.mitre.org/data/definitions/532.html)" + } + }, + "severity": "HIGH", + "firstObservedAt": "2026-02-18 12:01:00.079000+01:00", + "lastObservedAt": "2026-02-18 13:41:11.095000+01:00", + "updatedAt": "2026-02-18 13:41:11.095000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "codeVulnerabilityDetails": { + "filePath": { + "fileName": "api_client.py", + "filePath": "src/project_api/service/api_client.py", + "startLine": 268, + "endLine": 268 + }, + "detectorTags": [ + "data-integrity", + "injection", + "security", + "owasp-top10" + ], + "referenceUrls": [], + "ruleId": "python-log-injection", + "detectorId": "python/log-injection@v1.0", + "detectorName": "Log injection", + "cwes": [ + "CWE-117", + "CWE-93" + ] + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000014", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "cryptography is a package designed to expose cryptographic primitives and recipes to Python developers. Prior to 46.0.5, the public_key_from_numbers (or EllipticCurvePublicNumbers.public_key()), EllipticCurvePublicNumbers.public_key(), load_der_public_key() and load_pem_public_key() functions do not verify that the point belongs to the expected prime-order subgroup of the curve. This missing validation allows an attacker to provide a public key point P from a small-order subgroup. This can lead to security issues in various situations, such as the most commonly used signature verification (ECDSA) and shared key negotiation (ECDH). When the victim computes the shared secret as S = [victim_private_key]P via ECDH, this leaks information about victim_private_key mod (small_subgroup_order). For curves with cofactor > 1, this reveals the least significant bits of the private key. When these weak public keys are used in ECDSA , it's easy to forge signatures on the small subgroup. Only SECT curves are impacted by thi", + "title": "CVE-2026-26007 - cryptography", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "MEDIUM", + "firstObservedAt": "2026-02-11 22:36:39.094000+01:00", + "lastObservedAt": "2026-03-13 22:38:57.193000+01:00", + "updatedAt": "2026-03-13 22:38:57.193000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 6.5, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 6.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2026-26007", + "vulnerablePackages": [ + { + "name": "cryptography", + "version": "43.0.1", + "epoch": 0, + "packageManager": "PYTHON", + "filePath": "requirements.txt", + "fixedInVersion": "46.0.5" + }, + { + "name": "cryptography", + "version": "43.0.1", + "epoch": 0, + "packageManager": "PYTHON", + "filePath": "python/cryptography-43.0.1.dist-info/METADATA", + "fixedInVersion": "46.0.5", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 6.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N", + "version": "3.1", + "source": "NVD" + }, + { + "baseScore": 8.2, + "scoringVector": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X", + "version": "4.0", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2026-26007", + "vendorSeverity": "MEDIUM", + "vendorCreatedAt": "2026-02-10 23:17:00+01:00", + "vendorUpdatedAt": "2026-02-23 16:40:33+01:00", + "referenceUrls": [ + "https://github.com/pyca/cryptography/commit/0eebb9dbb6343d9bc1d91e5a2482ed4e054a6d8c", + "https://github.com/pyca/cryptography/security/advisories/GHSA-r6ph-v2qm-q3c2", + "https://nvd.nist.gov/vuln/detail/CVE-2026-26007" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 7e-05 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000015", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "Issue summary: Clients using RFC7250 Raw Public Keys (RPKs) to authenticate a server may fail to notice that the server was not authenticated, because handshakes don't abort as expected when the SSL_VERIFY_PEER verification mode is set.\n\nImpact summary: TLS and DTLS connections using raw public keys may be vulnerable to man-in-middle attacks when server authentication failure is not detected by clients.\n\nRPKs are disabled by default in both TLS clients and TLS servers. The issue only arises when TLS clients explicitly enable RPK use by the server, and the server, likewise, enables sending of an RPK instead of an X.509 certificate chain. The affected clients are those that then rely on the handshake to fail when the server's RPK fails to match one of the expected public keys, by setting the verification mode to SSL_VERIFY_PEER.\n\nClients that enable server-side raw public keys can still find out that raw public key verification failed by calling SSL_get_verify_result(), and those that do, and take appropriate a", + "title": "CVE-2024-12797 - cryptography", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "MEDIUM", + "firstObservedAt": "2025-02-12 21:55:49.747000+01:00", + "lastObservedAt": "2026-03-13 22:38:57.193000+01:00", + "updatedAt": "2026-03-13 22:38:57.193000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 6.3, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 6.3, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:L", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2024-12797", + "vulnerablePackages": [ + { + "name": "cryptography", + "version": "43.0.1", + "epoch": 0, + "packageManager": "PYTHON", + "filePath": "requirements.txt", + "fixedInVersion": "44.0.1" + }, + { + "name": "cryptography", + "version": "43.0.1", + "epoch": 0, + "packageManager": "PYTHON", + "filePath": "python/cryptography-43.0.1.dist-info/METADATA", + "fixedInVersion": "44.0.1", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 6.3, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:L", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2024-12797", + "vendorSeverity": "MEDIUM", + "vendorCreatedAt": "2025-02-11 17:15:38+01:00", + "vendorUpdatedAt": "2025-02-18 15:15:27+01:00", + "referenceUrls": [ + "https://github.com/openssl/openssl/commit/798779d43494549b611233f92652f0da5328fbe7", + "https://github.com/openssl/openssl/commit/87ebd203feffcf92ad5889df92f90bb0ee10a699", + "https://nvd.nist.gov/vuln/detail/CVE-2024-12797", + "https://openssl-library.org/news/secadv/20250211.txt", + "https://github.com/openssl/openssl/commit/738d4f9fdeaad57660dcba50a619fafced3fd5e9" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.00869 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000016", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "An excluded subdomain constraint in a certificate chain does not restrict the usage of wildcard SANs in the leaf certificate. For example a constraint that excludes the subdomain test.example.com does not prevent a leaf certificate from claiming the SAN *.example.com.", + "title": "CVE-2025-61727 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "MEDIUM", + "firstObservedAt": "2025-12-26 14:21:44.740000+01:00", + "lastObservedAt": "2026-03-07 23:40:17.698000+01:00", + "updatedAt": "2026-03-07 23:40:17.698000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 6.5, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 6.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-61727", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.25.5", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 6.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-61727", + "vendorSeverity": "MEDIUM", + "vendorCreatedAt": "2025-12-03 21:16:25+01:00", + "vendorUpdatedAt": "2025-12-18 21:15:10+01:00", + "referenceUrls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-61727", + "https://groups.google.com/g/golang-announce/c/8FJoBkPddm4" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.00011 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000017", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "When Conn.Handshake fails during ALPN negotiation the error contains attacker controlled information (the ALPN protocols sent by the client) which is not escaped.", + "title": "CVE-2025-58189 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "MEDIUM", + "firstObservedAt": "2025-12-26 14:21:44.742000+01:00", + "lastObservedAt": "2026-03-13 22:38:57.161000+01:00", + "updatedAt": "2026-03-13 22:38:57.161000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 5.3, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 5.3, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-58189", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.25.2", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 5.3, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-58189", + "vendorSeverity": "MEDIUM", + "vendorCreatedAt": "2025-10-30 00:16:19+01:00", + "vendorUpdatedAt": "2026-01-29 16:49:24+01:00", + "referenceUrls": [ + "https://groups.google.com/g/golang-announce/c/4Emdl2iQ_bI", + "https://nvd.nist.gov/vuln/detail/CVE-2025-58189" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 9e-05 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000018", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "The processing time for parsing some invalid inputs scales non-linearly with respect to the size of the input. This affects programs which parse untrusted PEM inputs.", + "title": "CVE-2025-61723 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "HIGH", + "firstObservedAt": "2025-12-26 14:21:44.744000+01:00", + "lastObservedAt": "2026-03-13 22:38:57.161000+01:00", + "updatedAt": "2026-03-13 22:38:57.161000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 7.5, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 7.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-61723", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.25.2", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 7.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-61723", + "vendorSeverity": "HIGH", + "vendorCreatedAt": "2025-10-30 00:16:19+01:00", + "vendorUpdatedAt": "2026-01-29 16:49:05+01:00", + "referenceUrls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-61723", + "https://groups.google.com/g/golang-announce/c/4Emdl2iQ_bI" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.00028 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/00000000000000000000000000000019", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "The Reader.ReadResponse function constructs a response string through repeated string concatenation of lines. When the number of lines in a response is large, this can cause excessive CPU consumption.", + "title": "CVE-2025-61724 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "MEDIUM", + "firstObservedAt": "2025-12-26 14:21:44.744000+01:00", + "lastObservedAt": "2026-03-13 22:38:57.161000+01:00", + "updatedAt": "2026-03-13 22:38:57.161000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 5.3, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 5.3, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-61724", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.25.2", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 5.3, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-61724", + "vendorSeverity": "MEDIUM", + "vendorCreatedAt": "2025-10-30 00:16:20+01:00", + "vendorUpdatedAt": "2026-01-29 16:30:53+01:00", + "referenceUrls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-61724", + "https://groups.google.com/g/golang-announce/c/4Emdl2iQ_bI" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.00016 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/0000000000000000000000000000001a", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "tar.Reader does not set a maximum size on the number of sparse region data blocks in GNU tar pax 1.0 sparse files. A maliciously-crafted archive containing a large number of sparse regions can cause a Reader to read an unbounded amount of data from the archive into memory. When reading from a compressed source, a small compressed input can result in large allocations.", + "title": "CVE-2025-58183 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "MEDIUM", + "firstObservedAt": "2025-12-26 14:21:44.745000+01:00", + "lastObservedAt": "2026-03-13 22:38:57.161000+01:00", + "updatedAt": "2026-03-13 22:38:57.161000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 4.3, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 4.3, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-58183", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.25.2", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 4.3, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-58183", + "vendorSeverity": "MEDIUM", + "vendorCreatedAt": "2025-10-30 00:16:19+01:00", + "vendorUpdatedAt": "2025-11-04 23:16:33+01:00", + "referenceUrls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-58183", + "https://groups.google.com/g/golang-announce/c/4Emdl2iQ_bI" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.00013 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/0000000000000000000000000000001b", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "Cancelling a query (e.g. by cancelling the context passed to one of the query methods) during a call to the Scan method of the returned Rows can result in unexpected results if other queries are being made in parallel. This can result in a race condition that may overwrite the expected results with those of another query, causing the call to Scan to return either unexpected results from the other query or an error.", + "title": "CVE-2025-47907 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "HIGH", + "firstObservedAt": "2025-12-26 14:21:44.743000+01:00", + "lastObservedAt": "2026-03-07 23:40:17.699000+01:00", + "updatedAt": "2026-03-07 23:40:17.699000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 7.0, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 7.0, + "scoringVector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:L", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-47907", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.24.6", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 7.0, + "scoringVector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:L", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-47907", + "vendorSeverity": "HIGH", + "vendorCreatedAt": "2025-08-07 18:15:30+02:00", + "vendorUpdatedAt": "2026-01-29 20:11:50+01:00", + "referenceUrls": [ + "https://groups.google.com/g/golang-announce/c/x5MKroML2yM", + "https://nvd.nist.gov/vuln/detail/CVE-2025-47907" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.00012 + } + }, + { + "findingArn": "arn:aws:inspector2:us-west-2:123456789012:finding/0000000000000000000000000000001c", + "awsAccountId": "123456789012", + "type": "PACKAGE_VULNERABILITY", + "description": "The ParseAddress function constructs domain-literal address components through repeated string concatenation. When parsing large domain-literal components, this can cause excessive CPU consumption.", + "title": "CVE-2025-61725 - go/stdlib", + "remediation": { + "recommendation": { + "text": "None Provided" + } + }, + "severity": "HIGH", + "firstObservedAt": "2025-12-26 14:21:44.745000+01:00", + "lastObservedAt": "2026-03-13 22:38:57.161000+01:00", + "updatedAt": "2026-03-13 22:38:57.161000+01:00", + "status": "ACTIVE", + "resources": [ + { + "type": "AWS_LAMBDA_FUNCTION", + "id": "arn:aws:lambda:us-west-2:123456789012:function:web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD:$LATEST", + "partition": "aws", + "region": "us-west-2", + "tags": { + "InspectorCodeExclusion": "None", + "InspectorExclusion": "None", + "aws:cloudformation:logical-id": "healthCheck", + "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-west-2:123456789012:stack/web-user-manager-api-stage/a1b2c3d4-e5f6-7890-abcd-ef1234567890", + "aws:cloudformation:stack-name": "web-user-manager-api-stage", + "deployed_at": "2026-02-18T12:38:52Z", + "deployed_by": "user1@example.com", + "env": "stage", + "environment": "stage", + "gitlab_ci_job": "1234567", + "lambda:createdBy": "SAM", + "owner_email": "user1@example.com", + "project": "web-user-manager-api", + "service": "web-user-manager-api", + "team": "backend-team-web-user-manager" + }, + "details": { + "awsLambdaFunction": { + "functionName": "web-user-manager-api-stage-healthCheck-EXAMPLE1ABCD", + "runtime": "PYTHON_3_12", + "codeSha256": "abc123def456ghi789jkl012mno345pqr678stu901vw==", + "version": "$LATEST", + "executionRoleArn": "arn:aws:iam::123456789012:role/web-user-manager-api-stage-LambdaExecutionRole-EXAMPLE12345", + "layers": [ + "arn:aws:lambda:us-west-2:123456789012:layer:web-user-manager-api-stage:12", + "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + ], + "vpcConfig": { + "subnetIds": [ + "subnet-03709ee21c427acf6", + "subnet-0b6f7a6987b5e689d", + "subnet-0123c6fff46639b68" + ], + "securityGroupIds": [ + "sg-0fd8fe5dae2694a95" + ], + "vpcId": "vpc-055aa15ae33f4297b" + }, + "packageType": "ZIP", + "architectures": [ + "X86_64" + ], + "lastModifiedAt": "2026-02-18 13:40:35.830000+01:00" + } + } + } + ], + "inspectorScore": 7.5, + "inspectorScoreDetails": { + "adjustedCvss": { + "scoreSource": "NVD", + "cvssSource": "NVD", + "version": "3.1", + "score": 7.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "adjustments": [] + } + }, + "packageVulnerabilityDetails": { + "vulnerabilityId": "CVE-2025-61725", + "vulnerablePackages": [ + { + "name": "go/stdlib", + "version": "1.24.4", + "epoch": 0, + "packageManager": "GENERIC", + "filePath": "extensions/collector", + "fixedInVersion": "1.25.2", + "sourceLambdaLayerArn": "arn:aws:lambda:us-west-2:123456789013:layer:opentelemetry-collector-amd64-0_19_0:1" + } + ], + "source": "NVD", + "cvss": [ + { + "baseScore": 7.5, + "scoringVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + "version": "3.1", + "source": "NVD" + } + ], + "relatedVulnerabilities": [], + "sourceUrl": "https://nvd.nist.gov/vuln/detail/CVE-2025-61725", + "vendorSeverity": "HIGH", + "vendorCreatedAt": "2025-10-30 00:16:20+01:00", + "vendorUpdatedAt": "2025-12-09 19:15:56+01:00", + "referenceUrls": [ + "https://nvd.nist.gov/vuln/detail/CVE-2025-61725", + "https://groups.google.com/g/golang-announce/c/4Emdl2iQ_bI" + ] + }, + "fixAvailable": "YES", + "exploitAvailable": "NO", + "epss": { + "score": 0.0003 + } + } + ] +} diff --git a/unittests/scans/stackhawk/stackhawk_empty.json b/unittests/scans/stackhawk/stackhawk_empty.json new file mode 100644 index 00000000000..056193baafe --- /dev/null +++ b/unittests/scans/stackhawk/stackhawk_empty.json @@ -0,0 +1,32 @@ +{ + "service": "StackHawk", + "scanCompleted": { + "scan": { + "comment defect dojo team": "This is an empty StackHawk scan results", + "id": "e2ff5651-7eef-47e9-b743-0c2f7d861e27", + "hawkscanVersion": "2.1.1", + "env": "Development", + "status": "COMPLETED", + "application": "Secured Application", + "startedTimestamp": "2022-02-16T23:07:19.575Z", + "scanURL": "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27" + }, + "scanDuration": "21", + "spiderDuration": "45", + "completedScanStats": { + "urlsCount": "31", + "duration": "66", + "scanResultsStats": { + "totalCount": "0", + "lowCount": "0", + "mediumCount": "0", + "highCount": "0", + "lowTriagedCount": "0", + "mediumTriagedCount": "0", + "highTriagedCount": "0" + } + }, + "findings": [ + ] + } +} diff --git a/unittests/test_importers_performance.py b/unittests/test_importers_performance.py index a3dfd37074e..1a9c9fc137d 100644 --- a/unittests/test_importers_performance.py +++ b/unittests/test_importers_performance.py @@ -51,6 +51,7 @@ STACK_HAWK_FILENAME = get_unit_tests_scans_path("stackhawk") / "stackhawk_many_vul_without_duplicated_findings.json" STACK_HAWK_SUBSET_FILENAME = get_unit_tests_scans_path("stackhawk") / "stackhawk_many_vul_without_duplicated_findings_subset.json" +STACK_HAWK_EMPTY = get_unit_tests_scans_path("stackhawk") / "stackhawk_empty.json" STACK_HAWK_SCAN_TYPE = "StackHawk HawkScan" @@ -126,12 +127,17 @@ def _import_reimport_performance( expected_num_async_tasks2, expected_num_queries3, expected_num_async_tasks3, + expected_num_queries4, + expected_num_async_tasks4, scan_file1, scan_file2, scan_file3, + scan_file4, scan_type, product_name, engagement_name, + *, + close_old_findings4=False, ): """ Test import/reimport/reimport performance with specified scan files and scan type. @@ -195,6 +201,7 @@ def _import_reimport_performance( "verified": True, "sync": True, "scan_type": scan_type, + "service": "Secured Application", "tags": ["performance-test-reimport", "reimport-tag-in-param", "reimport-go-faster"], "apply_tags_to_findings": True, } @@ -224,10 +231,44 @@ def _import_reimport_performance( "verified": True, "sync": True, "scan_type": scan_type, + "service": "Secured Application", } reimporter = DefaultReImporter(**reimport_options) test, _, _len_new_findings, _len_closed_findings, _, _, _ = reimporter.process_scan(scan) + # Fourth import (reimport again, empty report) + # Each assertion context manager is wrapped in its own subTest so that if one fails, the others still run. + # This allows us to see all count mismatches in a single test run, making it easier to fix + # all incorrect expected values at once rather than fixing them one at a time. + # Nested with statements are intentional - each assertion needs its own subTest wrapper. + with ( # noqa: SIM117 + self.subTest("reimport3"), impersonate(Dojo_User.objects.get(username="admin")), + scan_file4.open(encoding="utf-8") as scan, + ): + with self.subTest(step="reimport3", metric="queries"): + with self.assertNumQueries(expected_num_queries4): + with self.subTest(step="reimport3", metric="async_tasks"): + with self._assertNumAsyncTask(expected_num_async_tasks4): + reimport_options = { + "test": test, + "user": lead, + "lead": lead, + "scan_date": None, + "minimum_severity": "Info", + "active": True, + "verified": True, + "sync": True, + "scan_type": scan_type, + # StackHawk parser sets the service field causing close old findings to fail if we do not specify the service field + # This is a big problem that needs fixing. Parsers should not set the service field. + "service": "Secured Application", + "close_old_findings": close_old_findings4, + } + reimporter = DefaultReImporter(**reimport_options) + test, _, len_new_findings4, len_closed_findings4, _, _, _ = reimporter.process_scan(scan) + logger.info("Step 4: new=%s closed=%s", len_new_findings4, len_closed_findings4) + self.assertGreater(len_closed_findings4, 0, "Step 4 (empty reimport with close_old_findings=True) should close findings") + @tag("performance") @skip_unless_v2 @@ -235,7 +276,7 @@ class TestDojoImporterPerformanceSmall(TestDojoImporterPerformanceBase): """Performance tests using small sample files (StackHawk, ~6 findings).""" - def _import_reimport_performance(self, expected_num_queries1, expected_num_async_tasks1, expected_num_queries2, expected_num_async_tasks2, expected_num_queries3, expected_num_async_tasks3): + def _import_reimport_performance(self, expected_num_queries1, expected_num_async_tasks1, expected_num_queries2, expected_num_async_tasks2, expected_num_queries3, expected_num_async_tasks3, expected_num_queries4, expected_num_async_tasks4): """ Log output can be quite large as when the assertNumQueries fails, all queries are printed. It could be usefule to capture the output in `less`: @@ -251,12 +292,16 @@ def _import_reimport_performance(self, expected_num_queries1, expected_num_async expected_num_async_tasks2, expected_num_queries3, expected_num_async_tasks3, + expected_num_queries4, + expected_num_async_tasks4, scan_file1=STACK_HAWK_SUBSET_FILENAME, scan_file2=STACK_HAWK_FILENAME, scan_file3=STACK_HAWK_SUBSET_FILENAME, + scan_file4=STACK_HAWK_EMPTY, scan_type=STACK_HAWK_SCAN_TYPE, product_name="TestDojoDefaultImporter", engagement_name="Test Create Engagement", + close_old_findings4=True, ) @override_settings(ENABLE_AUDITLOG=True) @@ -486,7 +531,7 @@ def setUp(self): for model in [Location, LocationFindingReference]: ContentType.objects.get_for_model(model) - def _import_reimport_performance(self, expected_num_queries1, expected_num_async_tasks1, expected_num_queries2, expected_num_async_tasks2, expected_num_queries3, expected_num_async_tasks3): + def _import_reimport_performance(self, expected_num_queries1, expected_num_async_tasks1, expected_num_queries2, expected_num_async_tasks2, expected_num_queries3, expected_num_async_tasks3, expected_num_queries4, expected_num_async_tasks4): r""" Log output can be quite large as when the assertNumQueries fails, all queries are printed. It could be useful to capture the output in `less`: @@ -502,12 +547,16 @@ def _import_reimport_performance(self, expected_num_queries1, expected_num_async expected_num_async_tasks2, expected_num_queries3, expected_num_async_tasks3, + expected_num_queries4, + expected_num_async_tasks4, scan_file1=STACK_HAWK_SUBSET_FILENAME, scan_file2=STACK_HAWK_FILENAME, scan_file3=STACK_HAWK_SUBSET_FILENAME, + scan_file4=STACK_HAWK_EMPTY, scan_type=STACK_HAWK_SCAN_TYPE, product_name="TestDojoDefaultImporterLocations", engagement_name="Test Create Engagement Locations", + close_old_findings4=True, ) @override_settings(ENABLE_AUDITLOG=True) @@ -526,6 +575,8 @@ def test_import_reimport_reimport_performance_pghistory_async(self): expected_num_async_tasks2=17, expected_num_queries3=346, expected_num_async_tasks3=16, + expected_num_queries4=212, + expected_num_async_tasks4=6, ) @override_settings(ENABLE_AUDITLOG=True) @@ -548,6 +599,8 @@ def test_import_reimport_reimport_performance_pghistory_no_async(self): expected_num_async_tasks2=17, expected_num_queries3=355, expected_num_async_tasks3=16, + expected_num_queries4=212, + expected_num_async_tasks4=6, ) @override_settings(ENABLE_AUDITLOG=True) @@ -571,6 +624,8 @@ def test_import_reimport_reimport_performance_pghistory_no_async_with_product_gr expected_num_async_tasks2=19, expected_num_queries3=359, expected_num_async_tasks3=18, + expected_num_queries4=222, + expected_num_async_tasks4=8, ) def _deduplication_performance(self, expected_num_queries1, expected_num_async_tasks1, expected_num_queries2, expected_num_async_tasks2, *, check_duplicates=True): diff --git a/unittests/test_prepare_duplicates_for_delete.py b/unittests/test_prepare_duplicates_for_delete.py index de786c50ad6..3630f287fdf 100644 --- a/unittests/test_prepare_duplicates_for_delete.py +++ b/unittests/test_prepare_duplicates_for_delete.py @@ -13,7 +13,19 @@ from django.utils import timezone from dojo.finding.helper import prepare_duplicates_for_delete -from dojo.models import Engagement, Finding, Product, Product_Type, Test, Test_Type, User, UserContactInfo +from dojo.models import ( + Dojo_User, + Engagement, + Finding, + Finding_Group, + Product, + Product_Type, + Risk_Acceptance, + Test, + Test_Type, + User, + UserContactInfo, +) from .dojo_test_case import DojoTestCase @@ -409,3 +421,52 @@ def test_delete_product_with_tags(self): self.assertEqual(product_shared_tag.count, 0) finding_shared_tag.refresh_from_db() self.assertEqual(finding_shared_tag.count, 0) + + def test_delete_product_with_reverse_m2m_relations(self): + """ + Deleting a product with findings that have reverse M2M relations succeeds. + + Reverse M2M through tables (M2M fields on other models pointing to Finding) + must be cleared before findings are deleted. This tests: + - Finding_Group.findings (dojo_finding_group_findings) + - Risk_Acceptance.accepted_findings (dojo_risk_acceptance_accepted_findings) + """ + from dojo.utils import async_delete # noqa: PLC0415 + + finding_a = self._create_finding(self.test1, "Grouped Finding A") + finding_b = self._create_finding(self.test1, "Grouped Finding B") + finding_c = self._create_finding(self.test1, "Risk Accepted Finding") + + # Finding_Group with findings + creator = Dojo_User.objects.first() or Dojo_User.objects.create(username="testcreator") + group = Finding_Group.objects.create( + name="Test Group", + test=self.test1, + creator=creator, + ) + group.findings.add(finding_a, finding_b) + + # Risk_Acceptance with accepted findings + ra = Risk_Acceptance.objects.create( + name="Test RA", + owner=self.testuser, + ) + ra.accepted_findings.add(finding_c) + # Link to engagement so we can verify it survives + self.engagement1.risk_acceptance.add(ra) + + product_id = self.product.id + group_id = group.id + ra_id = ra.id + + with impersonate(self.testuser): + async_del = async_delete() + async_del.delete(self.product) + + self.assertFalse(Product.objects.filter(id=product_id).exists()) + self.assertFalse(Finding_Group.objects.filter(id=group_id).exists()) + self.assertFalse(Finding.objects.filter(id__in=[finding_a.id, finding_b.id, finding_c.id]).exists()) + # Risk_Acceptance itself survives (no FK to product/engagement), + # but its accepted_findings M2M entries should be gone + self.assertTrue(Risk_Acceptance.objects.filter(id=ra_id).exists()) + self.assertEqual(Risk_Acceptance.objects.get(id=ra_id).accepted_findings.count(), 0) diff --git a/unittests/test_rest_framework.py b/unittests/test_rest_framework.py index 4d8e78e6931..95807d4c536 100644 --- a/unittests/test_rest_framework.py +++ b/unittests/test_rest_framework.py @@ -1643,6 +1643,19 @@ def test_update_object_not_authorized(self): response = self.client.put(relative_url, self.payload) self.assertEqual(403, response.status_code, response.content[:1000]) + def test_delete_removes_location(self): + """Verify that deleting a URL via the API also deletes the associated Location.""" + url_obj = URL.objects.get(pk=self.delete_id) + location_id = url_obj.location_id + self.assertTrue(Location.objects.filter(pk=location_id).exists()) + + relative_url = f"{self.url}{location_id}/" + response = self.client.delete(relative_url) + self.assertEqual(204, response.status_code, response.content[:1000]) + + self.assertFalse(Location.objects.filter(pk=location_id).exists()) + self.assertFalse(URL.objects.filter(pk=self.delete_id).exists()) + @versioned_fixtures class EngagementTest(BaseClass.RelatedObjectsTest, BaseClass.BaseClassTest): diff --git a/unittests/test_tags.py b/unittests/test_tags.py index f29ea69f6ae..b9077e1daab 100644 --- a/unittests/test_tags.py +++ b/unittests/test_tags.py @@ -369,12 +369,12 @@ def assert_tags_in_findings(findings: list[dict], expected_finding_count: int, d findings = response["results"] # Make sure we have what we are looking for assert_tags_in_findings(findings, 2, ["security", "network"]) - # Reimport with a different report that has more tags + # Reimport with a different report that has more tags — matched findings should retain their original tags self.reimport_scan_with_params(test_id, self.generic_sample_with_more_tags_filename, scan_type="Generic Findings Import") response = self.get_test_findings_api(test_id) findings = response["results"] - # Make sure we have what we are looking for - assert_tags_in_findings(findings, 2, ["security", "network", "hardened"]) + # Tags from the report are not applied to matched findings on reimport, consistent with other fields + assert_tags_in_findings(findings, 2, ["security", "network"]) @versioned_fixtures diff --git a/unittests/tools/test_aws_inspector2_parser.py b/unittests/tools/test_aws_inspector2_parser.py index cc0a9aa7b32..21b1cecf70c 100644 --- a/unittests/tools/test_aws_inspector2_parser.py +++ b/unittests/tools/test_aws_inspector2_parser.py @@ -1,6 +1,7 @@ -from datetime import datetime +from datetime import date, datetime from dateutil.tz import tzoffset +from django.conf import settings from dojo.models import Test from dojo.tools.aws_inspector2.parser import AWSInspector2Parser @@ -26,7 +27,7 @@ def test_aws_inspector2_parser_with_one_vuln_has_one_findings(self): self.assertEqual("CVE-2021-3744 - linux", findings[0].title) self.assertEqual("Medium", findings[0].severity) self.assertEqual("CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H", findings[0].cvssv3) - self.assertIsNone(findings[0].cvssv3_score) # The score will be created by the finding save method + self.assertEqual(5.5, findings[0].cvssv3_score) def test_aws_inspector2_parser_with_many_vuln_has_many_findings(self): with (get_unit_tests_scans_path("aws_inspector2") / "aws_inspector2_many_vul.json").open(encoding="utf-8") as testfile: @@ -39,7 +40,39 @@ def test_aws_inspector2_parser_with_many_vuln_has_many_findings(self): # 2024-06-14T04:03:53.051000+02:00 self.assertEqual(datetime(2024, 6, 14, 4, 3, 53, 51000, tzinfo=tzoffset(None, 7200)), findings[0].mitigated) self.assertEqual("CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H", findings[0].cvssv3) - self.assertIsNone(findings[0].cvssv3_score) # The score will be created by the finding save method + self.assertEqual(5.5, findings[0].cvssv3_score) + + def test_aws_inspector2_package_vuln_metadata_fields(self): + """Verify that packageVulnerabilityDetails metadata fields are populated on findings.""" + with (get_unit_tests_scans_path("aws_inspector2") / "aws_inspector2_package_vuln_metadata.json").open(encoding="utf-8") as testfile: + parser = AWSInspector2Parser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(28, len(findings)) + # Use the first finding (CVE-2025-58187 - go/stdlib) for field assertions + finding = findings[0] + # component_name and component_version from vulnerablePackages[0] + self.assertEqual("go/stdlib", finding.component_name) + self.assertEqual("1.24.4", finding.component_version) + # file_path from vulnerablePackages[0].filePath + self.assertEqual("extensions/collector", finding.file_path) + # references from referenceUrls joined with newlines + self.assertEqual( + "https://nvd.nist.gov/vuln/detail/CVE-2025-58187\nhttps://groups.google.com/g/golang-announce/c/4Emdl2iQ_bI", + finding.references, + ) + # publish_date parsed from vendorCreatedAt + self.assertEqual(date(2025, 10, 30), finding.publish_date) + # cvssv3_score from packageVulnerabilityDetails.cvss[].baseScore (v3.x entry) + self.assertEqual(7.5, finding.cvssv3_score) + # vulnerability ID still populated + self.assertIn("CVE-2025-58187", finding.unsaved_vulnerability_ids) + # LocationData.dependency populated for package vulnerability findings + if settings.V3_FEATURE_LOCATIONS: + dependency_locations = [loc for loc in finding.unsaved_locations if loc.type == "dependency"] + self.assertEqual(1, len(dependency_locations)) + self.assertEqual("go/stdlib", dependency_locations[0].data["name"]) + self.assertEqual("1.24.4", dependency_locations[0].data["version"]) + self.assertEqual("extensions/collector", dependency_locations[0].data["file_path"]) def test_aws_inspector2_parser_empty_with_error(self): with self.assertRaises(TypeError) as context, \