"""authorization-obligations task 3.1: the checker runs in MAP with config, manifest counters and no sandbox candidacy.""" from __future__ import annotations import json from pathlib import Path import pytest from openultrasast.cli import main APP = ( "from flask import request\n\n\n" "@app.route('/books/')\n@login_required\ndef guarded(title):\n" " return Book.query.filter_by(book_title=title).first()\n\n\n" "@app.route('/books/mine/<title>')\ndef constrained(title):\n" " user_id = request.user.id\n" " return Book.query.filter_by(user_id=user_id, book_title=title).first()\n\n\n" "@app.route('/books/shared/<title>')\ndef constrained_too(title):\n" " owner = current_user.id\n" " return Book.query.filter_by(owner=owner, book_title=title).first()\n\n\n" "@app.route('/books/any/<title>')\ndef leaky(title):\n" " owner = request.args.get('owner')\n" " return Book.query.filter_by(user_id=owner, book_title=title).first()\n" ) def _repo(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path: repo = tmp_path / "repo" repo.mkdir() (repo / "app.py").write_text(APP) monkeypatch.setenv("OPENULTRASAST_RUNS_DIR", ".runs") monkeypatch.setenv("OPENULTRASAST_SANDBOX_PROBE", "0") return repo def _run_dir(repo: Path) -> Path: return sorted((repo / ".runs").iterdir())[-1] def test_standard_scan_emits_obligation_findings_and_the_manifest_block(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: repo = _repo(tmp_path, monkeypatch) (repo / "openultrasast.toml").write_text("[obligations]\nmin_siblings = 2\n") assert main(["scan", str(repo), "--mode", "standard", "--config", str(repo / "openultrasast.toml")]) == 0 run_dir = _run_dir(repo) findings = json.loads((run_dir / "findings.json").read_text())["findings"] obligations = [f for f in findings if f["finding_id"].startswith("obligation:")] leaky = [f for f in obligations if f["function_name"] == "leaky" and "discharger:identity_constraint" in f["tags"]] assert leaky and leaky[0]["evidence_level"] == "suspicion" and "obligation_evidence:consistency_violation" in leaky[0]["tags"] assert "app.py::constrained" in leaky[0]["rationale"] manifest = json.loads((run_dir / "manifest.json").read_text()) block = manifest["obligations"] assert block["sibling_sets"] == 1 and block["operations"] == 4 and block["policy_version"] is None assert block["findings_by_label"]["consistency_violation"] >= 1 and block["under_populated"] == 0 assert any(d["reason"] == "obligations_function_local" for d in manifest["degradations"]) (local,) = [d for d in block["degradations"] if d["reason"] == "obligations_function_local"] # design: the block carries them assert local["language"] == "python" and local["files"] == ["app.py"] assert block["sets"] == [{"module": "app", "resource": "book", "handlers": 4}] report = (run_dir / "report.md").read_text() assert "Sibling sets evaluated: 1 (under-populated: 0)" in report and "Policy version: none" in report assert "- `app` / `book`: 4 handlers" in report def test_declared_policy_is_read_from_the_target_and_versioned_in_the_manifest(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: repo = _repo(tmp_path, monkeypatch) (repo / "openultrasast.toml").write_text("[obligations]\nmin_siblings = 2\n") (repo / ".openultrasast").mkdir() (repo / ".openultrasast" / "obligations.toml").write_text( 'version = 1\n[[resource]]\nname = "book"\nsensitivity = "high"\nidentity_field = "user_id"\n\n' '[[route]]\npath = "/books/any/*"\naccess = "public"\n' ) assert main(["scan", str(repo), "--mode", "standard", "--config", str(repo / "openultrasast.toml")]) == 0 run_dir = _run_dir(repo) manifest = json.loads((run_dir / "manifest.json").read_text()) assert len(manifest["obligations"]["policy_version"]) == 40 findings = json.loads((run_dir / "findings.json").read_text())["findings"] leaky = [f for f in findings if f["finding_id"].startswith("obligation:") and f["function_name"] == "leaky"] assert any("obligation_evidence:declared_policy_violation" in f["tags"] for f in leaky) assert not any("discharger:path_guard" in f["tags"] for f in leaky) # declared public: the guard obligation is waived def test_quick_scan_and_disabled_config_skip_obligations(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: repo = _repo(tmp_path, monkeypatch) assert main(["scan", str(repo), "--mode", "quick"]) == 0 manifest = json.loads((_run_dir(repo) / "manifest.json").read_text()) assert "obligations" not in manifest (repo / "openultrasast.toml").write_text("[obligations]\nenabled = false\n") assert main(["scan", str(repo), "--mode", "standard", "--config", str(repo / "openultrasast.toml")]) == 0 manifest = json.loads((_run_dir(repo) / "manifest.json").read_text()) assert "obligations" not in manifest findings = json.loads((_run_dir(repo) / "findings.json").read_text())["findings"] assert not any(f["finding_id"].startswith("obligation:") for f in findings)