mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 03:49:26 +00:00
feat(model): v4 measured; a parameter-fed field becomes strong carried only when the exact flow confirms it
v4 (provenance split): pmpro 69 and wpstatistics 172 unchanged -- their tier-4 members are source-fed through same-file helpers that read the request; mwwpform 68 -> 248, because its CVE's region is fed by a constructor parameter, the shape the split demotes and the exact flow had put at 30. v5 asks the flow for exactly the parameter-fed fields a sink-bearing region reads, memoised per (family, file, field), and reports carriedBy for diagnosis. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
20d53f1c4d
commit
983eda5886
@@ -179,7 +179,16 @@ A phase that cannot show that is not an improvement, it is a story.
|
|||||||
The proxy is too loose: folding "assigned from a parameter" in with "assigned from a source" put 555
|
The proxy is too loose: folding "assigned from a parameter" in with "assigned from a source" put 555
|
||||||
and 569 regions in tier 4 -- every constructor assigns a field from a parameter -- and the CVEs sit in
|
and 569 regions in tier 4 -- every constructor assigns a field from a parameter -- and the CVEs sit in
|
||||||
those tiers on score alone. v4 splits the provenance: source-fed (or fed by a same-file method that
|
those tiers on score alone. v4 splits the provenance: source-fed (or fed by a same-file method that
|
||||||
reads a source) promotes to tier 4; parameter-fed only orders within a tier (weight +0.75). Measuring.
|
reads a source) promotes to tier 4; parameter-fed only orders within a tier (weight +0.75).
|
||||||
|
|
||||||
|
**v4, measured:** pmpro 69 and wpstatistics 172, both UNCHANGED with tier 4 still 555 and 569 -- their
|
||||||
|
tier-4 members are source-fed under the one-level rule (fields assigned from calls to same-file
|
||||||
|
helpers that read `$_REQUEST`, which on those plugins is a real request path, so the tier is roughly
|
||||||
|
honest and the CVE's position there is a within-tier question). mwwpform went 68 → **248**: its CVE's
|
||||||
|
region is fed by `$this->attachments = $attachments` in a constructor, exactly the parameter-fed shape
|
||||||
|
the split demotes, and exactly the shape the exact flow had put at 30. So v5 asks the exact flow for
|
||||||
|
precisely the parameter-fed fields a sink-bearing region reads -- memoised per (family, file, field)
|
||||||
|
for the batch, which the arbiter's memos were not until today -- and for nothing else.
|
||||||
|
|
||||||
- **Phase 3 — the LLM ranker.** Same evidence, ordered by a model. Gate: beats phase 2 leave-one-repository-out.
|
- **Phase 3 — the LLM ranker.** Same evidence, ordered by a model. Gate: beats phase 2 leave-one-repository-out.
|
||||||
If it does not, phase 2 ships and phase 3 does not.
|
If it does not, phase 2 ships and phase 3 does not.
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -647,8 +647,24 @@
|
|||||||
// flow form was a wall. It puts `_delete_files()` (fed by `$this->attachments`) and `record()` (fed by
|
// flow form was a wall. It puts `_delete_files()` (fed by `$this->attachments`) and `record()` (fed by
|
||||||
// a filter) where their sources say, instead of one tier below every region with a `$_GET` in its own
|
// a filter) where their sources say, instead of one tier below every region with a `$_GET` in its own
|
||||||
// body. Asked only where there is a sink to carry to, so a plugin's 21,000 tier-0 pairs pay nothing.
|
// body. Asked only where there is a sink to carry to, so a plugin's 21,000 tier-0 pairs pay nothing.
|
||||||
val carriedKind = if (sinkList.nonEmpty && familyInRepo) strongest(List(fieldCarriedKind, hookCarriedKind)) else ""
|
// Weak becomes strong only when the FLOW says so. A parameter-fed field is what every constructor
|
||||||
val carried = carriedKind.nonEmpty
|
// makes and what MW WP Form's `_delete_files()` is actually fed by; structure cannot tell the two
|
||||||
|
// apart, the join can. So the exact form is asked here for exactly the parameter-fed fields a
|
||||||
|
// sink-bearing region reads -- memoised per (family, file, field) for the batch -- and nowhere else.
|
||||||
|
// That bounds the flow queries to the cases the structure could not settle, instead of the 1,040
|
||||||
|
// sink-bearing pairs that did not finish in 1,800 s.
|
||||||
|
val structuralKind = if (sinkList.nonEmpty && familyInRepo) strongest(List(fieldCarriedKind, hookCarriedKind)) else ""
|
||||||
|
val carriedKind =
|
||||||
|
if (structuralKind != "parameter") structuralKind
|
||||||
|
else {
|
||||||
|
val confirmed = cpg.call
|
||||||
|
.nameExact(FIELD_ACCESS)
|
||||||
|
.filter(c => inScope(c.method))
|
||||||
|
.l
|
||||||
|
.exists(r => prefixKind(r.code.trim, fedFields(r.method.filename)) == "parameter" && taintedPrefixes(r.code.trim, r.method.filename))
|
||||||
|
if (confirmed) "source" else "parameter"
|
||||||
|
}
|
||||||
|
val carried = carriedKind.nonEmpty
|
||||||
val summary = ujson.Obj(
|
val summary = ujson.Obj(
|
||||||
"kind" -> "summary",
|
"kind" -> "summary",
|
||||||
"sinks" -> sinkList.size,
|
"sinks" -> sinkList.size,
|
||||||
@@ -656,6 +672,7 @@
|
|||||||
"sourceNear" -> sourceNear,
|
"sourceNear" -> sourceNear,
|
||||||
"carried" -> carried,
|
"carried" -> carried,
|
||||||
"carriedKind" -> carriedKind,
|
"carriedKind" -> carriedKind,
|
||||||
|
"carriedBy" -> (if (structuralKind.isEmpty) "" else if (fieldCarriedKind == structuralKind) "field" else "hook"),
|
||||||
"familyInRepo" -> familyInRepo
|
"familyInRepo" -> familyInRepo
|
||||||
)
|
)
|
||||||
val perSink = sinkList.map { sink =>
|
val perSink = sinkList.map { sink =>
|
||||||
|
|||||||
Reference in New Issue
Block a user