Skip to content

Commit 4027cbf

Browse files
authored
Merge branch 'main' into osv-cvss4
2 parents 8fef8de + ab99939 commit 4027cbf

File tree

13 files changed

+534
-11
lines changed

13 files changed

+534
-11
lines changed

docker-compose.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ services:
1313

1414
vulnerablecode_redis:
1515
image: redis
16-
# Enable redis data persistence using the "Append Only File" with the
17-
# default policy of fsync every second. See https://redis.io/topics/persistence
18-
command: redis-server --appendonly yes
1916
volumes:
2017
- vulnerablecode_redis_data:/data
2118
restart: always

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ dateparser==1.1.1
2727
decorator==5.1.1
2828
defusedxml==0.7.1
2929
distro==1.7.0
30-
Django==4.2.22
30+
Django==4.2.25
3131
django-altcha==0.2.0
3232
django-crispy-forms==2.3
3333
django-environ==0.11.2

vulnerabilities/improvers/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
enhance_with_metasploit as enhance_with_metasploit_v2,
3131
)
3232
from vulnerabilities.pipelines.v2_improvers import flag_ghost_packages as flag_ghost_packages_v2
33+
from vulnerabilities.pipelines.v2_improvers import unfurl_version_range as unfurl_version_range_v2
3334
from vulnerabilities.utils import create_registry
3435

3536
IMPROVERS_REGISTRY = create_registry(
@@ -67,6 +68,7 @@
6768
compute_package_risk_v2.ComputePackageRiskPipeline,
6869
compute_version_rank_v2.ComputeVersionRankPipeline,
6970
compute_advisory_todo_v2.ComputeToDo,
71+
unfurl_version_range_v2.UnfurlVersionRangePipeline,
7072
compute_advisory_todo.ComputeToDo,
7173
]
7274
)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Generated by Django 4.2.22 on 2025-09-03 09:45
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("vulnerabilities", "0101_advisorytodov2_todorelatedadvisoryv2_and_more"),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name="impactedpackage",
15+
name="affecting_vers",
16+
field=models.TextField(
17+
blank=True,
18+
help_text="VersionRange expression for package vulnerable to this impact.",
19+
null=True,
20+
),
21+
),
22+
migrations.AlterField(
23+
model_name="impactedpackage",
24+
name="base_purl",
25+
field=models.CharField(
26+
help_text="Version less PURL related to impacted range.", max_length=500
27+
),
28+
),
29+
migrations.AlterField(
30+
model_name="impactedpackage",
31+
name="fixed_vers",
32+
field=models.TextField(
33+
blank=True,
34+
help_text="VersionRange expression for packages fixing the vulnerable package in this impact.",
35+
null=True,
36+
),
37+
),
38+
]
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Generated by Django 4.2.22 on 2025-10-31 14:49
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("vulnerabilities", "0102_alter_impactedpackage_affecting_vers_and_more"),
10+
]
11+
12+
operations = [
13+
migrations.CreateModel(
14+
name="CodeCommit",
15+
fields=[
16+
(
17+
"id",
18+
models.AutoField(
19+
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
20+
),
21+
),
22+
(
23+
"commit_hash",
24+
models.CharField(
25+
help_text="Unique commit identifier (e.g., SHA).", max_length=64
26+
),
27+
),
28+
(
29+
"vcs_url",
30+
models.URLField(
31+
help_text="URL of the repository containing the commit.", max_length=1024
32+
),
33+
),
34+
(
35+
"commit_rank",
36+
models.IntegerField(
37+
default=0,
38+
help_text="Rank of the commit to support ordering by commit. Rank zero means the rank has not been defined yet",
39+
),
40+
),
41+
(
42+
"commit_author",
43+
models.CharField(
44+
blank=True, help_text="Author of the commit.", max_length=100, null=True
45+
),
46+
),
47+
(
48+
"commit_date",
49+
models.DateTimeField(
50+
blank=True,
51+
help_text="Timestamp indicating when this commit was created.",
52+
null=True,
53+
),
54+
),
55+
(
56+
"commit_message",
57+
models.TextField(
58+
blank=True, help_text="Commit message or description.", null=True
59+
),
60+
),
61+
],
62+
options={
63+
"unique_together": {("commit_hash", "vcs_url")},
64+
},
65+
),
66+
migrations.AddField(
67+
model_name="impactedpackage",
68+
name="affecting_commits",
69+
field=models.ManyToManyField(
70+
help_text="Commits introducing this impact.",
71+
related_name="affecting_commits_in_impacts",
72+
to="vulnerabilities.codecommit",
73+
),
74+
),
75+
migrations.AddField(
76+
model_name="impactedpackage",
77+
name="fixed_by_commits",
78+
field=models.ManyToManyField(
79+
help_text="Commits fixing this impact.",
80+
related_name="fixing_commits_in_impacts",
81+
to="vulnerabilities.codecommit",
82+
),
83+
),
84+
]

vulnerabilities/models.py

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
from functools import cached_property
1717
from itertools import groupby
1818
from operator import attrgetter
19+
from traceback import format_exc as traceback_format_exc
20+
from typing import List
1921
from typing import Union
2022
from urllib.parse import urljoin
2123

@@ -2927,17 +2929,19 @@ class ImpactedPackage(models.Model):
29272929

29282930
base_purl = models.CharField(
29292931
max_length=500,
2930-
blank=True,
2932+
blank=False,
29312933
help_text="Version less PURL related to impacted range.",
29322934
)
29332935

29342936
affecting_vers = models.TextField(
29352937
blank=True,
2938+
null=True,
29362939
help_text="VersionRange expression for package vulnerable to this impact.",
29372940
)
29382941

29392942
fixed_vers = models.TextField(
29402943
blank=True,
2944+
null=True,
29412945
help_text="VersionRange expression for packages fixing the vulnerable package in this impact.",
29422946
)
29432947

@@ -2953,6 +2957,18 @@ class ImpactedPackage(models.Model):
29532957
help_text="Packages vulnerable to this impact.",
29542958
)
29552959

2960+
affecting_commits = models.ManyToManyField(
2961+
"CodeCommit",
2962+
related_name="affecting_commits_in_impacts",
2963+
help_text="Commits introducing this impact.",
2964+
)
2965+
2966+
fixed_by_commits = models.ManyToManyField(
2967+
"CodeCommit",
2968+
related_name="fixing_commits_in_impacts",
2969+
help_text="Commits fixing this impact.",
2970+
)
2971+
29562972
created_at = models.DateTimeField(
29572973
auto_now_add=True,
29582974
db_index=True,
@@ -3065,6 +3081,41 @@ def get_or_create_from_purl(self, purl: Union[PackageURL, str]):
30653081

30663082
return package, is_created
30673083

3084+
def bulk_get_or_create_from_purls(self, purls: List[Union[PackageURL, str]]):
3085+
"""
3086+
Return new or existing Packages given ``purls`` list of PackageURL object or PURL string.
3087+
"""
3088+
purl_strings = [str(p) for p in purls]
3089+
existing_packages = PackageV2.objects.filter(package_url__in=purl_strings)
3090+
existing_purls = set(existing_packages.values_list("package_url", flat=True))
3091+
3092+
all_packages = list(existing_packages)
3093+
packages_to_create = []
3094+
for purl in purls:
3095+
if str(purl) in existing_purls:
3096+
continue
3097+
3098+
purl_dict = purl_to_dict(purl)
3099+
purl = PackageURL(**purl_dict)
3100+
3101+
normalized = normalize_purl(purl=purl)
3102+
for name, value in purl_to_dict(normalized).items():
3103+
setattr(self, name, value)
3104+
3105+
purl_dict["package_url"] = str(normalized)
3106+
purl_dict["plain_package_url"] = str(utils.plain_purl(normalized))
3107+
3108+
packages_to_create.append(PackageV2(**purl_dict))
3109+
3110+
try:
3111+
new_packages = PackageV2.objects.bulk_create(packages_to_create)
3112+
except Exception as e:
3113+
logging.error(f"Error creating PackageV2: {e} \n {traceback_format_exc()}")
3114+
return []
3115+
3116+
all_packages.extend(new_packages)
3117+
return all_packages
3118+
30683119
def only_vulnerable(self):
30693120
return self._vulnerable(True)
30703121

@@ -3334,3 +3385,32 @@ class AdvisoryExploit(models.Model):
33343385
@property
33353386
def get_known_ransomware_campaign_use_type(self):
33363387
return "Known" if self.known_ransomware_campaign_use else "Unknown"
3388+
3389+
3390+
class CodeCommit(models.Model):
3391+
"""
3392+
A CodeCommit Represents a single VCS commit (e.g., Git) related to a ImpactedPackage.
3393+
"""
3394+
3395+
commit_hash = models.CharField(max_length=64, help_text="Unique commit identifier (e.g., SHA).")
3396+
vcs_url = models.URLField(
3397+
max_length=1024, help_text="URL of the repository containing the commit."
3398+
)
3399+
3400+
commit_rank = models.IntegerField(
3401+
default=0,
3402+
help_text="Rank of the commit to support ordering by commit. Rank "
3403+
"zero means the rank has not been defined yet",
3404+
)
3405+
commit_author = models.CharField(
3406+
max_length=100, null=True, blank=True, help_text="Author of the commit."
3407+
)
3408+
commit_date = models.DateTimeField(
3409+
null=True, blank=True, help_text="Timestamp indicating when this commit was created."
3410+
)
3411+
commit_message = models.TextField(
3412+
null=True, blank=True, help_text="Commit message or description."
3413+
)
3414+
3415+
class Meta:
3416+
unique_together = ("commit_hash", "vcs_url")

0 commit comments

Comments
 (0)