from pathlib import Path import re API_DIR = Path(__file__).parents[1] / "app" / "api" UNSAFE_PATTERNS = ( re.compile(r"[\"']traceback[\"']\s*:\s*traceback\.format_exc\(\)"), re.compile(r"[\"']error[\"']\s*:\s*str\((?:e|exc)\)"), re.compile(r"t\([^\n]*error\s*=\s*str\((?:e|exc)\)"), re.compile(r"(?:project|state)\.error\s*=\s*str\((?:e|exc)\)"), re.compile(r"fail_task\([^\n]*str\((?:e|exc)\)"), ) TARGET_FILES = ( "simulation.py", "graph.py", "report.py", "agent_group.py", "template.py", ) def test_api_does_not_expose_or_persist_raw_exception_details(): findings = [] for filename in TARGET_FILES: path = API_DIR / filename source = path.read_text(encoding="utf-8") for pattern in UNSAFE_PATTERNS: for match in pattern.finditer(source): line = source.count("\n", 0, match.start()) + 1 findings.append(f"{filename}:{line}:{match.group(0)}") assert findings == [], "unsafe exception details found:\n" + "\n".join(findings)