Refine vulnerability report amendments

This commit is contained in:
Alex Schapiro
2026-08-19 21:34:05 +00:00
parent 18556da0cd
commit 9c1a0c9002
5 changed files with 46 additions and 69 deletions
+29 -19
View File
@@ -61,6 +61,14 @@ def report_state(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> ReportState
endpoint="/redirect",
method="GET",
cwe="CWE-601",
code_locations=[
{
"file": "src/redirect.py",
"start_line": 10,
"end_line": 12,
"snippet": "return redirect(url)",
},
],
)
return state
@@ -99,20 +107,6 @@ async def test_update_requires_nonempty_reason() -> None:
assert result == {"success": False, "error": "update_reason cannot be empty"}
async def test_update_rejects_target_and_cve_changes() -> None:
result = await _do_update(
report_id="vuln-0001",
update_reason="The chain reached a second asset.",
target="https://other.example.com",
cve="CVE-2024-12345",
)
assert result["success"] is False
assert "File a new report instead" in result["error"]
assert "target" in result["error"]
assert "cve" in result["error"]
async def test_update_changes_impact_only(report_state: ReportState) -> None:
result = await _do_update(
report_id="vuln-0001",
@@ -180,9 +174,6 @@ async def test_update_callback_fires(report_state: ReportState) -> None:
async def test_update_persists_all_report_artifacts(report_state: ReportState) -> None:
report_state.final_scan_result = "# Executive Summary\n\nThe scan is complete."
report_state.save_run_data()
result = await _do_update(
report_id="vuln-0001",
update_reason="The chain proves account takeover.",
@@ -194,13 +185,11 @@ async def test_update_persists_all_report_artifacts(report_state: ReportState) -
assert result["success"] is True
run_dir = report_state.get_run_dir()
finding_md = (run_dir / "vulnerabilities" / "vuln-0001.md").read_text(encoding="utf-8")
executive_md = (run_dir / "penetration_test_report.md").read_text(encoding="utf-8")
findings = json.loads((run_dir / "vulnerabilities.json").read_text(encoding="utf-8"))
sarif = json.loads((run_dir / "findings.sarif").read_text(encoding="utf-8"))
sarif_finding = sarif["runs"][0]["results"][0]
assert "An attacker can take over an account." in finding_md
assert "An attacker can take over an account." in executive_md
assert findings[0]["impact"] == "An attacker can take over an account."
assert findings[0]["severity"] == "critical"
assert sarif_finding["properties"]["strix"]["impact"] == (
@@ -209,6 +198,27 @@ async def test_update_persists_all_report_artifacts(report_state: ReportState) -
assert sarif_finding["properties"]["strix"]["severity"] == "critical"
@pytest.mark.parametrize(
"code_locations",
[[], [{"file": "../invalid.py", "start_line": 1}]],
)
async def test_update_rejects_empty_code_locations(
report_state: ReportState,
code_locations: list[dict[str, Any]],
) -> None:
original_locations = report_state.vulnerability_reports[0]["code_locations"]
result = await _do_update(
report_id="vuln-0001",
update_reason="The source review did not provide a valid location.",
code_locations=code_locations,
)
assert result["success"] is False
assert any("code_locations" in error for error in result["errors"])
assert report_state.vulnerability_reports[0]["code_locations"] == original_locations
async def test_update_fails_without_global_report_state(
monkeypatch: pytest.MonkeyPatch,
) -> None: