mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-19 13:10:03 +00:00
Ran the humanizer rules over 79 prose files in the active specs (brief, design, requirements, research and narrative docs). Removed em dashes, significance inflation, forced rule-of-three, bold-label list items and filler. Skipped tasks.md checklists and the retired specs (harnessx-*, openrouter-sast-harness, unseen-repo-evaluation). Every number, path, command, hash and identifier was preserved: checked each file against HEAD for drift in numbers, inline code and code fences, zero drift across all 79 files. Co-Authored-By: Claude Opus 4.8 <[email protected]>
175 lines
11 KiB
Markdown
175 lines
11 KiB
Markdown
# Release remediation research, 2026-09-14
|
||
|
||
Status: investigation under the maintainer's instruction to continue towards release.
|
||
This record does not approve rollout, replace the existing design, or mark a production
|
||
remediation complete. The published candidate is `v1.2.0-alpha.1`, commit `04f8880`.
|
||
|
||
## Summary
|
||
|
||
Two independent constraints remain after task 2.19 restored Node's complete named census:
|
||
engine lifecycle cost and the scope of completeness evidence. A faster engine cannot
|
||
repair missing context; suppressing completeness gaps cannot prove useful detection.
|
||
Both belong in the existing contributor-scan boundary, with comparison/admission changes
|
||
owned by pre-push-safety-net. The ranker continues to select all analysis work.
|
||
|
||
## Engine lifecycle investigation
|
||
|
||
The earlier task 2.3 decision rejected server mode on the measured large C workload:
|
||
evaluation dominated its elapsed time. That decision remains valid for that measurement.
|
||
It does not establish the best lifecycle for small, frequently changed API repositories.
|
||
|
||
The fresh Node priming transaction reopened the declared inputs and completed in 338.157s.
|
||
Its two frontends took 5.536s and 5.451s; overlays 15.779s and 15.239s; standalone census
|
||
13.716s and 13.708s. Each of eight query invocations took another 13.264–22.783s. These
|
||
are individual process receipts, not estimates of exclusive JVM startup time. The remaining
|
||
transaction time includes Python orchestration, cache publication and other work and must
|
||
not be attributed to the JVM without a separate measurement.
|
||
|
||
The first identical-tip replay took 18.874s with two graph hits, 1,512 query hits, and no
|
||
engine subprocesses. Thus compatible persistence now works on this workload. Every head
|
||
question still has incomplete change context; base questions have `graph_incomplete` from
|
||
the vendor boundary described below. Identical-tip timing is not changed-code qualification.
|
||
|
||
Joern documents a local interpreter server with synchronous and asynchronous query APIs:
|
||
[official server contract](https://docs.joern.io/server/). This supplies a candidate transport,
|
||
not a sandbox. Before adopting it, probe the actual pinned 4.0.625 image in a disposable,
|
||
network-disabled container with no published ports, a private graph copy and process-group
|
||
cleanup. Compare an actual named census against disposable script execution, record startup,
|
||
load and repeated request times separately, and test cancellation of an in-flight request.
|
||
A census microbenchmark cannot establish security-query equivalence or hook p95.
|
||
|
||
### Completed lifecycle probe
|
||
|
||
[Full receipts and all three instruments](../../../benchmarks/measurements/2026-09-14-joern-session-lifecycle.json)
|
||
retain the failed first attempt as well as both successful file-receipt attempts.
|
||
The first attempt received HTTP `success=true` with an empty stdout for the census;
|
||
the `println` payload went to the process log. It failed rather than interpreting that
|
||
response as a zero. The repaired instrument writes a fresh private result file per
|
||
request and checks a unique receipt before accepting its census.
|
||
|
||
The final attempt reopened all 44 source files (95,411 bytes), verified the cached graph
|
||
digest, loaded a private copy, and matched names, counts and overlays against disposable
|
||
execution. It confirmed entry into a deliberately hanging operation before cancellation,
|
||
then verified the entire process group disappeared. The cached graph remained unchanged.
|
||
|
||
| Final attempt phase | Observed seconds |
|
||
|---|---:|
|
||
| Disposable census invocation | 14.292 |
|
||
| Server startup through usable request | 12.805 |
|
||
| Graph load | 3.636 |
|
||
| First census request | 1.402 |
|
||
| Four warm census requests | 0.339, 0.467, 0.353, 0.221 |
|
||
| Kill and process-group reaping | 0.043 |
|
||
|
||
Decision: a transaction-owned local session is a promising candidate for the owner
|
||
implementation. The adapter needs explicit request receipts; HTTP status alone is not
|
||
an answer contract. This probe does not cover full taint/dominance/config equivalence,
|
||
multiple graph epochs, concurrent transactions, overlays in-session or production
|
||
failure recovery. It neither overturns the large-C evaluation result nor proves 30s p95.
|
||
|
||
### Completed full runtime profile
|
||
|
||
The [post-census scorecard](../../../benchmarks/measurements/2026-09-14-nodegoat-post-census-feasibility.json)
|
||
and its compressed 115-file evidence bundle retain all 21 planned transactions plus
|
||
priming, raw scans, process traces, CLI output and exact instruments. All 22 scan artifacts
|
||
match the frozen runtime/core provenance; recomputing the scorecard reproduced its result.
|
||
There were no missing cases or instrument failures. Eighteen transactions timed out;
|
||
the three identical-tip cases took 18.521–18.874s. Completion remains 0/24 target checks;
|
||
maximum observed cancellation/report overrun was 0.8732s. Runtime and rollout remain NO-GO.
|
||
|
||
Verification: seven runtime-scorecard tests pass; JSON/bundle round-trip, hashes, population,
|
||
provenance and scorecard recomputation pass. Production source is unchanged from the
|
||
released alpha; this is evidence validation, not a new full implementation verification.
|
||
|
||
## Completeness diagnosis
|
||
|
||
### Missing family context producer
|
||
|
||
`model/scan.py:_evidence_pass` dispatches only taint queries and records their context by
|
||
the exact family-specific question identity. `affected_context` requires `context_summary`
|
||
and readable method extents for every question. Neither `dominance.sc` nor `config.sc`
|
||
exports that contract. Consequently access-control and configuration questions cannot
|
||
complete change context through the production path. This is deterministic missing
|
||
integration, not evidence that the ranker selected the wrong region.
|
||
|
||
Do not copy taint context into other families: dominance deliberately evaluates sibling
|
||
operations across a file; configuration has different scope; source, sink and guard
|
||
summaries have different obligations. A producer must describe the actual scope of the
|
||
query it accompanies. Missing extents, unresolved external calls and unsupported reasoning
|
||
remain explicit. Context relationships alone never prove an exploitable flow or guard loss.
|
||
|
||
### Exclusion is currently a global completion veto
|
||
|
||
`model/partitions.py` records `vendor_semantics_unresolved` when it excludes any vendor
|
||
path. `model/scan.py` includes that reason in `graph_gaps`, changing every otherwise
|
||
completed outcome to `graph_incomplete`. In the fresh Node prime, this is the only base
|
||
degradation, despite a complete 44-file first-party census and successful query receipts.
|
||
|
||
Vendor exclusion must remain physical. The missing contract is which question actually
|
||
requires excluded semantics. Distinguish input-integrity failures, which invalidate the
|
||
affected graph, from an excluded dependency whose relevance needs query evidence. Only
|
||
an explicit, complete dependency proof or versioned summary can discharge that question's
|
||
boundary; lack of a recorded dependency is not such proof.
|
||
|
||
### Line ambiguity propagates beyond the affected correspondence
|
||
|
||
`push/snapshot.py` conservatively omits non-unique unchanged lines and records a file-level
|
||
`ambiguous_line_correspondence`. `model/regions.py:affected_context` inherits any existing
|
||
boundary into every question. `push/policy.py:compare_evidence` also rejects a candidate
|
||
when any transaction context boundary exists. Repeated unchanged lines can therefore
|
||
invalidate an otherwise distinct, uniquely mapped operation elsewhere.
|
||
|
||
Retain ambiguous mappings as unavailable. A future repair must bind the required base/head
|
||
correspondence to the specific operation and dependency context, with absent, renamed,
|
||
removed-guard and ambiguous-operation controls. Aggregate coverage must retain every gap.
|
||
Do not delete the ambiguity check or treat lexical alignment as a semantic proof.
|
||
|
||
Comparison currently also requires all selected base questions to complete, no base
|
||
degradations, and no non-tier-zero deferred question. That prevents a complete target
|
||
comparison from surviving an unrelated unsupported family. Any amendment must establish
|
||
the complete base counterpart and its required scope explicitly; a missing raw finding
|
||
in an incomplete base scan cannot establish novelty. This change belongs to the push
|
||
comparison policy, consuming evidence ownership supplied by the shared scan contract.
|
||
|
||
### Query identity and witness identity differ
|
||
|
||
The Node contribution target is selected through a file-fallback injection question
|
||
(`function=None`), while raw rows report `<lambda>2` at lines 32–34. The declared benchmark
|
||
target is `handleContributionsUpdate`. VAmPI similarly has a raw SQLI site without an exact
|
||
function target question. The benchmark correctly refuses exact-target completion today.
|
||
Production normalization must carry verified query-to-operation provenance; do not inject
|
||
benchmark function names into regions or change the denominator to count coincident sites.
|
||
|
||
## Bounded remediation sequence
|
||
|
||
1. Finish and preserve the unchanged seven-class runtime profile, including all failures.
|
||
Run the isolated lifecycle probe afterwards so the experiments do not contend for CPU.
|
||
2. Use those results to choose one engine lifecycle amendment. If a session is promising,
|
||
keep it transaction-owned inside the existing backend: one deadline, serialized requests,
|
||
explicit graph identity/epoch, private leases, failure poisoning, kill-and-reap cancellation,
|
||
and fresh census on each answer. No resident laptop service is implied. Compare every
|
||
shipped query kind with the disposable path before any production switch.
|
||
3. Specify question-owned completeness across scan and comparison boundaries. First add
|
||
authentic family context producers, then dependency/correspondence ownership, with paired
|
||
PHP/JavaScript normalized controls and VAmPI regressions. Unknown ownership remains a
|
||
blocker. A family that cannot provide this evidence stays experimental.
|
||
4. Refreeze runtime and semantic identities. Rerun changed-code latency/completion and the
|
||
independent reviewed vulnerable/fixed/benign populations together. Regenerate eligibility
|
||
only after the existing joint gates pass; then repeat packaged acceptance validation.
|
||
|
||
This sequence separates runtime transport from evidence semantics. It adds no detector,
|
||
second IR, language-specific rank boost, vendor graph expansion or differential CPG mutation.
|
||
|
||
## Verification needed for implementation
|
||
|
||
| Boundary | Required evidence |
|
||
|---|---|
|
||
| `cpg/backend.py`, candidate local session transport | Actual pinned launch/API; full query equivalence; malformed/absent response; switched graph isolation; concurrent transactions; deadline, crash and orphan cleanup |
|
||
| `cpg/queries/{taint,dominance,config}.sc`, `model/scan.py` | Context from actual query scope; authentic per-family methods; answered-empty distinct from unavailable; unchanged rank decisions |
|
||
| `model/contracts.py`, `model/regions.py`, `model/partitions.py` | Explicit gap ownership; first-party input failures remain blocking; dependent vendor/unknown paths unresolved; unrelated exclusion never silently proves completeness |
|
||
| `push/snapshot.py`, `push/policy.py` | Exact operation correspondence; guard deletion; same-named and ambiguous operations; incomplete base cannot establish novelty; aggregate partial coverage retained |
|
||
| Evaluation and eligibility | Frozen identities and populations; unchanged 30s/2s and precision/recall/completion gates; no capability enabled by a microbenchmark |
|
||
|
||
Production changes require task-local review and fresh ordinary scan gates, runtime smoke,
|
||
and downstream acceptance evidence. This research record is not that verification.
|