Files
Open_Ultra_SAST/.kiro/specs
Marius CiepluchandClaude Opus 5 9910dd18b9 measure(php): the query cost is the matched sink count, and the blocker is identified
Open since September and re-measured nine times. The cost of a taint batch is the number of CALL
NODES a family sink names match in the repository. Not the request count, not the declared sink
count, not any request parameter. reachableByFlows is asked per matched sink, and PHP
soutput-encoding sinks are echo and print, which a WordPress plugin writes thousands of times.

Three controlled sweeps on one graph, built once.

  Batch size exonerated: 400 requests answer in 170 s, and cost per request FALLS with size because
  roughly 70 s is fixed JVM start and graph load.

  Request parameters exonerated: at 200 requests the full production shape, call depth 3 with
  parameter sources, costs 221 s against a 150 s baseline.

  The family is the variable: at the same 100 requests, SQL injection 147 s with six declared sinks,
  path 194 s with sixteen, output encoding 704 s with seven.

And the driver named its own expensive step once it was asked to: 2,435 evidence requests in 45.5 s,
then 315 arbitration requests unanswered at 1,200 s, then a split abandoned for want of time.

It survived since September because every reproduction outside the driver carried the SQL sinks --
the family the declared target belongs to, and the one family that is cheap on this subject. Nine
hypotheses were eliminated by re-measuring the cheap case.

Splitting never rescued it because a failed batch is split by REQUEST COUNT and each part carries the
same everywhere-sinks. contributor-scan 7.7 carries the fix: budget a batch by the sink nodes it
implies, using the count the evidence pass already computes, and report a family whose sinks are
everywhere as expensive rather than as failed.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
2026-09-22 09:53:52 +02:00
..