Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ description = "Secure Contain Protect — inspect, sanitize, contain, quarantine
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"mcp>=1.2.0",
"mcp>=1.2.0,<2",
"requests>=2.28.0",
]

Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
mcp>=1.2.0
mcp>=1.2.0,<2
2 changes: 2 additions & 0 deletions src/scp/registry_ssot.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ def _load_quarantine_snapshot(quarantine_path: str | Path) -> dict:
path = Path(quarantine_path)
if not _path_under_registry_fetch(path):
raise ValueError("quarantine_path_rejected")
if path.suffix != ".txt":
raise ValueError("quarantine_provenance_rejected")
if not path.is_file():
raise ValueError("quarantine_file_not_found")

Expand Down
23 changes: 23 additions & 0 deletions tests/test_registry_ssot.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,3 +235,26 @@ def test_apply_merge_rejects_wrong_sidecar_reason(isolated_ssot):
res = registry_ssot.apply_merge(path, approve=True)
assert res["merged"] is False
assert res["reason"] == "quarantine_provenance_rejected"


def test_apply_merge_rejects_json_payload_as_its_own_sidecar(isolated_ssot):
"""A merge payload must be the .txt file paired with a separate sidecar."""
snap = _snap([_rec("bad.selfsidecar.001")])
forged = scp_utils.registry_fetch_quarantine_dir() / "forged.json"
forged.parent.mkdir(parents=True, exist_ok=True)
forged.write_text(
json.dumps(
{
"reason": "registry_fetch",
"snapshot": snap,
"meta": {"reason": "registry_fetch", "source": "forged"},
}
),
encoding="utf-8",
)

res = registry_ssot.apply_merge(forged, approve=True)

assert res["merged"] is False
assert res["reason"] == "quarantine_provenance_rejected"
assert registry_ssot.load_ssot() == []
Loading