Skip to content

Commit caab3c0

Browse files
authored
Merge branch 'main' into Page-Updated
2 parents 1851616 + 56eb442 commit caab3c0

27 files changed

+1419
-181
lines changed

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ else
4242
SUDO_POSTGRES=
4343
endif
4444

45+
ifeq ($(UNAME), Darwin)
46+
GET_SECRET_KEY=`head /dev/urandom | base64 | head -c50`
47+
endif
48+
4549
virtualenv:
4650
@echo "-> Bootstrap the virtualenv with PYTHON_EXE=${PYTHON_EXE}"
4751
@${PYTHON_EXE} ${VIRTUALENV_PYZ} --never-download --no-periodic-update ${VENV}

docker-compose.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ version: "3"
33
services:
44
db:
55
image: postgres:13
6+
command: -c config_file=/etc/postgresql/postgresql.conf
67
env_file:
78
- docker.env
89
volumes:
910
- db_data:/var/lib/postgresql/data/
11+
- ./etc/postgresql/postgresql.conf:/etc/postgresql/postgresql.conf
1012

1113
vulnerablecode:
1214
build: .

etc/postgresql/postgresql.conf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Default configuration for development build
2+
# DB Version: 13
3+
# OS Type: linux
4+
# DB Type: development
5+
# Data Storage: local
6+
7+
listen_addresses = '*'
8+
max_connections = 100
9+
shared_buffers = 128MB
10+
dynamic_shared_memory_type = posix
11+
max_wal_size = 1GB
12+
min_wal_size = 80MB

requirements.txt

Lines changed: 2 additions & 2 deletions
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.16
30+
Django==4.2.17
3131
django-crispy-forms==2.3
3232
django-environ==0.11.2
3333
django-filter==24.3
@@ -53,7 +53,7 @@ ipython==8.10.0
5353
isort==5.10.1
5454
itypes==1.2.0
5555
jedi==0.18.1
56-
Jinja2==3.1.4
56+
Jinja2==3.1.5
5757
jsonschema==3.2.0
5858
license-expression==30.3.1
5959
lxml==4.9.1

vulnerabilities/api_v2.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from rest_framework.response import Response
2222
from rest_framework.reverse import reverse
2323

24+
from vulnerabilities.models import CodeFix
2425
from vulnerabilities.models import Package
2526
from vulnerabilities.models import Vulnerability
2627
from vulnerabilities.models import VulnerabilityReference
@@ -198,14 +199,25 @@ def get_affected_by_vulnerabilities(self, obj):
198199
Return a dictionary with vulnerabilities as keys and their details, including fixed_by_packages.
199200
"""
200201
result = {}
202+
request = self.context.get("request")
201203
for vuln in getattr(obj, "prefetched_affected_vulnerabilities", []):
202204
fixed_by_package = vuln.fixed_by_packages.first()
203205
purl = None
204206
if fixed_by_package:
205207
purl = fixed_by_package.package_url
208+
# Get code fixed for a vulnerability
209+
code_fixes = CodeFix.objects.filter(
210+
affected_package_vulnerability__vulnerability=vuln
211+
).distinct()
212+
code_fix_urls = [
213+
reverse("codefix-detail", args=[code_fix.id], request=request)
214+
for code_fix in code_fixes
215+
]
216+
206217
result[vuln.vulnerability_id] = {
207218
"vulnerability_id": vuln.vulnerability_id,
208219
"fixed_by_packages": purl,
220+
"code_fixes": code_fix_urls,
209221
}
210222
return result
211223

@@ -521,3 +533,76 @@ def lookup(self, request):
521533

522534
qs = self.get_queryset().for_purls([purl]).with_is_vulnerable()
523535
return Response(PackageV2Serializer(qs, many=True, context={"request": request}).data)
536+
537+
538+
class CodeFixSerializer(serializers.ModelSerializer):
539+
"""
540+
Serializer for the CodeFix model.
541+
Provides detailed information about a code fix.
542+
"""
543+
544+
affected_vulnerability_id = serializers.CharField(
545+
source="affected_package_vulnerability.vulnerability.vulnerability_id",
546+
read_only=True,
547+
help_text="ID of the affected vulnerability.",
548+
)
549+
affected_package_purl = serializers.CharField(
550+
source="affected_package_vulnerability.package.package_url",
551+
read_only=True,
552+
help_text="PURL of the affected package.",
553+
)
554+
fixed_package_purl = serializers.CharField(
555+
source="fixed_package_vulnerability.package.package_url",
556+
read_only=True,
557+
help_text="PURL of the fixing package (if available).",
558+
)
559+
created_at = serializers.DateTimeField(
560+
format="%Y-%m-%dT%H:%M:%SZ",
561+
read_only=True,
562+
help_text="Timestamp when the code fix was created.",
563+
)
564+
updated_at = serializers.DateTimeField(
565+
format="%Y-%m-%dT%H:%M:%SZ",
566+
read_only=True,
567+
help_text="Timestamp when the code fix was last updated.",
568+
)
569+
570+
class Meta:
571+
model = CodeFix
572+
fields = [
573+
"id",
574+
"commits",
575+
"pulls",
576+
"downloads",
577+
"patch",
578+
"affected_vulnerability_id",
579+
"affected_package_purl",
580+
"fixed_package_purl",
581+
"notes",
582+
"references",
583+
"is_reviewed",
584+
"created_at",
585+
"updated_at",
586+
]
587+
read_only_fields = ["created_at", "updated_at"]
588+
589+
590+
class CodeFixViewSet(viewsets.ReadOnlyModelViewSet):
591+
"""
592+
API endpoint that allows viewing CodeFix entries.
593+
"""
594+
595+
queryset = CodeFix.objects.all()
596+
serializer_class = CodeFixSerializer
597+
598+
def get_queryset(self):
599+
"""
600+
Optionally filter by vulnerability ID.
601+
"""
602+
queryset = super().get_queryset()
603+
vulnerability_id = self.request.query_params.get("vulnerability_id")
604+
if vulnerability_id:
605+
queryset = queryset.filter(
606+
affected_package_vulnerability__vulnerability__vulnerability_id=vulnerability_id
607+
)
608+
return queryset

vulnerabilities/importers/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
# See https://aboutcode.org for more information about nexB OSS projects.
88
#
99

10-
from vulnerabilities.importers import alpine_linux
1110
from vulnerabilities.importers import apache_httpd
1211
from vulnerabilities.importers import apache_kafka
1312
from vulnerabilities.importers import apache_tomcat
@@ -35,6 +34,7 @@
3534
from vulnerabilities.importers import vulnrichment
3635
from vulnerabilities.importers import xen
3736
from vulnerabilities.pipelines import VulnerableCodeBaseImporterPipeline
37+
from vulnerabilities.pipelines import alpine_linux_importer
3838
from vulnerabilities.pipelines import github_importer
3939
from vulnerabilities.pipelines import gitlab_importer
4040
from vulnerabilities.pipelines import nginx_importer
@@ -44,7 +44,6 @@
4444
from vulnerabilities.pipelines import pysec_importer
4545

4646
IMPORTERS_REGISTRY = [
47-
alpine_linux.AlpineImporter,
4847
openssl.OpensslImporter,
4948
redhat.RedhatImporter,
5049
debian.DebianImporter,
@@ -78,6 +77,7 @@
7877
github_importer.GitHubAPIImporterPipeline,
7978
nvd_importer.NVDImporterPipeline,
8079
pysec_importer.PyPIImporterPipeline,
80+
alpine_linux_importer.AlpineLinuxImporterPipeline,
8181
]
8282

8383
IMPORTERS_REGISTRY = {

vulnerabilities/improvers/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
from vulnerabilities.improvers import valid_versions
1111
from vulnerabilities.improvers import vulnerability_status
1212
from vulnerabilities.pipelines import VulnerableCodePipeline
13+
from vulnerabilities.pipelines import add_cvss31_to_CVEs
14+
from vulnerabilities.pipelines import collect_commits
1315
from vulnerabilities.pipelines import compute_package_risk
1416
from vulnerabilities.pipelines import compute_package_version_rank
1517
from vulnerabilities.pipelines import enhance_with_exploitdb
@@ -41,6 +43,8 @@
4143
enhance_with_exploitdb.ExploitDBImproverPipeline,
4244
compute_package_risk.ComputePackageRiskPipeline,
4345
compute_package_version_rank.ComputeVersionRankPipeline,
46+
collect_commits.CollectFixCommitsPipeline,
47+
add_cvss31_to_CVEs.CVEAdvisoryMappingPipeline,
4448
]
4549

4650
IMPROVERS_REGISTRY = {
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# Generated by Django 4.2.16 on 2025-01-08 13:28
2+
3+
from django.db import migrations, models
4+
import django.db.models.deletion
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
("vulnerabilities", "0085_alter_package_is_ghost_alter_package_version_rank_and_more"),
11+
]
12+
13+
operations = [
14+
migrations.CreateModel(
15+
name="CodeFix",
16+
fields=[
17+
(
18+
"id",
19+
models.AutoField(
20+
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
21+
),
22+
),
23+
(
24+
"commits",
25+
models.JSONField(
26+
blank=True,
27+
default=list,
28+
help_text="List of commit identifiers using VCS URLs associated with the code change.",
29+
),
30+
),
31+
(
32+
"pulls",
33+
models.JSONField(
34+
blank=True,
35+
default=list,
36+
help_text="List of pull request URLs associated with the code change.",
37+
),
38+
),
39+
(
40+
"downloads",
41+
models.JSONField(
42+
blank=True,
43+
default=list,
44+
help_text="List of download URLs for the patched code.",
45+
),
46+
),
47+
(
48+
"patch",
49+
models.TextField(
50+
blank=True,
51+
help_text="The code change as a patch in unified diff format.",
52+
null=True,
53+
),
54+
),
55+
(
56+
"notes",
57+
models.TextField(
58+
blank=True,
59+
help_text="Notes or instructions about this code change.",
60+
null=True,
61+
),
62+
),
63+
(
64+
"references",
65+
models.JSONField(
66+
blank=True,
67+
default=list,
68+
help_text="URL references related to this code change.",
69+
),
70+
),
71+
(
72+
"is_reviewed",
73+
models.BooleanField(
74+
default=False, help_text="Indicates if this code change has been reviewed."
75+
),
76+
),
77+
(
78+
"created_at",
79+
models.DateTimeField(
80+
auto_now_add=True,
81+
help_text="Timestamp indicating when this code change was created.",
82+
),
83+
),
84+
(
85+
"updated_at",
86+
models.DateTimeField(
87+
auto_now=True,
88+
help_text="Timestamp indicating when this code change was last updated.",
89+
),
90+
),
91+
(
92+
"affected_package_vulnerability",
93+
models.ForeignKey(
94+
help_text="The affected package version to which this code fix applies.",
95+
on_delete=django.db.models.deletion.CASCADE,
96+
related_name="code_fix",
97+
to="vulnerabilities.affectedbypackagerelatedvulnerability",
98+
),
99+
),
100+
(
101+
"base_package_version",
102+
models.ForeignKey(
103+
blank=True,
104+
help_text="The base package version to which this code change applies.",
105+
null=True,
106+
on_delete=django.db.models.deletion.SET_NULL,
107+
related_name="codechanges",
108+
to="vulnerabilities.package",
109+
),
110+
),
111+
(
112+
"fixed_package_vulnerability",
113+
models.ForeignKey(
114+
blank=True,
115+
help_text="The fixing package version with this code fix",
116+
null=True,
117+
on_delete=django.db.models.deletion.SET_NULL,
118+
related_name="code_fix",
119+
to="vulnerabilities.fixingpackagerelatedvulnerability",
120+
),
121+
),
122+
],
123+
options={
124+
"abstract": False,
125+
},
126+
),
127+
]
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
from django.db import migrations
3+
4+
"""
5+
Update the created_by field on Advisory from the old qualified_name
6+
to the new pipeline_id.
7+
"""
8+
9+
10+
def update_created_by(apps, schema_editor):
11+
from vulnerabilities.pipelines.alpine_linux_importer import AlpineLinuxImporterPipeline
12+
13+
Advisory = apps.get_model("vulnerabilities", "Advisory")
14+
Advisory.objects.filter(created_by="vulnerabilities.importers.alpine_linux.AlpineImporter").update(
15+
created_by=AlpineLinuxImporterPipeline.pipeline_id
16+
)
17+
18+
19+
def reverse_update_created_by(apps, schema_editor):
20+
from vulnerabilities.pipelines.alpine_linux_importer import AlpineLinuxImporterPipeline
21+
22+
Advisory = apps.get_model("vulnerabilities", "Advisory")
23+
Advisory.objects.filter(created_by=AlpineLinuxImporterPipeline.pipeline_id).update(
24+
created_by="vulnerabilities.importers.alpine_linux.AlpineImporter"
25+
)
26+
27+
28+
class Migration(migrations.Migration):
29+
30+
dependencies = [
31+
("vulnerabilities", "0086_codefix"),
32+
]
33+
34+
operations = [
35+
migrations.RunPython(update_created_by, reverse_code=reverse_update_created_by),
36+
]

0 commit comments

Comments
 (0)