diff options
| -rw-r--r-- | checklists/migrations/0007_alter_securityissue_cve_year_number.py | 29 | ||||
| -rw-r--r-- | checklists/models.py | 8 | ||||
| -rw-r--r-- | checklists/tests/test_models.py | 38 |
3 files changed, 73 insertions, 2 deletions
diff --git a/checklists/migrations/0007_alter_securityissue_cve_year_number.py b/checklists/migrations/0007_alter_securityissue_cve_year_number.py new file mode 100644 index 00000000..0bc2811c --- /dev/null +++ b/checklists/migrations/0007_alter_securityissue_cve_year_number.py @@ -0,0 +1,29 @@ +# Generated by Django 6.0.4 on 2026-05-07 02:32 + +import django.core.validators +from django.db import migrations, models + +import checklists.models + + +class Migration(migrations.Migration): + + dependencies = [ + ("checklists", "0006_remove_securityissue_attack_complexity_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="securityissue", + name="cve_year_number", + field=models.CharField( + default=checklists.models.get_cve_default, + max_length=1024, + unique=True, + validators=[ + django.core.validators.RegexValidator(regex="CVE-\\d{4}-\\d{4,5}") + ], + verbose_name="CVE ID", + ), + ), + ] diff --git a/checklists/models.py b/checklists/models.py index ad44dbf7..41b9a2b1 100644 --- a/checklists/models.py +++ b/checklists/models.py @@ -2,7 +2,7 @@ import datetime import json from django.contrib.auth.models import User -from django.core.validators import MaxValueValidator, MinValueValidator +from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator from django.db import models from django.db.models.functions import Cast, Substr from django.shortcuts import reverse @@ -467,7 +467,11 @@ class SecurityIssue(models.Model): choices=[(i, i) for i in ("DSF", "MITRE")], ) cve_year_number = models.CharField( - "CVE ID", max_length=1024, unique=True, default=get_cve_default + "CVE ID", + max_length=1024, + unique=True, + default=get_cve_default, + validators=[RegexValidator(regex=r"CVE-\d{4}-\d{4,5}")], ) objects = SecurityIssueManager() diff --git a/checklists/tests/test_models.py b/checklists/tests/test_models.py index 73ad4851..192df301 100644 --- a/checklists/tests/test_models.py +++ b/checklists/tests/test_models.py @@ -3,6 +3,7 @@ import re import zoneinfo from datetime import UTC, date, datetime +from django.core.exceptions import ValidationError from django.db import IntegrityError from django.template.loader import render_to_string from django.test import RequestFactory, TestCase, override_settings @@ -872,6 +873,43 @@ class GetCvssSeverityTests(TestCase): self.assertEqual(get_cvss_severity(10.0), "CRITICAL") +class SecurityIssueTestCase(TestCase): + def test_cve_year_number_invalid(self): + invalid_cve_numbers = [ + "CVE-2026-1", + "CVE-2026-XXXX", + "CVE-20026-1111", + ] + for cve in invalid_cve_numbers: + with self.subTest(cve=cve): + with self.assertRaises(ValidationError) as context: + SecurityIssue(cve_year_number=cve).full_clean() + + self.assertEqual( + context.exception.message_dict.get("cve_year_number"), + ["Enter a valid value."], + ) + + def test_cve_year_number_valid(self): + valid_cve_numbers = [ + "CVE-2026-12345", + "CVE-2026-1234", + ] + for cve in valid_cve_numbers: + with self.subTest(cve=cve): + # No ValidationError raised. + SecurityIssue(cve_year_number=cve).full_clean( + exclude=( + "summary", + "description", + "cve_type", + "impact", + "confirmed_at", + "reported_at", + ) + ) + + class CvssMetricsInCveDataTests(TestCase): factory = Factory() |
