Skip to content

Commit 1be46da

Browse files
committed
feat: upgrade impact score
1 parent 9b6323d commit 1be46da

File tree

7 files changed

+92
-2
lines changed

7 files changed

+92
-2
lines changed

backend/application/core/api/filters.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ def get_has_completed_assessment(
272272
("last_observation_log", "last_observation_log"),
273273
("epss_score", "epss_score"),
274274
("stackable_score", "stackable_score"),
275+
("upgrade_impact_score", "upgrade_impact_score"),
275276
("origin_component_location", "origin_component_location"),
276277
("has_potential_duplicates", "has_potential_duplicates"),
277278
("patch_available", "patch_available"),
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Generated by Django 5.1.4 on 2024-12-19 19:31
2+
3+
import django.core.validators
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
("core", "0066_merge_20241216_1336"),
11+
]
12+
13+
operations = [
14+
migrations.AddField(
15+
model_name="observation",
16+
name="upgrade_impact_score",
17+
field=models.IntegerField(
18+
null=True,
19+
validators=[
20+
django.core.validators.MinValueValidator(0),
21+
django.core.validators.MaxValueValidator(999999),
22+
],
23+
),
24+
),
25+
]
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Generated by Django 5.1.4 on 2024-12-19 19:42
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("core", "0067_observation_upgrade_impact_score"),
10+
(
11+
"import_observations",
12+
"0010_vulnerability_check_last_import_licenses_deleted_and_more",
13+
),
14+
("rules", "0017_alter_rule_approval_remark"),
15+
("vex", "0007_alter_csaf_tracking_current_release_date_and_more"),
16+
]
17+
18+
operations = [
19+
migrations.AddIndex(
20+
model_name="observation",
21+
index=models.Index(
22+
fields=["upgrade_impact_score"], name="core_observ_upgrade_f3aeed_idx"
23+
),
24+
),
25+
]

backend/application/core/models.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,9 @@ class Observation(Model):
678678
on_delete=SET_NULL,
679679
)
680680
risk_acceptance_expiry_date = DateField(null=True)
681+
upgrade_impact_score = IntegerField(
682+
null=True, validators=[MinValueValidator(0), MaxValueValidator(999999)]
683+
)
681684

682685
class Meta:
683686
indexes = [
@@ -701,6 +704,7 @@ class Meta:
701704
Index(fields=["patch_available"]),
702705
Index(fields=["in_vulncheck_kev"]),
703706
Index(fields=["exploit_available"]),
707+
Index(fields=["upgrade_impact_score"]),
704708
]
705709

706710
def __str__(self):

backend/application/import_observations/parsers/cyclone_dx/parser.py

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,35 @@ def _create_observations( # pylint: disable=too-many-locals
321321
component, recommendation
322322
)
323323

324+
upgrade_impact_score = 0
325+
if patched_versions:
326+
327+
def parse_version(version: str):
328+
version = version.split("-")[0]
329+
# Remove everything that is not a number or a dot
330+
version = "".join(
331+
[c for c in version if c.isdigit() or c == "."]
332+
)
333+
rettuple = tuple(map(int, version.split(".")[:3]))
334+
for _ in range(3 - len(rettuple)):
335+
rettuple += (0,)
336+
return rettuple
337+
338+
v1 = parse_version(component.version)
339+
lowest_impact_score = 9999999
340+
patched_versions_split = patched_versions.split(",")
341+
for patched_version in patched_versions_split:
342+
v2 = parse_version(patched_version)
343+
major_diff = abs(v2[0] - v1[0])
344+
minor_diff = abs(v2[1] - v1[1])
345+
patch_diff = abs(v2[2] - v1[2])
346+
upgrade_impact_score = (
347+
major_diff * 100 + minor_diff * 10 + patch_diff
348+
)
349+
if upgrade_impact_score < lowest_impact_score:
350+
lowest_impact_score = upgrade_impact_score
351+
upgrade_impact_score = lowest_impact_score
352+
324353
observation = Observation(
325354
title=title,
326355
description=description,
@@ -342,6 +371,7 @@ def _create_observations( # pylint: disable=too-many-locals
342371
origin_source_file=self.metadata.file,
343372
origin_component_location=component_location,
344373
patched_in_versions=patched_versions,
374+
upgrade_impact_score=upgrade_impact_score,
345375
patch_available=bool(patched_versions),
346376
)
347377

@@ -484,12 +514,15 @@ def _get_component_location(self, component_json: dict[str, str]) -> str:
484514
def _get_patched_versions(self, component: Component, recommendation: str) -> str:
485515
if not recommendation:
486516
return ""
517+
component_name = re.sub(r":\d+", "", component.name)
487518

488519
group = re.search(
489-
r"Upgrade (\S+:)?" + component.name + r" to version ([a-z0-9\.\-_\s,]+)",
520+
r"Upgrade (\S+:)?"
521+
+ component_name
522+
+ r" to version (\d+:)?([a-z0-9\.\-_\s,]+)",
490523
recommendation,
491524
)
492525
if group:
493-
return group.group(2)
526+
return group.group(3)
494527

495528
return ""

frontend/src/core/observations/ObservationList.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ const ObservationList = () => {
140140
<ChipField source="current_status" label="Status" />
141141
<NumberField source="epss_score" label="EPSS" />
142142
<NumberField source="stackable_score" label="Stackable Score" />
143+
<NumberField source="upgrade_impact_score" label="Upgrade Impact Score" />
143144
{/* <TextField source="origin_service_name" label="Service" /> */}
144145
<TextField
145146
source="origin_component_name_version"

frontend/src/core/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ export interface Observation extends RaRecord {
104104
epss_score: number;
105105
epss_percentile: number;
106106
stackable_score: number;
107+
upgrade_impact_score: number;
107108
cwe: number;
108109
found: Date;
109110
scanner: string;

0 commit comments

Comments
 (0)