usestrix/strix · error · ValueError

Failed to calculate CVSS for validated vector

Error message

Failed to calculate CVSS for validated vector: {vector}

What it means

The reporting tool builds a CVSS:3.1 vector from a breakdown, wraps cvss-lib's CVSS3(vector), and calls scores()/severities(). If the library throws even for a vector that passed earlier validation, it re-raises as ValueError('Failed to calculate CVSS for validated vector: ...') with the original exception chained. The message includes the exact vector for diagnosis.

Solutions

  1. Inspect the vector in the error message and compare each metric against the CVSS 3.1 spec (AV:N|A|L|P, AC:L|H, PR:N|L|H, UI:N|R, S:U|C, C/I/A:N|L|H).
  2. Fix the source breakdown (usually LLM output constrained by the reporting prompt/tool schema) and resubmit the finding.
  3. Pin/align the cvss library version with what this Strix release was tested against.
  4. If a specific metric value is legitimately unavailable, map it to the closest valid value before vector construction.

Example fix

# before
breakdown = {"attack_vector": "N", "privileges_required": "admin", ...}
# vector: .../PR:admin/... -> library raises

# after
breakdown = {"attack_vector": "N", "privileges_required": "H", ...}
# vector: .../PR:H/... -> valid CVSS:3.1
Defensive patterns

Strategy: try-catch

Validate before calling

from cvss import CVSS3

def cvss_vector_computable(breakdown: dict) -> bool:
    vector = (f"CVSS:3.1/AV:{breakdown['attack_vector']}/AC:{breakdown['attack_complexity']}"
              f"/PR:{breakdown['privileges_required']}/UI:{breakdown['user_interaction']}"
              f"/S:{breakdown['scope']}/C:{breakdown['confidentiality']}"
              f"/I:{breakdown['integrity']}/A:{breakdown['availability']}")
    try:
        CVSS3(vector).scores()
        return True
    except Exception:
        return False

Type guard

CVSS_ENUMS = {
    "attack_vector": {"N", "A", "L", "P"}, "attack_complexity": {"L", "H"},
    "privileges_required": {"N", "L", "H"}, "user_interaction": {"N", "R"},
    "scope": {"U", "C"}, "confidentiality": {"N", "L", "H"},
    "integrity": {"N", "L", "H"}, "availability": {"N", "L", "H"},
}

def is_valid_breakdown(b: dict) -> bool:
    return all(b.get(k) in vals for k, vals in CVSS_ENUMS.items())

Try / catch

try:
    score, severity, vector = compute_cvss(breakdown)
except ValueError as exc:
    if "Failed to calculate CVSS" in str(exc):
        breakdown = clamp_to_enums(breakdown)  # snap values to CVSS 3.1 domains
        score, severity, vector = compute_cvss(breakdown)
    else:
        raise

Prevention

When it happens

Trigger: A breakdown that string-formats into a syntactically plausible but semantically invalid CVSS:3.1 vector — e.g. an out-of-domain value like PR:admin, S:P combined with metrics the library rejects, or a library version whose parser is stricter than the upstream validator.

Common situations: LLM-generated vulnerability breakdowns with non-canonical metric values; cvss library major-version change tightening parsing; locale/case issues if values weren't normalized before formatting.

Related errors


AI-assisted analysis of usestrix/strix@8551339130 (2026-08-15). Data as JSON: /api/errors/3fe5f9faf0a4e13d. Report an issue: GitHub.

Appendix: source

Thrown at strix/tools/reporting/tool.py:144


def _calculate_cvss(breakdown: dict[str, str]) -> tuple[float, str, str]:
    from cvss import CVSS3

    vector = (
        f"CVSS:3.1/AV:{breakdown['attack_vector']}/AC:{breakdown['attack_complexity']}/"
        f"PR:{breakdown['privileges_required']}/UI:{breakdown['user_interaction']}/"
        f"S:{breakdown['scope']}/C:{breakdown['confidentiality']}/"
        f"I:{breakdown['integrity']}/A:{breakdown['availability']}"
    )

    try:
        cvss = CVSS3(vector)
        score = cvss.scores()[0]
        base_severity = cvss.severities()[0].lower()
    except Exception as exc:
        msg = f"Failed to calculate CVSS for validated vector: {vector}"
        raise ValueError(msg) from exc

    severity = "info" if base_severity == "none" else base_severity
    return score, severity, vector


_REQUIRED_FIELDS = {
    "title": "Title cannot be empty",
    "description": "Description cannot be empty",
    "impact": "Impact cannot be empty",
    "target": "Target cannot be empty",
    "technical_analysis": "Technical analysis cannot be empty",
    "poc_description": "PoC description cannot be empty",
    "poc_script_code": "PoC script/code is REQUIRED - provide the actual exploit/payload",
    "remediation_steps": "Remediation steps cannot be empty",
    "evidence": "Evidence cannot be empty - provide concrete proof of the finding",
    "assumptions": "Assumptions cannot be empty - state exploitability prerequisites",
}

View on GitHub (pinned to 8551339130)