diff --git a/docs/howto-4-product-vulnerability-analysis.rst b/docs/howto-4-product-vulnerability-analysis.rst index 8ba494b6..896de351 100644 --- a/docs/howto-4-product-vulnerability-analysis.rst +++ b/docs/howto-4-product-vulnerability-analysis.rst @@ -11,8 +11,7 @@ Overview Product Vulnerability Analysis in DejaCode helps teams assess, review, and manage vulnerabilities specific to individual Products. The platform supports detailed -analysis workflows, data propagation across related products, and integration with -external tools via the **REST API**. +analysis workflows and data propagation across related products. 1. Accessing Product Vulnerability Analysis ------------------------------------------- @@ -39,36 +38,12 @@ vulnerability, enabling in-depth review and understanding of its potential impac .. image:: images/howto-4-product-vulnerability-analysis/vulnerabilities-tab.jpg -Each entry includes the following information: - -- **Vulnerability ID**: - A unique identifier prefixed with "VCID-", such as **VCID-2024-0001**, ensuring - traceability. -- **Aliases**: - Alternate identifiers for the vulnerability, including **CVE identifiers** - (e.g., **CVE-2019-17571**). -- **Severity Levels**: - Categorized as **critical**, **high**, **medium**, or **low**, based on potential - impact. -- **Exploitability Score**: - Indicates the likelihood of exploitation, with three levels: - - - **0.5**: No known exploits. - - **1.0**: Potential exploits exist. - - **2.0**: Known exploits are available. - -- **Risk Score**: - A value between **0.0** and **10.0**, representing the overall risk posed by the - vulnerability. - This score is calculated by multiplying the highest severity with its weight and - the exploitability score, capped at **10.0**. -- **Affected Packages**: - Links to the affected packages and their versions. +Each entry includes the vulnerability ID, its aliases, severity, exploitability, and +risk score, along with links to the affected packages. -.. note:: - All vulnerability details, including analysis results and propagation status, are - accessible through the **REST API**, enabling automated workflows and seamless - integration with external tools. +.. seealso:: + Refer to :ref:`reference_vulnerability_management` for a complete description of + these fields and how the risk score is calculated. 3. Conducting Analysis ---------------------- @@ -158,10 +133,6 @@ To analyze a vulnerability effectively: 6. **Save Changes**: Save your analysis to ensure it is available for reference and propagated as needed. -.. note:: - The analysis data is also accessible via the **REST API**, making it possible to - integrate with automated tools and workflows. - 4. Propagating Analysis Across Products --------------------------------------- @@ -177,15 +148,16 @@ To streamline reviews, DejaCode supports analysis data propagation: 5. Leveraging REST API for Automation ------------------------------------- -The **REST API** provides full access to vulnerability analysis data, enabling -programmatic workflows such as: - -- Querying vulnerabilities linked to specific Products. -- Automating analysis result updates. +Vulnerability analyses are available at ``/api/v2/vulnerability_analyses/``, supporting +create, retrieve, update, and list operations. Use it to query analyses for specific +products or packages, and to automate analysis updates as part of your own workflows. -Refer to the **API documentation** from the **"Tools" menu** for detailed guidance on -using these endpoints. +.. seealso:: + Refer to the **API documentation** from the **"Tools" menu** for the full list of + fields and filters. .. seealso:: Explore the :ref:`reference_vulnerability_management` chapter for an overview of - related features. + related features. If you are looking for automated, rule-based recommendations + instead of manual review, refer to :ref:`reference_vulnerability_triage` and + :ref:`how_to_7`. diff --git a/docs/howto-7-vulnerability-triage-configuration.rst b/docs/howto-7-vulnerability-triage-configuration.rst new file mode 100644 index 00000000..98ea8812 --- /dev/null +++ b/docs/howto-7-vulnerability-triage-configuration.rst @@ -0,0 +1,160 @@ +.. _how_to_7: + +How To 7 - Configure Vulnerability Triage +========================================= + +This chapter explains how to create and configure **Triage Rulesets** for your +Dataspace and how to assign them to products. Triage rulesets automatically detect +vulnerabilities that match configured conditions and recommend a remediation action to +your product teams. + +All rulesets are disabled by default. You must create and configure the rulesets that +are relevant to your security program, then assign them to the products you want to +monitor. + +.. seealso:: + Refer to :ref:`reference_vulnerability_triage` for a complete description of all + available rules, actions, triage record lifecycle, and configuration options. + +.. tip:: + To get started quickly, a set of reference rulesets and presets covering common + scenarios can be seeded automatically with ``./manage.py create_triage_rulesets + ``. This section covers creating a ruleset manually for full + control over its rules and thresholds. + +1. Create a Triage Ruleset +-------------------------- + +1. From the DejaCode **Administration dashboard**, navigate to + :guilabel:`Vulnerabilities > Triage Rulesets`. +2. Click :guilabel:`Add Triage Ruleset`. +3. Fill in the **Name** field with a descriptive label (e.g., "Critical and Exploited"). +4. Select an **Action** from the dropdown. This is the remediation action that will be + recommended when any rule in the ruleset fires. +5. Set a **Precedence** value (integer). Higher values take priority when multiple + rulesets match the same vulnerability on the same product. +6. Leave **Enabled** checked to make the ruleset active immediately after saving. + +.. image:: images/howto-7-vulnerability-triage-configuration/add-ruleset-form.jpg + +2. Configure Rules +------------------ + +Below the base fields, each built-in rule appears as a collapsible section. + +1. Expand the rule sections you want to activate. +2. Check the :guilabel:`Enable [Rule Name]` checkbox to include that rule in the + ruleset evaluation. +3. For rules that support parameters, adjust the threshold values: + + - **Risk Score**: set :guilabel:`Min risk score` (default 8.0) to restrict + detection to vulnerabilities at or above that score. + - **Weighted Risk**: set :guilabel:`Min weighted risk score` (default 8.0) to + restrict detection by weighted package exposure. + - **Stale Vulnerability**: set :guilabel:`Max days` (default 30) and + :guilabel:`Min risk score` (default 8.0). + +A ruleset must have at least one rule enabled to produce any triage records. + +Click :guilabel:`Save` to create the ruleset. Disabling a rule that was previously +active removes the triage records it produced on the next evaluation. + +.. image:: images/howto-7-vulnerability-triage-configuration/rule-sections.jpg + :width: 500 + +3. Set Up an Analysis Preset +---------------------------- + +An **Analysis Preset** instructs the engine to automatically apply default analysis +values to each vulnerability matched by the ruleset. This is useful when you want to +pre-fill new analyses with a known state, such as marking newly detected vulnerabilities +as ``in_triage``. + +To create an Analysis Preset: + +1. Navigate to :guilabel:`Vulnerabilities > Analysis Presets`. +2. Click :guilabel:`Add Analysis Preset`. +3. Fill in the **Name** and optionally a **Description**. +4. Under **Analysis defaults**, configure the fields you want the engine to apply: + + - **State**: e.g., ``in_triage`` to mark all new analyses as being evaluated. + - **Justification**, **Responses**, **Detail**, **Is Reachable**: leave blank to + leave that field unchanged on any existing analysis. + +5. Click :guilabel:`Save`. + +To attach the preset to a ruleset, open the ruleset form and select the preset in the +:guilabel:`Analysis Preset` field, then save. + +.. image:: images/howto-7-vulnerability-triage-configuration/add-preset-form.jpg + +.. note:: + Only analyses created by the preset are updated on subsequent evaluation runs. + Any analysis modified by a user is never overwritten. + +4. Link a Request Template +-------------------------- + +When a **Request Template** is linked to a ruleset, the engine opens one DejaCode +request per new triage record automatically. This routes newly detected vulnerabilities +into a review workflow without manual intervention. + +Prerequisites: + +- A **Request Template** of content type **Product** must already exist under + :guilabel:`Workflow > Request Templates`. +- The template must have a creator (the user who created it): they are used as the + automatic requester. A template with no creator is rejected when you try to select + it on a ruleset. + +To link a template to a ruleset: + +1. Open the ruleset form in the Admin interface. +2. Select the template in the :guilabel:`Request Template` field. Only product-type + templates are listed. +3. Click :guilabel:`Save`. + +From the next evaluation, new triage records will have a DejaCode request opened +automatically. Triage records that already have a linked request are not affected by +subsequent evaluations. + +.. _how_to_7_assign_rulesets: + +5. Assign Rulesets to Products +------------------------------ + +A ruleset has no effect until it is assigned to one or more products. + +1. Open a product detail page. +2. Navigate to the :guilabel:`Vulnerabilities` tab. +3. Click :guilabel:`Manage Triage Rulesets` in the triage panel header. +4. In the modal that opens, select the rulesets you want to assign to this product. +5. Click :guilabel:`Save`. + +.. image:: images/howto-7-vulnerability-triage-configuration/manage-rulesets-modal.jpg + +The engine evaluates all assigned and enabled rulesets immediately. The +**Recommendation** column appears in the Vulnerabilities tab as soon as at least one +enabled ruleset is assigned. + +To unassign a ruleset, open the same modal and deselect it. Existing triage records +for that ruleset are deleted (a record with an open request is kept so reassigning the +ruleset later reconnects to it instead of opening a duplicate). Preset-applied analyses +are left in place: only the tracking record is removed, not the analysis itself. + +6. Manage Precedence +-------------------- + +When multiple rulesets are assigned to a product and their rules overlap on the same +vulnerability, only the record from the highest-precedence ruleset is displayed in the +Recommendation column. Lower-precedence records still exist and are maintained by the +engine, but are hidden from the product view. + +To adjust precedence: + +1. Open the ruleset form in the Admin interface. +2. Change the :guilabel:`Precedence` value. A higher number raises the ruleset's + priority. +3. Click :guilabel:`Save`. + +Re-evaluation of all assigned products is triggered automatically after saving. diff --git a/docs/images/howto-7-vulnerability-triage-configuration/add-preset-form.jpg b/docs/images/howto-7-vulnerability-triage-configuration/add-preset-form.jpg new file mode 100644 index 00000000..51b0742c Binary files /dev/null and b/docs/images/howto-7-vulnerability-triage-configuration/add-preset-form.jpg differ diff --git a/docs/images/howto-7-vulnerability-triage-configuration/add-ruleset-form.jpg b/docs/images/howto-7-vulnerability-triage-configuration/add-ruleset-form.jpg new file mode 100644 index 00000000..d28c70b3 Binary files /dev/null and b/docs/images/howto-7-vulnerability-triage-configuration/add-ruleset-form.jpg differ diff --git a/docs/images/howto-7-vulnerability-triage-configuration/manage-rulesets-modal.jpg b/docs/images/howto-7-vulnerability-triage-configuration/manage-rulesets-modal.jpg new file mode 100644 index 00000000..21094cb4 Binary files /dev/null and b/docs/images/howto-7-vulnerability-triage-configuration/manage-rulesets-modal.jpg differ diff --git a/docs/images/howto-7-vulnerability-triage-configuration/rule-sections.jpg b/docs/images/howto-7-vulnerability-triage-configuration/rule-sections.jpg new file mode 100644 index 00000000..765de97a Binary files /dev/null and b/docs/images/howto-7-vulnerability-triage-configuration/rule-sections.jpg differ diff --git a/docs/images/reference-vulnerability-triage/vulnerabilities-tab.jpg b/docs/images/reference-vulnerability-triage/vulnerabilities-tab.jpg new file mode 100644 index 00000000..99ba76aa Binary files /dev/null and b/docs/images/reference-vulnerability-triage/vulnerabilities-tab.jpg differ diff --git a/docs/images/reference-vulnerability-triage/vulnerability-popover.jpg b/docs/images/reference-vulnerability-triage/vulnerability-popover.jpg new file mode 100644 index 00000000..c11973ca Binary files /dev/null and b/docs/images/reference-vulnerability-triage/vulnerability-popover.jpg differ diff --git a/docs/images/tutorial-8-vulnerability-triage/analysis-modal.jpg b/docs/images/tutorial-8-vulnerability-triage/analysis-modal.jpg new file mode 100644 index 00000000..c2dbed2b Binary files /dev/null and b/docs/images/tutorial-8-vulnerability-triage/analysis-modal.jpg differ diff --git a/docs/images/tutorial-8-vulnerability-triage/recommendation-cell.jpg b/docs/images/tutorial-8-vulnerability-triage/recommendation-cell.jpg new file mode 100644 index 00000000..bc8f863a Binary files /dev/null and b/docs/images/tutorial-8-vulnerability-triage/recommendation-cell.jpg differ diff --git a/docs/images/tutorial-8-vulnerability-triage/vulnerabilities-tab.jpg b/docs/images/tutorial-8-vulnerability-triage/vulnerabilities-tab.jpg new file mode 100644 index 00000000..7cae00b9 Binary files /dev/null and b/docs/images/tutorial-8-vulnerability-triage/vulnerabilities-tab.jpg differ diff --git a/docs/index.rst b/docs/index.rst index 5846e2f1..e8d2251a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -24,6 +24,7 @@ Welcome to the very start of your DejaCode journey! tutorial-5-sboms tutorial-6-vuln-report tutorial-7-policy-rules + tutorial-8-vulnerability-triage .. toctree:: :maxdepth: 1 @@ -35,6 +36,7 @@ Welcome to the very start of your DejaCode journey! howto-4-product-vulnerability-analysis howto-5-product-object-permissions howto-6-policy-rules-configuration + howto-7-vulnerability-triage-configuration .. toctree:: :maxdepth: 1 @@ -43,6 +45,7 @@ Welcome to the very start of your DejaCode journey! reference-data-models reference-vulnerability-management reference-policy-rules + reference-vulnerability-triage reference-1 reference-2 reference-3-cravex diff --git a/docs/reference-vulnerability-management.rst b/docs/reference-vulnerability-management.rst index a0daecf1..e1520c50 100644 --- a/docs/reference-vulnerability-management.rst +++ b/docs/reference-vulnerability-management.rst @@ -13,7 +13,7 @@ This documentation outlines how vulnerabilities are **collected**, **displayed** Introduction ------------ -DejaCode’s vulnerability management system relies on the **VulnerableCodeDB** service +DejaCode's vulnerability management system relies on the **VulnerableCodeDB** service to collect and process vulnerability data. This service is integrated into DejaCode to provide seamless tracking and management of vulnerabilities associated with software packages and components. @@ -191,6 +191,9 @@ For a step-by-step guide on using these features, refer to the dedicated For automated compliance monitoring of vulnerability exposure across your products, refer to :ref:`reference_policy_rules` and :ref:`how_to_6`. +For automated detection and remediation recommendations based on configurable rules, +refer to :ref:`reference_vulnerability_triage` and :ref:`how_to_7`. + 6. Configuration Settings ------------------------- diff --git a/docs/reference-vulnerability-triage.rst b/docs/reference-vulnerability-triage.rst new file mode 100644 index 00000000..5f49f2df --- /dev/null +++ b/docs/reference-vulnerability-triage.rst @@ -0,0 +1,349 @@ +.. _reference_vulnerability_triage: + +Vulnerability Triage Engine +=========================== + +DejaCode includes a **Vulnerability Triage Engine** that evaluates configurable +detection rules against your product inventory and recommends a remediation action for +each matched vulnerability. It provides a structured way to prioritize, track, and act +on vulnerability exposure across your products. + +When a ruleset fires, DejaCode creates a **triage record** linking the vulnerability to +the product and the ruleset that detected it. The record carries the recommended action, +the detection date, the last evaluation date, and an optional link to a DejaCode request +opened automatically by the engine. + +Rulesets are **disabled by default**. Each dataspace creates and configures the rulesets +that are relevant to its security program via the **Admin** interface. + +1. Built-in Rules +----------------- + +Seven rules are available out of the box. Each rule implements a specific detection +condition evaluated against the vulnerabilities known to affect the product's packages. + +.. list-table:: + :header-rows: 1 + :widths: 28 72 + + * - Label + - Description + * - | **Risk Score** + | ``risk_score`` + - Detects vulnerabilities whose risk score is at or above the configured threshold. + * - | **Weighted Risk** + | ``weighted_risk`` + - Detects vulnerabilities affecting at least one package whose weighted risk score + meets the configured threshold. The weighted risk score combines the vulnerability + risk with the package's exposure level in the product. + * - | **Exploited Vulnerability** + | ``exploited_vulnerability`` + - Detects vulnerabilities for which a known active exploit is available + (exploitability value equals 2.0). + * - | **Reachable Vulnerability** + | ``reachable_vulnerability`` + - Detects vulnerabilities confirmed as reachable in the product context: at least + one VulnerabilityAnalysis record for this vulnerability has ``is_reachable`` set + to true. + * - | **Unresolved Vulnerability** + | ``unresolved_vulnerability`` + - Detects vulnerabilities affecting the product where at least one package has no + completed triage analysis (i.e., no analysis in a terminal state: resolved, + resolved_with_pedigree, or not_affected). + * - | **Stale Vulnerability** + | ``stale_vulnerability`` + - Detects high-risk vulnerabilities that have remained unaddressed beyond the + configured number of days. Considers only vulnerabilities whose risk score meets + or exceeds the configured minimum. + * - | **Dev-Only Vulnerable Package** + | ``dev_only_vulnerable_package`` + - Detects vulnerabilities that exclusively affect packages marked as non-deployed + in the product, indicating a lower exposure risk. + +.. seealso:: + Refer to :ref:`reference_vulnerability_management` for background on vulnerability + fields such as risk score and exploitability. + +1.1 Rule Parameters +^^^^^^^^^^^^^^^^^^^ + +The following parameters are supported by rules that accept them: + +**Risk Score** (``risk_score``) + +- ``min_risk_score`` (float, 0.0-10.0): only flag vulnerabilities whose risk score is + greater than or equal to this value. Defaults to ``8.0``. + +**Weighted Risk** (``weighted_risk``) + +- ``min_weighted_risk_score`` (float, 0.0-10.0): only flag vulnerabilities affecting a + package whose weighted risk score is greater than or equal to this value. Defaults to + ``8.0``. + +**Stale Vulnerability** (``stale_vulnerability``) + +- ``max_days`` (integer, min 1): maximum number of days a high-risk vulnerability may + remain without a completed analysis before it is flagged. Defaults to ``30``. +- ``min_risk_score`` (float, 0.0-10.0): only consider vulnerabilities whose risk score + is greater than or equal to this value. Defaults to ``8.0``. + +2. Triage Actions +----------------- + +Each ruleset recommends a single remediation action. The action is stored on every +triage record created by that ruleset and displayed in the **Recommendation** column +of the product Vulnerabilities tab. + +.. list-table:: + :header-rows: 1 + + * - Action + - Label + * - ``upgrade`` + - Upgrade Package + * - ``apply_patch`` + - Apply Patch + * - ``forensic_analysis`` + - Forensic Analysis + * - ``reachability_analysis`` + - Reachability Analysis + * - ``change_config`` + - Change Configuration + * - ``replace_package`` + - Replace Package + * - ``notify`` + - Notify + * - ``create_request`` + - Create DejaCode Request + +3. Triage Record Lifecycle +-------------------------- + +A **triage record** is created per (vulnerability, product, ruleset) combination the +first time a ruleset evaluation matches a vulnerability. Its lifecycle follows these +states: + +- **Detected**: the record is created the first time the ruleset fires for the + vulnerability. ``detected_date`` is set at this point and never changes on subsequent + evaluations. +- **Active**: the record is updated in place on each subsequent evaluation as long as + the vulnerability still matches any active rule in the ruleset. ``last_checked`` is + updated on every run. +- **Deleted**: when a vulnerability no longer matches any rule in the ruleset, its + triage record is deleted. Any preset-applied analysis for that vulnerability is also + removed. If the conditions recur later, a new record is created with a fresh + ``detected_date``. + +Only **active** triage records appear in the product Vulnerabilities tab. + +4. Configuration +---------------- + +The triage engine is configured through **Triage Rulesets** in the Admin interface +under :guilabel:`Vulnerabilities > Triage Rulesets`. + +.. seealso:: + For step-by-step instructions on creating and configuring rulesets through the Admin + UI, refer to :ref:`how_to_7`. + +4.1 Triage Ruleset +^^^^^^^^^^^^^^^^^^ + +Each ruleset combines one or more detection rules with a single recommended action: + +.. list-table:: + :header-rows: 1 + + * - Field + - Description + * - **Name** + - A descriptive name for the ruleset (e.g., "Critical Vulnerabilities"). + * - **Action** + - The remediation action to recommend when the ruleset fires. + * - **Precedence** + - Integer controlling priority when multiple rulesets match the same vulnerability + for the same product. The ruleset with the highest precedence value wins and its + triage record is displayed. Unique per dataspace, so ties cannot occur. + * - **Enabled** + - When unchecked, the ruleset is excluded from all evaluations and its existing + triage records are deleted immediately. Any preset-applied analysis is left in + place: only the tracking record is removed, not the analysis itself. + * - **Analysis Preset** + - Optional. An AnalysisPreset whose default values are applied automatically to + each matched vulnerability (see section 4.2). + * - **Request Template** + - Optional. A RequestTemplate of content type Product used to open a DejaCode + request automatically for each new triage record (see section 4.3). + +4.2 Analysis Preset +^^^^^^^^^^^^^^^^^^^ + +An **Analysis Preset** defines default vulnerability analysis values that the engine +applies automatically to each (product_package, vulnerability) pair matched by the +ruleset. + +.. list-table:: + :header-rows: 1 + + * - Field + - Description + * - **State** + - Default analysis state (e.g., ``in_triage``). + * - **Justification** + - Default justification value. + * - **Responses** + - Default response values (multiple choice). + * - **Detail** + - Default free-text detail. + * - **Is Reachable** + - Default reachability flag (true/false/unknown). + +Only non-blank preset fields are applied to each analysis. User-owned analyses (those +not created by a preset) are never overwritten. When a user edits an auto-applied +analysis, it becomes user-owned and the engine will not modify it again. + +Analysis Presets are managed in the Admin interface under +:guilabel:`Vulnerabilities > Analysis Presets`. + +.. seealso:: + Refer to :ref:`how_to_4` for the meaning of each analysis field (State, + Justification, Responses, Detail). + +4.3 Request Template +^^^^^^^^^^^^^^^^^^^^ + +When a **Request Template** is assigned to a ruleset, the engine automatically opens +one DejaCode request per new triage record using the template's title and content as +defaults. + +Key behaviors: + +- The template must be of content type **Product**. +- The engine uses the request template's creator as the requester. A request template + with no creator cannot be selected on a ruleset: this is validated when the ruleset + is saved, both in the Admin and through the REST API. +- The request is linked to the triage record. Users can navigate to it directly from + the Recommendation column in the Vulnerabilities tab. +- Requests are created once per triage record. Re-evaluation does not open additional + requests for an existing record. + +4.4 Seeding Reference Rulesets +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A set of reference rulesets and analysis presets, covering common scenarios (critical +exploited vulnerabilities, reachable vulnerabilities, stale vulnerabilities, dev-only +packages, and more) can be seeded into a dataspace with the ``create_triage_rulesets`` +management command:: + + ./manage.py create_triage_rulesets + +The command refuses to run if the dataspace already has triage rulesets. Pass +``--reset`` to delete all existing rulesets and presets in the dataspace first and +recreate them from scratch; you will be prompted for confirmation unless ``--noinput`` +is also passed. Resetting removes every product's ruleset assignments, which must be +redone manually afterward. + +5. Evaluation +------------- + +5.1 Automatic Evaluation +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The engine re-evaluates a product's assigned rulesets automatically and immediately +whenever any of the following changes occur, so results are reflected on the very next +page reload without any manual action: + +- A **ruleset** already assigned to one or more products is edited and saved, from the + Admin interface or through the REST API: every assigned product is re-evaluated. +- A **ruleset is assigned to or unassigned from** a product, from the product + Vulnerabilities tab or through the REST API. +- A **package is added to or removed from** a product. +- A **VulnerabilityAnalysis** record for a package in the product is saved or deleted. + +.. note:: + Bulk operations (importing a CSV of packages, importing a ScanCode.io scan, or + cloning a product) evaluate each affected product once in the background after the + import completes, instead of once per imported row. Results may take a short moment + to appear after a large bulk import. + +5.2 Manual Re-evaluation +^^^^^^^^^^^^^^^^^^^^^^^^^ + +A full re-evaluation of every enabled ruleset against every product in a dataspace can +be triggered from the command line:: + + ./manage.py evaluate_triage + +This is intended for scheduled runs or recovery after data changes. + +6. Vulnerabilities Tab +---------------------- + +The **Vulnerabilities** tab on each product detail page provides a per-vulnerability +view of the product's affected packages. When at least one enabled ruleset is assigned +to the product, a **Recommendation** column appears. A link to open the +:guilabel:`Manage Triage Rulesets` panel is available from the tab's navigation bar for +users with change permission on the product. + +For each vulnerability row, the Recommendation cell shows: + +- The recommended **action** (colored badge). +- The **ruleset name** that produced the recommendation. +- The **detection date** (Since). +- A link to the **associated request**, if one was opened automatically. + +When multiple rulesets are assigned and their rules overlap on the same vulnerability, +only the record from the highest-precedence ruleset is displayed. + +.. image:: images/reference-vulnerability-triage/vulnerabilities-tab.jpg + +Hovering the info icon next to a vulnerability ID shows a popover with its aliases, +summary, exploitability, and risk score. + +.. image:: images/reference-vulnerability-triage/vulnerability-popover.jpg + :width: 500 + +Vulnerability analysis values (state, justification, responses, reachability) are +shown in adjacent columns and can be edited inline via the edit icon. When an analysis +was auto-applied by a preset, an "Auto-applied" indicator with the preset name is shown +in place of the usual last-modified-by information. + +The table can be filtered by **Triage action**, **Analysis state**, **Justification**, +**Responses**, and **Reachability**. + +7. REST API +----------- + +A product's active triage recommendations are accessible via the REST API at:: + + GET /api/v2/products/{uuid}/triage_records/ + +The response is a list of active recommendations, one entry per vulnerability, from +the highest-precedence matching ruleset, each including: + +- ``advisory_id``: the vulnerability identifier. +- ``ruleset``: the name of the ruleset that produced the recommendation. +- ``recommended_action``: the remediation action. +- ``matched_rules``: the rule types that matched. +- ``request``: a string representation of the associated request, or ``null``. +- ``detected_date`` and ``last_checked``. + +Triage rulesets and analysis presets support full create, retrieve, update, and delete +operations at:: + + /api/v2/triage_rulesets/ + /api/v2/analysis_presets/ + +A product's ruleset assignments can be listed and managed at:: + + GET /api/v2/products/{uuid}/manage_triage_rulesets/ + POST /api/v2/products/{uuid}/manage_triage_rulesets/ + +The ``GET`` response lists every enabled ruleset in the product's dataspace, each +flagged with an ``assigned`` boolean. The ``POST`` endpoint assigns or unassigns one +ruleset at a time and re-evaluates the product immediately:: + + {"ruleset": "", "assigned": true} + +Vulnerability analyses, including whether they were auto-applied by a preset, are also +available at ``/api/v2/vulnerability_analyses/``. diff --git a/docs/tutorial-4-vulnerabilities.rst b/docs/tutorial-4-vulnerabilities.rst index c5041693..333b5d01 100644 --- a/docs/tutorial-4-vulnerabilities.rst +++ b/docs/tutorial-4-vulnerabilities.rst @@ -70,6 +70,10 @@ Conduct Vulnerability Analysis .. image:: images/tutorial-4-vulnerabilities/vulnerabilities-tab-with-analysis.jpg +.. seealso:: + Refer to :ref:`how_to_4` for a detailed guide on each analysis field and its + meaning. + Export CycloneDX SBOM with VEX ------------------------------ @@ -81,3 +85,8 @@ Export CycloneDX SBOM with VEX 2. The analysis details you provide for product package vulnerabilities are included in the ``vulnerabilities`` section of the CycloneDX VEX output. + +.. seealso:: + Once your administrator has configured triage rulesets for your Dataspace, this + manual review is complemented by automated remediation recommendations. Refer to + :ref:`user_tutorial_8_vulnerability_triage` to get started. diff --git a/docs/tutorial-8-vulnerability-triage.rst b/docs/tutorial-8-vulnerability-triage.rst new file mode 100644 index 00000000..5df06747 --- /dev/null +++ b/docs/tutorial-8-vulnerability-triage.rst @@ -0,0 +1,129 @@ +.. _user_tutorial_8_vulnerability_triage: + +Tutorial 8 - Vulnerability Triage +================================= + +Your DejaCode administrator has set up triage rulesets for your Dataspace, and one or +more of them have been assigned to the product you want to review. This tutorial walks +you through discovering triage recommendations on a product, understanding what they +mean, recording your vulnerability analysis, and tracking the associated requests. + +.. seealso:: + Refer to :ref:`reference_vulnerability_triage` for a complete description of all + available rules, actions, and triage record lifecycle. If you are an administrator + and need to create or configure rulesets, refer to :ref:`how_to_7`. If this is your + first time reviewing a product's vulnerabilities, start with + :ref:`user_tutorial_4_vulnerabilities`. + +Sign into DejaCode. + +1. Open the Vulnerabilities Tab +------------------------------- + +1. From the main navigation, browse to the product you want to review. +2. Open the product detail page and navigate to the :guilabel:`Vulnerabilities` tab. + +The tab lists all packages in the product that have known vulnerabilities. Each package +row expands to show the individual vulnerabilities that affect it, along with their +risk scores and exploitability indicators. Hover the info icon next to a vulnerability +ID for a quick summary of its aliases, description, exploitability, and risk score. + +When triage rulesets are assigned to the product, a :guilabel:`Recommendation` column +appears between the vulnerability ID and the analysis status columns. If you do not +see this column, no ruleset is assigned to this product yet: refer to +:ref:`how_to_7_assign_rulesets` for how to assign one. + +.. image:: images/tutorial-8-vulnerability-triage/vulnerabilities-tab.jpg + +2. Read the Recommendation Column +--------------------------------- + +Each row in the Recommendation column can show up to four pieces of information: + +- **Action badge**: the remediation action recommended by the highest-precedence + ruleset that matched this vulnerability (e.g., **Upgrade Package**, + **Reachability Analysis**, **Notify**). +- **Ruleset name**: the name of the ruleset that produced the recommendation. +- **Since**: the date when the triage engine first detected this vulnerability for + this product. +- **Request link**: if a DejaCode request was opened automatically for this + vulnerability, a link appears here. Click it to open the request in a new tab. + +If a vulnerability row has no recommendation badge, no enabled ruleset currently +matches it for this product. + +.. image:: images/tutorial-8-vulnerability-triage/recommendation-cell.jpg + :width: 300 + +3. Filter and Prioritize +------------------------ + +Use the filter controls at the top of the Vulnerabilities tab to narrow down the list: + +- Filter by **Triage action** to focus on vulnerabilities requiring a specific + remediation (e.g., show only those flagged for an upgrade). +- Filter by **Risk score** to surface the most critical vulnerabilities first. +- Filter by **Analysis state** to identify vulnerabilities not yet triaged. + +4. Record a Vulnerability Analysis +---------------------------------- + +The Recommendation column tells you what action to take. To record your analysis +findings: + +1. In the vulnerability row, click the edit icon on the right side of the row. +2. An analysis modal opens for that package and vulnerability combination. +3. Fill in the fields that apply to your findings: + + - **State**: select the analysis state that reflects your conclusion (e.g., + *In Triage*, *Resolved*, *Not Affected*). + - **Justification**: select the reason for your conclusion if applicable. + - **Responses**: select one or more response actions you are taking. + - **Is Reachable**: indicate whether the vulnerability is reachable in this + product's runtime context. + - **Detail**: add any free-text notes for your team. + +4. Click :guilabel:`Save`. The analysis values appear in the row immediately. + +.. image:: images/tutorial-8-vulnerability-triage/analysis-modal.jpg + +.. seealso:: + Refer to :ref:`how_to_4` for a detailed guide on vulnerability analysis fields + and their meaning. + +.. note:: + If an Analysis Preset was configured for the ruleset, some fields may already be + pre-filled when you open the modal. An "Auto-applied" indicator with the preset + name appears in the row for these analyses instead of the usual last-modified-by + information. You can modify any pre-filled value. Once you save, the analysis + becomes yours and the engine will not overwrite it. + +5. Track Open Requests +---------------------- + +When the administrator has configured a Request Template on the ruleset, the engine +opens one request per matched vulnerability automatically. The request link appears in +the Recommendation column below the detection date. + +To work with the request: + +1. Click the :guilabel:`Request #` link in the Recommendation column. +2. The request opens in a new tab with the full workflow context. +3. Use the request to coordinate remediation with your team, add comments, and + record the resolution outcome. + +The linked request is not automatically closed when the triage record is cleared. This +allows you to track remediation progress independently of the triage state. + +6. Recommendations Update Automatically +--------------------------------------- + +There is no manual re-evaluation step: recommendations are recalculated immediately +whenever something relevant changes, and the refreshed result is there on your next +page reload. + +- Saving your own vulnerability analysis re-evaluates the product right away. +- A package being added to or removed from the product re-evaluates it too. + +Vulnerabilities whose conditions are no longer met by any active ruleset rule will have +their recommendation cleared from the column. diff --git a/vulnerabilities/triage/api.py b/vulnerabilities/triage/api.py index 2e90bbf4..b3214048 100644 --- a/vulnerabilities/triage/api.py +++ b/vulnerabilities/triage/api.py @@ -14,6 +14,7 @@ from dje.api import DataspacedSerializer from dje.api import ExtraPermissionsViewSetMixin from dje.api_custom import TabPermission +from vulnerabilities.triage.engine import evaluate_ruleset from vulnerabilities.triage.models import AnalysisPreset from vulnerabilities.triage.models import TriageRuleset @@ -137,3 +138,14 @@ class TriageRulesetViewSet( def get_queryset(self): return super().get_queryset().select_related("analysis_preset", "request_template") + + def perform_update(self, serializer): + """Mirror TriageRulesetAdmin.save_model(): re-evaluate or clean up on change.""" + ruleset = serializer.save() + + if not ruleset.enabled: + ruleset.triage_records.filter(request__isnull=True).delete() + return + + for assignment in ruleset.product_triage_rulesets.select_related("product"): + evaluate_ruleset(ruleset=ruleset, product=assignment.product) diff --git a/vulnerabilities/triage/tests/test_api.py b/vulnerabilities/triage/tests/test_api.py index 8c89c309..96fdfa96 100644 --- a/vulnerabilities/triage/tests/test_api.py +++ b/vulnerabilities/triage/tests/test_api.py @@ -12,13 +12,20 @@ from rest_framework import status +from component_catalog.tests import make_package from dje.models import Dataspace from dje.tests import create_superuser from product_portfolio.models import Product +from product_portfolio.tests import make_product +from product_portfolio.tests import make_product_package +from vulnerabilities.tests import make_vulnerability +from vulnerabilities.triage.engine import evaluate_ruleset from vulnerabilities.triage.models import AnalysisPreset from vulnerabilities.triage.models import TriageAction +from vulnerabilities.triage.models import TriageRecord from vulnerabilities.triage.models import TriageRuleset from vulnerabilities.triage.tests import make_analysis_preset +from vulnerabilities.triage.tests import make_product_triage_ruleset from vulnerabilities.triage.tests import make_triage_ruleset from workflow.models import RequestTemplate @@ -165,6 +172,42 @@ def test_api_triageruleset_endpoint_update(self): self.ruleset.refresh_from_db() self.assertFalse(self.ruleset.enabled) + def test_api_triageruleset_endpoint_update_reevaluates_assigned_products(self): + # Regression: editing a ruleset via the API must re-evaluate its assigned + # products, matching what already happens when editing it in the Admin. + self.client.login(username="super_user", password="secret") + product = make_product(self.dataspace) + package = make_package(self.dataspace) + make_product_package(product, package=package) + vulnerability = make_vulnerability(self.dataspace, affecting=package, risk_score=9.0) + make_product_triage_ruleset(product, ruleset=self.ruleset) + self.assertFalse(TriageRecord.objects.exists()) + + data = {"rules_config": {"risk_score": {"is_active": True, "min_risk_score": 8.0}}} + response = self.client.patch(self.detail_url, data=data, content_type="application/json") + + self.assertEqual(status.HTTP_200_OK, response.status_code) + record = TriageRecord.objects.get() + self.assertEqual(vulnerability, record.vulnerability) + + def test_api_triageruleset_endpoint_disabling_deletes_its_triage_records(self): + self.client.login(username="super_user", password="secret") + product = make_product(self.dataspace) + package = make_package(self.dataspace) + make_product_package(product, package=package) + make_vulnerability(self.dataspace, affecting=package, risk_score=9.0) + self.ruleset.rules_config = {"risk_score": {"is_active": True, "min_risk_score": 8.0}} + self.ruleset.save() + make_product_triage_ruleset(product, ruleset=self.ruleset) + evaluate_ruleset(self.ruleset, product) + self.assertTrue(TriageRecord.objects.exists()) + + data = {"enabled": False} + response = self.client.patch(self.detail_url, data=data, content_type="application/json") + + self.assertEqual(status.HTTP_200_OK, response.status_code) + self.assertFalse(TriageRecord.objects.exists()) + def test_api_triageruleset_endpoint_delete(self): self.client.login(username="super_user", password="secret") response = self.client.delete(self.detail_url)