|
1 | 1 | """Pure helpers for vulnerability identifiers (no model imports, safe to import anywhere).""" |
2 | 2 |
|
3 | 3 |
|
4 | | -def cwe_number(value) -> int | None: |
5 | | - """ |
6 | | - ``"CWE-79"`` / ``"79"`` / ``79`` -> ``79`` (positive int, case-insensitive); anything else -> ``None``. |
7 | | -
|
8 | | - CWE numbers are positive, so ``0`` (Finding.cwe's "unset" sentinel) and non-numeric input -> ``None``. |
9 | | - """ |
10 | | - if value is None: |
11 | | - return None |
12 | | - token = str(value).strip().upper().removeprefix("CWE-") |
13 | | - if not token.isdigit(): |
14 | | - return None |
15 | | - number = int(token) |
16 | | - return number if number > 0 else None |
17 | | - |
18 | | - |
19 | | -def cwe_label(value) -> str | None: |
20 | | - """``79`` / ``"79"`` / ``"CWE-79"`` -> ``"CWE-79"`` (canonical, case-insensitive); invalid -> ``None``.""" |
21 | | - number = cwe_number(value) |
22 | | - return f"CWE-{number}" if number is not None else None |
23 | | - |
24 | | - |
25 | | -def parse_cwes(text: str | None) -> list[str]: |
26 | | - """ |
27 | | - Parse CWEs from user text (one per line or comma-separated) into canonical ``CWE-<n>`` labels. |
28 | | -
|
29 | | - Accepts ``89`` or ``CWE-89`` (case-insensitive); ignores anything non-numeric; deduplicates. |
30 | | - """ |
31 | | - result: list[str] = [] |
32 | | - for token in (text or "").replace(",", "\n").split(): |
33 | | - label = cwe_label(token) |
34 | | - if label is not None and label not in result: |
35 | | - result.append(label) |
36 | | - return result |
37 | | - |
38 | | - |
39 | | -def finding_cwe_labels(cwe, unsaved_cwes=None) -> list[str]: |
40 | | - """Canonical ``CWE-<n>`` labels for a finding: the primary ``cwe`` first, then extras, deduplicated.""" |
41 | | - labels: list[str] = [] |
42 | | - primary = cwe_label(cwe) |
43 | | - if primary is not None: |
44 | | - labels.append(primary) |
45 | | - for extra in unsaved_cwes or []: |
46 | | - label = cwe_label(extra) |
47 | | - if label is not None: |
48 | | - labels.append(label) |
49 | | - return list(dict.fromkeys(labels)) |
50 | | - |
51 | | - |
52 | 4 | def resolve_vulnerability_id_type(vulnerability_id: str | None) -> str | None: |
53 | 5 | """ |
54 | 6 | Autodetect the type from the id's leading prefix (the part before the first ``-``). |
|
0 commit comments