mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-18 20:49:28 +00:00
fix(scan): a catch-all function's parameters are not attacker input; field reads need the same field
Two classes the traced PMPro survivors named after 1f91c0b:
- The mapper records every named PHP function as an entry of kind
`function` (3,507 of PMPro's 4,412), and every entry's parameters were
sources, so internal helpers became injections: sendCancelAdminEmail's
$user, a gateway hook callback's $user_id/$morder fired by do_action.
Regions now carry the entry kind; parameters are input only for request
entries (route, parser, privileged surface). Call depth is unchanged, so
such a region is still followed into its callees. JavaScript and Python
emit no `function` entries.
- The object rule is general: a field read continues a flow through the
bare object only if the taint came through the SAME field, or was
assigned to the variable or passed in as a parameter. It now also cuts
$this->Gateway -> this -> $this->user_id (memberorder.php:705).
plausible() memoises the sink test per node and skips the object walk for
paths with no field access (the filter had cost one outlier 101 s -> 160 s).
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
1f91c0b089
commit
da0ee576f8
@@ -66,6 +66,10 @@ class ScanRegion:
|
||||
# Does the project's own build declaration name this file? True when it declares nothing at all --
|
||||
# silence is not exclusion, and no repository is penalised for a build system we cannot read.
|
||||
shipped: bool = True
|
||||
# What the mapper called the entry: `route`, `parser`, `privileged_surface`, ... or `function`, which is
|
||||
# its catch-all for a named function with no evidence of receiving a request. Only the scan's parameter
|
||||
# rule reads it, because only it depends on whether a parameter carries request data.
|
||||
entry_kind: str = ""
|
||||
|
||||
|
||||
def regions_for(entries: Sequence[object], targets: Sequence[object], *, shipped: frozenset[str] | None = None) -> tuple[ScanRegion, ...]:
|
||||
@@ -126,6 +130,7 @@ def regions_for(entries: Sequence[object], targets: Sequence[object], *, shipped
|
||||
families=families,
|
||||
rank=rank,
|
||||
source="module_scope" if module_body else "entry_point",
|
||||
entry_kind=str(getattr(entry, "kind", "") or ""),
|
||||
)
|
||||
|
||||
# A nameless entry point IS the file. Where a named region already covers that file it adds nothing but
|
||||
|
||||
Reference in New Issue
Block a user