Repository navigation
v0.3.0
0.3.0 (2026-05-15)
A precision-and-robustness release. Lambdas and functional-style Java code
get more accurate taint tracking; rules can now constrain on generic type
arguments and wildcards; alias analysis is more precise and no longer hangs
on a handful of real-world inputs; scans recover cleanly under tight memory
or time limits. The Java XSS ruleset is split into a content-type-aware
ERROR rule and a broader NOTE rule, so CI gates can be wired to ERROR
without drowning in noise.
Better taint tracking through lambdas
Taint flowing through lambdas and method references is now tracked
flow-sensitively. Only the lambda implementations whose allocation actually
reaches a call site are analyzed there — no more dispatching to every
lambda the analyzer has ever seen for a given functional interface. Traces
through functional-style code are shorter and more precise.
Generics in rule patterns
Type arguments in your YAML signatures are now actually enforced:
- Patterns like
ResponseEntity<Resource>,List<String>,
Map<String, ?>constrain the match — they used to be silently dropped. - The
?wildcard is now first-class in Java patterns. - A method-decl pattern's return type is checked, so combinations like
pattern-inside ResponseEntity<?> $M(...)with
pattern-not-inside ResponseEntity<Integer> $M(...)filter by return
type as written. - Raw uses (
ResponseEntity) and unbound wildcards (<?>) at call sites
match any pattern's type-argument slot, since they represent unknown
types. - Pass-through rules over generic returns (e.g.
List.getreturningE)
continue to match when their pattern is written against the erased type.
When classpath info isn't available to resolve the generic view of a
method, matching falls back to erased-name semantics rather than going
silent.
Alias analysis: precision and reliability
- Heap-only alias relations are no longer thrown away. When two fields or
array elements are known to alias but no local variable in the current
method holds either, the analyzer now keeps that relation and uses it
for taint propagation. - An unsound strong update on array stores has been removed. Writing
arr[i] = …no longer kills aliasing on the rest of the array. - The algorithm that invalidates aliases reachable from method-outer
locations has been rewritten. Two real-world inputs that previously hung
the analyzer or produced bursts of false positives are now stable. - Long alias-resolution chains now respond to cancel signals immediately
instead of running to completion.
Robustness under tight memory and time limits
- Cancel signals (timeout, memory pressure) now propagate into the inner
loops of the analyzer. Previously a global cancel could be ignored while
the alias or summary fixed point was still running; now it takes effect
promptly. - The source-file indexer no longer re-indexes the same source root once
per registered project location. Projects with many locations sharing
source roots use less memory and CPU at startup. - Class-name extraction no longer swallows
OutOfMemoryErroror
StackOverflowError. Under memory pressure the scan now fails with a
clear error instead of continuing with corrupted intermediate state.
Autobuilder skips hidden directories
The Gradle and Maven autobuilders now skip any directory whose name starts
with . under the project root (.git, .idea, .gradle, .opentaint,
vendored build caches, …). Previously they could descend into these and
sometimes pick up build outputs as real source projects.
Bundled rule additions
Spring DeferredResult is now a recognized pass-through, so taint flows
through setResult / setErrorResult in Spring async endpoints.
Java XSS: ERROR and NOTE tiers
The single XSS rule for Servlet and Spring is now a pair per framework:
- ERROR-tier —
xss-in-servlet-app,xss-in-spring-app. Fires only
when the response content type is statically confirmed to betext/html:
an explicitsetContentType("text/html…"),produces = "text/html"on a
Spring mapping, or a response builder withcontentType(MediaType.TEXT_HTML).
Suitable for blocking CI gates. - NOTE-tier —
response-injection-in-servlet-app,
response-injection-in-spring-app. Fires on any direct write of
untrusted input into a response writer or Spring response, regardless of
content type. Catches the broader pattern at lower confidence.
Both tiers share the same sanitizer list: OWASP Java Encoder
(Encode.forHtml), OWASP HTML Sanitizer (PolicyFactory.sanitize),
AntiSamy (scan), JSoup (clean), Spring HtmlUtils.htmlEscape, Apache
Commons StringEscapeUtils.escapeHtml{,3,4}, and OWASP ESAPI
encodeForHTML. For Spring, ResponseEntity constructions whose headers
were set to a non-HTML content type are also treated as sanitized.
ERROR rules ship with full CWE-79 documentation: vulnerable example, two
safe examples (HTML encoding and DTO-returning), references, and
provenance.
CLI
The "update available" check no longer runs during the update command
itself. The running process is on the old version, so the check would
otherwise queue a stale "update available" hint for the version that's
currently being installed.
Install / upgrade
fresh install
curl -fsSL https://opentaint.org/install.sh | bash
irm https://opentaint.org/install.ps1 | iex
brew install --cask seqra/tap/opentaint
in-place upgrade
opentaint self-update
🎁 Features
- analyzer: Enhance type-aware pattern matching and generic type handling (#99) (c19a8bc)
- analyzer: Fix taint configuration loader performance (#146) (f15ed3a)
- analyzer: Keep unbound aliases (#126) (ac3cefb)
- autobuilder: Ignore hidden dirs (#129) (5f5fa4e)
- cli: Update bundled dependency versions (#114) (c360d9f)
- core: Fact based lambda resolution (#116) (fbe95e3)
- rules: Tune XSS rules, separate ERROR and NOTE version (#113) (910476e)
🐞 Bug Fixes
- analyzer: Fix AA cancellation (#108) (a5cb123)
- analyzer: Fix analyzer performance on small memory limits (#110) (0ab7925)
- analyzer: Fix outer calls handling in alias analysis (#124) (7ff10d3)
- analyzer: Match raw and wildcard generics as any type (#118) (5236e63)
- cli: Suppress update banner after running update command (#142) (982e7c6)