mirror of
https://github.com/usestrix/strix.git
synced 2026-10-10 03:28:11 +00:00
Merge 976a4e05d9 into 03d2c6c168
This commit is contained in:
commit
5895d9e792
2 changed files with 195 additions and 1 deletions
|
|
@ -1883,7 +1883,7 @@ def _build_dependency_evidence(
|
|||
return evidence
|
||||
|
||||
|
||||
async def _do_create_dependency( # noqa: PLR0912
|
||||
async def _do_create_dependency( # noqa: PLR0912, PLR0915
|
||||
*,
|
||||
title: str,
|
||||
description: str,
|
||||
|
|
@ -1905,6 +1905,8 @@ async def _do_create_dependency( # noqa: PLR0912
|
|||
manifest_path: str | None = None,
|
||||
reachability: str = "unknown",
|
||||
reachability_evidence: str | None = None,
|
||||
code_locations: list[dict[str, Any]] | None = None,
|
||||
fix_verification: str | None = None,
|
||||
contextual_cvss_breakdown: dict[str, str] | None = None,
|
||||
contextual_cvss_reasoning: str | None = None,
|
||||
agent_id: str | None = None,
|
||||
|
|
@ -1947,6 +1949,16 @@ async def _do_create_dependency( # noqa: PLR0912
|
|||
if manifest_err:
|
||||
errors.append(manifest_err)
|
||||
|
||||
parsed_locations = _normalize_code_locations(code_locations)
|
||||
if parsed_locations:
|
||||
errors.extend(_validate_code_locations(parsed_locations))
|
||||
elif code_locations:
|
||||
errors.append(
|
||||
"code_locations were dropped as unusable - every location needs a relative "
|
||||
"'file' and an integer 'start_line'"
|
||||
)
|
||||
errors.extend(_validate_fix_verification(parsed_locations, fix_verification))
|
||||
|
||||
reachability = (reachability or "unknown").strip().lower()
|
||||
if reachability not in _VALID_REACHABILITY:
|
||||
errors.append(
|
||||
|
|
@ -2053,6 +2065,8 @@ async def _do_create_dependency( # noqa: PLR0912
|
|||
cvss=cvss_score if advisory_cvss is not None else None,
|
||||
cve=parsed_cve,
|
||||
cwe=cwe,
|
||||
code_locations=parsed_locations,
|
||||
fix_verification=fix_verification,
|
||||
finding_class="dependency_cve",
|
||||
dependency_metadata=dependency_metadata,
|
||||
agent_id=agent_id if isinstance(agent_id, str) else None,
|
||||
|
|
@ -2107,6 +2121,8 @@ async def create_dependency_report(
|
|||
dependency_path: str | None = None,
|
||||
reachability: str = "unknown",
|
||||
reachability_evidence: str | None = None,
|
||||
code_locations: list[dict[str, Any]] | None = None,
|
||||
fix_verification: str | None = None,
|
||||
contextual_cvss_breakdown: dict[str, str] | None = None,
|
||||
contextual_cvss_reasoning: str | None = None,
|
||||
) -> str:
|
||||
|
|
@ -2217,6 +2233,23 @@ async def create_dependency_report(
|
|||
is off in production), and say who controls the input. State
|
||||
it plainly when no entry point reaches the sink — that is the
|
||||
most useful result a reader can get.
|
||||
code_locations: Where application code imports or calls the package —
|
||||
the evidence behind your ``reachability`` claim. List of dicts,
|
||||
same shape as ``create_vulnerability_report``::
|
||||
|
||||
{"file": "src/api/client.ts", "start_line": 14, "end_line": 14,
|
||||
"snippet": "const x = require('pkg')", "label": "imports it"}
|
||||
|
||||
Cite the repo-relative ``file`` and the exact 1-based
|
||||
``start_line`` where ``snippet`` actually sits — verify against
|
||||
the real file, never guess. A location may also propose
|
||||
the fix itself: ``fix_before`` (verbatim current code, e.g. the
|
||||
manifest pin line) + ``fix_after`` (same lines with the fixed
|
||||
version) — that combination requires ``fix_verification``.
|
||||
fix_verification: Required whenever any ``code_locations`` entry
|
||||
carries ``fix_after``. Same bar as a normal finding: security
|
||||
closure, bypass review, preserved behavior, and how each was
|
||||
checked.
|
||||
contextual_cvss_breakdown: **Required.** Full CVSS v3.1 rating of this
|
||||
CVE **in this codebase** — the same 8-metric object as
|
||||
``create_vulnerability_report``'s ``cvss_breakdown``:
|
||||
|
|
@ -2277,6 +2310,8 @@ async def create_dependency_report(
|
|||
manifest_path=manifest_path,
|
||||
reachability=reachability,
|
||||
reachability_evidence=reachability_evidence,
|
||||
code_locations=code_locations,
|
||||
fix_verification=fix_verification,
|
||||
contextual_cvss_breakdown=contextual_cvss_breakdown,
|
||||
contextual_cvss_reasoning=contextual_cvss_reasoning,
|
||||
agent_id=agent_id,
|
||||
|
|
|
|||
|
|
@ -408,6 +408,165 @@ async def test_dependency_report_records_transitive_chain(report_state: ReportSt
|
|||
)
|
||||
|
||||
|
||||
async def test_dependency_report_persists_code_locations(report_state: ReportState) -> None:
|
||||
"""Usage-site locations file onto a dependency finding like any other."""
|
||||
result = await _do_create_dependency(
|
||||
title="CVE-2021-23337 in lodash 4.17.20",
|
||||
description="Command injection via template.",
|
||||
target="repo/package.json",
|
||||
cve="CVE-2021-23337",
|
||||
package_name="lodash",
|
||||
installed_version="4.17.20",
|
||||
impact="Arbitrary command execution.",
|
||||
remediation_steps="Upgrade to 4.17.21.",
|
||||
assumptions="Assumes the template sink is reachable.",
|
||||
package_ecosystem="npm",
|
||||
manifest_path="package-lock.json",
|
||||
fixed_version="4.17.21",
|
||||
cwe="CWE-94",
|
||||
advisory_cvss=7.2,
|
||||
technical_analysis=None,
|
||||
fix_effort="trivial",
|
||||
reachability="vulnerable_symbol_used",
|
||||
reachability_evidence=_DEP_EVIDENCE,
|
||||
code_locations=[
|
||||
{
|
||||
"file": "src/render.ts",
|
||||
"start_line": 14,
|
||||
"end_line": 14,
|
||||
"snippet": "const merge = require('lodash').merge",
|
||||
"label": "imports the vulnerable package",
|
||||
}
|
||||
],
|
||||
contextual_cvss_breakdown=_DEP_CONTEXT,
|
||||
contextual_cvss_reasoning=_DEP_REASONING,
|
||||
)
|
||||
assert result["success"] is True
|
||||
locs = report_state.vulnerability_reports[0]["code_locations"]
|
||||
assert locs[0]["file"] == "src/render.ts"
|
||||
assert locs[0]["label"] == "imports the vulnerable package"
|
||||
|
||||
|
||||
async def test_dependency_report_fix_locations_require_verification(
|
||||
report_state: ReportState,
|
||||
) -> None:
|
||||
"""A location proposing a fix still requires fix_verification."""
|
||||
result = await _do_create_dependency(
|
||||
title="CVE-2021-23337 in lodash 4.17.20",
|
||||
description="Command injection via template.",
|
||||
target="repo/package.json",
|
||||
cve="CVE-2021-23337",
|
||||
package_name="lodash",
|
||||
installed_version="4.17.20",
|
||||
impact="Arbitrary command execution.",
|
||||
remediation_steps="Upgrade to 4.17.21.",
|
||||
assumptions="Assumes the template sink is reachable.",
|
||||
package_ecosystem="npm",
|
||||
manifest_path="package-lock.json",
|
||||
fixed_version="4.17.21",
|
||||
cwe="CWE-94",
|
||||
advisory_cvss=7.2,
|
||||
technical_analysis=None,
|
||||
fix_effort="trivial",
|
||||
reachability="imported",
|
||||
reachability_evidence=_DEP_EVIDENCE,
|
||||
code_locations=[
|
||||
{
|
||||
"file": "package-lock.json",
|
||||
"start_line": 10,
|
||||
"end_line": 10,
|
||||
"fix_before": '"lodash": "4.17.20"',
|
||||
"fix_after": '"lodash": "4.17.21"',
|
||||
}
|
||||
],
|
||||
contextual_cvss_breakdown=_DEP_CONTEXT,
|
||||
contextual_cvss_reasoning=_DEP_REASONING,
|
||||
)
|
||||
assert result["success"] is False
|
||||
assert any("fix_verification" in e for e in result["errors"])
|
||||
assert not report_state.vulnerability_reports
|
||||
|
||||
|
||||
async def test_dependency_report_fix_locations_persist_with_verification(
|
||||
report_state: ReportState,
|
||||
) -> None:
|
||||
"""A fix-pair location files when fix_verification is supplied, and both
|
||||
fields persist on the stored report."""
|
||||
result = await _do_create_dependency(
|
||||
title="CVE-2021-23337 in lodash 4.17.20",
|
||||
description="Command injection via template.",
|
||||
target="repo/package.json",
|
||||
cve="CVE-2021-23337",
|
||||
package_name="lodash",
|
||||
installed_version="4.17.20",
|
||||
impact="Arbitrary command execution.",
|
||||
remediation_steps="Upgrade to 4.17.21.",
|
||||
assumptions="Assumes the template sink is reachable.",
|
||||
package_ecosystem="npm",
|
||||
manifest_path="package-lock.json",
|
||||
fixed_version="4.17.21",
|
||||
cwe="CWE-94",
|
||||
advisory_cvss=7.2,
|
||||
technical_analysis=None,
|
||||
fix_effort="trivial",
|
||||
reachability="imported",
|
||||
reachability_evidence=_DEP_EVIDENCE,
|
||||
code_locations=[
|
||||
{
|
||||
"file": "package-lock.json",
|
||||
"start_line": 10,
|
||||
"end_line": 10,
|
||||
"fix_before": '"lodash": "4.17.20"',
|
||||
"fix_after": '"lodash": "4.17.21"',
|
||||
}
|
||||
],
|
||||
fix_verification="Bump verified: lockfile parses and the sink is unreachable.",
|
||||
contextual_cvss_breakdown=_DEP_CONTEXT,
|
||||
contextual_cvss_reasoning=_DEP_REASONING,
|
||||
)
|
||||
assert result["success"] is True
|
||||
report = report_state.vulnerability_reports[0]
|
||||
loc = report["code_locations"][0]
|
||||
assert loc["fix_before"] == '"lodash": "4.17.20"'
|
||||
assert loc["fix_after"] == '"lodash": "4.17.21"'
|
||||
assert report["fix_verification"] == (
|
||||
"Bump verified: lockfile parses and the sink is unreachable."
|
||||
)
|
||||
|
||||
|
||||
async def test_dependency_report_rejects_unusable_locations(
|
||||
report_state: ReportState,
|
||||
) -> None:
|
||||
"""A supplied list that normalizes to nothing errors instead of filing
|
||||
silently without the requested usage evidence."""
|
||||
result = await _do_create_dependency(
|
||||
title="CVE-2021-23337 in lodash 4.17.20",
|
||||
description="Command injection via template.",
|
||||
target="repo/package.json",
|
||||
cve="CVE-2021-23337",
|
||||
package_name="lodash",
|
||||
installed_version="4.17.20",
|
||||
impact="Arbitrary command execution.",
|
||||
remediation_steps="Upgrade to 4.17.21.",
|
||||
assumptions="Assumes the template sink is reachable.",
|
||||
package_ecosystem="npm",
|
||||
manifest_path="package-lock.json",
|
||||
fixed_version="4.17.21",
|
||||
cwe="CWE-94",
|
||||
advisory_cvss=7.2,
|
||||
technical_analysis=None,
|
||||
fix_effort="trivial",
|
||||
reachability="imported",
|
||||
reachability_evidence=_DEP_EVIDENCE,
|
||||
code_locations=[{"file": "/abs/path.ts", "snippet": "require('lodash')"}],
|
||||
contextual_cvss_breakdown=_DEP_CONTEXT,
|
||||
contextual_cvss_reasoning=_DEP_REASONING,
|
||||
)
|
||||
assert result["success"] is False
|
||||
assert any("dropped as unusable" in e for e in result["errors"])
|
||||
assert not report_state.vulnerability_reports
|
||||
|
||||
|
||||
async def test_dependency_report_omits_blank_chain_fields(report_state: ReportState) -> None:
|
||||
result = await _do_create_dependency(
|
||||
title="CVE-2024-0001 in sample 1.0.0",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue