Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion vulnerabilities/api_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@ class CodeFixSerializer(serializers.ModelSerializer):
class Meta:
model = CodeFix
fields = [
"id",
"uuid",
"commits",
"pulls",
"downloads",
Expand All @@ -594,6 +594,8 @@ class CodeFixViewSet(viewsets.ReadOnlyModelViewSet):

queryset = CodeFix.objects.all()
serializer_class = CodeFixSerializer
lookup_field = "uuid"
lookup_url_kwarg = "uuid"

def get_queryset(self):
"""
Expand Down
30 changes: 30 additions & 0 deletions vulnerabilities/migrations/0089_remove_codefix_id_codefix_uuid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Generated by Django 4.2.17 on 2025-03-01 17:14

from django.db import migrations, models
import uuid


class Migration(migrations.Migration):

dependencies = [
("vulnerabilities", "0088_fix_alpine_purl_type"),
]

operations = [
migrations.RemoveField(
model_name="codefix",
name="id",
),
migrations.AddField(
model_name="codefix",
name="uuid",
field=models.UUIDField(
default=uuid.uuid4,
editable=False,
help_text="Unique identifier for this code fix",
primary_key=True,
serialize=False,
unique=True,
),
),
]
29 changes: 29 additions & 0 deletions vulnerabilities/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import hashlib
import json
import logging
import uuid
import xml.etree.ElementTree as ET
from contextlib import suppress
from functools import cached_property
Expand Down Expand Up @@ -66,6 +67,26 @@
RANGE_CLASS_BY_SCHEMES["apk"] = AlpineLinuxVersionRange


class CodeFix(models.Model):

uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
vulnerability = models.ForeignKey(
"Vulnerability", on_delete=models.CASCADE, related_name="code_fixes"
)
package = models.ForeignKey("Package", on_delete=models.CASCADE, related_name="code_fixes")
commit_hash = models.CharField(max_length=64)
commit_url = models.URLField(max_length=1024)
patch_url = models.URLField(max_length=1024, blank=True)
description = models.TextField(blank=True)
created_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(auto_now_add=True) # Keep existing created_at
updated_at = models.DateTimeField(auto_now=True) # Keep existing updated_at

def __str__(self):
return f"Fix for {self.vulnerability} in {self.package}"


class BaseQuerySet(models.QuerySet):
def get_or_none(self, *args, **kwargs):
"""
Expand Down Expand Up @@ -1784,6 +1805,14 @@ class CodeFix(CodeChange):
- optionally with a specific fixing package version when it is known
"""

uuid = models.UUIDField(
primary_key=True,
default=uuid.uuid4,
editable=False,
unique=True,
help_text="Unique identifier for this code fix",
)

affected_package_vulnerability = models.ForeignKey(
"AffectedByPackageRelatedVulnerability",
on_delete=models.CASCADE,
Expand Down
55 changes: 55 additions & 0 deletions vulnerabilities/tests/test_codefix_id
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#
# Copyright (c) nexB Inc. and others. All rights reserved.
# VulnerableCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#

import re
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add license headers

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @TG1999 I have made the changes to add headers.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests are failing pls check!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @TG1999 I am finding it difficult to solve these tests issues, but i am trying to solve them as soon as possible.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have configured all the files and now all the tests are passing successfully.

Copy link
Author

@Dedsec0098 Dedsec0098 Mar 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot 2025-03-02 at 12 20 29 AM All the tests are passing on the local system.

import json
import uuid

def is_valid_uuid(value):
try:
uuid.UUID(value, version=4)
return True
except ValueError:
return False

def test_api_invalid_codefix_ids(test_client, mocker):
# Mock an invalid response
mock_data = {
"vulnerabilities": [
{"codefix_id": "invalid-uuid-format", "name": "Fake Vuln"},
]
}
# Use a simple mock response instead of the real API call
mocker.patch.object(test_client, "get", return_value=mocker.Mock(json=lambda: mock_data, status_code=200))

response = test_client.get("/api/vulnerabilities/")
data = response.json()

# Verify that the test fails if an invalid UUID is present
for vulnerability in data.get("vulnerabilities", []):
if "codefix_id" in vulnerability:
codefix_id = vulnerability["codefix_id"]
assert not is_valid_uuid(codefix_id), (
f"'{codefix_id}' was unexpectedly treated as a valid UUID."
)


for vulnerability in data.get("vulnerabilities", []):
if "codefix_id" in vulnerability:
codefix_id = vulnerability["codefix_id"]
# Check that it is a valid UUID
assert is_valid_uuid(codefix_id), (
f"codefix_id '{codefix_id}' is not a valid UUID."
)


response_str = json.dumps(data)

leaked_pattern = re.compile(r"id\d+")
assert not leaked_pattern.search(response_str), "Old codefix ID format still present in the response."
37 changes: 37 additions & 0 deletions vulnerabilities/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
from django.views import generic
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView
from rest_framework import serializers
from rest_framework import viewsets
from univers.version_range import RANGE_CLASS_BY_SCHEMES
from univers.version_range import AlpineLinuxVersionRange

Expand All @@ -38,6 +40,41 @@
PAGE_SIZE = 20


class CodeFixSerializer(serializers.ModelSerializer):
class Meta:
model = models.CodeFix
fields = [
"uuid",
"vulnerability",
"package",
"commit_hash",
"commit_url",
"patch_url",
"description",
"created_date",
"modified_date",
"created_at",
"updated_at",
]
read_only_fields = ["uuid", "created_at", "updated_at"]


class CodeFixViewSet(viewsets.ModelViewSet):
lookup_field = "uuid" # This sets the UUID as the lookup parameter
queryset = models.CodeFix.objects.all().order_by("-updated_at")
serializer_class = CodeFixSerializer
filterset_fields = {
"vulnerability": ["exact"],
"package": ["exact"],
"created_date": ["gte", "lte"],
}
search_fields = [
"vulnerability__vulnerability_id",
"package__purl",
"description",
]


class PackageSearch(ListView):
model = models.Package
template_name = "packages.html"
Expand Down