Files
Open_Ultra_SAST/tests/test_cpg_backend.py
T
Marius CiepluchandClaude Opus 5 fe45081b43 fix(ci): run ruff format, and record run 5 at 90% pair-correct
CI was red on `ruff format --check`: 23 files. I ran `ruff check` after every
change this session and never once ran `ruff format --check`, though CI runs
both. Lint passing is not formatting passing, and I treated one as evidence for
the other for the whole session.

Formatting applied. The full CI sequence now reproduces locally: format, lint,
mypy over 94 files, 735 tests, three gates byte-identical, compileall, and the
semantic job's 16 marked tests.

Also records run 5 of the pipeline measurement, which the vampi fix lifted as
predicted:

                       hunter (K=5)   pipeline (K=1)
  pair-correct              76.7%          90.0%
  leak                      12.3%           6.7%
  detection                    --          96.7%
  cost                     ~$0.69        $0.0068

27 of 30 pairs. Five runs, each step from a measurement contradicting an
assumption: 73.3 (no pipeline path) -> 73.3 (routing fixed, IDENTICAL, which
exposed the discarded verdict) -> 80.0 (residual question matched to its
arbiter) -> 86.7 (aiohttp settings) -> 90.0 (dominance question no longer
contradicting its own evidence).

One miss left: dsvpwa-dsvpwa-main, whose setting is an argparse --ssl default
rather than a security-setting call. Out of reach before the settings work and
still is; contorting the arbiter around one pair would be worse than the miss.

The caveat is recorded beside the number: 30 pairs of one slice, and the slice
iterated against all session. The +16% overfitting gap against vfc-js is why
contributor-scan Req 8.1/8.2 exist.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-08 19:46:58 +02:00

108 lines
4.3 KiB
Python

"""model-grounded-detection task 2.1: the Joern seam, out of process and capability-detected.
Joern is a JVM tool. The whole integration is one subprocess boundary so that the core install stays
zero-dependency and an absent engine degrades to `suspicion` with a recorded reason rather than a traceback.
Nothing here imports a JVM binding, and every test runs with Joern absent.
"""
from __future__ import annotations
import json
from pathlib import Path
import pytest
def test_without_joern_the_resolved_backend_is_the_null_one(monkeypatch: pytest.MonkeyPatch) -> None:
from openultrasast.cpg.backend import NullBackend, resolve_cpg_backend
monkeypatch.setenv("OPENULTRASAST_JOERN_PROBE", "off")
backend = resolve_cpg_backend()
assert isinstance(backend, NullBackend)
assert backend.available() is False
assert backend.build(Path(".")) is None, "an absent engine yields no CPG, and the caller degrades"
def test_the_capability_probe_reuses_the_existing_joern_probe(monkeypatch: pytest.MonkeyPatch) -> None:
"""`semantic/engines.joern_available` already exists; the model layer must not grow a second probe."""
from openultrasast.cpg.capability import has_cpg
monkeypatch.setenv("OPENULTRASAST_JOERN_PROBE", "off")
assert has_cpg() is False
monkeypatch.setenv("OPENULTRASAST_JOERN_PROBE", "on")
assert has_cpg() is True
def test_the_seam_imports_nothing_outside_the_standard_library() -> None:
"""Req 4.2: the core install has no dependencies, so the seam may not import one at module load."""
import ast
source = Path("src/openultrasast/cpg/backend.py").read_text()
imported = set()
for node in ast.walk(ast.parse(source)):
if isinstance(node, ast.ImportFrom) and node.module and node.level == 0:
imported.add(node.module.split(".")[0])
elif isinstance(node, ast.Import):
imported.update(alias.name.split(".")[0] for alias in node.names)
stdlib = {
"__future__",
"json",
"os",
"re",
"shutil",
"subprocess",
"tempfile",
"dataclasses",
"pathlib",
"typing",
"collections",
"logging",
"hashlib",
}
assert imported <= stdlib, f"the seam imports outside the standard library: {sorted(imported - stdlib)}"
assert "import jpype" not in source and "py4j" not in source, "Joern is reached by subprocess, never in-process"
def test_a_scripted_backend_parses_a_query_result_without_joern(tmp_path: Path) -> None:
"""The parsing is exercised by canned JSON, so the query contract is testable with no engine installed."""
from openultrasast.cpg.backend import CpgResult
payload = [{"sink": "os.system", "source": "request.args", "path": ["a", "b"], "sanitized": False}]
def run(query: str, params: dict[str, object]) -> object:
assert query == "taint"
return payload
result = CpgResult(cpg_path=tmp_path / "cpg.bin", run=run)
assert result.run("taint", {}) == payload
def test_joern_output_is_read_from_a_delimited_block_not_from_noisy_stdout() -> None:
"""Joern prints a banner and a REPL prompt; the payload is fenced so the parse cannot swallow either."""
from openultrasast.cpg.backend import BEGIN, END, extract_payload
noisy = f"Compiling...\nJoern v4.0\n{BEGIN}\n{json.dumps([{'sink': 'eval'}])}\n{END}\njoern> \n"
assert extract_payload(noisy) == [{"sink": "eval"}]
assert extract_payload("no markers at all") is None
assert extract_payload(f"{BEGIN}\nnot json\n{END}") is None
def test_a_failing_or_slow_engine_fails_closed(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
"""Fail closed: a build or query that errors yields no verdict, never a wrong one."""
import subprocess
from openultrasast.cpg.backend import JoernBackend
def boom(*args: object, **kwargs: object) -> object:
raise subprocess.TimeoutExpired(cmd="joern-parse", timeout=1)
backend = JoernBackend(runner=boom)
monkeypatch.setenv("OPENULTRASAST_JOERN_PROBE", "on")
assert backend.build(tmp_path) is None
def test_the_query_scripts_are_shipped_beside_the_seam() -> None:
"""The CPGQL is ours and is data: it lives with the package, not inlined in a Python string."""
queries = Path("src/openultrasast/cpg/queries")
assert (queries / "taint.sc").is_file(), "the injection taint query must ship with the package"