feat(rules): Update rules to use star operator - #314
Open
misonijnik wants to merge 14 commits into
Open
misonijnik wants to merge 14 commits into
misonijnik wants to merge 14 commits into
Conversation
misonijnik
force-pushed
the
misonijnik/3-rules
branch
3 times, most recently
from
July 30, 2026 08:10
f5be3ef to
97adcc7
Compare
misonijnik
force-pushed
the
misonijnik/3-rules
branch
2 times, most recently
from
August 12, 2026 09:24
9508d6a to
c3403d7
Compare
misonijnik
force-pushed
the
misonijnik/3-rules
branch
from
August 14, 2026 10:12
c3403d7 to
11ca418
Compare
misonijnik
marked this pull request as ready for review
August 14, 2026 10:15
Saloed
force-pushed
the
misonijnik/3-rules
branch
from
August 17, 2026 19:25
11ca418 to
bc5cc77
Compare
misonijnik
force-pushed
the
misonijnik/3-rules
branch
2 times, most recently
from
August 18, 2026 15:45
41185cc to
56224bf
Compare
Saloed
force-pushed
the
misonijnik/3-rules
branch
2 times, most recently
from
August 19, 2026 22:19
fd0a4b7 to
e9f5c2b
Compare
misonijnik
force-pushed
the
misonijnik/3-rules
branch
from
August 23, 2026 23:33
e9f5c2b to
7edc184
Compare
misonijnik
force-pushed
the
misonijnik/3-rules
branch
3 times, most recently
from
August 27, 2026 16:12
e5a818d to
baabde0
Compare
misonijnik
force-pushed
the
misonijnik/3-rules
branch
from
August 27, 2026 16:14
baabde0 to
e671fb8
Compare
misonijnik
force-pushed
the
misonijnik/3-rules
branch
from
August 27, 2026 16:20
e671fb8 to
57ec305
Compare
misonijnik
force-pushed
the
misonijnik/3-rules
branch
2 times, most recently
from
August 27, 2026 16:23
ec9f952 to
757b7fd
Compare
Saloed
force-pushed
the
misonijnik/3-rules
branch
from
September 14, 2026 13:20
757b7fd to
56a00bb
Compare
Saloed
approved these changes
Sep 14, 2026
…e star Replaces the two hard-coded Spring hacks with rule-level star operators: the controller parameter source is now `$*UNTRUSTED`, and the controller-return any-field sinks are expressed with a starred metavar. Both the source hack and the sink hack are deleted. Also restores the Z2F-gate bypass for controller-return sinks and tightens the source `$TYPE` regex, which the hack had been masking.
Keeps array and primitive parameters as plain value sources, stars the untrusted-path-source pattern-not with a fresh metavar, drops the List adapter overloads from the command-injection sink, and collapses the servlet upload source read-back -- all expressible directly now that a starred metavar means whole-object taint. Documents the pattern-not star limitation, the sink focus requirement and the Go parity story in the rules README.
resolveArrayPosition was the last implicit type-triggered array mechanism: it silently gave every array- or Object-typed source ASSIGN position an element twin. The star operator expresses the same thing from the rules, and does it better -- the any-field star is recursive, so it also catches the deep Map<String,String[]> flows the element-only twin missed. Array and vararg sink args are now starred explicitly, the implicit sink any-field emission is gone, and the Go side drops its blanket any-accessor emission in favour of explicit variadic taint in the Go model config.
Makes the servlet source whole-object and adds the channel-model getter passthroughs it reads back, and stars the xss and response-injection value sanitizers so a sanitized wrapper is recognised as clean at every depth.
Collapses the source down to a single focused form, focuses and stars the session-store sink, and flags a tainted attribute NAME as well as a tainted value -- previously only the value was considered.
Makes the java.io.File model field-sensitive with starred path sinks, and migrates every starred metavar in the ruleset, the Spring rule provider and the rules README to the $*VAR spelling the parser accepts.
The one false positive the rule-tests have been carrying since before this batch: InsecureDesignSamples#validateBeforeCrossingTrustBoundarySecure reads a value back out of the session and stores it again, which is the textbook safe shape, and it reported. The source pattern was `$*RESULT = $REQ.$FUNC(...)` with $REQ bound by the sibling pattern-inside and getSession excluded by a $FUNC regex. Probing the analyzer with three rewritten regexes shows what actually happens: ^zzzNoSuchMethodzzz$ -> 0 findings (the regex constraint is applied) ^getSession$ -> 2 findings (getSession calls do reach the sink) ^getAttribute$ -> 2 findings, including the FP The last one is the answer: `session.getAttribute(..)` matches `$REQ.$FUNC(..)` because the $REQ binding from pattern-inside is not enforced in the sibling pattern, so any receiver matches. Reading back out of the session became a source, and the getSession exclusion never saw the call it was meant to stop. Typing the receiver in the pattern itself - `(HttpServletRequest $REQ).$FUNC(...)`, which is what the sink patterns already do - keeps the three true positives and drops the false one. The rule-tests are now 0 FP / 0 FN for the first time.
`StringUtils.arrayToCommaDelimitedString(dir.listFiles())` joins
`String.valueOf(element)`
for every element, so a mark on an element *object* -- or on any field
of it, e.g.
`java.io.File#path` -- belongs on the returned String as a plain value.
The library model instead copies `arg(0)[*]` verbatim, which carries the
element's own
accessors over into a String result; `result.java.io.File#path` is
correctly rejected by
the type checker and the flow dies there. WebGoat's
ResponseEntity.status(..).body(
StringUtils.arrayToCommaDelimitedString(catPicture.getParentFile().listFiles())
.getBytes())
lost its `xss-in-spring-app` finding at ProfileUploadRetrieval.java:114
that way.
A propagator with a **starred** `from` reads through the element's
fields and assigns a
plain value, which is exactly the join's semantics. The star has to sit
on the pattern
occurrence -- the `from:`/`to:` YAML fields stay starless, like
`focus-metavariable`.
Verified: dropping the star loses the shape again; on WebGoat the
propagator adds exactly
one finding, the lost one (65 vs 64 results).
Propagators are per-rule, and only `mode: taint` lib rules -- the sink
libs -- have the
slot, so this repeats in each sink lib where the helper can appear on a
flow.
…ing() The per-method propagator worked around a broken config passthrough that carried element field structure (e.g. File#path) into a String result. Replace with a generic toString() propagator: the dataflow approximation for arrayToCommaDelimitedString now models the actual iteration + toString() call, so the propagator just needs to keep taint alive through toString().
The note said that the star gives the element taint through a routing at the use site. That is not how it works. The star gives the taint at the source, and the engine keeps it at the primitive element read.
Saloed
force-pushed
the
misonijnik/3-rules
branch
from
September 23, 2026 21:36
56a00bb to
2b1261c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.