From 0edf76cd9079381c864ff2376d8aab6776c40bea Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 22 May 2026 16:40:16 +0200 Subject: [PATCH 1/8] feat(analyzer): Add third-party + stdlib taint passThrough propagators Extract the passThrough (propagator) rules from misonijnik/codeql-rules that the rule-test suite depends on but the main-built analyzer jar does not yet bundle. Adds 13 per-jar propagator files under config/jar-split and extends stdlib.yaml, so a future analyzer release ships them by default and the rules CI no longer needs to overlay them. --- .../java-config/jar-split/ant-1.10.14.yaml | 13 +++ .../jar-split/commons-codec-1.16.0.yaml | 16 +++ .../jar-split/commons-io-2.15.1.yaml | 8 ++ .../java-config/jar-split/groovy-3.0.21.yaml | 9 ++ .../jar-split/httpcore5-5.2.4.yaml | 7 ++ .../jar-split/jenkins-core-2.426.3.yaml | 7 ++ .../jar-split/mvel2-2.5.2.Final.yaml | 26 +++++ .../java-config/jar-split/okhttp-4.12.0.yaml | 16 +++ .../jar-split/spring-jdbc-5.3.39.yaml | 9 ++ .../jar-split/spring-ldap-core-2.4.1.yaml | 109 ++++++++++++++++++ .../jar-split/spring-web-5.3.39.yaml | 16 +++ .../jar-split/unboundid-ldapsdk-6.0.11.yaml | 5 + .../jar-split/velocity-engine-core-2.3.yaml | 13 +++ .../config/java-config/stdlib.yaml | 87 ++++++++++++++ 14 files changed, 341 insertions(+) create mode 100644 core/opentaint-config/java-config/config/java-config/jar-split/ant-1.10.14.yaml create mode 100644 core/opentaint-config/java-config/config/java-config/jar-split/commons-codec-1.16.0.yaml create mode 100644 core/opentaint-config/java-config/config/java-config/jar-split/commons-io-2.15.1.yaml create mode 100644 core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml create mode 100644 core/opentaint-config/java-config/config/java-config/jar-split/httpcore5-5.2.4.yaml create mode 100644 core/opentaint-config/java-config/config/java-config/jar-split/jenkins-core-2.426.3.yaml create mode 100644 core/opentaint-config/java-config/config/java-config/jar-split/mvel2-2.5.2.Final.yaml create mode 100644 core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml create mode 100644 core/opentaint-config/java-config/config/java-config/jar-split/spring-jdbc-5.3.39.yaml create mode 100644 core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml create mode 100644 core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml create mode 100644 core/opentaint-config/java-config/config/java-config/jar-split/unboundid-ldapsdk-6.0.11.yaml create mode 100644 core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/ant-1.10.14.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/ant-1.10.14.yaml new file mode 100644 index 000000000..603e04614 --- /dev/null +++ b/core/opentaint-config/java-config/config/java-config/jar-split/ant-1.10.14.yaml @@ -0,0 +1,13 @@ +passThrough: +# Apache Ant: FileSet.setDir(File) / setFile(File) — the file argument +# is stored on the FileSet instance, so a subsequent +# `copy.addFileset(fs)` sink that requires a tainted $FILE detects +# the flow. +- function: org.apache.tools.ant.types.FileSet#setDir + copy: + - from: arg(0) + to: this +- function: org.apache.tools.ant.types.FileSet#setFile + copy: + - from: arg(0) + to: this diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/commons-codec-1.16.0.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/commons-codec-1.16.0.yaml new file mode 100644 index 000000000..10459d5ee --- /dev/null +++ b/core/opentaint-config/java-config/config/java-config/jar-split/commons-codec-1.16.0.yaml @@ -0,0 +1,16 @@ +passThrough: +# Apache Commons Codec — Base64 encode/decode just re-codes bytes +# without disturbing the underlying tainted data, so taint should +# flow from input to output. +- function: org.apache.commons.codec.binary.Base64#encodeBase64String + copy: + - from: arg(0) + to: result +- function: org.apache.commons.codec.binary.Base64#encodeBase64 + copy: + - from: arg(0) + to: result +- function: org.apache.commons.codec.binary.Base64#decodeBase64 + copy: + - from: arg(0) + to: result diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/commons-io-2.15.1.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/commons-io-2.15.1.yaml new file mode 100644 index 000000000..ee9f1aa58 --- /dev/null +++ b/core/opentaint-config/java-config/config/java-config/jar-split/commons-io-2.15.1.yaml @@ -0,0 +1,8 @@ +passThrough: +# Apache Commons IO: IOUtils.toString(InputStream|Reader|URL, ...) just +# reads bytes/chars from its input and produces a String — taint flows +# from the input source argument to the resulting String. +- function: org.apache.commons.io.IOUtils#toString + copy: + - from: arg(0) + to: result diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml new file mode 100644 index 000000000..07bb9afcb --- /dev/null +++ b/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml @@ -0,0 +1,9 @@ +passThrough: +# Groovy compiler: CompilationUnit.addSource(name, source) — the +# source text becomes part of the CompilationUnit instance that's +# later compiled by .compile(), so the source-text argument taints +# the unit. +- function: org.codehaus.groovy.control.CompilationUnit#addSource + copy: + - from: arg(1) + to: this diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/httpcore5-5.2.4.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/httpcore5-5.2.4.yaml new file mode 100644 index 000000000..92c8a81fd --- /dev/null +++ b/core/opentaint-config/java-config/config/java-config/jar-split/httpcore5-5.2.4.yaml @@ -0,0 +1,7 @@ +passThrough: +# Apache HttpComponents 5 — String-arg wrapper constructor that the +# SSRF sink rules use as an inline taint carrier. +- function: org.apache.hc.core5.http.io.entity.StringEntity# + copy: + - from: arg(*) + to: this diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/jenkins-core-2.426.3.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/jenkins-core-2.426.3.yaml new file mode 100644 index 000000000..565b6f2f5 --- /dev/null +++ b/core/opentaint-config/java-config/config/java-config/jar-split/jenkins-core-2.426.3.yaml @@ -0,0 +1,7 @@ +passThrough: +# hudson.FilePath wrapper constructor — taint flows from any +# String/File/URL argument into the constructed FilePath instance. +- function: hudson.FilePath# + copy: + - from: arg(*) + to: this diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/mvel2-2.5.2.Final.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/mvel2-2.5.2.Final.yaml new file mode 100644 index 000000000..5dc56a586 --- /dev/null +++ b/core/opentaint-config/java-config/config/java-config/jar-split/mvel2-2.5.2.Final.yaml @@ -0,0 +1,26 @@ +passThrough: +# MVEL compile / executeExpression chain — compileExpression(expr) +# returns a Serializable that's later passed to executeExpression / +# MVELRuntime.execute as a tainted compiled program. The compile +# methods just pass the input expression text through to the result. +- function: org.mvel2.MVEL#compileExpression + copy: + - from: arg(0) + to: result +- function: org.mvel2.MVEL#compileSetExpression + copy: + - from: arg(0) + to: result +- function: org.mvel2.MVEL#compileGetExpression + copy: + - from: arg(0) + to: result +# JSR-223 ScriptEngine compile / compiledScript +- function: org.mvel2.jsr223.MvelScriptEngine#compile + copy: + - from: arg(0) + to: result +- function: org.mvel2.jsr223.MvelScriptEngine#compiledScript + copy: + - from: arg(0) + to: result diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml new file mode 100644 index 000000000..8a22331b3 --- /dev/null +++ b/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml @@ -0,0 +1,16 @@ +passThrough: +# OkHttp Request.Builder — `new Request.Builder().url($X).build()` chain. +# `.url()` mutates the builder and returns it (taint flows arg→this and +# arg→result and this→result so the chain propagates through `.build()`). +- function: okhttp3.Request$Builder#url + copy: + - from: arg(0) + to: result + - from: arg(0) + to: this + - from: this + to: result +- function: okhttp3.Request$Builder#build + copy: + - from: this + to: result diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/spring-jdbc-5.3.39.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/spring-jdbc-5.3.39.yaml new file mode 100644 index 000000000..cfc9b8e02 --- /dev/null +++ b/core/opentaint-config/java-config/config/java-config/jar-split/spring-jdbc-5.3.39.yaml @@ -0,0 +1,9 @@ +passThrough: +# Spring JDBC: NamedParameterUtils.parseSqlStatement(sql) returns a +# ParsedSql wrapping the original SQL, which is then passed to +# (Named)JdbcTemplate query/update sinks. The parse step itself just +# preserves taint into the result. +- function: org.springframework.jdbc.core.namedparam.NamedParameterUtils#parseSqlStatement + copy: + - from: arg(0) + to: result diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml new file mode 100644 index 000000000..8b44a1e5b --- /dev/null +++ b/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml @@ -0,0 +1,109 @@ +passThrough: +# Spring LDAP query builder chain: +# LdapQueryBuilder.query().base(dn).where(attr).is(val) ... -> LdapQuery +# +# The chain mixes the public LdapQueryBuilder/ConditionCriteria/ +# ContainerCriteria interfaces with the package-private +# DefaultConditionCriteria / DefaultContainerCriteria impls. The +# analyzer's chain-split sees the impl-class call sites, so both +# interface and impl entries are needed. +# +# The direct `arg(0) → result` form is what actually propagates taint +# through the chain; the two-step `arg(0)→this` + `this→result` form +# alone wasn't enough (the chain has too many implicit intermediates +# for two-step propagation to reach end-to-end without the direct +# shortcut). +- function: org.springframework.ldap.query.LdapQueryBuilder#base + copy: + - from: arg(0) + to: result + - from: arg(0) + to: this + - from: this + to: result +- function: org.springframework.ldap.query.LdapQueryBuilder#where + copy: + - from: arg(0) + to: result + - from: arg(0) + to: this + - from: this + to: result +- function: org.springframework.ldap.query.LdapQueryBuilder#filter + copy: + - from: arg(0) + to: result + - from: arg(0) + to: this + - from: this + to: result +- function: org.springframework.ldap.query.ConditionCriteria#is + copy: + - from: arg(0) + to: result + - from: arg(0) + to: this + - from: this + to: result +- function: org.springframework.ldap.query.ConditionCriteria#like + copy: + - from: arg(0) + to: result + - from: arg(0) + to: this + - from: this + to: result +- function: org.springframework.ldap.query.ConditionCriteria#whitespaceWildcardsLike + copy: + - from: arg(0) + to: result + - from: arg(0) + to: this + - from: this + to: result +- function: org.springframework.ldap.query.ContainerCriteria#and + copy: + - from: this + to: result +- function: org.springframework.ldap.query.ContainerCriteria#or + copy: + - from: this + to: result +- function: org.springframework.ldap.query.DefaultConditionCriteria#is + copy: + - from: arg(0) + to: this + - from: arg(0) + to: result + - from: this + to: result +- function: org.springframework.ldap.query.DefaultConditionCriteria#like + copy: + - from: arg(0) + to: this + - from: arg(0) + to: result + - from: this + to: result +- function: org.springframework.ldap.query.DefaultConditionCriteria#whitespaceWildcardsLike + copy: + - from: arg(0) + to: this + - from: arg(0) + to: result + - from: this + to: result +- function: org.springframework.ldap.query.DefaultContainerCriteria#and + copy: + - from: this + to: result +- function: org.springframework.ldap.query.DefaultContainerCriteria#or + copy: + - from: this + to: result +- function: org.springframework.ldap.query.DefaultContainerCriteria#append + copy: + - from: arg(0) + to: this + - from: this + to: result diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml new file mode 100644 index 000000000..0d3ac94bd --- /dev/null +++ b/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml @@ -0,0 +1,16 @@ +passThrough: +# Spring RequestEntity static factories + builder .build() — used by +# the SSRF rule's chained-builder pattern: +# RequestEntity.get(URI.create($X)).build() +- function: org.springframework.http.RequestEntity#get + copy: + - from: arg(0) + to: result +- function: org.springframework.http.RequestEntity$BodyBuilder#build + copy: + - from: this + to: result +- function: org.springframework.http.RequestEntity$HeadersBuilder#build + copy: + - from: this + to: result diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/unboundid-ldapsdk-6.0.11.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/unboundid-ldapsdk-6.0.11.yaml new file mode 100644 index 000000000..466f26e62 --- /dev/null +++ b/core/opentaint-config/java-config/config/java-config/jar-split/unboundid-ldapsdk-6.0.11.yaml @@ -0,0 +1,5 @@ +passThrough: +- function: com.unboundid.ldap.sdk.SearchRequest# + copy: + - from: arg(*) + to: this diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml new file mode 100644 index 000000000..309cc5d3e --- /dev/null +++ b/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml @@ -0,0 +1,13 @@ +passThrough: +# Apache Velocity: VelocityContext.put($k, $v) and the AbstractContext +# super-class — taint flows from the value argument into the context +# instance so a tainted value carried into the context reaches a +# subsequent VelocityEngine.evaluate / Template.merge sink. +- function: org.apache.velocity.VelocityContext#put + copy: + - from: arg(1) + to: this +- function: org.apache.velocity.context.AbstractContext#put + copy: + - from: arg(1) + to: this diff --git a/core/opentaint-config/java-config/config/java-config/stdlib.yaml b/core/opentaint-config/java-config/config/java-config/stdlib.yaml index 6d809f14f..1d9e8bfbd 100644 --- a/core/opentaint-config/java-config/config/java-config/stdlib.yaml +++ b/core/opentaint-config/java-config/config/java-config/stdlib.yaml @@ -21358,3 +21358,90 @@ passThrough: to: - this - .java.io.InputStream##java.lang.Object + +# ── Collection / Iterator / Iterable / Enumeration ───────────────────── +- function: java.util.Collection#iterator + copy: + - from: this + to: result +- function: java.lang.Iterable#iterator + copy: + - from: this + to: result +- function: java.util.Iterator#next + copy: + - from: this + to: result +- function: java.util.Enumeration#nextElement + copy: + - from: this + to: result + +# ── java.lang.String#getBytes (String → byte[]) ──────────────────────── +- function: java.lang.String#getBytes + copy: + - from: this + to: result + +# ── java.util.Base64$Encoder ────────────────────────────────────────── +- function: java.util.Base64$Encoder#encodeToString + copy: + - from: arg(0) + to: result +- function: java.util.Base64$Encoder#encode + copy: + - from: arg(0) + to: result + +# ── java.net.URL (String) constructor (direct arg→this; the existing +# URL#(String) entry uses arg(*) which doesn't apply consistently +# enough for tests like UnsafeStaplerServeFileServlet) ──────────────── +- function: java.net.URL# + signature: (java.lang.String) void + copy: + - from: arg(0) + to: this + +# ── java.net.URI ────────────────────────────────────────────────────── +- function: java.net.URI#create + copy: + - from: arg(0) + to: result + +# ── javax.management JMX (stdlib management API) ─────────────────────── +- function: javax.management.remote.JMXServiceURL# + copy: + - from: arg(*) + to: this +- function: javax.management.remote.JMXConnectorFactory#newJMXConnector + copy: + - from: arg(0) + to: result + +# ── javax.xml.transform.stream.StreamSource ──────────────────────────── +- function: javax.xml.transform.stream.StreamSource# + copy: + - from: arg(*) + to: this + +# ── java.net.http.HttpRequest$Builder (Java 11+ HttpClient) ─────────── +- function: java.net.http.HttpRequest#newBuilder + copy: + - from: arg(0) + to: result +- function: java.net.http.HttpRequest$Builder#uri + copy: + - from: arg(0) + to: result + - from: arg(0) + to: this + - from: this + to: result +- function: java.net.http.HttpRequest$Builder#build + copy: + - from: this + to: result +- function: java.net.http.HttpRequest$Builder#GET + copy: + - from: this + to: result From 47442d0d8f9b95dd156a136893306f71fc2bc1d7 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sun, 24 May 2026 10:08:56 +0200 Subject: [PATCH 2/8] refactor(analyzer): Complete passThrough builder chains and package coverage Refine the propagators added in 309492bd0 using the engine's actual propagation semantics (no implicit this->result for unmodeled library calls; whole-object taint subsumes field reads but virtual-field taint does not satisfy a whole-object sink). Fix broken fluent chains by modeling every intermediate link, not just the endpoints: - okhttp Request.Builder: cover all builder methods, not only url/build. - spring-web RequestEntity: cover all static factories and the HeadersBuilder/BodyBuilder chain, not only get/build. - java.net.http HttpRequest.Builder: cover header/POST/PUT/method/etc., not only uri/GET/build. Broaden per-package coverage: - commons-io IOUtils: toByteArray/toCharArray/readLines. - commons-codec Base64: URL-safe and chunked encode variants. - java.util.Base64.Decoder: decode/wrap (decode direction). - spring-jdbc: substituteNamedParameters/parseSqlStatementIntoString. - spring-ldap: LdapQueryBuilder config carriers + gte/lte/not (iface+impl). - velocity: Context interface put. - groovy CompilationUnit.addSource: arg(*) to cover File/URL/SourceUnit overloads where the source is the first argument. Wrapper constructors keep whole-object arg(*)->this on purpose: their sinks consume the whole object, so a virtual-field-only taint would be a false negative. --- .../jar-split/commons-codec-1.16.0.yaml | 12 +++ .../jar-split/commons-io-2.15.1.yaml | 19 ++++- .../java-config/jar-split/groovy-3.0.21.yaml | 12 +-- .../java-config/jar-split/okhttp-4.12.0.yaml | 78 +++++++++++++++++- .../jar-split/spring-jdbc-5.3.39.yaml | 15 +++- .../jar-split/spring-ldap-core-2.4.1.yaml | 62 ++++++++++++++ .../jar-split/spring-web-5.3.39.yaml | 82 ++++++++++++++++++- .../jar-split/velocity-engine-core-2.3.yaml | 14 +++- .../config/java-config/stdlib.yaml | 74 ++++++++++++++++- 9 files changed, 344 insertions(+), 24 deletions(-) diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/commons-codec-1.16.0.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/commons-codec-1.16.0.yaml index 10459d5ee..b7fde8002 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/commons-codec-1.16.0.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/commons-codec-1.16.0.yaml @@ -10,6 +10,18 @@ passThrough: copy: - from: arg(0) to: result +- function: org.apache.commons.codec.binary.Base64#encodeBase64URLSafeString + copy: + - from: arg(0) + to: result +- function: org.apache.commons.codec.binary.Base64#encodeBase64URLSafe + copy: + - from: arg(0) + to: result +- function: org.apache.commons.codec.binary.Base64#encodeBase64Chunked + copy: + - from: arg(0) + to: result - function: org.apache.commons.codec.binary.Base64#decodeBase64 copy: - from: arg(0) diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/commons-io-2.15.1.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/commons-io-2.15.1.yaml index ee9f1aa58..f5a37647d 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/commons-io-2.15.1.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/commons-io-2.15.1.yaml @@ -1,8 +1,21 @@ passThrough: -# Apache Commons IO: IOUtils.toString(InputStream|Reader|URL, ...) just -# reads bytes/chars from its input and produces a String — taint flows -# from the input source argument to the resulting String. +# Apache Commons IO: IOUtils read helpers consume an input source +# (InputStream | Reader | URL | byte[] | char[]) given as the first +# argument and materialize its content — taint flows from that input +# source to the returned String / byte[] / char[] / List. - function: org.apache.commons.io.IOUtils#toString copy: - from: arg(0) to: result +- function: org.apache.commons.io.IOUtils#toByteArray + copy: + - from: arg(0) + to: result +- function: org.apache.commons.io.IOUtils#toCharArray + copy: + - from: arg(0) + to: result +- function: org.apache.commons.io.IOUtils#readLines + copy: + - from: arg(0) + to: result diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml index 07bb9afcb..5bbb797a5 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml @@ -1,9 +1,11 @@ passThrough: -# Groovy compiler: CompilationUnit.addSource(name, source) — the -# source text becomes part of the CompilationUnit instance that's -# later compiled by .compile(), so the source-text argument taints -# the unit. +# Groovy compiler: CompilationUnit.addSource(...) — the source becomes +# part of the CompilationUnit instance that is later run by .compile(), +# so the source argument taints the unit. The source is the 2nd arg of +# addSource(name, source|InputStream) but the 1st arg of the +# addSource(File) / addSource(URL) / addSource(SourceUnit) overloads, so +# copy from any argument into the unit. - function: org.codehaus.groovy.control.CompilationUnit#addSource copy: - - from: arg(1) + - from: arg(*) to: this diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml index 8a22331b3..c142e5ee0 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml @@ -1,15 +1,87 @@ passThrough: -# OkHttp Request.Builder — `new Request.Builder().url($X).build()` chain. -# `.url()` mutates the builder and returns it (taint flows arg→this and -# arg→result and this→result so the chain propagates through `.build()`). +# OkHttp Request.Builder fluent chain, e.g. +# new Request.Builder().url($X).addHeader(..).post($BODY).build() +# Library calls have no implicit this->result propagation, so every +# builder method that may appear mid-chain must carry the builder taint +# to its return value, or the chain breaks at the first unmodeled link. +# `.url()` additionally seeds the builder from its (tainted) argument and +# `.build()` carries the accumulated builder taint into the Request. - function: okhttp3.Request$Builder#url copy: - from: arg(0) + to: this + - from: arg(0) + to: result + - from: this + to: result +- function: okhttp3.Request$Builder#header + copy: + - from: arg(*) + to: this + - from: this + to: result +- function: okhttp3.Request$Builder#addHeader + copy: + - from: arg(*) + to: this + - from: this + to: result +- function: okhttp3.Request$Builder#headers + copy: + - from: arg(0) + to: this + - from: this + to: result +- function: okhttp3.Request$Builder#post + copy: + - from: arg(0) + to: this + - from: this + to: result +- function: okhttp3.Request$Builder#put + copy: + - from: arg(0) + to: this + - from: this to: result +- function: okhttp3.Request$Builder#patch + copy: + - from: arg(0) + to: this + - from: this + to: result +- function: okhttp3.Request$Builder#delete + copy: - from: arg(0) to: this - from: this to: result +- function: okhttp3.Request$Builder#method + copy: + - from: arg(*) + to: this + - from: this + to: result +- function: okhttp3.Request$Builder#get + copy: + - from: this + to: result +- function: okhttp3.Request$Builder#head + copy: + - from: this + to: result +- function: okhttp3.Request$Builder#removeHeader + copy: + - from: this + to: result +- function: okhttp3.Request$Builder#cacheControl + copy: + - from: this + to: result +- function: okhttp3.Request$Builder#tag + copy: + - from: this + to: result - function: okhttp3.Request$Builder#build copy: - from: this diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/spring-jdbc-5.3.39.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/spring-jdbc-5.3.39.yaml index cfc9b8e02..157a69417 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/spring-jdbc-5.3.39.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/spring-jdbc-5.3.39.yaml @@ -1,9 +1,18 @@ passThrough: # Spring JDBC: NamedParameterUtils.parseSqlStatement(sql) returns a -# ParsedSql wrapping the original SQL, which is then passed to -# (Named)JdbcTemplate query/update sinks. The parse step itself just -# preserves taint into the result. +# ParsedSql wrapping the original SQL; substituteNamedParameters(parsedSql|sql, +# ..) then expands it back into the SQL String passed to the +# (Named)JdbcTemplate query/update sinks. Each step preserves taint from +# its SQL/ParsedSql input (arg(0)) into the result. - function: org.springframework.jdbc.core.namedparam.NamedParameterUtils#parseSqlStatement copy: - from: arg(0) to: result +- function: org.springframework.jdbc.core.namedparam.NamedParameterUtils#substituteNamedParameters + copy: + - from: arg(0) + to: result +- function: org.springframework.jdbc.core.namedparam.NamedParameterUtils#parseSqlStatementIntoString + copy: + - from: arg(0) + to: result diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml index 8b44a1e5b..26ec5b8ce 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml @@ -61,6 +61,48 @@ passThrough: to: this - from: this to: result +- function: org.springframework.ldap.query.ConditionCriteria#gte + copy: + - from: arg(0) + to: result + - from: arg(0) + to: this + - from: this + to: result +- function: org.springframework.ldap.query.ConditionCriteria#lte + copy: + - from: arg(0) + to: result + - from: arg(0) + to: this + - from: this + to: result +# `.not()` is a value-less modifier that returns the same criteria — pure +# chain carrier. +- function: org.springframework.ldap.query.ConditionCriteria#not + copy: + - from: this + to: result +# LdapQueryBuilder configuration methods (searchScope/countLimit/timeLimit/ +# attributes) return the builder unchanged; they are pure chain carriers +# that may appear between base() and where(), so the builder taint must +# survive across them. +- function: org.springframework.ldap.query.LdapQueryBuilder#searchScope + copy: + - from: this + to: result +- function: org.springframework.ldap.query.LdapQueryBuilder#countLimit + copy: + - from: this + to: result +- function: org.springframework.ldap.query.LdapQueryBuilder#timeLimit + copy: + - from: this + to: result +- function: org.springframework.ldap.query.LdapQueryBuilder#attributes + copy: + - from: this + to: result - function: org.springframework.ldap.query.ContainerCriteria#and copy: - from: this @@ -93,6 +135,26 @@ passThrough: to: result - from: this to: result +- function: org.springframework.ldap.query.DefaultConditionCriteria#gte + copy: + - from: arg(0) + to: this + - from: arg(0) + to: result + - from: this + to: result +- function: org.springframework.ldap.query.DefaultConditionCriteria#lte + copy: + - from: arg(0) + to: this + - from: arg(0) + to: result + - from: this + to: result +- function: org.springframework.ldap.query.DefaultConditionCriteria#not + copy: + - from: this + to: result - function: org.springframework.ldap.query.DefaultContainerCriteria#and copy: - from: this diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml index 0d3ac94bd..a1f382a3c 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml @@ -1,12 +1,71 @@ passThrough: -# Spring RequestEntity static factories + builder .build() — used by -# the SSRF rule's chained-builder pattern: -# RequestEntity.get(URI.create($X)).build() +# Spring RequestEntity fluent chain, e.g. the SSRF rule's pattern +# RequestEntity.get(URI.create($X)).accept(..).header(..).build() +# The static factories seed the builder from the (tainted) URI argument; +# every intermediate HeadersBuilder/BodyBuilder method must carry the +# builder taint to its return value (no implicit this->result exists), +# and .build() carries it into the constructed RequestEntity which the +# RestTemplate sink consumes whole. +# +# ── Static factories (URI is the first arg, except method(HttpMethod, URI)) ── - function: org.springframework.http.RequestEntity#get copy: - from: arg(0) to: result -- function: org.springframework.http.RequestEntity$BodyBuilder#build +- function: org.springframework.http.RequestEntity#head + copy: + - from: arg(0) + to: result +- function: org.springframework.http.RequestEntity#post + copy: + - from: arg(0) + to: result +- function: org.springframework.http.RequestEntity#put + copy: + - from: arg(0) + to: result +- function: org.springframework.http.RequestEntity#patch + copy: + - from: arg(0) + to: result +- function: org.springframework.http.RequestEntity#delete + copy: + - from: arg(0) + to: result +- function: org.springframework.http.RequestEntity#options + copy: + - from: arg(0) + to: result +- function: org.springframework.http.RequestEntity#method + copy: + - from: arg(*) + to: result +# ── HeadersBuilder chain (get/head/delete/options return this) ── +- function: org.springframework.http.RequestEntity$HeadersBuilder#header + copy: + - from: arg(*) + to: result + - from: this + to: result +- function: org.springframework.http.RequestEntity$HeadersBuilder#headers + copy: + - from: arg(*) + to: result + - from: this + to: result +- function: org.springframework.http.RequestEntity$HeadersBuilder#accept + copy: + - from: this + to: result +- function: org.springframework.http.RequestEntity$HeadersBuilder#acceptCharset + copy: + - from: this + to: result +- function: org.springframework.http.RequestEntity$HeadersBuilder#ifModifiedSince + copy: + - from: this + to: result +- function: org.springframework.http.RequestEntity$HeadersBuilder#ifNoneMatch copy: - from: this to: result @@ -14,3 +73,18 @@ passThrough: copy: - from: this to: result +# ── BodyBuilder chain (post/put/patch/method return this) ── +- function: org.springframework.http.RequestEntity$BodyBuilder#contentLength + copy: + - from: this + to: result +- function: org.springframework.http.RequestEntity$BodyBuilder#contentType + copy: + - from: this + to: result +- function: org.springframework.http.RequestEntity$BodyBuilder#body + copy: + - from: arg(0) + to: result + - from: this + to: result diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml index 309cc5d3e..a92cf0e63 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml @@ -1,8 +1,14 @@ passThrough: -# Apache Velocity: VelocityContext.put($k, $v) and the AbstractContext -# super-class — taint flows from the value argument into the context -# instance so a tainted value carried into the context reaches a -# subsequent VelocityEngine.evaluate / Template.merge sink. +# Apache Velocity: Context.put($k, $v) — the value argument is stored on +# the context instance, so a tainted value carried into the context +# reaches a subsequent VelocityEngine.evaluate / Template.merge sink that +# consumes the whole context. Entries cover the Context interface, the +# AbstractContext super-class and the concrete VelocityContext, since the +# call site may be typed to any of them. +- function: org.apache.velocity.context.Context#put + copy: + - from: arg(1) + to: this - function: org.apache.velocity.VelocityContext#put copy: - from: arg(1) diff --git a/core/opentaint-config/java-config/config/java-config/stdlib.yaml b/core/opentaint-config/java-config/config/java-config/stdlib.yaml index 1d9e8bfbd..bbb4a244a 100644 --- a/core/opentaint-config/java-config/config/java-config/stdlib.yaml +++ b/core/opentaint-config/java-config/config/java-config/stdlib.yaml @@ -21383,7 +21383,7 @@ passThrough: - from: this to: result -# ── java.util.Base64$Encoder ────────────────────────────────────────── +# ── java.util.Base64$Encoder / $Decoder ─────────────────────────────── - function: java.util.Base64$Encoder#encodeToString copy: - from: arg(0) @@ -21392,6 +21392,14 @@ passThrough: copy: - from: arg(0) to: result +- function: java.util.Base64$Decoder#decode + copy: + - from: arg(0) + to: result +- function: java.util.Base64$Decoder#wrap + copy: + - from: arg(0) + to: result # ── java.net.URL (String) constructor (direct arg→this; the existing # URL#(String) entry uses arg(*) which doesn't apply consistently @@ -21425,6 +21433,12 @@ passThrough: to: this # ── java.net.http.HttpRequest$Builder (Java 11+ HttpClient) ─────────── +# Fluent chain, e.g. +# HttpRequest.newBuilder(URI.create($X)).header(..).GET().build() +# newBuilder seeds the builder from the (tainted) URI; every intermediate +# builder method must carry the builder taint to its return value (no +# implicit this->result exists) and .build() carries it into the +# HttpRequest that the HttpClient send/sendAsync sink consumes whole. - function: java.net.http.HttpRequest#newBuilder copy: - from: arg(0) @@ -21437,7 +21451,43 @@ passThrough: to: this - from: this to: result -- function: java.net.http.HttpRequest$Builder#build +- function: java.net.http.HttpRequest$Builder#header + copy: + - from: arg(*) + to: this + - from: this + to: result +- function: java.net.http.HttpRequest$Builder#headers + copy: + - from: arg(*) + to: this + - from: this + to: result +- function: java.net.http.HttpRequest$Builder#setHeader + copy: + - from: arg(*) + to: this + - from: this + to: result +- function: java.net.http.HttpRequest$Builder#POST + copy: + - from: arg(0) + to: this + - from: this + to: result +- function: java.net.http.HttpRequest$Builder#PUT + copy: + - from: arg(0) + to: this + - from: this + to: result +- function: java.net.http.HttpRequest$Builder#method + copy: + - from: arg(*) + to: this + - from: this + to: result +- function: java.net.http.HttpRequest$Builder#DELETE copy: - from: this to: result @@ -21445,3 +21495,23 @@ passThrough: copy: - from: this to: result +- function: java.net.http.HttpRequest$Builder#timeout + copy: + - from: this + to: result +- function: java.net.http.HttpRequest$Builder#version + copy: + - from: this + to: result +- function: java.net.http.HttpRequest$Builder#expectContinue + copy: + - from: this + to: result +- function: java.net.http.HttpRequest$Builder#copy + copy: + - from: this + to: result +- function: java.net.http.HttpRequest$Builder#build + copy: + - from: this + to: result From d35886d7acb7d28a59f8e69098f34224f5eeb779 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Mon, 25 May 2026 16:35:37 +0200 Subject: [PATCH 3/8] refactor(analyzer): Route wrapper/builder taint through typed virtual fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the new propagators precise and type-correct. A bare `arg -> this` (or `arg -> result`) makes the whole object abstract-tainted, so every later field read of it matches via abstract refinement — over-tainting — and copies a value of one type onto an object of another. Instead, store the differently-typed argument into a `` virtual field of the target: from: arg(i) to: - this # or result - .java.lang.Object##java.lang.Object This is precise (reading unrelated real fields no longer matches, since the node is no longer abstract) and type-safe (a field accessor owned by java.lang.Object is always type-compatible, so the slot survives every chain step and the Builder -> Product type change of build()/body() under a plain this->result carry). A sink that consumes the whole object still matches the slot by prefix. Applied to: StringEntity, hudson.FilePath, unboundid SearchRequest, JMXServiceURL/JMXConnectorFactory, StreamSource, java.net.URL(String), VelocityContext.put, CompilationUnit.addSource, ant FileSet set*, and the okhttp Request.Builder / java.net.http HttpRequest.Builder / spring-web RequestEntity / spring-ldap query-builder chains. Builder data methods store into both result (chained `a().b()`) and this (non-chained `x.a(); x.b()`) and carry this->result; every chain link keeps this->result so the chain survives. Pure transforms that *produce* the tainted value (toString/decode/getBytes/URI.create/MVEL.compile/ substituteNamedParameters/iterator.next) stay bare, since the result is itself the tainted value with no surrounding state to over-taint. --- .../java-config/jar-split/ant-1.10.14.yaml | 14 +- .../java-config/jar-split/groovy-3.0.21.yaml | 9 +- .../jar-split/httpcore5-5.2.4.yaml | 9 +- .../jar-split/jenkins-core-2.426.3.yaml | 7 +- .../java-config/jar-split/okhttp-4.12.0.yaml | 92 ++++++++++--- .../jar-split/spring-ldap-core-2.4.1.yaml | 126 +++++++++++++----- .../jar-split/spring-web-5.3.39.yaml | 71 +++++++--- .../jar-split/unboundid-ldapsdk-6.0.11.yaml | 8 +- .../jar-split/velocity-engine-core-2.3.yaml | 22 ++- .../config/java-config/stdlib.yaml | 108 ++++++++++++--- 10 files changed, 365 insertions(+), 101 deletions(-) diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/ant-1.10.14.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/ant-1.10.14.yaml index 603e04614..1ec6fb375 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/ant-1.10.14.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/ant-1.10.14.yaml @@ -1,13 +1,19 @@ passThrough: # Apache Ant: FileSet.setDir(File) / setFile(File) — the file argument # is stored on the FileSet instance, so a subsequent -# `copy.addFileset(fs)` sink that requires a tainted $FILE detects -# the flow. +# `copy.addFileset(fs)` sink that requires a tainted $FILE detects the +# flow. The File argument has a different type than FileSet, so it is +# stored in a virtual field instead of tainting the whole instance; the +# sink that consumes the whole FileSet still matches it by prefix. - function: org.apache.tools.ant.types.FileSet#setDir copy: - from: arg(0) - to: this + to: + - this + - .java.lang.Object##java.lang.Object - function: org.apache.tools.ant.types.FileSet#setFile copy: - from: arg(0) - to: this + to: + - this + - .java.lang.Object##java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml index 5bbb797a5..c17a91074 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml @@ -4,8 +4,13 @@ passThrough: # so the source argument taints the unit. The source is the 2nd arg of # addSource(name, source|InputStream) but the 1st arg of the # addSource(File) / addSource(URL) / addSource(SourceUnit) overloads, so -# copy from any argument into the unit. +# copy from any argument. The argument type differs from CompilationUnit, +# so it is stored in a virtual field rather than tainting the whole +# instance; a sink that consumes the whole unit still matches it by +# prefix. - function: org.codehaus.groovy.control.CompilationUnit#addSource copy: - from: arg(*) - to: this + to: + - this + - .java.lang.Object##java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/httpcore5-5.2.4.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/httpcore5-5.2.4.yaml index 92c8a81fd..fced88b16 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/httpcore5-5.2.4.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/httpcore5-5.2.4.yaml @@ -1,7 +1,12 @@ passThrough: # Apache HttpComponents 5 — String-arg wrapper constructor that the -# SSRF sink rules use as an inline taint carrier. +# SSRF sink rules use as an inline taint carrier. The argument has a +# different type than the StringEntity, so it is stored in a virtual +# field rather than tainting the whole instance; a sink that consumes +# the whole entity still matches it by prefix. - function: org.apache.hc.core5.http.io.entity.StringEntity# copy: - from: arg(*) - to: this + to: + - this + - .java.lang.Object##java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/jenkins-core-2.426.3.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/jenkins-core-2.426.3.yaml index 565b6f2f5..b2fb57a12 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/jenkins-core-2.426.3.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/jenkins-core-2.426.3.yaml @@ -1,7 +1,12 @@ passThrough: # hudson.FilePath wrapper constructor — taint flows from any # String/File/URL argument into the constructed FilePath instance. +# The argument type differs from FilePath, so it is stored in a virtual +# field instead of tainting the whole object; a path-traversal sink that +# consumes the whole FilePath still matches it by prefix. - function: hudson.FilePath# copy: - from: arg(*) - to: this + to: + - this + - .java.lang.Object##java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml index c142e5ee0..ddb0841e8 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml @@ -1,65 +1,127 @@ passThrough: # OkHttp Request.Builder fluent chain, e.g. # new Request.Builder().url($X).addHeader(..).post($BODY).build() -# Library calls have no implicit this->result propagation, so every -# builder method that may appear mid-chain must carry the builder taint -# to its return value, or the chain breaks at the first unmodeled link. -# `.url()` additionally seeds the builder from its (tainted) argument and -# `.build()` carries the accumulated builder taint into the Request. +# +# Data-bearing methods store their (differently-typed) argument into a +# virtual field instead of tainting the whole builder — this keeps +# precision (unrelated builder/request state stays untainted) while a +# sink that consumes the whole Request still matches the slot by prefix. +# The slot is owned by java.lang.Object so it survives the +# Builder -> Request type change of .build() under a plain this->result +# carry. +# +# Each data method stores into both `result` (for chained use, +# `.url($X).build()`) and `this` (for non-chained use, `b.url($X); b.build()`), +# and carries this->result to forward taint accumulated by earlier links. +# Pure chain links carry this->result only. Library calls have no implicit +# this->result, so every link must forward the builder taint or the chain +# breaks at the first unmodeled method. - function: okhttp3.Request$Builder#url copy: - from: arg(0) - to: this + to: + - result + - .java.lang.Object##java.lang.Object - from: arg(0) - to: result + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#header copy: - from: arg(*) - to: this + to: + - result + - .java.lang.Object##java.lang.Object + - from: arg(*) + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#addHeader copy: - from: arg(*) - to: this + to: + - result + - .java.lang.Object##java.lang.Object + - from: arg(*) + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#headers copy: - from: arg(0) - to: this + to: + - result + - .java.lang.Object##java.lang.Object + - from: arg(0) + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#post copy: - from: arg(0) - to: this + to: + - result + - .java.lang.Object##java.lang.Object + - from: arg(0) + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#put copy: - from: arg(0) - to: this + to: + - result + - .java.lang.Object##java.lang.Object + - from: arg(0) + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#patch copy: - from: arg(0) - to: this + to: + - result + - .java.lang.Object##java.lang.Object + - from: arg(0) + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#delete copy: - from: arg(0) - to: this + to: + - result + - .java.lang.Object##java.lang.Object + - from: arg(0) + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#method copy: - from: arg(*) - to: this + to: + - result + - .java.lang.Object##java.lang.Object + - from: arg(*) + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#get diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml index 26ec5b8ce..4d05cd01c 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml @@ -8,73 +8,109 @@ passThrough: # analyzer's chain-split sees the impl-class call sites, so both # interface and impl entries are needed. # -# The direct `arg(0) → result` form is what actually propagates taint -# through the chain; the two-step `arg(0)→this` + `this→result` form -# alone wasn't enough (the chain has too many implicit intermediates -# for two-step propagation to reach end-to-end without the direct -# shortcut). +# Data-bearing methods store their (differently-typed) attribute/value +# argument into a virtual field instead of tainting the whole builder / +# criteria object — precise, while an LdapTemplate sink consuming the +# whole LdapQuery matches the slot by prefix. The slot is stored into +# both `result` (chained use, the dominant style here) and `this` +# (non-chained use), and each link carries this->result. The +# slot is owned by java.lang.Object so it survives the +# LdapQueryBuilder -> ConditionCriteria -> ContainerCriteria -> LdapQuery +# type changes along the chain under plain this->result carries. - function: org.springframework.ldap.query.LdapQueryBuilder#base copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object - from: arg(0) - to: this + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: org.springframework.ldap.query.LdapQueryBuilder#where copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object - from: arg(0) - to: this + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: org.springframework.ldap.query.LdapQueryBuilder#filter copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object - from: arg(0) - to: this + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: org.springframework.ldap.query.ConditionCriteria#is copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object - from: arg(0) - to: this + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: org.springframework.ldap.query.ConditionCriteria#like copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object - from: arg(0) - to: this + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: org.springframework.ldap.query.ConditionCriteria#whitespaceWildcardsLike copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object - from: arg(0) - to: this + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: org.springframework.ldap.query.ConditionCriteria#gte copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object - from: arg(0) - to: this + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: org.springframework.ldap.query.ConditionCriteria#lte copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object - from: arg(0) - to: this + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result # `.not()` is a value-less modifier that returns the same criteria — pure @@ -114,41 +150,61 @@ passThrough: - function: org.springframework.ldap.query.DefaultConditionCriteria#is copy: - from: arg(0) - to: this + to: + - result + - .java.lang.Object##java.lang.Object - from: arg(0) - to: result + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: org.springframework.ldap.query.DefaultConditionCriteria#like copy: - from: arg(0) - to: this + to: + - result + - .java.lang.Object##java.lang.Object - from: arg(0) - to: result + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: org.springframework.ldap.query.DefaultConditionCriteria#whitespaceWildcardsLike copy: - from: arg(0) - to: this + to: + - result + - .java.lang.Object##java.lang.Object - from: arg(0) - to: result + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: org.springframework.ldap.query.DefaultConditionCriteria#gte copy: - from: arg(0) - to: this + to: + - result + - .java.lang.Object##java.lang.Object - from: arg(0) - to: result + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: org.springframework.ldap.query.DefaultConditionCriteria#lte copy: - from: arg(0) - to: this + to: + - result + - .java.lang.Object##java.lang.Object - from: arg(0) - to: result + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: org.springframework.ldap.query.DefaultConditionCriteria#not @@ -166,6 +222,12 @@ passThrough: - function: org.springframework.ldap.query.DefaultContainerCriteria#append copy: - from: arg(0) - to: this + to: + - result + - .java.lang.Object##java.lang.Object + - from: arg(0) + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml index a1f382a3c..14eb52e54 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml @@ -1,56 +1,89 @@ passThrough: # Spring RequestEntity fluent chain, e.g. the SSRF rule's pattern # RequestEntity.get(URI.create($X)).accept(..).header(..).build() -# The static factories seed the builder from the (tainted) URI argument; -# every intermediate HeadersBuilder/BodyBuilder method must carry the -# builder taint to its return value (no implicit this->result exists), -# and .build() carries it into the constructed RequestEntity which the -# RestTemplate sink consumes whole. +# +# The static factories store their (differently-typed) URI argument into +# a virtual field of the created builder instead of tainting it whole; +# data-bearing builder methods do the same. Every builder method also +# carries this->result so the chain survives (no implicit this->result +# exists), and .build() carries the slot into the RequestEntity — the +# slot is owned by java.lang.Object so it survives the +# Builder -> RequestEntity type change under a plain this->result carry. +# The RestTemplate sink that consumes the whole RequestEntity matches the +# slot by prefix. # # ── Static factories (URI is the first arg, except method(HttpMethod, URI)) ── - function: org.springframework.http.RequestEntity#get copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object - function: org.springframework.http.RequestEntity#head copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object - function: org.springframework.http.RequestEntity#post copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object - function: org.springframework.http.RequestEntity#put copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object - function: org.springframework.http.RequestEntity#patch copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object - function: org.springframework.http.RequestEntity#delete copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object - function: org.springframework.http.RequestEntity#options copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object - function: org.springframework.http.RequestEntity#method copy: - from: arg(*) - to: result + to: + - result + - .java.lang.Object##java.lang.Object # ── HeadersBuilder chain (get/head/delete/options return this) ── - function: org.springframework.http.RequestEntity$HeadersBuilder#header copy: - from: arg(*) - to: result + to: + - result + - .java.lang.Object##java.lang.Object + - from: arg(*) + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: org.springframework.http.RequestEntity$HeadersBuilder#headers copy: - from: arg(*) - to: result + to: + - result + - .java.lang.Object##java.lang.Object + - from: arg(*) + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: org.springframework.http.RequestEntity$HeadersBuilder#accept @@ -85,6 +118,12 @@ passThrough: - function: org.springframework.http.RequestEntity$BodyBuilder#body copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object + - from: arg(0) + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/unboundid-ldapsdk-6.0.11.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/unboundid-ldapsdk-6.0.11.yaml index 466f26e62..dd663a056 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/unboundid-ldapsdk-6.0.11.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/unboundid-ldapsdk-6.0.11.yaml @@ -1,5 +1,11 @@ passThrough: +# com.unboundid.ldap.sdk.SearchRequest constructor — the base DN / filter +# arguments have a different type than SearchRequest, so they are stored +# in a virtual field rather than tainting the whole instance; an LDAP +# sink that consumes the whole SearchRequest still matches it by prefix. - function: com.unboundid.ldap.sdk.SearchRequest# copy: - from: arg(*) - to: this + to: + - this + - .java.lang.Object##java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml index a92cf0e63..80f9cfc36 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml @@ -2,18 +2,28 @@ passThrough: # Apache Velocity: Context.put($k, $v) — the value argument is stored on # the context instance, so a tainted value carried into the context # reaches a subsequent VelocityEngine.evaluate / Template.merge sink that -# consumes the whole context. Entries cover the Context interface, the -# AbstractContext super-class and the concrete VelocityContext, since the -# call site may be typed to any of them. +# consumes the whole context. The value type differs from the context, +# so it is stored in a virtual field rather than tainting the whole +# instance (which would over-taint every other entry read back out of +# the context); the sink that consumes the whole context still matches it +# by prefix. Entries cover the Context interface, the AbstractContext +# super-class and the concrete VelocityContext, since the call site may +# be typed to any of them. - function: org.apache.velocity.context.Context#put copy: - from: arg(1) - to: this + to: + - this + - .java.lang.Object##java.lang.Object - function: org.apache.velocity.VelocityContext#put copy: - from: arg(1) - to: this + to: + - this + - .java.lang.Object##java.lang.Object - function: org.apache.velocity.context.AbstractContext#put copy: - from: arg(1) - to: this + to: + - this + - .java.lang.Object##java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/stdlib.yaml b/core/opentaint-config/java-config/config/java-config/stdlib.yaml index bbb4a244a..7aa8463a7 100644 --- a/core/opentaint-config/java-config/config/java-config/stdlib.yaml +++ b/core/opentaint-config/java-config/config/java-config/stdlib.yaml @@ -21401,14 +21401,19 @@ passThrough: - from: arg(0) to: result -# ── java.net.URL (String) constructor (direct arg→this; the existing -# URL#(String) entry uses arg(*) which doesn't apply consistently -# enough for tests like UnsafeStaplerServeFileServlet) ──────────────── +# ── java.net.URL (String) constructor — the String argument has a +# different type than URL, so it is stored in a virtual field rather +# than tainting the whole instance; an SSRF/file sink that consumes +# the whole URL still matches it by prefix. (The existing arg(*) +# URL# entry didn't apply consistently enough for tests like +# UnsafeStaplerServeFileServlet.) ───────────────────────────────────── - function: java.net.URL# signature: (java.lang.String) void copy: - from: arg(0) - to: this + to: + - this + - .java.lang.Object##java.lang.Object # ── java.net.URI ────────────────────────────────────────────────────── - function: java.net.URI#create @@ -21416,75 +21421,134 @@ passThrough: - from: arg(0) to: result -# ── javax.management JMX (stdlib management API) ─────────────────────── +# ── javax.management JMX (stdlib management API) — the URL/service args +# have different types than the JMXServiceURL / JMXConnector they end +# up in, so they are stored in virtual fields rather than tainting the +# whole instance; a sink consuming the whole object matches by prefix. - function: javax.management.remote.JMXServiceURL# copy: - from: arg(*) - to: this + to: + - this + - .java.lang.Object##java.lang.Object - function: javax.management.remote.JMXConnectorFactory#newJMXConnector copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object -# ── javax.xml.transform.stream.StreamSource ──────────────────────────── +# ── javax.xml.transform.stream.StreamSource — the InputStream/Reader/ +# systemId arg differs in type from StreamSource, so it goes into a +# virtual field; the XXE sink consuming the whole source matches by +# prefix. ────────────────────────────────────────────────────────── - function: javax.xml.transform.stream.StreamSource# copy: - from: arg(*) - to: this + to: + - this + - .java.lang.Object##java.lang.Object # ── java.net.http.HttpRequest$Builder (Java 11+ HttpClient) ─────────── # Fluent chain, e.g. # HttpRequest.newBuilder(URI.create($X)).header(..).GET().build() -# newBuilder seeds the builder from the (tainted) URI; every intermediate -# builder method must carry the builder taint to its return value (no -# implicit this->result exists) and .build() carries it into the -# HttpRequest that the HttpClient send/sendAsync sink consumes whole. +# Data-bearing methods store their (differently-typed) argument into a +# virtual field instead of tainting the whole builder — precise, while a +# sink consuming the whole HttpRequest matches the slot by prefix. The +# slot is owned by java.lang.Object so it survives the +# Builder -> HttpRequest type change of .build() under a plain +# this->result carry. Each data method stores into both `result` (chained +# use) and `this` (non-chained use) and carries this->result; pure links +# carry this->result only (no implicit this->result exists for library +# calls). - function: java.net.http.HttpRequest#newBuilder copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object - function: java.net.http.HttpRequest$Builder#uri copy: - from: arg(0) - to: result + to: + - result + - .java.lang.Object##java.lang.Object - from: arg(0) - to: this + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#header copy: - from: arg(*) - to: this + to: + - result + - .java.lang.Object##java.lang.Object + - from: arg(*) + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#headers copy: - from: arg(*) - to: this + to: + - result + - .java.lang.Object##java.lang.Object + - from: arg(*) + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#setHeader copy: - from: arg(*) - to: this + to: + - result + - .java.lang.Object##java.lang.Object + - from: arg(*) + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#POST copy: - from: arg(0) - to: this + to: + - result + - .java.lang.Object##java.lang.Object + - from: arg(0) + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#PUT copy: - from: arg(0) - to: this + to: + - result + - .java.lang.Object##java.lang.Object + - from: arg(0) + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#method copy: - from: arg(*) - to: this + to: + - result + - .java.lang.Object##java.lang.Object + - from: arg(*) + to: + - this + - .java.lang.Object##java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#DELETE From 39253c3449b39ececb6c8554603d514690c3ff19 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Mon, 25 May 2026 17:47:17 +0200 Subject: [PATCH 4/8] refactor(analyzer): Drop passThrough approximations duplicated elsewhere MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Several new propagators repeated rules already present in other bundled config files (all .yaml under /config are concatenated at load time, so a second copy of the same function is a real runtime duplicate). Removed: - commons-codec: Base64#encodeBase64 / #decodeBase64 — already in config.yaml (identical arg(0)->result). Kept the String / URL-safe / chunked variants, which are not. - stdlib: dropped the catch-all (no-signature) entries that existing signature-specific rules already cover better: String#getBytes, URI#create, Enumeration#nextElement (existing () entry already has this->result), URL#(String) (existing same-signature entry), Base64$Decoder#decode (existing typed overloads), and StreamSource# (jmod.yaml has all typed overloads). Also dropped Collection#iterator (covered by the kept Iterable#iterator via override). Kept Iterable#iterator / Iterator#next generics — the existing entries only model element-level (.Element) flow, so these add the whole-collection this->result carry. - spring-web-5.3.39: dropped the RequestEntity HeadersBuilder/BodyBuilder chain methods — spring-web-7.0.2.yaml already provides them. Kept only the static factories (get/post/method/...), because v7 models those as this->result, a no-op for static methods; the arg-based form here is what actually carries the URI. Note: spring-web-7.0.2.yaml's RequestEntity static factories are dead (this-based on static methods); they should be fixed or removed there separately. --- .../jar-split/commons-codec-1.16.0.yaml | 12 +-- .../jar-split/spring-web-5.3.39.yaml | 91 +++---------------- .../config/java-config/stdlib.yaml | 55 +---------- 3 files changed, 20 insertions(+), 138 deletions(-) diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/commons-codec-1.16.0.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/commons-codec-1.16.0.yaml index b7fde8002..5c87db7ed 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/commons-codec-1.16.0.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/commons-codec-1.16.0.yaml @@ -1,15 +1,13 @@ passThrough: # Apache Commons Codec — Base64 encode/decode just re-codes bytes # without disturbing the underlying tainted data, so taint should -# flow from input to output. +# flow from input to output. The plain encodeBase64 / decodeBase64 +# overloads are already covered by config.yaml; only the String / URL-safe +# / chunked variants are added here. - function: org.apache.commons.codec.binary.Base64#encodeBase64String copy: - from: arg(0) to: result -- function: org.apache.commons.codec.binary.Base64#encodeBase64 - copy: - - from: arg(0) - to: result - function: org.apache.commons.codec.binary.Base64#encodeBase64URLSafeString copy: - from: arg(0) @@ -22,7 +20,3 @@ passThrough: copy: - from: arg(0) to: result -- function: org.apache.commons.codec.binary.Base64#decodeBase64 - copy: - - from: arg(0) - to: result diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml index 14eb52e54..fa7c9fd40 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml @@ -1,18 +1,19 @@ passThrough: -# Spring RequestEntity fluent chain, e.g. the SSRF rule's pattern +# Spring RequestEntity static factories, e.g. the SSRF rule's pattern # RequestEntity.get(URI.create($X)).accept(..).header(..).build() # -# The static factories store their (differently-typed) URI argument into -# a virtual field of the created builder instead of tainting it whole; -# data-bearing builder methods do the same. Every builder method also -# carries this->result so the chain survives (no implicit this->result -# exists), and .build() carries the slot into the RequestEntity — the -# slot is owned by java.lang.Object so it survives the -# Builder -> RequestEntity type change under a plain this->result carry. -# The RestTemplate sink that consumes the whole RequestEntity matches the -# slot by prefix. -# -# ── Static factories (URI is the first arg, except method(HttpMethod, URI)) ── +# Only the static factories live here: the HeadersBuilder / BodyBuilder +# chain methods (header/accept/contentType/body/build/...) are already +# provided by spring-web-7.0.2.yaml (RequestEntity is the same class in +# both jars), so they are not duplicated here. The factories ARE needed +# here because spring-web-7.0.2.yaml models them as `this -> result`, +# which is a no-op for these *static* methods; the arg-based form below +# is what actually carries the (differently-typed) URI argument into the +# created builder. It is stored in a java.lang.Object-owned +# virtual field (precise, and it survives the builder -> RequestEntity +# type change of .build() under spring-web-7.0.2's this->result carry); +# the RestTemplate sink consuming the whole RequestEntity matches the +# slot by prefix. (URI is the first arg, except method(HttpMethod, URI).) - function: org.springframework.http.RequestEntity#get copy: - from: arg(0) @@ -61,69 +62,3 @@ passThrough: to: - result - .java.lang.Object##java.lang.Object -# ── HeadersBuilder chain (get/head/delete/options return this) ── -- function: org.springframework.http.RequestEntity$HeadersBuilder#header - copy: - - from: arg(*) - to: - - result - - .java.lang.Object##java.lang.Object - - from: arg(*) - to: - - this - - .java.lang.Object##java.lang.Object - - from: this - to: result -- function: org.springframework.http.RequestEntity$HeadersBuilder#headers - copy: - - from: arg(*) - to: - - result - - .java.lang.Object##java.lang.Object - - from: arg(*) - to: - - this - - .java.lang.Object##java.lang.Object - - from: this - to: result -- function: org.springframework.http.RequestEntity$HeadersBuilder#accept - copy: - - from: this - to: result -- function: org.springframework.http.RequestEntity$HeadersBuilder#acceptCharset - copy: - - from: this - to: result -- function: org.springframework.http.RequestEntity$HeadersBuilder#ifModifiedSince - copy: - - from: this - to: result -- function: org.springframework.http.RequestEntity$HeadersBuilder#ifNoneMatch - copy: - - from: this - to: result -- function: org.springframework.http.RequestEntity$HeadersBuilder#build - copy: - - from: this - to: result -# ── BodyBuilder chain (post/put/patch/method return this) ── -- function: org.springframework.http.RequestEntity$BodyBuilder#contentLength - copy: - - from: this - to: result -- function: org.springframework.http.RequestEntity$BodyBuilder#contentType - copy: - - from: this - to: result -- function: org.springframework.http.RequestEntity$BodyBuilder#body - copy: - - from: arg(0) - to: - - result - - .java.lang.Object##java.lang.Object - - from: arg(0) - to: - - this - - .java.lang.Object##java.lang.Object - - from: this - to: result diff --git a/core/opentaint-config/java-config/config/java-config/stdlib.yaml b/core/opentaint-config/java-config/config/java-config/stdlib.yaml index 7aa8463a7..7a2aed726 100644 --- a/core/opentaint-config/java-config/config/java-config/stdlib.yaml +++ b/core/opentaint-config/java-config/config/java-config/stdlib.yaml @@ -21359,11 +21359,9 @@ passThrough: - this - .java.io.InputStream##java.lang.Object -# ── Collection / Iterator / Iterable / Enumeration ───────────────────── -- function: java.util.Collection#iterator - copy: - - from: this - to: result +# ── Iterator / Iterable (whole-collection -> iterator/element; existing +# sig-specific entries only model element-level vf, so these add the +# whole-object carry) ────────────────────────────────────────────── - function: java.lang.Iterable#iterator copy: - from: this @@ -21372,18 +21370,8 @@ passThrough: copy: - from: this to: result -- function: java.util.Enumeration#nextElement - copy: - - from: this - to: result - -# ── java.lang.String#getBytes (String → byte[]) ──────────────────────── -- function: java.lang.String#getBytes - copy: - - from: this - to: result -# ── java.util.Base64$Encoder / $Decoder ─────────────────────────────── +# ── java.util.Base64$Encoder ────────────────────────────────────────── - function: java.util.Base64$Encoder#encodeToString copy: - from: arg(0) @@ -21392,35 +21380,11 @@ passThrough: copy: - from: arg(0) to: result -- function: java.util.Base64$Decoder#decode - copy: - - from: arg(0) - to: result - function: java.util.Base64$Decoder#wrap copy: - from: arg(0) to: result -# ── java.net.URL (String) constructor — the String argument has a -# different type than URL, so it is stored in a virtual field rather -# than tainting the whole instance; an SSRF/file sink that consumes -# the whole URL still matches it by prefix. (The existing arg(*) -# URL# entry didn't apply consistently enough for tests like -# UnsafeStaplerServeFileServlet.) ───────────────────────────────────── -- function: java.net.URL# - signature: (java.lang.String) void - copy: - - from: arg(0) - to: - - this - - .java.lang.Object##java.lang.Object - -# ── java.net.URI ────────────────────────────────────────────────────── -- function: java.net.URI#create - copy: - - from: arg(0) - to: result - # ── javax.management JMX (stdlib management API) — the URL/service args # have different types than the JMXServiceURL / JMXConnector they end # up in, so they are stored in virtual fields rather than tainting the @@ -21438,17 +21402,6 @@ passThrough: - result - .java.lang.Object##java.lang.Object -# ── javax.xml.transform.stream.StreamSource — the InputStream/Reader/ -# systemId arg differs in type from StreamSource, so it goes into a -# virtual field; the XXE sink consuming the whole source matches by -# prefix. ────────────────────────────────────────────────────────── -- function: javax.xml.transform.stream.StreamSource# - copy: - - from: arg(*) - to: - - this - - .java.lang.Object##java.lang.Object - # ── java.net.http.HttpRequest$Builder (Java 11+ HttpClient) ─────────── # Fluent chain, e.g. # HttpRequest.newBuilder(URI.create($X)).header(..).GET().build() From 69443a725cb6239b6d45ad48fb89a3da8bb3183b Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Mon, 25 May 2026 18:00:20 +0200 Subject: [PATCH 5/8] refactor(analyzer): Fix RequestEntity static factories in v7, drop 5.3.39 file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit spring-web-7.0.2.yaml modeled the RequestEntity.get/post/head/put/patch/ delete/options/method static factories as `this -> result`, which is a no-op for static methods, so they never carried the URI argument. Replace them with the arg-based form that stores the URI into a java.lang.Object- owned slot of the returned builder; the slot survives the builder -> RequestEntity type change of .build() under the existing this->result builder carries, and the RestTemplate sink consuming the whole RequestEntity matches it by prefix. With the factories fixed, spring-web-5.3.39.yaml (which only existed to provide working arg-based factories) is fully redundant — RequestEntity is the same class in both jars and all config now lives in spring-web-7.0.2.yaml — so delete it. --- .../jar-split/spring-web-5.3.39.yaml | 64 -------------- .../jar-split/spring-web-7.0.2.yaml | 85 ++++++++----------- 2 files changed, 37 insertions(+), 112 deletions(-) delete mode 100644 core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml deleted file mode 100644 index fa7c9fd40..000000000 --- a/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-5.3.39.yaml +++ /dev/null @@ -1,64 +0,0 @@ -passThrough: -# Spring RequestEntity static factories, e.g. the SSRF rule's pattern -# RequestEntity.get(URI.create($X)).accept(..).header(..).build() -# -# Only the static factories live here: the HeadersBuilder / BodyBuilder -# chain methods (header/accept/contentType/body/build/...) are already -# provided by spring-web-7.0.2.yaml (RequestEntity is the same class in -# both jars), so they are not duplicated here. The factories ARE needed -# here because spring-web-7.0.2.yaml models them as `this -> result`, -# which is a no-op for these *static* methods; the arg-based form below -# is what actually carries the (differently-typed) URI argument into the -# created builder. It is stored in a java.lang.Object-owned -# virtual field (precise, and it survives the builder -> RequestEntity -# type change of .build() under spring-web-7.0.2's this->result carry); -# the RestTemplate sink consuming the whole RequestEntity matches the -# slot by prefix. (URI is the first arg, except method(HttpMethod, URI).) -- function: org.springframework.http.RequestEntity#get - copy: - - from: arg(0) - to: - - result - - .java.lang.Object##java.lang.Object -- function: org.springframework.http.RequestEntity#head - copy: - - from: arg(0) - to: - - result - - .java.lang.Object##java.lang.Object -- function: org.springframework.http.RequestEntity#post - copy: - - from: arg(0) - to: - - result - - .java.lang.Object##java.lang.Object -- function: org.springframework.http.RequestEntity#put - copy: - - from: arg(0) - to: - - result - - .java.lang.Object##java.lang.Object -- function: org.springframework.http.RequestEntity#patch - copy: - - from: arg(0) - to: - - result - - .java.lang.Object##java.lang.Object -- function: org.springframework.http.RequestEntity#delete - copy: - - from: arg(0) - to: - - result - - .java.lang.Object##java.lang.Object -- function: org.springframework.http.RequestEntity#options - copy: - - from: arg(0) - to: - - result - - .java.lang.Object##java.lang.Object -- function: org.springframework.http.RequestEntity#method - copy: - - from: arg(*) - to: - - result - - .java.lang.Object##java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-7.0.2.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-7.0.2.yaml index a6ce562b7..f4a6125c7 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-7.0.2.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-7.0.2.yaml @@ -97,30 +97,29 @@ passThrough: copy: - from: this to: result +# RequestEntity.get/post/... are STATIC factories taking the URI as the +# first argument (HttpMethod, URI for method()); a this->result copy is a +# no-op for them. Carry the URI argument into the returned builder via a +# java.lang.Object-owned slot, which survives the +# builder -> RequestEntity type change of .build() under this->result. - function: org.springframework.http.RequestEntity#delete copy: - - from: - - this - - .org.springframework.http.RequestEntity##java.lang.Object - to: result - - from: this - to: result + - from: arg(0) + to: + - result + - .java.lang.Object##java.lang.Object - function: org.springframework.http.RequestEntity#get copy: - - from: - - this - - .org.springframework.http.RequestEntity##java.lang.Object - to: result - - from: this - to: result + - from: arg(0) + to: + - result + - .java.lang.Object##java.lang.Object - function: org.springframework.http.RequestEntity#head copy: - - from: - - this - - .org.springframework.http.RequestEntity##java.lang.Object - to: result - - from: this - to: result + - from: arg(0) + to: + - result + - .java.lang.Object##java.lang.Object - function: org.springframework.http.RequestEntity# copy: - from: arg(1) @@ -137,44 +136,34 @@ passThrough: - .org.springframework.http.RequestEntity##java.lang.Object - function: org.springframework.http.RequestEntity#method copy: - - from: - - this - - .org.springframework.http.RequestEntity##java.lang.Object - to: result - - from: this - to: result + - from: arg(*) + to: + - result + - .java.lang.Object##java.lang.Object - function: org.springframework.http.RequestEntity#options copy: - - from: - - this - - .org.springframework.http.RequestEntity##java.lang.Object - to: result - - from: this - to: result + - from: arg(0) + to: + - result + - .java.lang.Object##java.lang.Object - function: org.springframework.http.RequestEntity#patch copy: - - from: - - this - - .org.springframework.http.RequestEntity##java.lang.Object - to: result - - from: this - to: result + - from: arg(0) + to: + - result + - .java.lang.Object##java.lang.Object - function: org.springframework.http.RequestEntity#post copy: - - from: - - this - - .org.springframework.http.RequestEntity##java.lang.Object - to: result - - from: this - to: result + - from: arg(0) + to: + - result + - .java.lang.Object##java.lang.Object - function: org.springframework.http.RequestEntity#put copy: - - from: - - this - - .org.springframework.http.RequestEntity##java.lang.Object - to: result - - from: this - to: result + - from: arg(0) + to: + - result + - .java.lang.Object##java.lang.Object - function: org.springframework.http.ResponseEntity$BodyBuilder#body copy: - from: arg(0) From e2d0bb6cd73f81413f689d6ffee03da5cbe6646a Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Mon, 25 May 2026 18:12:24 +0200 Subject: [PATCH 6/8] refactor(analyzer): Use builder-typed RequestEntity slot with re-key at terminals MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to the static-factory fix: instead of a java.lang.Object-owned slot, store the factory's URI argument into the builder's own type slot (RequestEntity$HeadersBuilder#, which also covers BodyBuilder since it extends HeadersBuilder), and re-key it onto the RequestEntity# slot at the terminals .build() and .body(). This is more type-honest and unifies with the existing / getBody modeling (all RequestEntity construction paths now land taint in the same RequestEntity# slot), and a builder-typed slot is type-pruned if taint ever reaches a non-builder object. The cost is that every terminal returning a RequestEntity must re-key (HeadersBuilder is not a subtype of RequestEntity, so a plain this->result drops the builder-owned slot) — both build() and body() do. --- .../jar-split/spring-web-7.0.2.yaml | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-7.0.2.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-7.0.2.yaml index f4a6125c7..eb427416d 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-7.0.2.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-7.0.2.yaml @@ -53,6 +53,14 @@ passThrough: copy: - from: this to: result + # Terminal: re-key the builder slot onto the constructed RequestEntity + # (same reason as HeadersBuilder#build above). + - from: + - this + - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object + to: + - result + - .org.springframework.http.RequestEntity##java.lang.Object - function: org.springframework.http.RequestEntity$BodyBuilder#contentLength copy: - from: this @@ -73,6 +81,15 @@ passThrough: copy: - from: this to: result + # Terminal: re-key the builder slot onto the constructed RequestEntity + # (HeadersBuilder is not a subtype of RequestEntity, so a plain + # this->result would drop the builder-owned slot). + - from: + - this + - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object + to: + - result + - .org.springframework.http.RequestEntity##java.lang.Object - function: org.springframework.http.RequestEntity$HeadersBuilder#header copy: - from: arg(0) @@ -99,27 +116,29 @@ passThrough: to: result # RequestEntity.get/post/... are STATIC factories taking the URI as the # first argument (HttpMethod, URI for method()); a this->result copy is a -# no-op for them. Carry the URI argument into the returned builder via a -# java.lang.Object-owned slot, which survives the -# builder -> RequestEntity type change of .build() under this->result. +# no-op for them. Carry the URI argument into the returned builder's +# slot (owner HeadersBuilder, which also covers BodyBuilder +# since it extends HeadersBuilder). The chain methods carry this->result, +# and the terminals .build() / .body() re-key the builder slot into the +# RequestEntity# slot (see those entries). - function: org.springframework.http.RequestEntity#delete copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object - function: org.springframework.http.RequestEntity#get copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object - function: org.springframework.http.RequestEntity#head copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object - function: org.springframework.http.RequestEntity# copy: - from: arg(1) @@ -139,31 +158,31 @@ passThrough: - from: arg(*) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object - function: org.springframework.http.RequestEntity#options copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object - function: org.springframework.http.RequestEntity#patch copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object - function: org.springframework.http.RequestEntity#post copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object - function: org.springframework.http.RequestEntity#put copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object - function: org.springframework.http.ResponseEntity$BodyBuilder#body copy: - from: arg(0) From ec3bdd8fdb4e59ea2ed8a843dfadfc8861cb3934 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Tue, 26 May 2026 22:34:34 +0200 Subject: [PATCH 7/8] refactor(analyzer): Type virtual-field slot owners precisely with re-key at transitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the imprecise `java.lang.Object` slot owners in the new passthrough config with precise domain types, mirroring the spring-web RequestEntity reference (precise owner, java.lang.Object kept only as the field value type, re-key where the static type changes). - No type change (wrapper -> this, factory -> result): owner = the object's own type — ant FileSet, jenkins FilePath, httpcore5 StringEntity, unboundid SearchRequest, groovy CompilationUnit, JMX JMXServiceURL/JMXConnector; Velocity put() uses the common Context interface for all three receivers. - Single transition: builder-typed owner along the chain + one re-key at build() — okhttp Request.Builder -> Request, java.net.http HttpRequest.Builder -> HttpRequest. - Multi-transition Spring LDAP chain: owner tracks each stage (LdapQueryBuilder -> ConditionCriteria -> ContainerCriteria) with a re-key at every type change (where/is/like/gte/lte/whitespaceWildcardsLike/and/or/ filter), mirrored on the Default* impl entries. Re-key acceptance follows JIRFactTypeChecker.typeMayHaveSubtypeOf(resultType, owner); every transition is covered, so the slot reaches the terminal in exactly the cases the Object-owner baseline did (behavior-equivalent). --- .../java-config/jar-split/ant-1.10.14.yaml | 9 +- .../java-config/jar-split/groovy-3.0.21.yaml | 8 +- .../jar-split/httpcore5-5.2.4.yaml | 7 +- .../jar-split/jenkins-core-2.426.3.yaml | 7 +- .../java-config/jar-split/okhttp-4.12.0.yaml | 52 +++-- .../jar-split/spring-ldap-core-2.4.1.yaml | 191 ++++++++++++++---- .../jar-split/unboundid-ldapsdk-6.0.11.yaml | 7 +- .../jar-split/velocity-engine-core-2.3.yaml | 10 +- .../config/java-config/stdlib.yaml | 56 ++--- 9 files changed, 248 insertions(+), 99 deletions(-) diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/ant-1.10.14.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/ant-1.10.14.yaml index 1ec6fb375..b4e81f4cb 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/ant-1.10.14.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/ant-1.10.14.yaml @@ -3,17 +3,18 @@ passThrough: # is stored on the FileSet instance, so a subsequent # `copy.addFileset(fs)` sink that requires a tainted $FILE detects the # flow. The File argument has a different type than FileSet, so it is -# stored in a virtual field instead of tainting the whole instance; the -# sink that consumes the whole FileSet still matches it by prefix. +# stored in a virtual field (owned by FileSet, the object it sits on) +# instead of tainting the whole instance; the sink that consumes the +# whole FileSet still matches it by prefix. - function: org.apache.tools.ant.types.FileSet#setDir copy: - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .org.apache.tools.ant.types.FileSet##java.lang.Object - function: org.apache.tools.ant.types.FileSet#setFile copy: - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .org.apache.tools.ant.types.FileSet##java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml index c17a91074..4239ad6c8 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml @@ -5,12 +5,12 @@ passThrough: # addSource(name, source|InputStream) but the 1st arg of the # addSource(File) / addSource(URL) / addSource(SourceUnit) overloads, so # copy from any argument. The argument type differs from CompilationUnit, -# so it is stored in a virtual field rather than tainting the whole -# instance; a sink that consumes the whole unit still matches it by -# prefix. +# so it is stored in a virtual field (owned by CompilationUnit, the +# object it sits on) rather than tainting the whole instance; a sink that +# consumes the whole unit still matches it by prefix. - function: org.codehaus.groovy.control.CompilationUnit#addSource copy: - from: arg(*) to: - this - - .java.lang.Object##java.lang.Object + - .org.codehaus.groovy.control.CompilationUnit##java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/httpcore5-5.2.4.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/httpcore5-5.2.4.yaml index fced88b16..9409929b8 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/httpcore5-5.2.4.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/httpcore5-5.2.4.yaml @@ -2,11 +2,12 @@ passThrough: # Apache HttpComponents 5 — String-arg wrapper constructor that the # SSRF sink rules use as an inline taint carrier. The argument has a # different type than the StringEntity, so it is stored in a virtual -# field rather than tainting the whole instance; a sink that consumes -# the whole entity still matches it by prefix. +# field (owned by StringEntity, the object it sits on) rather than +# tainting the whole instance; a sink that consumes the whole entity +# still matches it by prefix. - function: org.apache.hc.core5.http.io.entity.StringEntity# copy: - from: arg(*) to: - this - - .java.lang.Object##java.lang.Object + - .org.apache.hc.core5.http.io.entity.StringEntity##java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/jenkins-core-2.426.3.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/jenkins-core-2.426.3.yaml index b2fb57a12..b5ca04f15 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/jenkins-core-2.426.3.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/jenkins-core-2.426.3.yaml @@ -2,11 +2,12 @@ passThrough: # hudson.FilePath wrapper constructor — taint flows from any # String/File/URL argument into the constructed FilePath instance. # The argument type differs from FilePath, so it is stored in a virtual -# field instead of tainting the whole object; a path-traversal sink that -# consumes the whole FilePath still matches it by prefix. +# field (owned by FilePath, the object it sits on) instead of tainting +# the whole object; a path-traversal sink that consumes the whole +# FilePath still matches it by prefix. - function: hudson.FilePath# copy: - from: arg(*) to: - this - - .java.lang.Object##java.lang.Object + - .hudson.FilePath##java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml index ddb0841e8..370df68f1 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml @@ -6,9 +6,10 @@ passThrough: # virtual field instead of tainting the whole builder — this keeps # precision (unrelated builder/request state stays untainted) while a # sink that consumes the whole Request still matches the slot by prefix. -# The slot is owned by java.lang.Object so it survives the -# Builder -> Request type change of .build() under a plain this->result -# carry. +# The slot is owned by Request.Builder along the chain; +# since Request is not a subtype of Request.Builder, a plain this->result +# at .build() would drop the slot, so .build() re-keys it onto a +# Request-owned slot (see that entry). # # Each data method stores into both `result` (for chained use, # `.url($X).build()`) and `this` (for non-chained use, `b.url($X); b.build()`), @@ -21,11 +22,11 @@ passThrough: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .okhttp3.Request$Builder##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .okhttp3.Request$Builder##java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#header @@ -33,11 +34,11 @@ passThrough: - from: arg(*) to: - result - - .java.lang.Object##java.lang.Object + - .okhttp3.Request$Builder##java.lang.Object - from: arg(*) to: - this - - .java.lang.Object##java.lang.Object + - .okhttp3.Request$Builder##java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#addHeader @@ -45,11 +46,11 @@ passThrough: - from: arg(*) to: - result - - .java.lang.Object##java.lang.Object + - .okhttp3.Request$Builder##java.lang.Object - from: arg(*) to: - this - - .java.lang.Object##java.lang.Object + - .okhttp3.Request$Builder##java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#headers @@ -57,11 +58,11 @@ passThrough: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .okhttp3.Request$Builder##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .okhttp3.Request$Builder##java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#post @@ -69,11 +70,11 @@ passThrough: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .okhttp3.Request$Builder##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .okhttp3.Request$Builder##java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#put @@ -81,11 +82,11 @@ passThrough: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .okhttp3.Request$Builder##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .okhttp3.Request$Builder##java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#patch @@ -93,11 +94,11 @@ passThrough: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .okhttp3.Request$Builder##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .okhttp3.Request$Builder##java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#delete @@ -105,11 +106,11 @@ passThrough: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .okhttp3.Request$Builder##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .okhttp3.Request$Builder##java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#method @@ -117,11 +118,11 @@ passThrough: - from: arg(*) to: - result - - .java.lang.Object##java.lang.Object + - .okhttp3.Request$Builder##java.lang.Object - from: arg(*) to: - this - - .java.lang.Object##java.lang.Object + - .okhttp3.Request$Builder##java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#get @@ -148,3 +149,12 @@ passThrough: copy: - from: this to: result + # Terminal: re-key the builder slot onto the constructed Request + # (Request is not a subtype of Request.Builder, so a plain this->result + # would drop the builder-owned slot). + - from: + - this + - .okhttp3.Request$Builder##java.lang.Object + to: + - result + - .okhttp3.Request##java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml index 4d05cd01c..fca8497a0 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml @@ -13,20 +13,27 @@ passThrough: # criteria object — precise, while an LdapTemplate sink consuming the # whole LdapQuery matches the slot by prefix. The slot is stored into # both `result` (chained use, the dominant style here) and `this` -# (non-chained use), and each link carries this->result. The -# slot is owned by java.lang.Object so it survives the -# LdapQueryBuilder -> ConditionCriteria -> ContainerCriteria -> LdapQuery -# type changes along the chain under plain this->result carries. +# (non-chained use), and each link carries this->result. +# +# The chain has no single common supertype — where() returns +# ConditionCriteria, is()/like()/... return ContainerCriteria, and()/or() +# return ConditionCriteria again — so the slot owner tracks the static +# type of each stage (LdapQueryBuilder -> ConditionCriteria -> +# ContainerCriteria), and every method that changes the type re-keys the +# incoming slot onto the new owner. A plain this->result alone would drop +# the slot at such a transition (e.g. ContainerCriteria is not a subtype +# of ConditionCriteria). LdapQueryBuilder.filter() goes straight to +# LdapQuery. - function: org.springframework.ldap.query.LdapQueryBuilder#base copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.LdapQueryBuilder##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.LdapQueryBuilder##java.lang.Object - from: this to: result - function: org.springframework.ldap.query.LdapQueryBuilder#where @@ -34,87 +41,136 @@ passThrough: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.LdapQueryBuilder##java.lang.Object - from: this to: result + # Re-key: LdapQueryBuilder -> ConditionCriteria. + - from: + - this + - .org.springframework.ldap.query.LdapQueryBuilder##java.lang.Object + to: + - result + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object - function: org.springframework.ldap.query.LdapQueryBuilder#filter copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.LdapQuery##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.LdapQueryBuilder##java.lang.Object - from: this to: result + # Re-key: LdapQueryBuilder -> LdapQuery. + - from: + - this + - .org.springframework.ldap.query.LdapQueryBuilder##java.lang.Object + to: + - result + - .org.springframework.ldap.query.LdapQuery##java.lang.Object - function: org.springframework.ldap.query.ConditionCriteria#is copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object - from: this to: result + # Re-key: ConditionCriteria -> ContainerCriteria. + - from: + - this + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + to: + - result + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - function: org.springframework.ldap.query.ConditionCriteria#like copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object - from: this to: result + # Re-key: ConditionCriteria -> ContainerCriteria. + - from: + - this + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + to: + - result + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - function: org.springframework.ldap.query.ConditionCriteria#whitespaceWildcardsLike copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object - from: this to: result + # Re-key: ConditionCriteria -> ContainerCriteria. + - from: + - this + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + to: + - result + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - function: org.springframework.ldap.query.ConditionCriteria#gte copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object - from: this to: result + # Re-key: ConditionCriteria -> ContainerCriteria. + - from: + - this + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + to: + - result + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - function: org.springframework.ldap.query.ConditionCriteria#lte copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object - from: this to: result -# `.not()` is a value-less modifier that returns the same criteria — pure -# chain carrier. + # Re-key: ConditionCriteria -> ContainerCriteria. + - from: + - this + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + to: + - result + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object +# `.not()` is a value-less modifier that returns the same ConditionCriteria +# — pure chain carrier, no type change. - function: org.springframework.ldap.query.ConditionCriteria#not copy: - from: this @@ -139,74 +195,127 @@ passThrough: copy: - from: this to: result +# and()/or() with a String attribute return ConditionCriteria (type change +# back from ContainerCriteria); the ContainerCriteria(ContainerCriteria) +# overloads return ContainerCriteria. The this->result carry keeps the slot +# for the same-type overload, and the re-key restores it for the +# ContainerCriteria -> ConditionCriteria overload (dropped harmlessly when +# the result is still a ContainerCriteria). - function: org.springframework.ldap.query.ContainerCriteria#and copy: - from: this to: result + - from: + - this + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + to: + - result + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object - function: org.springframework.ldap.query.ContainerCriteria#or copy: - from: this to: result + - from: + - this + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + to: + - result + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object - function: org.springframework.ldap.query.DefaultConditionCriteria#is copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object - from: this to: result + # Re-key: ConditionCriteria -> ContainerCriteria. + - from: + - this + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + to: + - result + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - function: org.springframework.ldap.query.DefaultConditionCriteria#like copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object - from: this to: result + # Re-key: ConditionCriteria -> ContainerCriteria. + - from: + - this + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + to: + - result + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - function: org.springframework.ldap.query.DefaultConditionCriteria#whitespaceWildcardsLike copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object - from: this to: result + # Re-key: ConditionCriteria -> ContainerCriteria. + - from: + - this + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + to: + - result + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - function: org.springframework.ldap.query.DefaultConditionCriteria#gte copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object - from: this to: result + # Re-key: ConditionCriteria -> ContainerCriteria. + - from: + - this + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + to: + - result + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - function: org.springframework.ldap.query.DefaultConditionCriteria#lte copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object - from: this to: result + # Re-key: ConditionCriteria -> ContainerCriteria. + - from: + - this + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + to: + - result + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - function: org.springframework.ldap.query.DefaultConditionCriteria#not copy: - from: this @@ -215,19 +324,33 @@ passThrough: copy: - from: this to: result + # Re-key: ContainerCriteria -> ConditionCriteria (String-attr overload). + - from: + - this + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + to: + - result + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object - function: org.springframework.ldap.query.DefaultContainerCriteria#or copy: - from: this to: result + # Re-key: ContainerCriteria -> ConditionCriteria (String-attr overload). + - from: + - this + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + to: + - result + - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object - function: org.springframework.ldap.query.DefaultContainerCriteria#append copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object - from: this to: result diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/unboundid-ldapsdk-6.0.11.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/unboundid-ldapsdk-6.0.11.yaml index dd663a056..73f048b5d 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/unboundid-ldapsdk-6.0.11.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/unboundid-ldapsdk-6.0.11.yaml @@ -1,11 +1,12 @@ passThrough: # com.unboundid.ldap.sdk.SearchRequest constructor — the base DN / filter # arguments have a different type than SearchRequest, so they are stored -# in a virtual field rather than tainting the whole instance; an LDAP -# sink that consumes the whole SearchRequest still matches it by prefix. +# in a virtual field (owned by SearchRequest, the object it sits on) +# rather than tainting the whole instance; an LDAP sink that consumes the +# whole SearchRequest still matches it by prefix. - function: com.unboundid.ldap.sdk.SearchRequest# copy: - from: arg(*) to: - this - - .java.lang.Object##java.lang.Object + - .com.unboundid.ldap.sdk.SearchRequest##java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml index 80f9cfc36..f96c0a46a 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml @@ -8,22 +8,24 @@ passThrough: # the context); the sink that consumes the whole context still matches it # by prefix. Entries cover the Context interface, the AbstractContext # super-class and the concrete VelocityContext, since the call site may -# be typed to any of them. +# be typed to any of them. The slot is owned by the Context interface, +# which all three receivers implement, so it is accepted on whichever +# static type the call site uses. - function: org.apache.velocity.context.Context#put copy: - from: arg(1) to: - this - - .java.lang.Object##java.lang.Object + - .org.apache.velocity.context.Context##java.lang.Object - function: org.apache.velocity.VelocityContext#put copy: - from: arg(1) to: - this - - .java.lang.Object##java.lang.Object + - .org.apache.velocity.context.Context##java.lang.Object - function: org.apache.velocity.context.AbstractContext#put copy: - from: arg(1) to: - this - - .java.lang.Object##java.lang.Object + - .org.apache.velocity.context.Context##java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/stdlib.yaml b/core/opentaint-config/java-config/config/java-config/stdlib.yaml index 7a2aed726..168b33631 100644 --- a/core/opentaint-config/java-config/config/java-config/stdlib.yaml +++ b/core/opentaint-config/java-config/config/java-config/stdlib.yaml @@ -21394,13 +21394,13 @@ passThrough: - from: arg(*) to: - this - - .java.lang.Object##java.lang.Object + - .javax.management.remote.JMXServiceURL##java.lang.Object - function: javax.management.remote.JMXConnectorFactory#newJMXConnector copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .javax.management.remote.JMXConnector##java.lang.Object # ── java.net.http.HttpRequest$Builder (Java 11+ HttpClient) ─────────── # Fluent chain, e.g. @@ -21408,28 +21408,29 @@ passThrough: # Data-bearing methods store their (differently-typed) argument into a # virtual field instead of tainting the whole builder — precise, while a # sink consuming the whole HttpRequest matches the slot by prefix. The -# slot is owned by java.lang.Object so it survives the -# Builder -> HttpRequest type change of .build() under a plain -# this->result carry. Each data method stores into both `result` (chained -# use) and `this` (non-chained use) and carries this->result; pure links -# carry this->result only (no implicit this->result exists for library -# calls). +# slot is owned by HttpRequest.Builder along the chain; +# since HttpRequest is not a subtype of HttpRequest.Builder, a plain +# this->result at .build() would drop the slot, so .build() re-keys it +# onto an HttpRequest-owned slot (see that entry). Each data method stores +# into both `result` (chained use) and `this` (non-chained use) and +# carries this->result; pure links carry this->result only (no implicit +# this->result exists for library calls). - function: java.net.http.HttpRequest#newBuilder copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .java.net.http.HttpRequest$Builder##java.lang.Object - function: java.net.http.HttpRequest$Builder#uri copy: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .java.net.http.HttpRequest$Builder##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .java.net.http.HttpRequest$Builder##java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#header @@ -21437,11 +21438,11 @@ passThrough: - from: arg(*) to: - result - - .java.lang.Object##java.lang.Object + - .java.net.http.HttpRequest$Builder##java.lang.Object - from: arg(*) to: - this - - .java.lang.Object##java.lang.Object + - .java.net.http.HttpRequest$Builder##java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#headers @@ -21449,11 +21450,11 @@ passThrough: - from: arg(*) to: - result - - .java.lang.Object##java.lang.Object + - .java.net.http.HttpRequest$Builder##java.lang.Object - from: arg(*) to: - this - - .java.lang.Object##java.lang.Object + - .java.net.http.HttpRequest$Builder##java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#setHeader @@ -21461,11 +21462,11 @@ passThrough: - from: arg(*) to: - result - - .java.lang.Object##java.lang.Object + - .java.net.http.HttpRequest$Builder##java.lang.Object - from: arg(*) to: - this - - .java.lang.Object##java.lang.Object + - .java.net.http.HttpRequest$Builder##java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#POST @@ -21473,11 +21474,11 @@ passThrough: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .java.net.http.HttpRequest$Builder##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .java.net.http.HttpRequest$Builder##java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#PUT @@ -21485,11 +21486,11 @@ passThrough: - from: arg(0) to: - result - - .java.lang.Object##java.lang.Object + - .java.net.http.HttpRequest$Builder##java.lang.Object - from: arg(0) to: - this - - .java.lang.Object##java.lang.Object + - .java.net.http.HttpRequest$Builder##java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#method @@ -21497,11 +21498,11 @@ passThrough: - from: arg(*) to: - result - - .java.lang.Object##java.lang.Object + - .java.net.http.HttpRequest$Builder##java.lang.Object - from: arg(*) to: - this - - .java.lang.Object##java.lang.Object + - .java.net.http.HttpRequest$Builder##java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#DELETE @@ -21532,3 +21533,12 @@ passThrough: copy: - from: this to: result + # Terminal: re-key the builder slot onto the constructed HttpRequest + # (HttpRequest is not a subtype of HttpRequest.Builder, so a plain + # this->result would drop the builder-owned slot). + - from: + - this + - .java.net.http.HttpRequest$Builder##java.lang.Object + to: + - result + - .java.net.http.HttpRequest##java.lang.Object From 0b087fdf54546fed0e8b1a4c22171f8fb4da1823 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 27 May 2026 14:19:50 +0200 Subject: [PATCH 8/8] refactor(analyzer): Exact per-overload signatures and named vfields in passthroughs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rework the new jar-split/stdlib passThrough rules for precision: - Replace arg(*) with per-overload `signature:` + exact arg indices (RequestEntity, okhttp/java.net.http builders, StringEntity, FilePath, CompilationUnit.addSource, JMXServiceURL, SearchRequest). Keep arg(*) only for genuine varargs (e.g. UriTemplate.expand). Use `*` return to avoid generic-erasure mismatch; exclude structurally non-taint args (e.g. RequestEntity.method's HttpMethod enum). - Rename branch-new slots to specific names: url / content / path / source / value / filter; SearchRequest split into baseDN / filter / attributes. Pre-existing slots left untouched. Note: named fields are no longer excluded from .* (AnyAccessor) unrolling — only the literal "" is special-cased (JIRTaintAnalyzer UnrollStrategy); ContainsMarkOnAnyField sinks still see the named sub-fields. - HttpHeaders: enumerate all 61 setter overloads + 24 read-back getters with exact signatures and per-header named vfields (Location, ContentType, ...; dynamic-name set/add/getFirst/get share DynamicHeader), keeping whole-object taint for header-injection sinks. - RequestEntity: fix the static factories (get/post/head/delete/options/put/ patch/method carry the URI/template args into the builder slot; this->result was a no-op for statics) and add the getUrl read-back accessor. - Drop explanatory comments from the passThrough YAML. --- .../java-config/jar-split/ant-1.10.14.yaml | 11 +- .../jar-split/commons-codec-1.16.0.yaml | 5 - .../jar-split/commons-io-2.15.1.yaml | 4 - .../java-config/jar-split/groovy-3.0.21.yaml | 42 +- .../jar-split/httpcore5-5.2.4.yaml | 46 +- .../jar-split/jenkins-core-2.426.3.yaml | 25 +- .../jar-split/mvel2-2.5.2.Final.yaml | 5 - .../java-config/jar-split/okhttp-4.12.0.yaml | 100 +- .../jar-split/spring-jdbc-5.3.39.yaml | 5 - .../jar-split/spring-ldap-core-2.4.1.yaml | 171 ++-- .../jar-split/spring-web-7.0.2.yaml | 904 +++++++++++++++++- .../jar-split/unboundid-ldapsdk-6.0.11.yaml | 168 +++- .../jar-split/velocity-engine-core-2.3.yaml | 18 +- .../config/java-config/stdlib.yaml | 135 ++- 14 files changed, 1319 insertions(+), 320 deletions(-) diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/ant-1.10.14.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/ant-1.10.14.yaml index b4e81f4cb..cab4deebe 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/ant-1.10.14.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/ant-1.10.14.yaml @@ -1,20 +1,13 @@ passThrough: -# Apache Ant: FileSet.setDir(File) / setFile(File) — the file argument -# is stored on the FileSet instance, so a subsequent -# `copy.addFileset(fs)` sink that requires a tainted $FILE detects the -# flow. The File argument has a different type than FileSet, so it is -# stored in a virtual field (owned by FileSet, the object it sits on) -# instead of tainting the whole instance; the sink that consumes the -# whole FileSet still matches it by prefix. - function: org.apache.tools.ant.types.FileSet#setDir copy: - from: arg(0) to: - this - - .org.apache.tools.ant.types.FileSet##java.lang.Object + - .org.apache.tools.ant.types.FileSet#path#java.lang.Object - function: org.apache.tools.ant.types.FileSet#setFile copy: - from: arg(0) to: - this - - .org.apache.tools.ant.types.FileSet##java.lang.Object + - .org.apache.tools.ant.types.FileSet#path#java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/commons-codec-1.16.0.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/commons-codec-1.16.0.yaml index 5c87db7ed..c12bda613 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/commons-codec-1.16.0.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/commons-codec-1.16.0.yaml @@ -1,9 +1,4 @@ passThrough: -# Apache Commons Codec — Base64 encode/decode just re-codes bytes -# without disturbing the underlying tainted data, so taint should -# flow from input to output. The plain encodeBase64 / decodeBase64 -# overloads are already covered by config.yaml; only the String / URL-safe -# / chunked variants are added here. - function: org.apache.commons.codec.binary.Base64#encodeBase64String copy: - from: arg(0) diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/commons-io-2.15.1.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/commons-io-2.15.1.yaml index f5a37647d..997b79c3d 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/commons-io-2.15.1.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/commons-io-2.15.1.yaml @@ -1,8 +1,4 @@ passThrough: -# Apache Commons IO: IOUtils read helpers consume an input source -# (InputStream | Reader | URL | byte[] | char[]) given as the first -# argument and materialize its content — taint flows from that input -# source to the returned String / byte[] / char[] / List. - function: org.apache.commons.io.IOUtils#toString copy: - from: arg(0) diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml index 4239ad6c8..fc399f6d1 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/groovy-3.0.21.yaml @@ -1,16 +1,36 @@ passThrough: -# Groovy compiler: CompilationUnit.addSource(...) — the source becomes -# part of the CompilationUnit instance that is later run by .compile(), -# so the source argument taints the unit. The source is the 2nd arg of -# addSource(name, source|InputStream) but the 1st arg of the -# addSource(File) / addSource(URL) / addSource(SourceUnit) overloads, so -# copy from any argument. The argument type differs from CompilationUnit, -# so it is stored in a virtual field (owned by CompilationUnit, the -# object it sits on) rather than tainting the whole instance; a sink that -# consumes the whole unit still matches it by prefix. - function: org.codehaus.groovy.control.CompilationUnit#addSource + signature: (java.io.File) * copy: - - from: arg(*) + - from: arg(0) to: - this - - .org.codehaus.groovy.control.CompilationUnit##java.lang.Object + - .org.codehaus.groovy.control.CompilationUnit#source#java.lang.Object +- function: org.codehaus.groovy.control.CompilationUnit#addSource + signature: (java.net.URL) * + copy: + - from: arg(0) + to: + - this + - .org.codehaus.groovy.control.CompilationUnit#source#java.lang.Object +- function: org.codehaus.groovy.control.CompilationUnit#addSource + signature: (java.lang.String, java.io.InputStream) * + copy: + - from: arg(1) + to: + - this + - .org.codehaus.groovy.control.CompilationUnit#source#java.lang.Object +- function: org.codehaus.groovy.control.CompilationUnit#addSource + signature: (java.lang.String, java.lang.String) * + copy: + - from: arg(1) + to: + - this + - .org.codehaus.groovy.control.CompilationUnit#source#java.lang.Object +- function: org.codehaus.groovy.control.CompilationUnit#addSource + signature: (org.codehaus.groovy.control.SourceUnit) * + copy: + - from: arg(0) + to: + - this + - .org.codehaus.groovy.control.CompilationUnit#source#java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/httpcore5-5.2.4.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/httpcore5-5.2.4.yaml index 9409929b8..7750eb749 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/httpcore5-5.2.4.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/httpcore5-5.2.4.yaml @@ -1,13 +1,43 @@ passThrough: -# Apache HttpComponents 5 — String-arg wrapper constructor that the -# SSRF sink rules use as an inline taint carrier. The argument has a -# different type than the StringEntity, so it is stored in a virtual -# field (owned by StringEntity, the object it sits on) rather than -# tainting the whole instance; a sink that consumes the whole entity -# still matches it by prefix. - function: org.apache.hc.core5.http.io.entity.StringEntity# + signature: (java.lang.String) * copy: - - from: arg(*) + - from: arg(0) to: - this - - .org.apache.hc.core5.http.io.entity.StringEntity##java.lang.Object + - .org.apache.hc.core5.http.io.entity.StringEntity#content#java.lang.Object +- function: org.apache.hc.core5.http.io.entity.StringEntity# + signature: (java.lang.String, org.apache.hc.core5.http.ContentType) * + copy: + - from: arg(0) + to: + - this + - .org.apache.hc.core5.http.io.entity.StringEntity#content#java.lang.Object +- function: org.apache.hc.core5.http.io.entity.StringEntity# + signature: (java.lang.String, java.nio.charset.Charset) * + copy: + - from: arg(0) + to: + - this + - .org.apache.hc.core5.http.io.entity.StringEntity#content#java.lang.Object +- function: org.apache.hc.core5.http.io.entity.StringEntity# + signature: (java.lang.String, org.apache.hc.core5.http.ContentType, boolean) * + copy: + - from: arg(0) + to: + - this + - .org.apache.hc.core5.http.io.entity.StringEntity#content#java.lang.Object +- function: org.apache.hc.core5.http.io.entity.StringEntity# + signature: (java.lang.String, java.nio.charset.Charset, boolean) * + copy: + - from: arg(0) + to: + - this + - .org.apache.hc.core5.http.io.entity.StringEntity#content#java.lang.Object +- function: org.apache.hc.core5.http.io.entity.StringEntity# + signature: (java.lang.String, org.apache.hc.core5.http.ContentType, java.lang.String, boolean) * + copy: + - from: arg(0) + to: + - this + - .org.apache.hc.core5.http.io.entity.StringEntity#content#java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/jenkins-core-2.426.3.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/jenkins-core-2.426.3.yaml index b5ca04f15..83506cce8 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/jenkins-core-2.426.3.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/jenkins-core-2.426.3.yaml @@ -1,13 +1,22 @@ passThrough: -# hudson.FilePath wrapper constructor — taint flows from any -# String/File/URL argument into the constructed FilePath instance. -# The argument type differs from FilePath, so it is stored in a virtual -# field (owned by FilePath, the object it sits on) instead of tainting -# the whole object; a path-traversal sink that consumes the whole -# FilePath still matches it by prefix. - function: hudson.FilePath# + signature: (hudson.remoting.VirtualChannel, java.lang.String) * copy: - - from: arg(*) + - from: arg(1) to: - this - - .hudson.FilePath##java.lang.Object + - .hudson.FilePath#path#java.lang.Object +- function: hudson.FilePath# + signature: (java.io.File) * + copy: + - from: arg(0) + to: + - this + - .hudson.FilePath#path#java.lang.Object +- function: hudson.FilePath# + signature: (hudson.FilePath, java.lang.String) * + copy: + - from: arg(1) + to: + - this + - .hudson.FilePath#path#java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/mvel2-2.5.2.Final.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/mvel2-2.5.2.Final.yaml index 5dc56a586..0cfd91d30 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/mvel2-2.5.2.Final.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/mvel2-2.5.2.Final.yaml @@ -1,8 +1,4 @@ passThrough: -# MVEL compile / executeExpression chain — compileExpression(expr) -# returns a Serializable that's later passed to executeExpression / -# MVELRuntime.execute as a tainted compiled program. The compile -# methods just pass the input expression text through to the result. - function: org.mvel2.MVEL#compileExpression copy: - from: arg(0) @@ -15,7 +11,6 @@ passThrough: copy: - from: arg(0) to: result -# JSR-223 ScriptEngine compile / compiledScript - function: org.mvel2.jsr223.MvelScriptEngine#compile copy: - from: arg(0) diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml index 370df68f1..e986be627 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/okhttp-4.12.0.yaml @@ -1,56 +1,56 @@ passThrough: -# OkHttp Request.Builder fluent chain, e.g. -# new Request.Builder().url($X).addHeader(..).post($BODY).build() -# -# Data-bearing methods store their (differently-typed) argument into a -# virtual field instead of tainting the whole builder — this keeps -# precision (unrelated builder/request state stays untainted) while a -# sink that consumes the whole Request still matches the slot by prefix. -# The slot is owned by Request.Builder along the chain; -# since Request is not a subtype of Request.Builder, a plain this->result -# at .build() would drop the slot, so .build() re-keys it onto a -# Request-owned slot (see that entry). -# -# Each data method stores into both `result` (for chained use, -# `.url($X).build()`) and `this` (for non-chained use, `b.url($X); b.build()`), -# and carries this->result to forward taint accumulated by earlier links. -# Pure chain links carry this->result only. Library calls have no implicit -# this->result, so every link must forward the builder taint or the chain -# breaks at the first unmodeled method. - function: okhttp3.Request$Builder#url copy: - from: arg(0) to: - result - - .okhttp3.Request$Builder##java.lang.Object + - .okhttp3.Request$Builder#url#java.lang.Object - from: arg(0) to: - this - - .okhttp3.Request$Builder##java.lang.Object + - .okhttp3.Request$Builder#url#java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#header + signature: (java.lang.String, java.lang.String) * copy: - - from: arg(*) + - from: arg(0) to: - result - - .okhttp3.Request$Builder##java.lang.Object - - from: arg(*) + - .okhttp3.Request$Builder#url#java.lang.Object + - from: arg(1) + to: + - result + - .okhttp3.Request$Builder#url#java.lang.Object + - from: arg(0) to: - this - - .okhttp3.Request$Builder##java.lang.Object + - .okhttp3.Request$Builder#url#java.lang.Object + - from: arg(1) + to: + - this + - .okhttp3.Request$Builder#url#java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#addHeader + signature: (java.lang.String, java.lang.String) * copy: - - from: arg(*) + - from: arg(0) + to: + - result + - .okhttp3.Request$Builder#url#java.lang.Object + - from: arg(1) to: - result - - .okhttp3.Request$Builder##java.lang.Object - - from: arg(*) + - .okhttp3.Request$Builder#url#java.lang.Object + - from: arg(0) + to: + - this + - .okhttp3.Request$Builder#url#java.lang.Object + - from: arg(1) to: - this - - .okhttp3.Request$Builder##java.lang.Object + - .okhttp3.Request$Builder#url#java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#headers @@ -58,11 +58,11 @@ passThrough: - from: arg(0) to: - result - - .okhttp3.Request$Builder##java.lang.Object + - .okhttp3.Request$Builder#url#java.lang.Object - from: arg(0) to: - this - - .okhttp3.Request$Builder##java.lang.Object + - .okhttp3.Request$Builder#url#java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#post @@ -70,11 +70,11 @@ passThrough: - from: arg(0) to: - result - - .okhttp3.Request$Builder##java.lang.Object + - .okhttp3.Request$Builder#url#java.lang.Object - from: arg(0) to: - this - - .okhttp3.Request$Builder##java.lang.Object + - .okhttp3.Request$Builder#url#java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#put @@ -82,11 +82,11 @@ passThrough: - from: arg(0) to: - result - - .okhttp3.Request$Builder##java.lang.Object + - .okhttp3.Request$Builder#url#java.lang.Object - from: arg(0) to: - this - - .okhttp3.Request$Builder##java.lang.Object + - .okhttp3.Request$Builder#url#java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#patch @@ -94,11 +94,11 @@ passThrough: - from: arg(0) to: - result - - .okhttp3.Request$Builder##java.lang.Object + - .okhttp3.Request$Builder#url#java.lang.Object - from: arg(0) to: - this - - .okhttp3.Request$Builder##java.lang.Object + - .okhttp3.Request$Builder#url#java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#delete @@ -106,23 +106,32 @@ passThrough: - from: arg(0) to: - result - - .okhttp3.Request$Builder##java.lang.Object + - .okhttp3.Request$Builder#url#java.lang.Object - from: arg(0) to: - this - - .okhttp3.Request$Builder##java.lang.Object + - .okhttp3.Request$Builder#url#java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#method + signature: (java.lang.String, okhttp3.RequestBody) * copy: - - from: arg(*) + - from: arg(0) to: - result - - .okhttp3.Request$Builder##java.lang.Object - - from: arg(*) + - .okhttp3.Request$Builder#url#java.lang.Object + - from: arg(1) + to: + - result + - .okhttp3.Request$Builder#url#java.lang.Object + - from: arg(0) + to: + - this + - .okhttp3.Request$Builder#url#java.lang.Object + - from: arg(1) to: - this - - .okhttp3.Request$Builder##java.lang.Object + - .okhttp3.Request$Builder#url#java.lang.Object - from: this to: result - function: okhttp3.Request$Builder#get @@ -149,12 +158,9 @@ passThrough: copy: - from: this to: result - # Terminal: re-key the builder slot onto the constructed Request - # (Request is not a subtype of Request.Builder, so a plain this->result - # would drop the builder-owned slot). - from: - this - - .okhttp3.Request$Builder##java.lang.Object + - .okhttp3.Request$Builder#url#java.lang.Object to: - result - - .okhttp3.Request##java.lang.Object + - .okhttp3.Request#url#java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/spring-jdbc-5.3.39.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/spring-jdbc-5.3.39.yaml index 157a69417..caeca73fe 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/spring-jdbc-5.3.39.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/spring-jdbc-5.3.39.yaml @@ -1,9 +1,4 @@ passThrough: -# Spring JDBC: NamedParameterUtils.parseSqlStatement(sql) returns a -# ParsedSql wrapping the original SQL; substituteNamedParameters(parsedSql|sql, -# ..) then expands it back into the SQL String passed to the -# (Named)JdbcTemplate query/update sinks. Each step preserves taint from -# its SQL/ParsedSql input (arg(0)) into the result. - function: org.springframework.jdbc.core.namedparam.NamedParameterUtils#parseSqlStatement copy: - from: arg(0) diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml index fca8497a0..d1d3a426d 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/spring-ldap-core-2.4.1.yaml @@ -1,39 +1,14 @@ passThrough: -# Spring LDAP query builder chain: -# LdapQueryBuilder.query().base(dn).where(attr).is(val) ... -> LdapQuery -# -# The chain mixes the public LdapQueryBuilder/ConditionCriteria/ -# ContainerCriteria interfaces with the package-private -# DefaultConditionCriteria / DefaultContainerCriteria impls. The -# analyzer's chain-split sees the impl-class call sites, so both -# interface and impl entries are needed. -# -# Data-bearing methods store their (differently-typed) attribute/value -# argument into a virtual field instead of tainting the whole builder / -# criteria object — precise, while an LdapTemplate sink consuming the -# whole LdapQuery matches the slot by prefix. The slot is stored into -# both `result` (chained use, the dominant style here) and `this` -# (non-chained use), and each link carries this->result. -# -# The chain has no single common supertype — where() returns -# ConditionCriteria, is()/like()/... return ContainerCriteria, and()/or() -# return ConditionCriteria again — so the slot owner tracks the static -# type of each stage (LdapQueryBuilder -> ConditionCriteria -> -# ContainerCriteria), and every method that changes the type re-keys the -# incoming slot onto the new owner. A plain this->result alone would drop -# the slot at such a transition (e.g. ContainerCriteria is not a subtype -# of ConditionCriteria). LdapQueryBuilder.filter() goes straight to -# LdapQuery. - function: org.springframework.ldap.query.LdapQueryBuilder#base copy: - from: arg(0) to: - result - - .org.springframework.ldap.query.LdapQueryBuilder##java.lang.Object + - .org.springframework.ldap.query.LdapQueryBuilder#filter#java.lang.Object - from: arg(0) to: - this - - .org.springframework.ldap.query.LdapQueryBuilder##java.lang.Object + - .org.springframework.ldap.query.LdapQueryBuilder#filter#java.lang.Object - from: this to: result - function: org.springframework.ldap.query.LdapQueryBuilder#where @@ -41,144 +16,131 @@ passThrough: - from: arg(0) to: - result - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object - from: arg(0) to: - this - - .org.springframework.ldap.query.LdapQueryBuilder##java.lang.Object + - .org.springframework.ldap.query.LdapQueryBuilder#filter#java.lang.Object - from: this to: result - # Re-key: LdapQueryBuilder -> ConditionCriteria. - from: - this - - .org.springframework.ldap.query.LdapQueryBuilder##java.lang.Object + - .org.springframework.ldap.query.LdapQueryBuilder#filter#java.lang.Object to: - result - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object - function: org.springframework.ldap.query.LdapQueryBuilder#filter copy: - from: arg(0) to: - result - - .org.springframework.ldap.query.LdapQuery##java.lang.Object + - .org.springframework.ldap.query.LdapQuery#filter#java.lang.Object - from: arg(0) to: - this - - .org.springframework.ldap.query.LdapQueryBuilder##java.lang.Object + - .org.springframework.ldap.query.LdapQueryBuilder#filter#java.lang.Object - from: this to: result - # Re-key: LdapQueryBuilder -> LdapQuery. - from: - this - - .org.springframework.ldap.query.LdapQueryBuilder##java.lang.Object + - .org.springframework.ldap.query.LdapQueryBuilder#filter#java.lang.Object to: - result - - .org.springframework.ldap.query.LdapQuery##java.lang.Object + - .org.springframework.ldap.query.LdapQuery#filter#java.lang.Object - function: org.springframework.ldap.query.ConditionCriteria#is copy: - from: arg(0) to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - from: arg(0) to: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object - from: this to: result - # Re-key: ConditionCriteria -> ContainerCriteria. - from: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - function: org.springframework.ldap.query.ConditionCriteria#like copy: - from: arg(0) to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - from: arg(0) to: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object - from: this to: result - # Re-key: ConditionCriteria -> ContainerCriteria. - from: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - function: org.springframework.ldap.query.ConditionCriteria#whitespaceWildcardsLike copy: - from: arg(0) to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - from: arg(0) to: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object - from: this to: result - # Re-key: ConditionCriteria -> ContainerCriteria. - from: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - function: org.springframework.ldap.query.ConditionCriteria#gte copy: - from: arg(0) to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - from: arg(0) to: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object - from: this to: result - # Re-key: ConditionCriteria -> ContainerCriteria. - from: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - function: org.springframework.ldap.query.ConditionCriteria#lte copy: - from: arg(0) to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - from: arg(0) to: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object - from: this to: result - # Re-key: ConditionCriteria -> ContainerCriteria. - from: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object -# `.not()` is a value-less modifier that returns the same ConditionCriteria -# — pure chain carrier, no type change. + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - function: org.springframework.ldap.query.ConditionCriteria#not copy: - from: this to: result -# LdapQueryBuilder configuration methods (searchScope/countLimit/timeLimit/ -# attributes) return the builder unchanged; they are pure chain carriers -# that may appear between base() and where(), so the builder taint must -# survive across them. - function: org.springframework.ldap.query.LdapQueryBuilder#searchScope copy: - from: this @@ -195,127 +157,116 @@ passThrough: copy: - from: this to: result -# and()/or() with a String attribute return ConditionCriteria (type change -# back from ContainerCriteria); the ContainerCriteria(ContainerCriteria) -# overloads return ContainerCriteria. The this->result carry keeps the slot -# for the same-type overload, and the re-key restores it for the -# ContainerCriteria -> ConditionCriteria overload (dropped harmlessly when -# the result is still a ContainerCriteria). - function: org.springframework.ldap.query.ContainerCriteria#and copy: - from: this to: result - from: - this - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object to: - result - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object - function: org.springframework.ldap.query.ContainerCriteria#or copy: - from: this to: result - from: - this - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object to: - result - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object - function: org.springframework.ldap.query.DefaultConditionCriteria#is copy: - from: arg(0) to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - from: arg(0) to: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object - from: this to: result - # Re-key: ConditionCriteria -> ContainerCriteria. - from: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - function: org.springframework.ldap.query.DefaultConditionCriteria#like copy: - from: arg(0) to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - from: arg(0) to: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object - from: this to: result - # Re-key: ConditionCriteria -> ContainerCriteria. - from: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - function: org.springframework.ldap.query.DefaultConditionCriteria#whitespaceWildcardsLike copy: - from: arg(0) to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - from: arg(0) to: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object - from: this to: result - # Re-key: ConditionCriteria -> ContainerCriteria. - from: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - function: org.springframework.ldap.query.DefaultConditionCriteria#gte copy: - from: arg(0) to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - from: arg(0) to: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object - from: this to: result - # Re-key: ConditionCriteria -> ContainerCriteria. - from: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - function: org.springframework.ldap.query.DefaultConditionCriteria#lte copy: - from: arg(0) to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - from: arg(0) to: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object - from: this to: result - # Re-key: ConditionCriteria -> ContainerCriteria. - from: - this - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - function: org.springframework.ldap.query.DefaultConditionCriteria#not copy: - from: this @@ -324,33 +275,31 @@ passThrough: copy: - from: this to: result - # Re-key: ContainerCriteria -> ConditionCriteria (String-attr overload). - from: - this - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object to: - result - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object - function: org.springframework.ldap.query.DefaultContainerCriteria#or copy: - from: this to: result - # Re-key: ContainerCriteria -> ConditionCriteria (String-attr overload). - from: - this - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object to: - result - - .org.springframework.ldap.query.ConditionCriteria##java.lang.Object + - .org.springframework.ldap.query.ConditionCriteria#filter#java.lang.Object - function: org.springframework.ldap.query.DefaultContainerCriteria#append copy: - from: arg(0) to: - result - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - from: arg(0) to: - this - - .org.springframework.ldap.query.ContainerCriteria##java.lang.Object + - .org.springframework.ldap.query.ContainerCriteria#filter#java.lang.Object - from: this to: result diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-7.0.2.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-7.0.2.yaml index eb427416d..5b4e09907 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-7.0.2.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/spring-web-7.0.2.yaml @@ -33,18 +33,755 @@ passThrough: to: - this - .org.springframework.http.HttpEntity#Body#java.lang.Object -- function: - package: org.springframework.http - class: HttpHeaders - name: - pattern: set.+ +- function: org.springframework.http.HttpHeaders#set + signature: (java.lang.String, java.lang.String) void copy: - from: arg(0) to: - this - - .org.springframework.http.HttpHeaders##java.lang.Object + - .org.springframework.http.HttpHeaders#DynamicHeader#java.lang.Object + - from: arg(1) + to: + - this + - .org.springframework.http.HttpHeaders#DynamicHeader#java.lang.Object + - from: arg(0) + to: this + - from: arg(1) + to: this +- function: org.springframework.http.HttpHeaders#add + signature: (java.lang.String, java.lang.String) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#DynamicHeader#java.lang.Object + - from: arg(1) + to: + - this + - .org.springframework.http.HttpHeaders#DynamicHeader#java.lang.Object + - from: arg(0) + to: this + - from: arg(1) + to: this +- function: org.springframework.http.HttpHeaders#setAll + signature: (java.util.Map) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#DynamicHeader#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setAccept + signature: (java.util.List) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Accept#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setAcceptCharset + signature: (java.util.List) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#AcceptCharset#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setAcceptLanguage + signature: (java.util.List) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#AcceptLanguage#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setAcceptLanguageAsLocales + signature: (java.util.List) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#AcceptLanguageAsLocales#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setAcceptPatch + signature: (java.util.List) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#AcceptPatch#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setAccessControlAllowCredentials + signature: (boolean) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#AccessControlAllowCredentials#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setAccessControlAllowHeaders + signature: (java.util.List) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#AccessControlAllowHeaders#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setAccessControlAllowMethods + signature: (java.util.List) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#AccessControlAllowMethods#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setAccessControlAllowOrigin + signature: (java.lang.String) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#AccessControlAllowOrigin#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setAccessControlExposeHeaders + signature: (java.util.List) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#AccessControlExposeHeaders#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setAccessControlMaxAge + signature: (java.time.Duration) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#AccessControlMaxAge#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setAccessControlMaxAge + signature: (long) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#AccessControlMaxAge#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setAccessControlRequestHeaders + signature: (java.util.List) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#AccessControlRequestHeaders#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setAccessControlRequestMethod + signature: (org.springframework.http.HttpMethod) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#AccessControlRequestMethod#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setAllow + signature: (java.util.Set) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Allow#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setBasicAuth + signature: (java.lang.String) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Authorization#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setBasicAuth + signature: (java.lang.String, java.lang.String) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Authorization#java.lang.Object + - from: arg(1) + to: + - this + - .org.springframework.http.HttpHeaders#Authorization#java.lang.Object + - from: arg(0) + to: this + - from: arg(1) + to: this +- function: org.springframework.http.HttpHeaders#setBasicAuth + signature: (java.lang.String, java.lang.String, java.nio.charset.Charset) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Authorization#java.lang.Object + - from: arg(1) + to: + - this + - .org.springframework.http.HttpHeaders#Authorization#java.lang.Object + - from: arg(0) + to: this + - from: arg(1) + to: this +- function: org.springframework.http.HttpHeaders#setBearerAuth + signature: (java.lang.String) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Authorization#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setCacheControl + signature: (org.springframework.http.CacheControl) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#CacheControl#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setCacheControl + signature: (java.lang.String) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#CacheControl#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setConnection + signature: (java.util.List) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Connection#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setConnection + signature: (java.lang.String) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Connection#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setContentDisposition + signature: (org.springframework.http.ContentDisposition) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#ContentDisposition#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setContentDispositionFormData + signature: (java.lang.String, java.lang.String) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#ContentDisposition#java.lang.Object + - from: arg(1) + to: + - this + - .org.springframework.http.HttpHeaders#ContentDisposition#java.lang.Object + - from: arg(0) + to: this + - from: arg(1) + to: this +- function: org.springframework.http.HttpHeaders#setContentLanguage + signature: (java.util.Locale) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#ContentLanguage#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setContentLength + signature: (long) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#ContentLength#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setContentType + signature: (org.springframework.http.MediaType) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#ContentType#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setDate + signature: (java.time.Instant) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Date#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setDate + signature: (long) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Date#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setDate + signature: (java.lang.String, long) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#DynamicHeader#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setDate + signature: (java.time.ZonedDateTime) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Date#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setETag + signature: (java.lang.String) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#ETag#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setExpires + signature: (java.time.Instant) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Expires#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setExpires + signature: (long) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Expires#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setExpires + signature: (java.time.ZonedDateTime) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Expires#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setHost + signature: (java.net.InetSocketAddress) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Host#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setIfMatch + signature: (java.util.List) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#IfMatch#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setIfMatch + signature: (java.lang.String) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#IfMatch#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setIfModifiedSince + signature: (java.time.Instant) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#IfModifiedSince#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setIfModifiedSince + signature: (long) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#IfModifiedSince#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setIfModifiedSince + signature: (java.time.ZonedDateTime) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#IfModifiedSince#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setIfNoneMatch + signature: (java.util.List) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#IfNoneMatch#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setIfNoneMatch + signature: (java.lang.String) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#IfNoneMatch#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setIfUnmodifiedSince + signature: (java.time.Instant) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#IfUnmodifiedSince#java.lang.Object - from: arg(0) to: this +- function: org.springframework.http.HttpHeaders#setIfUnmodifiedSince + signature: (long) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#IfUnmodifiedSince#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setIfUnmodifiedSince + signature: (java.time.ZonedDateTime) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#IfUnmodifiedSince#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setInstant + signature: (java.lang.String, java.time.Instant) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#DynamicHeader#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setLastModified + signature: (java.time.Instant) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#LastModified#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setLastModified + signature: (long) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#LastModified#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setLastModified + signature: (java.time.ZonedDateTime) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#LastModified#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setLocation + signature: (java.net.URI) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Location#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setOrigin + signature: (java.lang.String) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Origin#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setPragma + signature: (java.lang.String) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Pragma#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setRange + signature: (java.util.List) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Range#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setUpgrade + signature: (java.lang.String) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Upgrade#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setVary + signature: (java.util.List) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#Vary#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#setZonedDateTime + signature: (java.lang.String, java.time.ZonedDateTime) void + copy: + - from: arg(0) + to: + - this + - .org.springframework.http.HttpHeaders#DynamicHeader#java.lang.Object + - from: arg(0) + to: this +- function: org.springframework.http.HttpHeaders#get + signature: (java.lang.String) * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#DynamicHeader#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getFirst + signature: (java.lang.String) * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#DynamicHeader#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getValuesAsList + signature: (java.lang.String) * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#DynamicHeader#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getOrEmpty + signature: (java.lang.String) * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#DynamicHeader#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getOrDefault + signature: (java.lang.String, java.util.List) * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#DynamicHeader#java.lang.Object + to: result + - from: arg(1) + to: result +- function: org.springframework.http.HttpHeaders#getAccept + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#Accept#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getAcceptPatch + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#AcceptPatch#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getAccessControlAllowHeaders + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#AccessControlAllowHeaders#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getAccessControlAllowOrigin + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#AccessControlAllowOrigin#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getAccessControlExposeHeaders + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#AccessControlExposeHeaders#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getAccessControlRequestHeaders + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#AccessControlRequestHeaders#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getCacheControl + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#CacheControl#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getConnection + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#Connection#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getContentDisposition + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#ContentDisposition#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getContentType + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#ContentType#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getETag + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#ETag#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getHost + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#Host#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getIfMatch + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#IfMatch#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getIfNoneMatch + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#IfNoneMatch#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getLocation + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#Location#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getOrigin + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#Origin#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getPragma + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#Pragma#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getUpgrade + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#Upgrade#java.lang.Object + to: result +- function: org.springframework.http.HttpHeaders#getVary + signature: () * + copy: + - from: + - this + - .org.springframework.http.HttpHeaders#Vary#java.lang.Object + to: result - function: org.springframework.http.RequestEntity$BodyBuilder#body copy: - from: arg(0) @@ -53,14 +790,12 @@ passThrough: copy: - from: this to: result - # Terminal: re-key the builder slot onto the constructed RequestEntity - # (same reason as HeadersBuilder#build above). - from: - this - - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object to: - result - - .org.springframework.http.RequestEntity##java.lang.Object + - .org.springframework.http.RequestEntity#url#java.lang.Object - function: org.springframework.http.RequestEntity$BodyBuilder#contentLength copy: - from: this @@ -81,15 +816,12 @@ passThrough: copy: - from: this to: result - # Terminal: re-key the builder slot onto the constructed RequestEntity - # (HeadersBuilder is not a subtype of RequestEntity, so a plain - # this->result would drop the builder-owned slot). - from: - this - - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object to: - result - - .org.springframework.http.RequestEntity##java.lang.Object + - .org.springframework.http.RequestEntity#url#java.lang.Object - function: org.springframework.http.RequestEntity$HeadersBuilder#header copy: - from: arg(0) @@ -114,31 +846,66 @@ passThrough: copy: - from: this to: result -# RequestEntity.get/post/... are STATIC factories taking the URI as the -# first argument (HttpMethod, URI for method()); a this->result copy is a -# no-op for them. Carry the URI argument into the returned builder's -# slot (owner HeadersBuilder, which also covers BodyBuilder -# since it extends HeadersBuilder). The chain methods carry this->result, -# and the terminals .build() / .body() re-key the builder slot into the -# RequestEntity# slot (see those entries). - function: org.springframework.http.RequestEntity#delete + signature: (java.net.URI) * + copy: + - from: arg(0) + to: + - result + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object +- function: org.springframework.http.RequestEntity#delete + signature: (java.lang.String, java.lang.Object[]) * + copy: + - from: arg(0) + to: + - result + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object + - from: arg(1) + to: + - result + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object +- function: org.springframework.http.RequestEntity#get + signature: (java.net.URI) * copy: - from: arg(0) to: - result - - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object - function: org.springframework.http.RequestEntity#get + signature: (java.lang.String, java.lang.Object[]) * + copy: + - from: arg(0) + to: + - result + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object + - from: arg(1) + to: + - result + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object +- function: org.springframework.http.RequestEntity#getUrl + copy: + - from: + - this + - .org.springframework.http.RequestEntity#url#java.lang.Object + to: result +- function: org.springframework.http.RequestEntity#head + signature: (java.net.URI) * copy: - from: arg(0) to: - result - - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object - function: org.springframework.http.RequestEntity#head + signature: (java.lang.String, java.lang.Object[]) * copy: - from: arg(0) to: - result - - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object + - from: arg(1) + to: + - result + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object - function: org.springframework.http.RequestEntity# copy: - from: arg(1) @@ -146,43 +913,114 @@ passThrough: - from: arg(0) to: - this - - .org.springframework.http.RequestEntity##java.lang.Object + - .org.springframework.http.RequestEntity#url#java.lang.Object - from: arg(0) to: this - from: arg(1) to: - this - - .org.springframework.http.RequestEntity##java.lang.Object + - .org.springframework.http.RequestEntity#url#java.lang.Object - function: org.springframework.http.RequestEntity#method + signature: (org.springframework.http.HttpMethod, java.net.URI) * copy: - - from: arg(*) + - from: arg(1) + to: + - result + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object +- function: org.springframework.http.RequestEntity#method + signature: (org.springframework.http.HttpMethod, java.lang.String, java.lang.Object[]) * + copy: + - from: arg(1) + to: + - result + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object + - from: arg(2) + to: + - result + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object +- function: org.springframework.http.RequestEntity#method + signature: (org.springframework.http.HttpMethod, java.lang.String, java.util.Map) * + copy: + - from: arg(1) + to: + - result + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object + - from: arg(2) to: - result - - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object - function: org.springframework.http.RequestEntity#options + signature: (java.net.URI) * copy: - from: arg(0) to: - result - - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object +- function: org.springframework.http.RequestEntity#options + signature: (java.lang.String, java.lang.Object[]) * + copy: + - from: arg(0) + to: + - result + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object + - from: arg(1) + to: + - result + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object - function: org.springframework.http.RequestEntity#patch + signature: (java.net.URI) * + copy: + - from: arg(0) + to: + - result + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object +- function: org.springframework.http.RequestEntity#patch + signature: (java.lang.String, java.lang.Object[]) * + copy: + - from: arg(0) + to: + - result + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object + - from: arg(1) + to: + - result + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object +- function: org.springframework.http.RequestEntity#post + signature: (java.net.URI) * copy: - from: arg(0) to: - result - - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object - function: org.springframework.http.RequestEntity#post + signature: (java.lang.String, java.lang.Object[]) * + copy: + - from: arg(0) + to: + - result + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object + - from: arg(1) + to: + - result + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object +- function: org.springframework.http.RequestEntity#put + signature: (java.net.URI) * copy: - from: arg(0) to: - result - - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object - function: org.springframework.http.RequestEntity#put + signature: (java.lang.String, java.lang.Object[]) * copy: - from: arg(0) to: - result - - .org.springframework.http.RequestEntity$HeadersBuilder##java.lang.Object + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object + - from: arg(1) + to: + - result + - .org.springframework.http.RequestEntity$HeadersBuilder#url#java.lang.Object - function: org.springframework.http.ResponseEntity$BodyBuilder#body copy: - from: arg(0) diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/unboundid-ldapsdk-6.0.11.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/unboundid-ldapsdk-6.0.11.yaml index 73f048b5d..be38120c6 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/unboundid-ldapsdk-6.0.11.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/unboundid-ldapsdk-6.0.11.yaml @@ -1,12 +1,166 @@ passThrough: -# com.unboundid.ldap.sdk.SearchRequest constructor — the base DN / filter -# arguments have a different type than SearchRequest, so they are stored -# in a virtual field (owned by SearchRequest, the object it sits on) -# rather than tainting the whole instance; an LDAP sink that consumes the -# whole SearchRequest still matches it by prefix. - function: com.unboundid.ldap.sdk.SearchRequest# + signature: (java.lang.String, com.unboundid.ldap.sdk.SearchScope, java.lang.String, java.lang.String[]) * copy: - - from: arg(*) + - from: arg(0) to: - this - - .com.unboundid.ldap.sdk.SearchRequest##java.lang.Object + - .com.unboundid.ldap.sdk.SearchRequest#baseDN#java.lang.Object + - from: arg(2) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#filter#java.lang.Object + - from: arg(3) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#attributes#java.lang.Object +- function: com.unboundid.ldap.sdk.SearchRequest# + signature: (java.lang.String, com.unboundid.ldap.sdk.SearchScope, com.unboundid.ldap.sdk.Filter, java.lang.String[]) * + copy: + - from: arg(0) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#baseDN#java.lang.Object + - from: arg(3) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#attributes#java.lang.Object +- function: com.unboundid.ldap.sdk.SearchRequest# + signature: (com.unboundid.ldap.sdk.DN, com.unboundid.ldap.sdk.SearchScope, com.unboundid.ldap.sdk.Filter, java.lang.String[]) * + copy: + - from: arg(3) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#attributes#java.lang.Object +- function: com.unboundid.ldap.sdk.SearchRequest# + signature: (com.unboundid.ldap.sdk.SearchResultListener, java.lang.String, com.unboundid.ldap.sdk.SearchScope, java.lang.String, java.lang.String[]) * + copy: + - from: arg(1) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#baseDN#java.lang.Object + - from: arg(3) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#filter#java.lang.Object + - from: arg(4) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#attributes#java.lang.Object +- function: com.unboundid.ldap.sdk.SearchRequest# + signature: (com.unboundid.ldap.sdk.SearchResultListener, java.lang.String, com.unboundid.ldap.sdk.SearchScope, com.unboundid.ldap.sdk.Filter, java.lang.String[]) * + copy: + - from: arg(1) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#baseDN#java.lang.Object + - from: arg(4) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#attributes#java.lang.Object +- function: com.unboundid.ldap.sdk.SearchRequest# + signature: (com.unboundid.ldap.sdk.SearchResultListener, com.unboundid.ldap.sdk.DN, com.unboundid.ldap.sdk.SearchScope, com.unboundid.ldap.sdk.Filter, java.lang.String[]) * + copy: + - from: arg(4) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#attributes#java.lang.Object +- function: com.unboundid.ldap.sdk.SearchRequest# + signature: (java.lang.String, com.unboundid.ldap.sdk.SearchScope, com.unboundid.ldap.sdk.DereferencePolicy, int, int, boolean, java.lang.String, java.lang.String[]) * + copy: + - from: arg(0) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#baseDN#java.lang.Object + - from: arg(6) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#filter#java.lang.Object + - from: arg(7) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#attributes#java.lang.Object +- function: com.unboundid.ldap.sdk.SearchRequest# + signature: (java.lang.String, com.unboundid.ldap.sdk.SearchScope, com.unboundid.ldap.sdk.DereferencePolicy, int, int, boolean, com.unboundid.ldap.sdk.Filter, java.lang.String[]) * + copy: + - from: arg(0) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#baseDN#java.lang.Object + - from: arg(7) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#attributes#java.lang.Object +- function: com.unboundid.ldap.sdk.SearchRequest# + signature: (com.unboundid.ldap.sdk.DN, com.unboundid.ldap.sdk.SearchScope, com.unboundid.ldap.sdk.DereferencePolicy, int, int, boolean, com.unboundid.ldap.sdk.Filter, java.lang.String[]) * + copy: + - from: arg(7) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#attributes#java.lang.Object +- function: com.unboundid.ldap.sdk.SearchRequest# + signature: (com.unboundid.ldap.sdk.SearchResultListener, java.lang.String, com.unboundid.ldap.sdk.SearchScope, com.unboundid.ldap.sdk.DereferencePolicy, int, int, boolean, java.lang.String, java.lang.String[]) * + copy: + - from: arg(1) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#baseDN#java.lang.Object + - from: arg(7) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#filter#java.lang.Object + - from: arg(8) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#attributes#java.lang.Object +- function: com.unboundid.ldap.sdk.SearchRequest# + signature: (com.unboundid.ldap.sdk.SearchResultListener, java.lang.String, com.unboundid.ldap.sdk.SearchScope, com.unboundid.ldap.sdk.DereferencePolicy, int, int, boolean, com.unboundid.ldap.sdk.Filter, java.lang.String[]) * + copy: + - from: arg(1) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#baseDN#java.lang.Object + - from: arg(8) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#attributes#java.lang.Object +- function: com.unboundid.ldap.sdk.SearchRequest# + signature: (com.unboundid.ldap.sdk.SearchResultListener, com.unboundid.ldap.sdk.DN, com.unboundid.ldap.sdk.SearchScope, com.unboundid.ldap.sdk.DereferencePolicy, int, int, boolean, com.unboundid.ldap.sdk.Filter, java.lang.String[]) * + copy: + - from: arg(8) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#attributes#java.lang.Object +- function: com.unboundid.ldap.sdk.SearchRequest# + signature: (com.unboundid.ldap.sdk.SearchResultListener, com.unboundid.ldap.sdk.Control[], java.lang.String, com.unboundid.ldap.sdk.SearchScope, com.unboundid.ldap.sdk.DereferencePolicy, int, int, boolean, java.lang.String, java.lang.String[]) * + copy: + - from: arg(2) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#baseDN#java.lang.Object + - from: arg(8) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#filter#java.lang.Object + - from: arg(9) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#attributes#java.lang.Object +- function: com.unboundid.ldap.sdk.SearchRequest# + signature: (com.unboundid.ldap.sdk.SearchResultListener, com.unboundid.ldap.sdk.Control[], java.lang.String, com.unboundid.ldap.sdk.SearchScope, com.unboundid.ldap.sdk.DereferencePolicy, int, int, boolean, com.unboundid.ldap.sdk.Filter, java.lang.String[]) * + copy: + - from: arg(2) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#baseDN#java.lang.Object + - from: arg(9) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#attributes#java.lang.Object +- function: com.unboundid.ldap.sdk.SearchRequest# + signature: (com.unboundid.ldap.sdk.SearchResultListener, com.unboundid.ldap.sdk.Control[], com.unboundid.ldap.sdk.DN, com.unboundid.ldap.sdk.SearchScope, com.unboundid.ldap.sdk.DereferencePolicy, int, int, boolean, com.unboundid.ldap.sdk.Filter, java.lang.String[]) * + copy: + - from: arg(9) + to: + - this + - .com.unboundid.ldap.sdk.SearchRequest#attributes#java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml b/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml index f96c0a46a..d78915169 100644 --- a/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml +++ b/core/opentaint-config/java-config/config/java-config/jar-split/velocity-engine-core-2.3.yaml @@ -1,31 +1,19 @@ passThrough: -# Apache Velocity: Context.put($k, $v) — the value argument is stored on -# the context instance, so a tainted value carried into the context -# reaches a subsequent VelocityEngine.evaluate / Template.merge sink that -# consumes the whole context. The value type differs from the context, -# so it is stored in a virtual field rather than tainting the whole -# instance (which would over-taint every other entry read back out of -# the context); the sink that consumes the whole context still matches it -# by prefix. Entries cover the Context interface, the AbstractContext -# super-class and the concrete VelocityContext, since the call site may -# be typed to any of them. The slot is owned by the Context interface, -# which all three receivers implement, so it is accepted on whichever -# static type the call site uses. - function: org.apache.velocity.context.Context#put copy: - from: arg(1) to: - this - - .org.apache.velocity.context.Context##java.lang.Object + - .org.apache.velocity.context.Context#value#java.lang.Object - function: org.apache.velocity.VelocityContext#put copy: - from: arg(1) to: - this - - .org.apache.velocity.context.Context##java.lang.Object + - .org.apache.velocity.context.Context#value#java.lang.Object - function: org.apache.velocity.context.AbstractContext#put copy: - from: arg(1) to: - this - - .org.apache.velocity.context.Context##java.lang.Object + - .org.apache.velocity.context.Context#value#java.lang.Object diff --git a/core/opentaint-config/java-config/config/java-config/stdlib.yaml b/core/opentaint-config/java-config/config/java-config/stdlib.yaml index 168b33631..c2dda66c1 100644 --- a/core/opentaint-config/java-config/config/java-config/stdlib.yaml +++ b/core/opentaint-config/java-config/config/java-config/stdlib.yaml @@ -21359,9 +21359,6 @@ passThrough: - this - .java.io.InputStream##java.lang.Object -# ── Iterator / Iterable (whole-collection -> iterator/element; existing -# sig-specific entries only model element-level vf, so these add the -# whole-object carry) ────────────────────────────────────────────── - function: java.lang.Iterable#iterator copy: - from: this @@ -21371,7 +21368,6 @@ passThrough: - from: this to: result -# ── java.util.Base64$Encoder ────────────────────────────────────────── - function: java.util.Base64$Encoder#encodeToString copy: - from: arg(0) @@ -21385,88 +21381,117 @@ passThrough: - from: arg(0) to: result -# ── javax.management JMX (stdlib management API) — the URL/service args -# have different types than the JMXServiceURL / JMXConnector they end -# up in, so they are stored in virtual fields rather than tainting the -# whole instance; a sink consuming the whole object matches by prefix. - function: javax.management.remote.JMXServiceURL# + signature: (java.lang.String) * copy: - - from: arg(*) + - from: arg(0) + to: + - this + - .javax.management.remote.JMXServiceURL#url#java.lang.Object +- function: javax.management.remote.JMXServiceURL# + signature: (java.lang.String, java.lang.String, int) * + copy: + - from: arg(0) + to: + - this + - .javax.management.remote.JMXServiceURL#url#java.lang.Object + - from: arg(1) + to: + - this + - .javax.management.remote.JMXServiceURL#url#java.lang.Object +- function: javax.management.remote.JMXServiceURL# + signature: (java.lang.String, java.lang.String, int, java.lang.String) * + copy: + - from: arg(0) + to: + - this + - .javax.management.remote.JMXServiceURL#url#java.lang.Object + - from: arg(1) + to: + - this + - .javax.management.remote.JMXServiceURL#url#java.lang.Object + - from: arg(3) to: - this - - .javax.management.remote.JMXServiceURL##java.lang.Object + - .javax.management.remote.JMXServiceURL#url#java.lang.Object - function: javax.management.remote.JMXConnectorFactory#newJMXConnector copy: - from: arg(0) to: - result - - .javax.management.remote.JMXConnector##java.lang.Object + - .javax.management.remote.JMXConnector#url#java.lang.Object -# ── java.net.http.HttpRequest$Builder (Java 11+ HttpClient) ─────────── -# Fluent chain, e.g. -# HttpRequest.newBuilder(URI.create($X)).header(..).GET().build() -# Data-bearing methods store their (differently-typed) argument into a -# virtual field instead of tainting the whole builder — precise, while a -# sink consuming the whole HttpRequest matches the slot by prefix. The -# slot is owned by HttpRequest.Builder along the chain; -# since HttpRequest is not a subtype of HttpRequest.Builder, a plain -# this->result at .build() would drop the slot, so .build() re-keys it -# onto an HttpRequest-owned slot (see that entry). Each data method stores -# into both `result` (chained use) and `this` (non-chained use) and -# carries this->result; pure links carry this->result only (no implicit -# this->result exists for library calls). - function: java.net.http.HttpRequest#newBuilder copy: - from: arg(0) to: - result - - .java.net.http.HttpRequest$Builder##java.lang.Object + - .java.net.http.HttpRequest$Builder#url#java.lang.Object - function: java.net.http.HttpRequest$Builder#uri copy: - from: arg(0) to: - result - - .java.net.http.HttpRequest$Builder##java.lang.Object + - .java.net.http.HttpRequest$Builder#url#java.lang.Object - from: arg(0) to: - this - - .java.net.http.HttpRequest$Builder##java.lang.Object + - .java.net.http.HttpRequest$Builder#url#java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#header + signature: (java.lang.String, java.lang.String) * copy: - - from: arg(*) + - from: arg(0) to: - result - - .java.net.http.HttpRequest$Builder##java.lang.Object - - from: arg(*) + - .java.net.http.HttpRequest$Builder#url#java.lang.Object + - from: arg(1) + to: + - result + - .java.net.http.HttpRequest$Builder#url#java.lang.Object + - from: arg(0) to: - this - - .java.net.http.HttpRequest$Builder##java.lang.Object + - .java.net.http.HttpRequest$Builder#url#java.lang.Object + - from: arg(1) + to: + - this + - .java.net.http.HttpRequest$Builder#url#java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#headers + signature: (java.lang.String[]) * copy: - - from: arg(*) + - from: arg(0) to: - result - - .java.net.http.HttpRequest$Builder##java.lang.Object - - from: arg(*) + - .java.net.http.HttpRequest$Builder#url#java.lang.Object + - from: arg(0) to: - this - - .java.net.http.HttpRequest$Builder##java.lang.Object + - .java.net.http.HttpRequest$Builder#url#java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#setHeader + signature: (java.lang.String, java.lang.String) * copy: - - from: arg(*) + - from: arg(0) to: - result - - .java.net.http.HttpRequest$Builder##java.lang.Object - - from: arg(*) + - .java.net.http.HttpRequest$Builder#url#java.lang.Object + - from: arg(1) + to: + - result + - .java.net.http.HttpRequest$Builder#url#java.lang.Object + - from: arg(0) to: - this - - .java.net.http.HttpRequest$Builder##java.lang.Object + - .java.net.http.HttpRequest$Builder#url#java.lang.Object + - from: arg(1) + to: + - this + - .java.net.http.HttpRequest$Builder#url#java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#POST @@ -21474,11 +21499,11 @@ passThrough: - from: arg(0) to: - result - - .java.net.http.HttpRequest$Builder##java.lang.Object + - .java.net.http.HttpRequest$Builder#url#java.lang.Object - from: arg(0) to: - this - - .java.net.http.HttpRequest$Builder##java.lang.Object + - .java.net.http.HttpRequest$Builder#url#java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#PUT @@ -21486,23 +21511,32 @@ passThrough: - from: arg(0) to: - result - - .java.net.http.HttpRequest$Builder##java.lang.Object + - .java.net.http.HttpRequest$Builder#url#java.lang.Object - from: arg(0) to: - this - - .java.net.http.HttpRequest$Builder##java.lang.Object + - .java.net.http.HttpRequest$Builder#url#java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#method + signature: (java.lang.String, java.net.http.HttpRequest$BodyPublisher) * copy: - - from: arg(*) + - from: arg(0) to: - result - - .java.net.http.HttpRequest$Builder##java.lang.Object - - from: arg(*) + - .java.net.http.HttpRequest$Builder#url#java.lang.Object + - from: arg(1) + to: + - result + - .java.net.http.HttpRequest$Builder#url#java.lang.Object + - from: arg(0) + to: + - this + - .java.net.http.HttpRequest$Builder#url#java.lang.Object + - from: arg(1) to: - this - - .java.net.http.HttpRequest$Builder##java.lang.Object + - .java.net.http.HttpRequest$Builder#url#java.lang.Object - from: this to: result - function: java.net.http.HttpRequest$Builder#DELETE @@ -21533,12 +21567,9 @@ passThrough: copy: - from: this to: result - # Terminal: re-key the builder slot onto the constructed HttpRequest - # (HttpRequest is not a subtype of HttpRequest.Builder, so a plain - # this->result would drop the builder-owned slot). - from: - this - - .java.net.http.HttpRequest$Builder##java.lang.Object + - .java.net.http.HttpRequest$Builder#url#java.lang.Object to: - result - - .java.net.http.HttpRequest##java.lang.Object + - .java.net.http.HttpRequest#url#java.lang.Object