mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 03:49:26 +00:00
fix(cpg): single-query path drops params the script does not declare
taint.request_params emits guards/fixedOrigin/originAnchors/quotedSanitizers/
fieldParameterSources, which taint.sc reads from per-request JSON in its BATCH
branch but does NOT declare on `@main def exec` and does NOT consume in its
single-request branch (it defaults them). The single-query path passed them as
`--param guards=...` (disposable) or named args (session), so joern errored
`Unknown arguments` and every cpg.run("taint", ...) failed -- a silent zero of
the shape AGENTS.md warns about. scan_region->taint_verdict->_usable_flows and
the pair-path verdict()/verdicts() were dead; the push/scan batch route was
unaffected (it carries the extras as JSON the script parses itself).
Fix: parse the script's `@main def exec(...)` signature once (_declared_exec_params
+ memoised _declared_params) and, in query(), filter params to the declared set
before building either route. Faithful, not lossy -- the single-request branch
could never use those 5 fields. No-op for config/dominance (their request_params
emit only declared params; verified). Only taint sheds the 5 extras.
Verified end-to-end on banks (patched backend in the replay image): single-query
path now runs; baseline 0 findings, annotated search 2 path/model_entailed
findings (prompt->write_text). Regression test asserts no undeclared param
reaches the command line and the query parses, with a fake runner (no Joern).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
8f7fc4ae83
commit
a024656da0
@@ -166,6 +166,43 @@ def test_a_batch_is_one_invocation_carrying_many_requests(monkeypatch: pytest.Mo
|
||||
assert rows["r1"] and rows["r2"] == []
|
||||
|
||||
|
||||
def test_a_single_query_passes_only_params_the_script_declares(tmp_path: Path) -> None:
|
||||
"""A taint spec carries fields only the BATCH path consumes (`guards`, `fixedOrigin`, ...): the script
|
||||
reads them from each request's JSON, and its single-request branch defaults them. Passed to `exec` as
|
||||
`--param guards=...`, joern reports `Unknown arguments` and the whole query fails -- a silent zero of the
|
||||
exact shape AGENTS.md warns about. The single-query path must drop any name the script does not declare.
|
||||
"""
|
||||
from openultrasast.cpg.backend import BEGIN, END, JoernBackend, _declared_exec_params
|
||||
from openultrasast.model.specs import taint_specs
|
||||
from openultrasast.model.taint import request_params
|
||||
|
||||
calls: list[list[str]] = []
|
||||
|
||||
class _Done:
|
||||
returncode = 0
|
||||
stderr = ""
|
||||
stdout = f"{BEGIN}\n[]\n{END}\n"
|
||||
|
||||
def runner(command, **kwargs): # type: ignore[no-untyped-def]
|
||||
calls.append(list(command))
|
||||
return _Done()
|
||||
|
||||
backend = JoernBackend(runner=runner)
|
||||
spec = taint_specs(language="python")["path"]
|
||||
params = request_params(spec, function="from_prompt_path", file="x.py", parameter_sources=True)
|
||||
# The spec DOES emit the undeclared fields; the guard is that they do not reach the command line.
|
||||
undeclared = set(params) - _declared_exec_params((backend.queries_dir / "taint.sc").read_text())
|
||||
assert {"guards", "fixedOrigin", "originAnchors", "quotedSanitizers", "fieldParameterSources"} <= undeclared
|
||||
|
||||
result = backend.query(tmp_path / "cpg.bin", "taint", params)
|
||||
|
||||
assert result == [], "the query must parse, not fail on unknown arguments"
|
||||
assert len(calls) == 1
|
||||
passed = {part.split("=", 1)[0] for part in calls[0] if "=" in part}
|
||||
assert not (passed & {f"{name}" for name in undeclared}), f"undeclared params reached joern: {passed & undeclared}"
|
||||
assert {"sources", "sinks", "function"} <= passed, "declared params must still be sent"
|
||||
|
||||
|
||||
def test_a_failed_batch_yields_no_rows_for_any_request(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
"""Fail closed, as everywhere else: an engine that could not answer must not read as 'nothing here'."""
|
||||
from openultrasast.cpg.backend import JoernBackend
|
||||
|
||||
Reference in New Issue
Block a user