Skip to content

Commit bc8af88

Browse files
Merge branch 'main' into fix_dependencies
2 parents 930674d + 584b077 commit bc8af88

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+3789
-3358
lines changed

.github/workflows/docs.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on: [push, pull_request]
44

55
jobs:
66
build:
7-
runs-on: ubuntu-20.04
7+
runs-on: ubuntu-22.04
88

99
strategy:
1010
max-parallel: 4

.github/workflows/main.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ env:
99

1010
jobs:
1111
build:
12-
runs-on: ubuntu-20.04
12+
runs-on: ubuntu-22.04
1313

1414
services:
1515
postgres:

.github/workflows/pypi-release.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ on:
2121
jobs:
2222
build-pypi-distribs:
2323
name: Build and publish library to PyPI
24-
runs-on: ubuntu-20.04
24+
runs-on: ubuntu-22.04
2525

2626
steps:
2727
- uses: actions/checkout@master

CHANGELOG.rst

+21
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,27 @@ Release notes
22
=============
33

44

5+
Version v36.0.0
6+
---------------------
7+
8+
- Add indexes for models https://github.com/aboutcode-org/vulnerablecode/pull/1701
9+
- Add fixed by package in V2 API https://github.com/aboutcode-org/vulnerablecode/pull/1706
10+
- Add tests for num queries for views https://github.com/aboutcode-org/vulnerablecode/pull/1730
11+
- Add postgresql conf in docker-compose https://github.com/aboutcode-org/vulnerablecode/pull/1733
12+
- Add default postgresql.conf for local docker build https://github.com/aboutcode-org/vulnerablecode/pull/1735
13+
- Add models for CodeFix https://github.com/aboutcode-org/vulnerablecode/pull/1704
14+
- Migrate Alpine Linux importer to aboutcode pipeline https://github.com/aboutcode-org/vulnerablecode/pull/1737
15+
- VCIO-next: Allow CVSS3.1 Severities in NVD https://github.com/aboutcode-org/vulnerablecode/pull/1738
16+
- Add Pipeline to add missing CVSSV3.1 scores https://github.com/aboutcode-org/vulnerablecode/pull/1740
17+
- Add description and reference to the latest release on the homepage https://github.com/aboutcode-org/vulnerablecode/pull/1743
18+
- Use proper apk package type for Alpine https://github.com/aboutcode-org/vulnerablecode/pull/1739
19+
- Optimize vulnerabilities view https://github.com/aboutcode-org/vulnerablecode/pull/1728
20+
- Add CWE support in multiple importers https://github.com/aboutcode-org/vulnerablecode/pull/1526
21+
- Fast content ID migration https://github.com/aboutcode-org/vulnerablecode/pull/1795
22+
- Add captcha for user signup https://github.com/aboutcode-org/vulnerablecode/pull/1822
23+
- Move the package search box to the top by @keshav-space in https://github.com/aboutcode-org/vulnerablecode/pull/1832
24+
25+
526
Version v35.1.0
627
---------------------
728

docs/source/conf.py

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
"https://www.softwaretestinghelp.com/how-to-write-good-bug-report/", # Cloudflare protection
3737
"https://www.openssl.org/news/vulnerabilities.xml", # OpenSSL legacy advisory URL, not longer available
3838
"https://example.org/api/non-existent-packages",
39+
"https://github.com/aboutcode-org/vulnerablecode/pull/495/commits",
40+
"https://nvd.nist.gov/products/cpe",
3941
]
4042

4143
# Add any Sphinx extension module names here, as strings. They can be

requirements.txt

+4-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ charset-normalizer==2.0.12
2020
click==8.1.2
2121
coreapi==2.3.3
2222
coreschema==0.0.4
23-
cryptography==43.0.1
23+
cryptography==44.0.1
2424
crispy-bootstrap4==2024.1
2525
cwe2==3.0.0
2626
cvss==2.4
@@ -29,10 +29,11 @@ decorator==5.1.1
2929
defusedxml==0.7.1
3030
dephell_specifier==0.3.0
3131
distro==1.7.0
32-
Django==4.2.17
32+
Django==4.2.20
3333
django-crispy-forms==2.3
3434
django-environ==0.11.2
3535
django-filter==24.3
36+
django-recaptcha==4.0.0
3637
django-widget-tweaks==1.5.0
3738
djangorestframework==3.15.2
3839
doc8==0.11.1
@@ -55,7 +56,7 @@ ipython==8.10.0
5556
isort==5.10.1
5657
itypes==1.2.0
5758
jedi==0.18.1
58-
Jinja2==3.1.5
59+
Jinja2==3.1.6
5960
jsonschema==3.2.0
6061
license-expression==30.3.1
6162
lxml==4.9.1

setup.cfg

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = vulnerablecode
3-
version = 35.1.0
3+
version = 36.0.0
44
license = Apache-2.0 AND CC-BY-SA-4.0
55

66
# description must be on ONE line https://github.com/pypa/setuptools/issues/1390
@@ -99,6 +99,8 @@ install_requires =
9999
python-dotenv
100100
texttable
101101

102+
django-recaptcha>=4.0.0
103+
102104

103105
[options.extras_require]
104106
dev =

vulnerabilities/forms.py

+6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
from django import forms
1111
from django.core.validators import validate_email
12+
from django_recaptcha.fields import ReCaptchaField
13+
from django_recaptcha.widgets import ReCaptchaV2Checkbox
1214

1315
from vulnerabilities.models import ApiUser
1416

@@ -38,6 +40,10 @@ class ApiUserCreationForm(forms.ModelForm):
3840
Support a simplified creation for API-only users directly from the UI.
3941
"""
4042

43+
captcha = ReCaptchaField(
44+
error_messages={"required": ("Captcha is required")}, widget=ReCaptchaV2Checkbox
45+
)
46+
4147
class Meta:
4248
model = ApiUser
4349
fields = (

vulnerabilities/import_runner.py

+39-28
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
from django.core.exceptions import ValidationError
1717
from django.db import transaction
18+
from django.db.models.query import QuerySet
1819

1920
from vulnerabilities.importer import AdvisoryData
2021
from vulnerabilities.importer import Importer
@@ -96,25 +97,37 @@ def process_advisories(
9697
Insert advisories into the database
9798
Return the number of inserted advisories.
9899
"""
100+
from vulnerabilities.pipes.advisory import get_or_create_aliases
101+
from vulnerabilities.utils import compute_content_id
102+
99103
count = 0
100104
advisories = []
101105
for data in advisory_datas:
106+
content_id = compute_content_id(advisory_data=data)
107+
advisory = {
108+
"summary": data.summary,
109+
"affected_packages": [pkg.to_dict() for pkg in data.affected_packages],
110+
"references": [ref.to_dict() for ref in data.references],
111+
"date_published": data.date_published,
112+
"weaknesses": data.weaknesses,
113+
"created_by": importer_name,
114+
"date_collected": datetime.datetime.now(tz=datetime.timezone.utc),
115+
}
102116
try:
117+
aliases = get_or_create_aliases(aliases=data.aliases)
103118
obj, created = Advisory.objects.get_or_create(
104-
aliases=data.aliases,
105-
summary=data.summary,
106-
affected_packages=[pkg.to_dict() for pkg in data.affected_packages],
107-
references=[ref.to_dict() for ref in data.references],
108-
date_published=data.date_published,
109-
weaknesses=data.weaknesses,
110-
defaults={
111-
"created_by": importer_name,
112-
"date_collected": datetime.datetime.now(tz=datetime.timezone.utc),
113-
},
119+
unique_content_id=content_id,
114120
url=data.url,
121+
defaults=advisory,
115122
)
123+
obj.aliases.add(*aliases)
116124
if not obj.date_imported:
117125
advisories.append(obj)
126+
except Advisory.MultipleObjectsReturned:
127+
logger.error(
128+
f"Multiple Advisories returned: unique_content_id: {content_id}, url: {data.url}, advisory: {advisory!r}"
129+
)
130+
raise
118131
except Exception as e:
119132
logger.error(
120133
f"Error while processing {data!r} with aliases {data.aliases!r}: {e!r} \n {traceback_format_exc()}"
@@ -148,6 +161,8 @@ def process_inferences(inferences: List[Inference], advisory: Advisory, improver
148161
erroneous. Also, the atomic transaction for every advisory and its
149162
inferences makes sure that date_imported of advisory is consistent.
150163
"""
164+
from vulnerabilities.pipes.advisory import get_or_create_aliases
165+
151166
inferences_processed_count = 0
152167

153168
if not inferences:
@@ -157,9 +172,10 @@ def process_inferences(inferences: List[Inference], advisory: Advisory, improver
157172
logger.info(f"Improving advisory id: {advisory.id}")
158173

159174
for inference in inferences:
175+
aliases = get_or_create_aliases(inference.aliases)
160176
vulnerability = get_or_create_vulnerability_and_aliases(
161177
vulnerability_id=inference.vulnerability_id,
162-
aliases=inference.aliases,
178+
aliases=aliases,
163179
summary=inference.summary,
164180
advisory=advisory,
165181
)
@@ -265,14 +281,13 @@ def create_valid_vulnerability_reference(url, reference_id=None):
265281

266282

267283
def get_or_create_vulnerability_and_aliases(
268-
aliases: List[str], vulnerability_id=None, summary=None, advisory=None
284+
aliases: QuerySet, vulnerability_id=None, summary=None, advisory=None
269285
):
270286
"""
271287
Get or create vulnerabilitiy and aliases such that all existing and new
272288
aliases point to the same vulnerability
273289
"""
274-
aliases = set(alias.strip() for alias in aliases if alias and alias.strip())
275-
new_alias_names, existing_vulns = get_vulns_for_aliases_and_get_new_aliases(aliases)
290+
new_aliases, existing_vulns = get_vulns_for_aliases_and_get_new_aliases(aliases)
276291

277292
# All aliases must point to the same vulnerability
278293
vulnerability = None
@@ -310,11 +325,11 @@ def get_or_create_vulnerability_and_aliases(
310325
# f"Inconsistent summary for {vulnerability.vulnerability_id}. "
311326
# f"Existing: {vulnerability.summary!r}, provided: {summary!r}"
312327
# )
313-
associate_vulnerability_with_aliases(vulnerability=vulnerability, aliases=new_alias_names)
328+
associate_vulnerability_with_aliases(vulnerability=vulnerability, aliases=new_aliases)
314329
else:
315330
try:
316331
vulnerability = create_vulnerability_and_add_aliases(
317-
aliases=new_alias_names, summary=summary
332+
aliases=new_aliases, summary=summary
318333
)
319334
importer_name = get_importer_name(advisory)
320335
VulnerabilityChangeLog.log_import(
@@ -324,24 +339,22 @@ def get_or_create_vulnerability_and_aliases(
324339
)
325340
except Exception as e:
326341
logger.error(
327-
f"Cannot create vulnerability with summary {summary!r} and {new_alias_names!r} {e!r}.\n{traceback_format_exc()}."
342+
f"Cannot create vulnerability with summary {summary!r} and {new_aliases!r} {e!r}.\n{traceback_format_exc()}."
328343
)
329344
return
330345

331346
return vulnerability
332347

333348

334-
def get_vulns_for_aliases_and_get_new_aliases(aliases):
349+
def get_vulns_for_aliases_and_get_new_aliases(aliases: QuerySet):
335350
"""
336351
Return ``new_aliases`` that are not in the database and
337352
``existing_vulns`` that point to the given ``aliases``.
338353
"""
339-
new_aliases = set(aliases)
340-
existing_vulns = set()
341-
for alias in Alias.objects.filter(alias__in=aliases):
342-
existing_vulns.add(alias.vulnerability)
343-
new_aliases.remove(alias.alias)
344-
return new_aliases, existing_vulns
354+
new_aliases = aliases.filter(vulnerability__isnull=True)
355+
existing_vulns = [alias.vulnerability for alias in aliases.filter(vulnerability__isnull=False)]
356+
357+
return new_aliases, list(set(existing_vulns))
345358

346359

347360
@transaction.atomic
@@ -360,7 +373,5 @@ def create_vulnerability_and_add_aliases(aliases, summary):
360373

361374

362375
def associate_vulnerability_with_aliases(aliases, vulnerability):
363-
for alias_name in aliases:
364-
alias = Alias(alias=alias_name, vulnerability=vulnerability)
365-
alias.save()
366-
logger.info(f"New alias for {vulnerability!r}: {alias_name}")
376+
aliases.update(vulnerability=vulnerability)
377+
logger.info(f"New alias for {vulnerability!r}: {aliases}")

0 commit comments

Comments
 (0)