mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-19 04:59:28 +00:00
feat(model): phase 2 of flow-aware-ranking -- spend the region budget by evidence, weights published
`Evidence.score` orders pairs within a tier by one table of weights (open sinks, cleansed sinks, local / carried / near sources, entry, declared public), capped so volume stops counting, and zero for tier 0 so the weights can rank but never manufacture. `ScanBudget.order_by_evidence` runs the evidence pass over every region and cuts `max_regions` from each region's best (tier, score); `order_by_evidence()` is the one ordering function, used by the scan and by `benchmarks/ranking/position.py --evidence`. Off by default until the position benchmark says where the pinned CVEs land under it. 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
7ce0a30161
commit
60d13d7b6e
@@ -21,6 +21,20 @@ TIER_CLEANSED = 2 # a source exists, but every sink call is bound or cleansed o
|
||||
TIER_OPEN = 3 # a source exists and some sink call is computed and uncleansed: ask first
|
||||
TIER_OPEN_PUBLIC = 4 # tier 3 and declared public, or a source on the same statement: ask very first
|
||||
|
||||
# The within-tier weights, published here because they are the whole of what "heuristic ranking" means in
|
||||
# phase 2 and a reader should be able to see every one of them at once. They order, they never exclude.
|
||||
WEIGHTS: dict[str, float] = {
|
||||
"open_sink": 1.0, # per sink call that is computed, uncleansed and unbound, up to OPEN_SINK_CAP
|
||||
"cleansed_sink": -0.5, # per sink call that is cleansed on the call or bound, up to CLEANSED_SINK_CAP
|
||||
"source_local": 2.0, # a modelled source in the region's own body
|
||||
"carried": 1.5, # stage one of the two-stage join says a field or dispatch value arrives tainted
|
||||
"source_near": 1.0, # a modelled source within the arbiter's callDepth
|
||||
"entry": 0.5, # parameters untrusted by contract
|
||||
"access_declared_public": 1.0,
|
||||
}
|
||||
OPEN_SINK_CAP = 5
|
||||
CLEANSED_SINK_CAP = 3
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SinkEvidence:
|
||||
@@ -77,6 +91,33 @@ class Evidence:
|
||||
return TIER_OPEN_PUBLIC
|
||||
return TIER_OPEN
|
||||
|
||||
@property
|
||||
def score(self) -> float:
|
||||
"""Order WITHIN a tier, by the published weights below. Never across tiers: the tier is the predicate.
|
||||
|
||||
A weighted sum of the same exact facts the tier is made of, so it can rank but cannot manufacture --
|
||||
a pair with no sink scores nothing and stays tier 0 whatever its weights. Counts are capped because
|
||||
a file-scope region with 346 sinks is not 346 times more likely to hold the bug than one with 5;
|
||||
the cap is where the evidence stops saying more. Phase 2 of flow-aware-ranking.
|
||||
"""
|
||||
if self.tier == TIER_EXCLUDE:
|
||||
return 0.0 # no sink in reach: nothing to weigh, whatever the sources say
|
||||
w = WEIGHTS
|
||||
return (
|
||||
w["open_sink"] * min(len(self.open_sinks), OPEN_SINK_CAP)
|
||||
+ w["cleansed_sink"] * min(sum(1 for s in self.sinks if s.cleansed_on_call or self.is_bound(s)), CLEANSED_SINK_CAP)
|
||||
+ (w["source_local"] if self.source_local else 0.0)
|
||||
+ (w["carried"] if self.carried else 0.0)
|
||||
+ (w["source_near"] if self.source_near else 0.0)
|
||||
+ (w["entry"] if self.entry else 0.0)
|
||||
+ (w["access_declared_public"] if self.access_declared_public else 0.0)
|
||||
)
|
||||
|
||||
@property
|
||||
def order_key(self) -> tuple[int, float]:
|
||||
"""Higher sorts first: ``sorted(..., key=lambda e: e.order_key, reverse=True)``."""
|
||||
return (self.tier, self.score)
|
||||
|
||||
|
||||
def evidence_from_rows(
|
||||
rows: Sequence[Mapping[str, object]] | None,
|
||||
@@ -139,11 +180,14 @@ def _as_int(value: object) -> int:
|
||||
|
||||
|
||||
__all__ = [
|
||||
"CLEANSED_SINK_CAP",
|
||||
"OPEN_SINK_CAP",
|
||||
"TIER_CLEANSED",
|
||||
"TIER_EXCLUDE",
|
||||
"TIER_NO_SOURCE",
|
||||
"TIER_OPEN",
|
||||
"TIER_OPEN_PUBLIC",
|
||||
"WEIGHTS",
|
||||
"Evidence",
|
||||
"SinkEvidence",
|
||||
"evidence_from_rows",
|
||||
|
||||
Reference in New Issue
Block a user