Skip to content

Commit 89e6d40

Browse files
Pigbibicodex
andcommitted
fix: sanitize validator contract exceptions
Co-Authored-By: Codex <noreply@openai.com>
1 parent c9081be commit 89e6d40

2 files changed

Lines changed: 50 additions & 4 deletions

File tree

src/quant_advisor_research/artifact_integrity.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from .contracts import AdvisoryValidationError, validate_advisory_report
1111
from .period_contract import PeriodContractError, canonical_period_identity
12+
from .time_contract import TimeContractError
1213

1314

1415
ARTIFACT_INTEGRITY_VERSION = "validated_report.v1.canonical-json.sha256"
@@ -90,9 +91,18 @@ def _validated_snapshot(report: Mapping[str, Any]) -> dict[str, object]:
9091
snapshot = snapshot_json_wire(report)
9192
try:
9293
validate_advisory_report(snapshot)
93-
except AdvisoryValidationError:
94-
raise ArtifactIntegrityError("report_invalid") from None
95-
except (AttributeError, KeyError, TypeError, ValueError, OverflowError, UnicodeError, RecursionError):
94+
except (
95+
AdvisoryValidationError,
96+
TimeContractError,
97+
PeriodContractError,
98+
AttributeError,
99+
KeyError,
100+
TypeError,
101+
ValueError,
102+
OverflowError,
103+
UnicodeError,
104+
RecursionError,
105+
):
96106
raise ArtifactIntegrityError("report_invalid") from None
97107
return snapshot
98108

tests/test_artifact_integrity.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
import datetime as dt
44
import json
5+
import traceback
56
from collections import OrderedDict
67
from collections.abc import Mapping
78
from pathlib import Path
89
from types import MappingProxyType
910

1011
import pytest
1112

13+
import quant_advisor_research.artifact_integrity as artifact_integrity
1214
from quant_advisor_research.advisory_report import build_advisory_report
1315
from quant_advisor_research.artifact_integrity import (
1416
ARTIFACT_INTEGRITY_VERSION,
@@ -18,7 +20,8 @@
1820
make_artifact_integrity_evidence,
1921
)
2022
from quant_advisor_research.publisher import report_content_fingerprint
21-
from quant_advisor_research.time_contract import canonical_reference_time, normalize_aware_datetime
23+
from quant_advisor_research.period_contract import PeriodContractError
24+
from quant_advisor_research.time_contract import TimeContractError, canonical_reference_time, normalize_aware_datetime
2225

2326

2427
ROOT = Path(__file__).resolve().parents[1]
@@ -203,3 +206,36 @@ def items(self):
203206
evidence = make_artifact_integrity_evidence(MutatingMapping(report))
204207
assert report["generated_at"] != original
205208
assert evidence.digest == artifact_integrity_digest(dict(report, generated_at=original))
209+
210+
211+
@pytest.mark.parametrize("exception_type", [artifact_integrity.AdvisoryValidationError, TimeContractError, PeriodContractError])
212+
@pytest.mark.parametrize("operation", ["canonicalize", "digest", "evidence"])
213+
def test_known_validator_exceptions_are_sanitized(monkeypatch, exception_type, operation: str) -> None:
214+
marker = "UNTRUSTED_VALIDATOR_EXCEPTION"
215+
216+
def raise_known(_report) -> None:
217+
raise exception_type(marker)
218+
219+
monkeypatch.setattr(artifact_integrity, "validate_advisory_report", raise_known)
220+
report = build_report()
221+
call = {
222+
"canonicalize": artifact_integrity.canonicalize_validated_report,
223+
"digest": artifact_integrity_digest,
224+
"evidence": make_artifact_integrity_evidence,
225+
}[operation]
226+
227+
with pytest.raises(ArtifactIntegrityError, match="report_invalid") as error:
228+
call(report)
229+
assert error.value.__suppress_context__ is True
230+
assert marker not in repr(error.value)
231+
assert marker not in "".join(traceback.format_exception(error.value))
232+
233+
234+
def test_unexpected_runtime_error_is_not_swallowed(monkeypatch) -> None:
235+
def raise_unexpected(_report) -> None:
236+
raise RuntimeError("programming failure")
237+
238+
monkeypatch.setattr(artifact_integrity, "validate_advisory_report", raise_unexpected)
239+
240+
with pytest.raises(RuntimeError, match="programming failure"):
241+
artifact_integrity_digest(build_report())

0 commit comments

Comments
 (0)