Files
Open_Ultra_SAST/ops/smoke_partitions.py
T

153 lines
8.7 KiB
Python
Raw Normal View History

"""Real mixed-language graph input and global ranker smoke; no hook quality claim."""
from __future__ import annotations
import hashlib
import json
import os
import sys
import tempfile
import time
from dataclasses import asdict
from pathlib import Path
from openultrasast.cpg.backend import JoernBackend
from openultrasast.model.contracts import ExecutionBudget
from openultrasast.model.regions import ScanRegion
from openultrasast.model.scan import ScanBudget, scan_repository
def main() -> None:
include_tests = os.environ.get("OUSAST_SMOKE_INCLUDE_TESTS", "1") == "1"
deadline = ExecutionBudget(time.monotonic() + 900, 2.0)
records: list[dict[str, object]] = []
with tempfile.TemporaryDirectory(prefix="ousast-partitions-smoke-") as temporary:
base = Path(temporary)
root = base / "source"
queries = base / "queries"
queries.mkdir()
(queries / "partition_witness.sc").write_text("""@main def exec(cpgFile: String) = {
importCpg(cpgFile)
println("---OUSAST-CPG-BEGIN---")
println(ujson.write(ujson.Obj(
"files" -> ujson.Arr.from(cpg.file.name.l),
"methods" -> ujson.Arr.from(cpg.method.name.l)
)))
println("---OUSAST-CPG-END---")
}
""")
sources = {
"Gruntfile.js": "function build_config_marker() { return 42; }\n",
"src/api.php": "<?php\nfunction php_handler($req) { eval($req); }\n",
"server/api.js": "function js_handler(req) { eval(req.query.code); }\n",
"browser/client.js": "function browser_marker() { return 42; }\n",
"tests/probe.php": "<?php\nfunction php_test_marker() { return 42; }\n",
"tests/probe.js": "function js_test_marker() { return 42; }\n",
"vendor/library.php": "<?php\nfunction vendor_php_marker($req) { eval($req); }\n",
"node_modules/library.js": "function vendor_js_marker(req) { eval(req); }\n",
"unsupported.go": "package example\nfunc Unmodeled() {}\n",
}
suffix_tests = {f"checks/probe.{suffix}.js": f"js_{suffix}_marker" for suffix in ("test", "spec", "mock", "e2e")}
sources.update({path: f"function {method}() {{ return 42; }}\n" for path, method in suffix_tests.items()})
inputs = {}
for filename, content in sources.items():
path = root / filename
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(content)
data = path.read_bytes()
assert data and data == content.encode(), f"unread input: {filename}"
inputs[filename] = {"bytes": len(data), "sha256": hashlib.sha256(data).hexdigest()}
class RecordingBackend(JoernBackend):
def build(self, root: Path, *, language: str = "", **kwargs):
projected = {}
for source in root.rglob("*"):
if source.is_file():
data = source.read_bytes()
filename = source.relative_to(root).as_posix()
projected[filename] = {"bytes": len(data), "sha256": hashlib.sha256(data).hexdigest()}
assert projected[filename] == inputs[filename], f"projected input differs: {filename}"
print(json.dumps({"frontend": language, "projected_inputs": projected}), file=sys.stderr, flush=True)
graph = super().build(root, language=language, **kwargs)
assert graph is not None, f"real {language} graph failed: {self.last_failure}"
witness = JoernBackend(queries_dir=queries, heap_mb=1024, execution_budget=deadline).query(
graph.cpg_path, "partition_witness", {}
)
assert isinstance(witness, dict), f"{language} census unanswered"
print(json.dumps({"frontend": language, "graph_witness": witness}), file=sys.stderr, flush=True)
files = witness["files"]
methods = witness["methods"]
assert files and methods, f"{language} graph empty"
assert not any("vendor" in str(path) or "node_modules" in str(path) for path in files), witness
assert not any("vendor_" in str(method) for method in methods), witness
if language == "php":
assert any(str(path).endswith("src/api.php") for path in files), witness
assert any(str(path).endswith("tests/probe.php") for path in files), witness
assert "php_handler" in methods and "php_test_marker" in methods, witness
assert "js_handler" not in methods, witness
elif language == "javascript":
assert any(str(path).endswith("server/api.js") for path in files), witness
assert any(str(path).endswith("tests/probe.js") for path in files), witness
assert "js_handler" in methods and "js_test_marker" in methods, witness
assert any(str(path).endswith("Gruntfile.js") for path in files), witness
assert "build_config_marker" in methods, witness
for path, method in suffix_tests.items():
assert any(str(filename).endswith(path) for filename in files), witness
assert method in methods, witness
assert "php_handler" not in methods, witness
assert any(str(path).endswith("browser/client.js") for path in files), witness
assert "browser_marker" in methods, witness
else:
raise AssertionError(f"unexpected frontend: {language}")
records.append({"frontend": language, "input_root": str(root), "graph_witness": witness})
return graph
regions = (
ScanRegion("src/api.php", "php_handler", "php", ("injection",), 10.0, "entry_point"),
ScanRegion("server/api.js", "js_handler", "javascript", ("injection",), 9.0, "entry_point"),
ScanRegion("tests/probe.php", "php_test_marker", "php", ("injection",), 2.0, "entry_point"),
ScanRegion("tests/probe.js", "js_test_marker", "javascript", ("injection",), 1.0, "entry_point"),
ScanRegion("vendor/library.php", "vendor_php_marker", "php", ("injection",), 100.0, "entry_point"),
ScanRegion("node_modules/library.js", "vendor_js_marker", "javascript", ("injection",), 100.0, "entry_point"),
)
result = scan_repository(
root,
regions,
backend=RecordingBackend(heap_mb=1024, include_tests=include_tests),
budget=ScanBudget(max_regions=1),
execution_budget=deadline,
ranking_mode="static",
unit="partition-smoke",
population_complete=True,
)
assert {record["frontend"] for record in records} == {"php", "javascript"}, records
assert result.scope is not None
invalid_census = {"cpg_empty", "files_unparsed", "partition_file_census_unavailable", "partition_file_census_incomplete"}
assert not invalid_census.intersection(result.scope.unresolved_boundaries), result.scope
assert not any(d.get("reason") in invalid_census for d in result.degradations), result.degradations
assert [q.identity.function for q in result.scope.selected] == ["php_handler"], result.scope
assert {q.identity.function for q in result.scope.deferred} == {"js_handler", "php_test_marker", "js_test_marker"}, result.scope
assert len(result.question_outcomes) == 1, result.question_outcomes
assert result.question_outcomes[0].identity == result.scope.selected[0].identity
assert all("vendor" not in q.identity.path and "node_modules" not in q.identity.path for q in result.scope.selected), result.scope
assert any(p.language == "go" and p.status == "unsupported" for p in result.partitions), result.partitions
javascript = next(p for p in result.partitions if p.language == "javascript")
assert set(javascript.unshipped_paths) == {"tests/probe.js", *suffix_tests}, javascript
assert javascript.runtime == "unspecified", "runtime role needs declared evidence"
php = next(p for p in result.partitions if p.language == "php")
assert php.unshipped_paths == ("tests/probe.php",), php
assert all(not Path(record["input_root"]).exists() for record in records), "partition scratch leaked"
report = {
"purpose": "Real mixed PHP/JavaScript graph census and one global ranker budget; no admission or latency claim",
"shared_budget_seconds": 900,
"include_tests": include_tests,
"inputs": inputs,
"graph_witnesses": records,
"result": asdict(result),
}
print(json.dumps(report, indent=2))
if __name__ == "__main__":
main()