This commit is contained in:
Iliyan Angelov
2025-12-01 06:50:10 +02:00
parent 91f51bc6fe
commit 62c1fe5951
4682 changed files with 544807 additions and 31208 deletions

View File

@@ -0,0 +1,142 @@
from dataclasses import asdict, field
from pathlib import Path
from typing import List
from pydantic.dataclasses import dataclass
from typing_extensions import Self
from .util import dict_dump
from ..report.schemas.v3_0 import main as v3_0
from .base import FileType, SafetyBaseModel
from .package import PythonDependency, PythonSpecification
from .result import DependencyResultModel
from .vulnerability import ClosestSecureVersion, RemediationModel, Vulnerability
@dataclass
class FileModel(SafetyBaseModel):
location: Path
file_type: FileType
results: DependencyResultModel = field(
default_factory=lambda: DependencyResultModel(dependencies=[])
)
def as_v30(self) -> v3_0.File:
dependencies_output = []
for dep in self.results.dependencies:
specs: List[v3_0.AnalyzedSpecification] = []
for specification in dep.specifications:
rem = None
if specification.remediation:
closest = None
if specification.remediation.closest_secure:
closest_kwargs = asdict(
specification.remediation.closest_secure
)
closest = v3_0.ClosestSecureSpecification(**closest_kwargs)
rem = v3_0.Remediation(
vulnerabilities_found=specification.remediation.vulnerabilities_found,
closest_secure=closest,
recommended=specification.remediation.recommended,
other_recommended=specification.remediation.other_recommended,
)
analyzed = v3_0.AnalyzedSpecification(
raw=specification.raw,
vulnerabilities=v3_0.SpecificationVulnerabilities(
known_vulnerabilities=[
v3_0.Vulnerability(**vuln.to_model_dict())
for vuln in specification.vulnerabilities
],
remediation=rem,
),
)
specs.append(analyzed)
p = v3_0.Package(name=dep.name, specifications=specs)
dependencies_output.append(p)
return v3_0.File(
location=str(self.location),
type=self.file_type.value,
categories=[self.file_type.ecosystem.value],
results=v3_0.Results(dependencies=dependencies_output),
)
@classmethod
def from_v30(cls, obj: v3_0.SchemaModelV30) -> 'FileModel':
if not isinstance(obj, v3_0.File):
raise TypeError('Expected instance of v3_0.File')
location = Path(obj.location)
dependencies: List[PythonDependency] = []
for dep in obj.results.dependencies:
specs: List[PythonSpecification] = []
for specification in dep.specifications:
remediation_obj = None
remed = specification.vulnerabilities.remediation
if remed:
closest_sec = None
if remed.closest_secure:
closest_sec = ClosestSecureVersion(
**dict_dump(remed.closest_secure)
)
remediation_obj = RemediationModel(
vulnerabilities_found=remed.vulnerabilities_found,
more_info_url="",
recommended=remed.recommended,
closest_secure=closest_sec,
other_recommended=remed.other_recommended,
)
vulns: List[Vulnerability] = []
py_spec = PythonSpecification(specification.raw, found=location)
for vuln in specification.vulnerabilities.known_vulnerabilities:
ignored = False
ignored_expires = None
ignored_reason = None
ignored_code = None
if vuln.ignored:
ignored = True
ignored_expires = vuln.ignored.expires
ignored_reason = vuln.ignored.reason
ignored_code = vuln.ignored.code
vulns.append(
Vulnerability(
vulnerability_id=vuln.id,
package_name=py_spec.name,
ignored=ignored,
ignored_reason=ignored_reason,
ignored_expires=ignored_expires,
ignored_code=ignored_code,
vulnerable_spec=vuln.vulnerable_spec,
)
)
py_spec.remediation = remediation_obj
py_spec.vulnerabilities = vulns
specs.append(py_spec)
version = PythonDependency.find_version(specifications=specs)
dependencies.append(
PythonDependency(
name=dep.name, version=version, specifications=specs, found=location
)
)
results = DependencyResultModel(dependencies=dependencies)
return FileModel(
location=location, file_type=FileType(obj.type), results=results
)