Skip to content

Commit 0db9401

Browse files
authored
Add ignored_vulnerabilities field on the Project configuration #1271 (#1281)
* Add ignored_vulnerabilities field on the Project configuration #1271 Signed-off-by: tdruez <tdruez@nexb.com> * Minor change to the indentation for consistency #1271 Signed-off-by: tdruez <tdruez@nexb.com> --------- Signed-off-by: tdruez <tdruez@nexb.com>
1 parent 6be1c16 commit 0db9401

File tree

13 files changed

+925
-16
lines changed

13 files changed

+925
-16
lines changed

CHANGELOG.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ v34.6.3 (unreleased)
1111
- Fix an issue in the d2d JavaScript mapper.
1212
https://github.com/nexB/scancode.io/pull/1274
1313

14+
- Add support for a ``ignored_vulnerabilities`` field on the Project configuration.
15+
https://github.com/nexB/scancode.io/issues/1271
16+
1417
v34.6.2 (2024-06-18)
1518
--------------------
1619

docs/project-configuration.rst

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,20 @@ Content of a ``scancode-config.yml`` file:
5252
product_name: My Product Name
5353
product_version: '1.0'
5454
ignored_patterns:
55-
- '*.tmp'
56-
- 'tests/*'
55+
- '*.tmp'
56+
- 'tests/*'
5757
ignored_dependency_scopes:
5858
- package_type: npm
5959
scope: devDependencies
6060
- package_type: pypi
6161
scope: tests
62+
ignored_vulnerabilities:
63+
- VCID-q4q6-yfng-aaag
64+
- CVE-2024-27351
65+
- GHSA-vm8q-m57g-pff3
6266
63-
See the :ref:`project_configuration_settings` section for the details about each
64-
setting.
67+
See the following :ref:`project_configuration_settings` section for the details about
68+
each setting.
6569

6670
.. tip::
6771
You can generate the project configuration file from the
@@ -125,10 +129,10 @@ packages, define the following in your ``scancode-config.yml`` configuration fil
125129
.. code-block:: yaml
126130
127131
ignored_dependency_scopes:
128-
- package_type: npm
129-
scope: devDependencies
130-
- package_type: pypi
131-
scope: tests
132+
- package_type: npm
133+
scope: devDependencies
134+
- package_type: pypi
135+
scope: tests
132136
133137
If you prefer to use the :ref:`user_interface_project_settings` form, list each
134138
ignored scope using the `package_type:scope` syntax, **one per line**, such as:
@@ -141,3 +145,23 @@ ignored scope using the `package_type:scope` syntax, **one per line**, such as:
141145
.. warning::
142146
Be precise when listing scope names to avoid unintended exclusions.
143147
Ensure the scope names are correct and reflect your project requirements.
148+
149+
ignored_vulnerabilities
150+
^^^^^^^^^^^^^^^^^^^^^^^
151+
152+
Provide one or more vulnerability id to be ignored, **one per line**.
153+
154+
You can provide ``VCID`` from VulnerableCode or any aliases such as ``CVE`` or
155+
``GHSA``.
156+
157+
For example::
158+
159+
.. code-block:: yaml
160+
161+
ignored_vulnerabilities:
162+
- VCID-q4q6-yfng-aaag
163+
- CVE-2024-27351
164+
- GHSA-vm8q-m57g-pff3
165+
- OSV-2020-871
166+
- BIT-django-2024-24680
167+
- PYSEC-2024-28

docs/scancode-config.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,18 @@
99
# - Use ``*`` to match multiple characters.
1010
# - Use ``?`` to match a single character.
1111
#ignored_patterns:
12-
# - '*.tmp'
13-
# - 'tests/*'
12+
# - '*.tmp'
13+
# - 'tests/*'
1414

1515
# Specify certain dependency scopes to be ignored for a given package type.
1616
#ignored_dependency_scopes:
1717
# - package_type: npm
1818
# scope: devDependencies
1919
# - package_type: pypi
2020
# scope: tests
21+
22+
# Specify certain vulnerabilities to be ignored using VCID, CVE, or any aliases.
23+
#ignored_vulnerabilities:
24+
# - VCID-q4q6-yfng-aaag
25+
# - CVE-2024-27351
26+
# - GHSA-vm8q-m57g-pff3

scanpipe/forms.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,10 +365,16 @@ def prepare_value(self, value):
365365
"""
366366

367367

368+
ignored_vulnerabilities_help = """
369+
Specify certain vulnerabilities to be ignored using VCID, CVE, or any aliases.
370+
"""
371+
372+
368373
class ProjectSettingsForm(forms.ModelForm):
369374
settings_fields = [
370375
"ignored_patterns",
371376
"ignored_dependency_scopes",
377+
"ignored_vulnerabilities",
372378
"attribution_template",
373379
"product_name",
374380
"product_version",
@@ -399,6 +405,18 @@ class ProjectSettingsForm(forms.ModelForm):
399405
key_name="package_type",
400406
value_name="scope",
401407
)
408+
ignored_vulnerabilities = ListTextarea(
409+
label="Ignored vulnerabilities",
410+
required=False,
411+
help_text=convert_markdown_to_html(ignored_vulnerabilities_help.strip()),
412+
widget=forms.Textarea(
413+
attrs={
414+
"class": "textarea is-dynamic",
415+
"rows": 2,
416+
"placeholder": "VCID-q4q6-yfng-aaag\nCVE-2024-27351",
417+
},
418+
),
419+
)
402420
attribution_template = forms.CharField(
403421
label="Attribution template",
404422
required=False,

scanpipe/models.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,25 @@ def ignored_dependency_scopes_index(self):
863863
"""
864864
return self.get_ignored_dependency_scopes_index()
865865

866+
def get_ignored_vulnerabilities_set(self):
867+
"""
868+
Return a set of ``ignored_vulnerabilities`` setting values defined in this
869+
Project env.
870+
"""
871+
ignored_vulnerabilities = self.get_env(field_name="ignored_vulnerabilities")
872+
if ignored_vulnerabilities:
873+
return set(entry for entry in ignored_vulnerabilities)
874+
875+
return []
876+
877+
@cached_property
878+
def ignored_vulnerabilities_set(self):
879+
"""
880+
Return the computed value of get_ignored_vulnerabilities_set.
881+
The value is only generated once and cached for further calls.
882+
"""
883+
return self.get_ignored_vulnerabilities_set()
884+
866885
def clear_tmp_directory(self):
867886
"""
868887
Delete the whole content of the tmp/ directory.

scanpipe/pipelines/find_vulnerabilities.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,17 @@ def check_vulnerablecode_service_availability(self):
5353
def lookup_packages_vulnerabilities(self):
5454
"""Check for vulnerabilities for each of the project's discovered package."""
5555
packages = self.project.discoveredpackages.all()
56-
vulnerablecode.fetch_vulnerabilities(packages, logger=self.log)
56+
vulnerablecode.fetch_vulnerabilities(
57+
packages=packages,
58+
ignore_set=self.project.ignored_vulnerabilities_set,
59+
logger=self.log,
60+
)
5761

5862
def lookup_dependencies_vulnerabilities(self):
5963
"""Check for vulnerabilities for each of the project's discovered dependency."""
6064
dependencies = self.project.discovereddependencies.filter(is_resolved=True)
61-
vulnerablecode.fetch_vulnerabilities(dependencies, logger=self.log)
65+
vulnerablecode.fetch_vulnerabilities(
66+
packages=dependencies,
67+
ignore_set=self.project.ignored_vulnerabilities_set,
68+
logger=self.log,
69+
)

scanpipe/pipes/vulnerablecode.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,19 @@ def bulk_search_by_cpes(
202202
return request_post(url, data, timeout)
203203

204204

205-
def fetch_vulnerabilities(packages, chunk_size=1000, logger=logger.info):
205+
def filter_vulnerabilities(vulnerabilities, ignore_set):
206+
"""Filter out vulnerabilities based on a list of ignored IDs and aliases."""
207+
return [
208+
vulnerability
209+
for vulnerability in vulnerabilities
210+
if vulnerability.get("vulnerability_id") not in ignore_set
211+
and not any(alias in ignore_set for alias in vulnerability.get("aliases", []))
212+
]
213+
214+
215+
def fetch_vulnerabilities(
216+
packages, chunk_size=1000, logger=logger.info, ignore_set=None
217+
):
206218
"""
207219
Fetch and store vulnerabilities for each provided ``packages``.
208220
The PURLs are used for the lookups in batch of ``chunk_size`` per request.
@@ -217,7 +229,12 @@ def fetch_vulnerabilities(packages, chunk_size=1000, logger=logger.info):
217229
unsaved_objects = []
218230
for package in packages:
219231
if package_data := vulnerabilities_by_purl.get(package.package_url):
220-
if affected_by := package_data.get("affected_by_vulnerabilities", []):
232+
affected_by = package_data.get("affected_by_vulnerabilities", [])
233+
234+
if ignore_set and affected_by:
235+
affected_by = filter_vulnerabilities(affected_by, ignore_set)
236+
237+
if affected_by:
221238
package.affected_by_vulnerabilities = affected_by
222239
unsaved_objects.append(package)
223240

scanpipe/templates/scanpipe/project_settings.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,18 @@
7676
{{ form.ignored_dependency_scopes.help_text|safe|linebreaksbr }}
7777
</div>
7878
</div>
79+
80+
<div class="field">
81+
<label class="label" for="{{ form.ignored_vulnerabilities.id_for_label }}">
82+
{{ form.ignored_vulnerabilities.label }}
83+
</label>
84+
<div class="control">
85+
{{ form.ignored_vulnerabilities }}
86+
</div>
87+
<div class="help">
88+
{{ form.ignored_vulnerabilities.help_text|safe|linebreaksbr }}
89+
</div>
90+
</div>
7991
</div>
8092
</div>
8193

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
product_name: My Product Name
22
product_version: '1.0'
33
ignored_patterns:
4-
- '*.tmp'
5-
- 'tests/*'
4+
- '*.tmp'
5+
- 'tests/*'
66
ignored_dependency_scopes:
77
- package_type: npm
88
scope: devDependencies
99
- package_type: pypi
1010
scope: tests
11+
ignored_vulnerabilities:
12+
- VCID-q4q6-yfng-aaag
13+
- CVE-2024-27351
14+
- GHSA-vm8q-m57g-pff3

0 commit comments

Comments
 (0)