mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 03:49:26 +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
@@ -375,3 +375,16 @@ def test_a_killed_culprit_makes_its_family_dearer_and_nothing_else() -> None:
|
||||
assert sizer.rate("output_encoding") >= 54.0
|
||||
assert abs(sizer.rate("injection") - 1.0) < 1e-9
|
||||
assert sizer.fixed == 25.0, "a killed portion must not be read as a fixed-start sample"
|
||||
|
||||
|
||||
def test_only_a_request_entry_treats_its_parameters_as_attacker_input() -> None:
|
||||
"""The mapper's `function` kind is its catch-all; its parameters carry whatever the caller had."""
|
||||
from openultrasast.model import scan
|
||||
|
||||
route = ScanRegion("api.php", "handle", "php", ("injection",), 1.0, "entry_point", entry_kind="route")
|
||||
helper = ScanRegion("mail.php", "sendCancelAdminEmail", "php", ("injection",), 0.3, "entry_point", entry_kind="function")
|
||||
params = scan._grouped([("0", route, scan._spec_for("injection", "php")), ("1", helper, scan._spec_for("injection", "php"))])["taint"]
|
||||
assert params["0"]["parameterSources"] == "true"
|
||||
assert params["1"]["parameterSources"] == "false"
|
||||
# Still followed into its callees: only its own parameters stop being sources.
|
||||
assert params["1"]["callDepth"] == params["0"]["callDepth"] != "0"
|
||||
|
||||
Reference in New Issue
Block a user