Skip to content

Fix quarantine layout provenance escapes - #53

Closed
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/critical-bug-investigation-1537
Closed

cursor[bot] wants to merge 1 commit into
mainfrom
cursor/critical-bug-investigation-1537

Conversation

@cursor

@cursor cursor Bot commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

Bug and impact

  • A symlinked SCP_QUARANTINE_DIR/registry_fetch layout could be followed by quarantine list, purge, retention, and eviction code, exposing and deleting files outside the quarantine root.
  • The internal registry-fetch quarantine write path could write through that symlink outside the quarantine root.
  • scp_apply_registry_quarantine accepted registry paths when registry_fetch resolved back to the quarantine root, and could also accept a forged .json file as both payload and sidecar, bypassing the intended registry-fetch provenance boundary.
  • Fresh installs could resolve MCP 2.x, causing scp.antigen_mcp to crash on import because this code uses the MCP 1.x mcp.server.fastmcp API.

Root cause

Layout enumeration and write setup used Path.is_dir(), which follows symlinks, and the apply guard only checked resolved containment without requiring a real, strict registry_fetch/ child or a distinct .txt payload.

Fix

  • Added shared safe layout validation that rejects symlinked, non-contained, or root-equivalent layout directories.
  • Reused that validation for quarantine list/purge/quota walks and registry-fetch layout writes.
  • Tightened registry apply loading to require a real registry_fetch/ directory strictly below the quarantine root and a .txt payload path.
  • Bounded the MCP dependency to mcp>=1.2.0,<2.0.0.

Validation

  • RED/GREEN regressions for symlinked layout list/purge, symlinked layout write rejection, registry_fetch -> . apply rejection, .json self-sidecar rejection, and MCP dependency bounding.
  • PYTHONPATH=src python3 -m pytest tests/test_security_regressions.py -q -> 34 passed.
  • PYTHONPATH=src python3 -m pytest tests/test_security_regressions.py tests/test_registry_ssot.py tests/test_registry_fetch_r4.py tests/test_registry_load_order_r5.py tests/test_appsec_antigen_mcp_gates.py -q -> 80 passed.
  • PYTHONPATH=src python3 -m compileall -q src/scp and git diff --check passed.
  • Full suite after installing optional extras: 359 passed / 3 skipped / 3 failed. Remaining failures match known baseline contract hash mismatches and RT11 residual classification.
Open in Web View Automation 

@ManintheCrowds

Copy link
Copy Markdown
Owner

Audit: symlink layout + self-sidecar + MCP pin overlap; #60 carries layout/provenance. Closing as superseded by #60.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants