Document propagated-source argument-taint core-engine wall (3 failed experiments)
ober
1ab0dccfc40c0e0566dbb0c0f584e36d379ffe28
--- a/HANDOFF_OPUS_4_8.md +++ b/HANDOFF_OPUS_4_8.md @@ -370,3 +370,37 @@ and commit them with `src/**/*.ss`. Key files: `src/semgrep/scan.ss` (scanner, taint, generic matcher, reachability), `src/semgrep/match/structural.ss` (AST matcher), `tests/smoke.ss`, `tests/oracle/upstream-sweep.sh`. No git remote is configured, so commits cannot be pushed. + +## Propagated-source argument-taint — CORE-ENGINE WALL (2026-06-02) + +The remaining java-taint fixtures that involve a PROPAGATED variable used as a +call/constructor argument (taint_propagator_lambda func3 `new NodeSucc(nodePred)`, +func4 `students.forEach((n)->exec(n))`) are blocked on a deep interaction in the +taint-source EXPANSION fixpoint (expand-taint-sources / new-propagated-sources / +propagator-applies*), NOT on the surface argument-taint rules. + +THREE experiments, all reverted (smoke/numbers1 must stay green): +1. Relax `original-bare-variable-source?` (drop `origin==finding`, keep + `null? labels`) in BOTH the sink reach and the propagator → the whole taint + pipeline returns 0 findings for java-query; sink-output-findings never called. +2. Relax ONLY the propagator (separate `propagated-bare-variable-source?`) → + numbers1 regresses to [] : DBGO trace shows `sink(w)` and `sink(t)` get + `reaching0=0` — the intermediate-var reaches are LOST (not over-produced), + even though those methods' own propagation is unchanged. So it's a NON-LOCAL + fixpoint effect (extra propagated states from OTHER methods perturb the shared + `known` list). +3. Add `origin` to the `taint-state-already-present?` dedup key + the propagator + relaxation → numbers1 STILL []; AND func3 is STILL not fixed (nodeSucc never + tainted even though nodePred is eligible and its token is in the RHS). So the + dedup is not the (only) cause, and there is a hidden gate in propagator-applies* + that blocks a propagated source from propagating onward. + +NEXT (for whoever picks this up): instrument propagator-applies* on func3 to find +why `nodePred` (a tainted, propagated, bare-id source) does NOT taint the binding +`NodeSucc nodeSucc = new NodeSucc(nodePred)` even when admitted — that hidden gate +is the real blocker. Separately, the non-local numbers1 regression means the +expansion's state-identity/kill model must be made origin/path-aware before +propagated sources can safely re-propagate. This is a core-engine rework, not a +surface rule. lambda1 is unrelated (needs `@RequestParam Map<$TYPE,$TYPE> $VALUE` +annotated-generic-param method-sig pattern-inside matching + a `$QUERY` focus +off-by-one).