strix/tests/test_finding_verification.py
oyasumi 22dcc2fabf fix(verification): send verifier credential per call
Provider env vars are global, so installing the verification key via the
environment either clobbered or was clobbered by the primary key when both
used the same provider (setdefault only fills missing vars). Pass the
verification key as a per-call api_key in model_settings.extra_args instead,
in both the runtime path and startup warm-up, so a separate-provider verifier
authenticates correctly and warm-up no longer fails before the key exists.
2026-07-21 07:25:57 +00:00

96 lines
3 KiB
Python

"""Configuration and fail-closed finding-verification tests."""
from __future__ import annotations
from typing import TYPE_CHECKING
import pytest
from pydantic import ValidationError
from strix.config.settings import FindingVerificationSettings
from strix.report.state import ReportState, set_global_report_state
from strix.report.verification import _verifier_model_settings
from strix.tools.reporting.tool import _do_create
if TYPE_CHECKING:
from pathlib import Path
def test_verifier_key_sent_per_call_not_via_global_env() -> None:
verification = FindingVerificationSettings(
enabled=True,
model="anthropic/verifier",
api_key="verifier-key",
)
settings = _verifier_model_settings(verification, "anthropic/verifier")
# The key rides on the request, so a shared-provider primary key can't
# clobber it (and vice versa) through the global provider env var.
assert settings.extra_args["api_key"] == "verifier-key"
def test_verifier_settings_omit_api_key_when_unset() -> None:
verification = FindingVerificationSettings(enabled=True, model="anthropic/verifier")
settings = _verifier_model_settings(verification, "anthropic/verifier")
assert "api_key" not in (settings.extra_args or {})
_CVSS = {
"attack_vector": "N",
"attack_complexity": "L",
"privileges_required": "N",
"user_interaction": "N",
"scope": "U",
"confidentiality": "H",
"integrity": "H",
"availability": "H",
}
def test_verification_defaults_off() -> None:
settings = FindingVerificationSettings()
assert settings.enabled is False
assert settings.model is None
def test_enabled_verification_requires_model() -> None:
with pytest.raises(ValidationError, match="STRIX_VERIFICATION_MODEL"):
FindingVerificationSettings(enabled=True)
@pytest.mark.asyncio
async def test_rejected_finding_is_not_persisted(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.chdir(tmp_path)
state = ReportState("verification-test")
set_global_report_state(state)
async def reject(_candidate: dict[str, object]) -> dict[str, object]:
return {"status": "rejected", "confidence": 0.99, "reason": "PoC is contradicted"}
monkeypatch.setattr("strix.report.verification.verify_finding", reject)
result = await _do_create(
title="Claimed SQL injection",
description="Claim.",
impact="Database access.",
target="https://example.com",
technical_analysis="Claimed sink.",
poc_description="1. Send payload.",
poc_script_code="GET /?id=1",
remediation_steps="Parameterize queries.",
evidence="A normal response.",
assumptions="None.",
fix_effort="low",
cvss_breakdown=_CVSS,
endpoint="/",
method="GET",
cve=None,
cwe="CWE-89",
code_locations=None,
)
assert result["success"] is False
assert result["verification"]["status"] == "rejected"
assert state.vulnerability_reports == []