From 7f86f8cac71aa4adee3e364cfdb467d4335ab017 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Mon, 4 Nov 2024 11:21:42 +0100 Subject: [PATCH 01/11] Java: Prepare TypeFlow for separate instantiation of universal flow. --- .../semmle/code/java/dataflow/TypeFlow.qll | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll b/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll index c548c5db38b..f9046b1b65e 100644 --- a/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll @@ -13,24 +13,25 @@ private import semmle.code.java.dispatch.VirtualDispatch private import semmle.code.java.dataflow.internal.BaseSSA private import semmle.code.java.controlflow.Guards private import codeql.typeflow.TypeFlow +private import codeql.typeflow.UniversalFlow as UniversalFlow -private module Input implements TypeFlowInput { - private newtype TTypeFlowNode = +/** Gets `t` if it is a `RefType` or the boxed type if `t` is a primitive type. */ +private RefType boxIfNeeded(J::Type t) { + t.(PrimitiveType).getBoxedType() = result or + result = t +} + +module FlowStepsInput implements UniversalFlow::UniversalFlowInput { + private newtype TFlowNode = TField(Field f) { not f.getType() instanceof PrimitiveType } or TSsa(BaseSsaVariable ssa) { not ssa.getSourceVariable().getType() instanceof PrimitiveType } or TExpr(Expr e) or TMethod(Method m) { not m.getReturnType() instanceof PrimitiveType } - /** Gets `t` if it is a `RefType` or the boxed type if `t` is a primitive type. */ - private RefType boxIfNeeded(J::Type t) { - t.(PrimitiveType).getBoxedType() = result or - result = t - } - /** * A `Field`, `BaseSsaVariable`, `Expr`, or `Method`. */ - class TypeFlowNode extends TTypeFlowNode { + class FlowNode extends TFlowNode { string toString() { result = this.asField().toString() or result = this.asSsa().toString() or @@ -61,8 +62,6 @@ private module Input implements TypeFlowInput { } } - class Type = RefType; - private SrcCallable viableCallable_v1(Call c) { result = viableImpl_v1(c) or @@ -88,7 +87,7 @@ private module Input implements TypeFlowInput { * * For a given `n2`, this predicate must include all possible `n1` that can flow to `n2`. */ - predicate step(TypeFlowNode n1, TypeFlowNode n2) { + predicate step(FlowNode n1, FlowNode n2) { n2.asExpr().(ChooseExpr).getAResultExpr() = n1.asExpr() or exists(Field f, Expr e | @@ -134,7 +133,7 @@ private module Input implements TypeFlowInput { /** * Holds if `null` is the only value that flows to `n`. */ - predicate isNullValue(TypeFlowNode n) { + predicate isNullValue(FlowNode n) { n.asExpr() instanceof NullLiteral or exists(LocalVariableDeclExpr decl | @@ -144,11 +143,21 @@ private module Input implements TypeFlowInput { ) } - predicate isExcludedFromNullAnalysis(TypeFlowNode n) { + predicate isExcludedFromNullAnalysis(FlowNode n) { // Fields that are never assigned a non-null value are probably set by // reflection and are thus not always null. exists(n.asField()) } +} + +private module Input implements TypeFlowInput { + import FlowStepsInput + + class TypeFlowNode = FlowNode; + + predicate isExcludedFromNullAnalysis = FlowStepsInput::isExcludedFromNullAnalysis/1; + + class Type = RefType; predicate exactTypeBase(TypeFlowNode n, RefType t) { exists(ClassInstanceExpr e | From 6f32c4129d074a6087d7a6002293c1b8de3a213d Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Mon, 4 Nov 2024 14:09:36 +0100 Subject: [PATCH 02/11] Java: Add a default taint sanitizer for contains-checks on lists of constants. --- .../semmle/code/java/dataflow/FlowSteps.qll | 6 + .../dataflow/internal/TaintTrackingUtil.qll | 1 + .../security/ListOfConstantsSanitizer.qll | 259 ++++++++++++++++++ 3 files changed, 266 insertions(+) create mode 100644 java/ql/lib/semmle/code/java/security/ListOfConstantsSanitizer.qll diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll index e7d34d166b1..c931817e00b 100644 --- a/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll +++ b/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll @@ -28,6 +28,7 @@ private module Frameworks { private import semmle.code.java.frameworks.ThreadLocal private import semmle.code.java.frameworks.ratpack.RatpackExec private import semmle.code.java.frameworks.stapler.Stapler + private import semmle.code.java.security.ListOfConstantsSanitizer } /** @@ -189,3 +190,8 @@ private class NumberTaintPreservingCallable extends TaintPreservingCallable { * map-key and map-value content, so that e.g. a tainted `Map` is assumed to have tainted keys and values. */ abstract class TaintInheritingContent extends DataFlow::Content { } + +/** + * A sanitizer in all global taint flow configurations but not in local taint. + */ +abstract class DefaultTaintSanitizer extends DataFlow::Node { } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index ad770b75a3e..1c7db851a2c 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -161,6 +161,7 @@ private module Cached { */ cached predicate defaultTaintSanitizer(DataFlow::Node node) { + node instanceof DefaultTaintSanitizer or // Ignore paths through test code. node.getEnclosingCallable().getDeclaringType() instanceof NonSecurityTestClass or node.asExpr() instanceof ValidatedVariableAccess diff --git a/java/ql/lib/semmle/code/java/security/ListOfConstantsSanitizer.qll b/java/ql/lib/semmle/code/java/security/ListOfConstantsSanitizer.qll new file mode 100644 index 00000000000..0b6e3441802 --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/ListOfConstantsSanitizer.qll @@ -0,0 +1,259 @@ +/** + * Provides a default taint sanitizer identifying comparisons against lists of + * compile-time constants. + */ + +import java +private import codeql.typeflow.UniversalFlow as UniversalFlow +private import semmle.code.java.Collections +private import semmle.code.java.controlflow.Guards +private import semmle.code.java.dataflow.internal.BaseSSA +private import semmle.code.java.dataflow.TaintTracking +private import semmle.code.java.dataflow.TypeFlow +private import semmle.code.java.dispatch.VirtualDispatch + +private class FlowNode = FlowStepsInput::FlowNode; + +/** + * Holds if `n2` is an unmodifiable collection constructed from input `n1`, + * which is either another collection or a number of elements. + */ +private predicate unmodifiableCollectionStep(FlowNode n1, FlowNode n2) { + exists(Call c, Callable tgt | + n2.asExpr() = c and + n1.asExpr() = c.getAnArgument() and + c.getCallee().getSourceDeclaration() = tgt + | + tgt.hasQualifiedName("java.util", "Collections", + ["unmodifiableCollection", "unmodifiableList", "unmodifiableSet"]) + or + tgt.hasQualifiedName("java.util", ["List", "Set"], ["copyOf", "of"]) + or + tgt.hasQualifiedName("com.google.common.collect", ["ImmutableList", "ImmutableSet"], + ["copyOf", "of"]) + ) +} + +/** + * Holds if `n2` is a collection or array constructed from input `n1`, which is + * either a collection, an array, or a number of elements. + */ +private predicate collectionStep(FlowNode n1, FlowNode n2) { + n2.asExpr().(ArrayInit).getAnInit() = n1.asExpr() + or + n2.asExpr().(ArrayCreationExpr).getInit() = n1.asExpr() + or + unmodifiableCollectionStep(n1, n2) + or + exists(Call c, Callable tgt | + n2.asExpr() = c and + n1.asExpr() = c.getAnArgument() and + c.getCallee().getSourceDeclaration() = tgt + | + tgt.hasQualifiedName("java.util", "Arrays", "asList") + or + tgt.isStatic() and + tgt.hasName(["copyOf", "of"]) and + tgt.getDeclaringType().getASourceSupertype+().hasQualifiedName("java.util", "Collection") + or + tgt instanceof Constructor and + tgt.getNumberOfParameters() = 1 and + tgt.getParameterType(0) instanceof CollectionType and + tgt.getDeclaringType() instanceof CollectionType + ) +} + +private module BaseUniversalFlow = UniversalFlow::Make; + +private module UnmodifiableProp implements BaseUniversalFlow::NullaryPropertySig { + predicate hasPropertyBase(FlowNode n) { unmodifiableCollectionStep(_, n) } +} + +/** Holds if the given node is an unmodifiable collection. */ +private predicate unmodifiableCollection = + BaseUniversalFlow::FlowNullary::hasProperty/1; + +/** + * Holds if `v` is a collection or array with an access, `coll`, at which the + * element `e` gets added. + */ +private predicate collectionAddition(Variable v, VarAccess coll, Expr e) { + exists(MethodCall mc, Method m, int arg | + mc.getMethod().getSourceDeclaration().overridesOrInstantiates*(m) and + mc.getQualifier() = coll and + v.getAnAccess() = coll and + mc.getArgument(arg) = e + | + m.hasQualifiedName("java.util", "Collection", ["add", "addAll"]) and + m.getNumberOfParameters() = 1 and + arg = 0 + or + m.hasQualifiedName("java.util", "List", ["add", "addAll"]) and + m.getNumberOfParameters() = 2 and + arg = 1 + ) + or + v.getAnAccess() = coll and + exists(Assignment assign | assign.getSource() = e | + coll = assign.getDest().(ArrayAccess).getArray() + ) +} + +/** + * Holds if `n` represents a definition of `v` and `v` is a collection or + * array that has additions occurring as side-effects after its definition. + */ +private predicate nodeWithAddition(FlowNode n, Variable v) { + collectionAddition(v, _, _) and + ( + n.asField() = v + or + n.asSsa().getSourceVariable().getVariable() = v and + (n.asSsa() instanceof BaseSsaUpdate or n.asSsa().(BaseSsaImplicitInit).isParameterDefinition(_)) + ) +} + +/** Holds if `c` does not add elements to the given collection. */ +private predicate safeCallable(Callable c) { + c instanceof CollectionQueryMethod + or + c instanceof CollectionMethod and + c.hasName(["clear", "remove", "removeAll", "stream", "iterator", "toArray"]) + or + c.hasQualifiedName("org.apache.commons.lang3", "StringUtils", "join") +} + +/** + * Holds if `n` might be mutated in ways that adds elements that are not + * tracked by the `collectionAddition` predicate. + */ +private predicate collectionWithPossibleMutation(FlowNode n) { + not unmodifiableCollection(n) and + ( + exists(Expr e | + n.asExpr() = e and + (e.getType() instanceof CollectionType or e.getType() instanceof Array) and + not collectionAddition(_, e, _) and + not collectionStep(n, _) + | + exists(ArrayAccess aa | e = aa.getArray()) + or + exists(Call c, Callable tgt | c.getAnArgument() = e or c.getQualifier() = e | + tgt = c.getCallee().getSourceDeclaration() and + not safeCallable(tgt) + ) + ) + or + exists(FlowNode mid | + FlowStepsInput::step(n, mid) and + collectionWithPossibleMutation(mid) + ) + ) +} + +/** + * A collection constructor that constructs an empty mutable collection. + */ +private class EmptyCollectionConstructor extends Constructor { + EmptyCollectionConstructor() { + this.getDeclaringType() instanceof CollectionType and + forall(Type t | t = this.getAParamType() | t instanceof PrimitiveType) + } +} + +private module CollectionFlowStepsInput implements UniversalFlow::UniversalFlowInput { + import FlowStepsInput + + /** + * Holds if `n2` is a collection/array/constant whose value(s) are + * determined completely from the range of `n1` nodes. + */ + predicate step(FlowNode n1, FlowNode n2) { + // Exclude the regular input constraints for those nodes that are covered + // completely by `collectionStep`. + FlowStepsInput::step(n1, n2) and + not collectionStep(_, n2) + or + // For collections with side-effects in the form of additions, we add the + // sources of those additions as additional input that need to originate + // from constants. + exists(Variable v | + nodeWithAddition(n2, v) and + collectionAddition(v, _, n1.asExpr()) + ) + or + // Include various forms of collection transformation. + collectionStep(n1, n2) + } + + predicate isExcludedFromNullAnalysis = FlowStepsInput::isExcludedFromNullAnalysis/1; +} + +private module CollectionUniversalFlow = UniversalFlow::Make; + +private module ConstantCollectionProp implements CollectionUniversalFlow::NullaryPropertySig { + /** + * Holds if `n` forms the base case for finding collections of constants. + * These are individual constants and empty collections. + */ + predicate hasPropertyBase(FlowNode n) { + n.asExpr().isCompileTimeConstant() or + n.asExpr().(ConstructorCall).getConstructor() instanceof EmptyCollectionConstructor + } + + predicate barrier = collectionWithPossibleMutation/1; +} + +/** + * Holds if the given node is either a constant or a collection/array of + * constants. + */ +private predicate constantCollection = + CollectionUniversalFlow::FlowNullary::hasProperty/1; + +/** Gets the result of a case normalization call of `arg`. */ +private MethodCall normalizeCaseCall(Expr arg) { + exists(Method changecase | result.getMethod() = changecase | + changecase.hasName(["toUpperCase", "toLowerCase"]) and + changecase.getDeclaringType() instanceof TypeString and + arg = result.getQualifier() + or + changecase + .hasQualifiedName(["org.apache.commons.lang", "org.apache.commons.lang3"], "StringUtils", + ["lowerCase", "upperCase"]) and + arg = result.getArgument(0) + or + changecase + .hasQualifiedName("org.apache.hadoop.util", "StringUtils", ["toLowerCase", "toUpperCase"]) and + arg = result.getArgument(0) + ) +} + +/** + * Holds if the guard `g` ensures that the expression `e` is one of a set of + * known constants upon evaluating to `branch`. + */ +private predicate constantCollectionContainsCheck(Guard g, Expr e, boolean branch) { + exists(MethodCall mc, Method m, FlowNode n, Expr checked | + g = mc and + mc.getMethod().getSourceDeclaration().overridesOrInstantiates*(m) and + m.hasQualifiedName("java.util", "Collection", "contains") and + n.asExpr() = mc.getQualifier() and + constantCollection(n) and + checked = mc.getAnArgument() and + branch = true + | + checked = e or + checked = normalizeCaseCall(e) + ) +} + +/** + * A comparison against a list of compile-time constants, sanitizing taint by + * restricting to a set of known values. + */ +private class ListOfConstantsComparisonSanitizerGuard extends TaintTracking::DefaultTaintSanitizer { + ListOfConstantsComparisonSanitizerGuard() { + this = DataFlow::BarrierGuard::getABarrierNode() + } +} From 5a4b7203220d8342d59c2aa94f6b411c85ef0e50 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Mon, 4 Nov 2024 14:11:35 +0100 Subject: [PATCH 03/11] Java: Add change note. --- .../change-notes/2024-11-04-list-of-constants-sanitizer.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 java/ql/lib/change-notes/2024-11-04-list-of-constants-sanitizer.md diff --git a/java/ql/lib/change-notes/2024-11-04-list-of-constants-sanitizer.md b/java/ql/lib/change-notes/2024-11-04-list-of-constants-sanitizer.md new file mode 100644 index 00000000000..dea1e7ff81e --- /dev/null +++ b/java/ql/lib/change-notes/2024-11-04-list-of-constants-sanitizer.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Calling `coll.contains(x)` is now a taint sanitizer (for any query) for the value `x`, where `coll` is a collection of constants. From 2b1caa8a350a8ee7f4e8332511808b8cdd749f4d Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Mon, 4 Nov 2024 15:10:22 +0100 Subject: [PATCH 04/11] Java: Add test. --- .../test/library-tests/listofconstants/A.java | 35 +++++++++++++++++++ .../listofconstants/test.expected | 3 ++ .../library-tests/listofconstants/test.ql | 5 +++ 3 files changed, 43 insertions(+) create mode 100644 java/ql/test/library-tests/listofconstants/A.java create mode 100644 java/ql/test/library-tests/listofconstants/test.expected create mode 100644 java/ql/test/library-tests/listofconstants/test.ql diff --git a/java/ql/test/library-tests/listofconstants/A.java b/java/ql/test/library-tests/listofconstants/A.java new file mode 100644 index 00000000000..74129692d71 --- /dev/null +++ b/java/ql/test/library-tests/listofconstants/A.java @@ -0,0 +1,35 @@ +import java.util.*; + +public class A { + private static final Set SEPARATORS = + Collections.unmodifiableSet( + new HashSet<>(Arrays.asList("\t", "\n", ";"))); + + public static void sink(String s) { } + + private void checkSeparator(String separator) { + if (SEPARATORS.contains(separator)) { + sink(separator); + } + } + + public static final String URI1 = "yarn.io/gpu"; + public static final String URI2 = "yarn.io/fpga"; + + public static final Set SCHEMAS = Set.of(URI1, URI2, "s3a", "wasb"); + + private void checkSchema(String schema) { + if (SCHEMAS.contains(schema)) { + sink(schema); + } + } + + private void testAdd(String inp) { + Set s = new HashSet<>(); + s.add("AA"); + s.add("BB"); + if (s.contains(inp.toUpperCase())) { + sink(inp); + } + } +} diff --git a/java/ql/test/library-tests/listofconstants/test.expected b/java/ql/test/library-tests/listofconstants/test.expected new file mode 100644 index 00000000000..203d64cd46d --- /dev/null +++ b/java/ql/test/library-tests/listofconstants/test.expected @@ -0,0 +1,3 @@ +| A.java:12:12:12:20 | separator | +| A.java:23:12:23:17 | schema | +| A.java:32:12:32:14 | inp | diff --git a/java/ql/test/library-tests/listofconstants/test.ql b/java/ql/test/library-tests/listofconstants/test.ql new file mode 100644 index 00000000000..f56dfc0f11f --- /dev/null +++ b/java/ql/test/library-tests/listofconstants/test.ql @@ -0,0 +1,5 @@ +import java +import semmle.code.java.dataflow.FlowSteps + +from DefaultTaintSanitizer e +select e From 0d45f0efb26f1eee875c36afabb536507bc73541 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Wed, 6 Nov 2024 14:13:31 +0100 Subject: [PATCH 05/11] Java: Accept consistency check result. --- .../listofconstants/CONSISTENCY/typeParametersInScope.expected | 1 + 1 file changed, 1 insertion(+) create mode 100644 java/ql/test/library-tests/listofconstants/CONSISTENCY/typeParametersInScope.expected diff --git a/java/ql/test/library-tests/listofconstants/CONSISTENCY/typeParametersInScope.expected b/java/ql/test/library-tests/listofconstants/CONSISTENCY/typeParametersInScope.expected new file mode 100644 index 00000000000..1ea902154a6 --- /dev/null +++ b/java/ql/test/library-tests/listofconstants/CONSISTENCY/typeParametersInScope.expected @@ -0,0 +1 @@ +| Type A uses out-of-scope type variable E. Note the Java extractor is known to sometimes do this; the Kotlin extractor should not. | From 408a38d9fb866e61dff69695fba7409354a70f37 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Fri, 22 Nov 2024 10:35:43 +0100 Subject: [PATCH 06/11] Java: Address review comment, include addFirst,addLast. --- .../semmle/code/java/security/ListOfConstantsSanitizer.qll | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java/ql/lib/semmle/code/java/security/ListOfConstantsSanitizer.qll b/java/ql/lib/semmle/code/java/security/ListOfConstantsSanitizer.qll index 0b6e3441802..cc57fbce648 100644 --- a/java/ql/lib/semmle/code/java/security/ListOfConstantsSanitizer.qll +++ b/java/ql/lib/semmle/code/java/security/ListOfConstantsSanitizer.qll @@ -91,6 +91,10 @@ private predicate collectionAddition(Variable v, VarAccess coll, Expr e) { m.hasQualifiedName("java.util", "List", ["add", "addAll"]) and m.getNumberOfParameters() = 2 and arg = 1 + or + m.hasQualifiedName("java.util", "SequencedCollection", ["addFirst", "addLast"]) and + m.getNumberOfParameters() = 1 and + arg = 0 ) or v.getAnAccess() = coll and From 2ff2d257847723c30d4634bf3ef60abdb1343d38 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Fri, 22 Nov 2024 10:36:36 +0100 Subject: [PATCH 07/11] Java: Cherry-pick test from https://github.com/github/codeql/pull/17051 --- .../AllowListSanitizerWithJavaUtilList.java | 306 ++++++++++++++++++ .../AllowListSanitizerWithJavaUtilSet.java | 305 +++++++++++++++++ .../semmle/examples/SqlConcatenated.expected | 52 +++ .../semmle/examples/SqlTainted.expected | 144 +++++++++ 4 files changed, 807 insertions(+) create mode 100644 java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilList.java create mode 100644 java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilSet.java diff --git a/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilList.java b/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilList.java new file mode 100644 index 00000000000..8f97f022a71 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilList.java @@ -0,0 +1,306 @@ +// Test cases for CWE-089 (SQL injection and Java Persistence query injection) +// http://cwe.mitre.org/data/definitions/89.html +package test.cwe089.semmle.tests; + +import java.io.IOException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; + +class AllowListSanitizerWithJavaUtilList { + public static Connection connection; + public static final List goodAllowList1 = List.of("allowed1", "allowed2", "allowed3"); + public static final List goodAllowList2 = Collections.unmodifiableList(Arrays.asList("allowed1")); + public static final List goodAllowList3; + public static final List goodAllowList4; + public static final List badAllowList1 = List.of("allowed1", "allowed2", getNonConstantString()); + public static final List badAllowList2 = Collections.unmodifiableList(Arrays.asList("allowed1", getNonConstantString())); + public static final List badAllowList3; + public static final List badAllowList4; + public static final List badAllowList5; + public static List badAllowList6 = List.of("allowed1", "allowed2", "allowed3"); + public final List badAllowList7 = List.of("allowed1", "allowed2", "allowed3"); + + static { + goodAllowList3 = List.of("allowed1", "allowed2", "allowed3"); + goodAllowList4 = Collections.unmodifiableList(Arrays.asList("allowed1", "allowed2")); + badAllowList3 = List.of(getNonConstantString(), "allowed2", "allowed3"); + badAllowList4 = Collections.unmodifiableList(Arrays.asList("allowed1", getNonConstantString())); + badAllowList5 = new ArrayList(); + badAllowList5.add("allowed1"); + badAllowList5.add("allowed2"); + badAllowList5.add("allowed3"); + } + + public static String getNonConstantString() { + return String.valueOf(System.currentTimeMillis()); + } + + public static void main(String[] args) throws IOException, SQLException { + badAllowList6 = List.of("allowed1", getNonConstantString(), "allowed3"); + testStaticFields(args); + testLocal(args); + var x = new AllowListSanitizerWithJavaUtilList(); + x.testNonStaticFields(args); + testMultipleSources(args); + testEscape(args); + } + + private static void testStaticFields(String[] args) throws IOException, SQLException { + String tainted = args[1]; + // GOOD: an allowlist is used with constant strings + if(goodAllowList1.contains(tainted.toLowerCase())){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // GOOD: an allowlist is used with constant strings + if(goodAllowList2.contains(tainted.toUpperCase())){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // GOOD: an allowlist is used with constant strings + if(goodAllowList3.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // GOOD: an allowlist is used with constant strings + if(goodAllowList4.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: an allowlist is used with constant strings + if(badAllowList1.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: an allowlist is used with constant strings + if(badAllowList2.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: an allowlist is used with constant strings + if(badAllowList3.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: an allowlist is used with constant strings + if(badAllowList4.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: an allowlist is used with constant strings + if(badAllowList5.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: the allowlist is in a non-final field + if(badAllowList6.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + + private void testNonStaticFields(String[] args) throws IOException, SQLException { + String tainted = args[0]; + // BAD: the allowlist is in a non-static field + if(badAllowList7.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + + private static void testLocal(String[] args) throws IOException, SQLException { + String tainted = args[1]; + // GOOD: an allowlist is used with constant strings + { + List allowlist = List.of("allowed1", "allowed2", "allowed3"); + if(allowlist.contains(tainted.toLowerCase())){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + List allowlist = List.of("allowed1", "allowed2", args[2]); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // GOOD: an allowlist is used with constant strings + { + String[] allowedArray = {"allowed1", "allowed2", "allowed3"}; + List allowlist = List.of(allowedArray); + if(allowlist.contains(tainted.toUpperCase())){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + String[] allowedArray = {"allowed1", "allowed2", args[2]}; + List allowlist = List.of(allowedArray); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // GOOD: an allowlist is used with constant strings + { + List allowlist = Collections.unmodifiableList(Arrays.asList("allowed1")); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + List allowlist = Collections.unmodifiableList(Arrays.asList("allowed1", "allowed2", args[2])); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // GOOD: an allowlist is used with constant strings + { + String[] allowedArray = {"allowed1", "allowed2", "allowed3"}; + List allowlist = Collections.unmodifiableList(Arrays.asList(allowedArray)); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + String[] allowedArray = {"allowed1", "allowed2", args[2]}; + List allowlist = Collections.unmodifiableList(Arrays.asList(allowedArray)); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // GOOD: an allowlist is used with constant string + { + List allowlist = new ArrayList(); + allowlist.add("allowed1"); + allowlist.add("allowed2"); + allowlist.add("allowed3"); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + List allowlist = new ArrayList(); + allowlist.add("allowed1"); + allowlist.add(getNonConstantString()); + allowlist.add("allowed3"); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but it contains a non-compile-time constant element + { + List allowlist = new ArrayList(); + allowlist.add("allowed1"); + addNonConstantStringDirectly(allowlist); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + } + + private static void testMultipleSources(String[] args) throws IOException, SQLException { + String tainted = args[1]; + boolean b = args[2] == "True"; + { + // BAD: an allowlist is used which might contain constant strings + List allowlist = new ArrayList(); + allowlist.add("allowed1"); + if (b) { + allowlist.add(getNonConstantString()); + } + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + { + // BAD: an allowlist is used which might contain constant strings + List allowlist = b ? goodAllowList1 : badAllowList1; + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + { + // BAD: an allowlist is used which might contain constant strings + List allowlist = b ? goodAllowList1 : List.of("allowed1", "allowed2", args[2]);; + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + } + + private static void testEscape(String[] args) throws IOException, SQLException { + String tainted = args[1]; + boolean b = args[2] == "True"; + { + // BAD: an allowlist is used which contains constant strings + List allowlist = new ArrayList(); + addNonConstantStringViaLambda(e -> allowlist.add(e)); + if(allowlist.contains(tainted)){ // missing result + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + } + + private static void addNonConstantStringDirectly(List list) { + list.add(getNonConstantString()); + } + + private static void addNonConstantStringViaLambda(Consumer adder) { + adder.accept(getNonConstantString()); + } + +} diff --git a/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilSet.java b/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilSet.java new file mode 100644 index 00000000000..a9e1e0f99e5 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilSet.java @@ -0,0 +1,305 @@ +// Test cases for CWE-089 (SQL injection and Java Persistence query injection) +// http://cwe.mitre.org/data/definitions/89.html +package test.cwe089.semmle.tests; + +import java.io.IOException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.HashSet; +import java.util.List; +import java.util.Arrays; +import java.util.Collections; +import java.util.Set; +import java.util.function.Consumer; + +class AllowListSanitizerWithJavaUtilSet { + public static Connection connection; + public static final Set goodAllowList1 = Set.of("allowed1", "allowed2", "allowed3"); + public static final Set goodAllowList2 = Collections.unmodifiableSet(new HashSet(Arrays.asList("allowed1","allowed2"))); + public static final Set goodAllowList3; + public static final Set goodAllowList4; + public static final Set badAllowList1 = Set.of("allowed1", "allowed2", getNonConstantString()); + public static final Set badAllowList2 = Collections.unmodifiableSet(new HashSet(Arrays.asList("allowed1", getNonConstantString()))); + public static final Set badAllowList3; + public static final Set badAllowList4; + public static final Set badAllowList5; + public static Set badAllowList6 = Set.of("allowed1", "allowed2", "allowed3"); + public final Set badAllowList7 = Set.of("allowed1", "allowed2", "allowed3"); + + static { + goodAllowList3 = Set.of("allowed1", "allowed2", "allowed3"); + goodAllowList4 = Collections.unmodifiableSet(new HashSet(Arrays.asList("allowed1", "allowed2"))); + badAllowList3 = Set.of(getNonConstantString(), "allowed2", "allowed3"); + badAllowList4 = Collections.unmodifiableSet(new HashSet(Arrays.asList("allowed1", getNonConstantString()))); + badAllowList5 = new HashSet(); + badAllowList5.add("allowed1"); + badAllowList5.add("allowed2"); + badAllowList5.add("allowed3"); + } + + public static String getNonConstantString() { + return String.valueOf(System.currentTimeMillis()); + } + + public static void main(String[] args) throws IOException, SQLException { + badAllowList6 = Set.of("allowed1", getNonConstantString(), "allowed3"); + testStaticFields(args); + testLocal(args); + var x = new AllowListSanitizerWithJavaUtilSet(); + x.testNonStaticFields(args); + testMultipleSources(args); + testEscape(args); + } + + private static void testStaticFields(String[] args) throws IOException, SQLException { + String tainted = args[1]; + // GOOD: an allowlist is used with constant strings + if(goodAllowList1.contains(tainted.toLowerCase())){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // GOOD: an allowlist is used with constant strings + if(goodAllowList2.contains(tainted.toUpperCase())){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // GOOD: an allowlist is used with constant strings + if(goodAllowList3.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // GOOD: an allowlist is used with constant strings + if(goodAllowList4.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: an allowlist is used with constant strings + if(badAllowList1.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: an allowlist is used with constant strings + if(badAllowList2.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: an allowlist is used with constant strings + if(badAllowList3.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: an allowlist is used with constant strings + if(badAllowList4.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: an allowlist is used with constant strings + if(badAllowList5.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: the allowlist is in a non-final field + if(badAllowList6.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + + private void testNonStaticFields(String[] args) throws IOException, SQLException { + String tainted = args[1]; + // BAD: the allowlist is in a non-static field + if(badAllowList7.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + + private static void testLocal(String[] args) throws IOException, SQLException { + String tainted = args[1]; + // GOOD: an allowlist is used with constant strings + { + Set allowlist = Set.of("allowed1", "allowed2", "allowed3"); + if(allowlist.contains(tainted.toLowerCase())){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + Set allowlist = Set.of("allowed1", "allowed2", args[2]); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // GOOD: an allowlist is used with constant strings + { + String[] allowedArray = {"allowed1", "allowed2", "allowed3"}; + Set allowlist = Set.of(allowedArray); + if(allowlist.contains(tainted.toUpperCase())){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + String[] allowedArray = {"allowed1", "allowed2", args[2]}; + Set allowlist = Set.of(allowedArray); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // GOOD: an allowlist is used with constant strings + { + Set allowlist = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("allowed1"))); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + Set allowlist = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("allowed1", "allowed2", args[2]))); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // GOOD: an allowlist is used with constant strings + { + String[] allowedArray = {"allowed1", "allowed2", "allowed3"}; + Set allowlist = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(allowedArray))); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + String[] allowedArray = {"allowed1", "allowed2", args[2]}; + Set allowlist = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(allowedArray))); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // GOOD: an allowlist is used with constant string + { + Set allowlist = new HashSet(); + allowlist.add("allowed1"); + allowlist.add("allowed2"); + allowlist.add("allowed3"); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + Set allowlist = new HashSet(); + allowlist.add("allowed1"); + allowlist.add(getNonConstantString()); + allowlist.add("allowed3"); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but it contains a non-compile-time constant element + { + Set allowlist = new HashSet(); + allowlist.add("allowed1"); + addNonConstantStringDirectly(allowlist); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + } + + private static void testMultipleSources(String[] args) throws IOException, SQLException { + String tainted = args[1]; + boolean b = args[2] == "True"; + { + // BAD: an allowlist is used which might contain constant strings + Set allowlist = new HashSet(); + allowlist.add("allowed1"); + if (b) { + allowlist.add(getNonConstantString()); + } + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + { + // BAD: an allowlist is used which might contain constant strings + Set allowlist = b ? goodAllowList1 : badAllowList1; + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + { + // BAD: an allowlist is used which might contain constant strings + Set allowlist = b ? goodAllowList1 : Set.of("allowed1", "allowed2", args[2]);; + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + } + + private static void testEscape(String[] args) throws IOException, SQLException { + String tainted = args[1]; + boolean b = args[2] == "True"; + { + // BAD: an allowlist is used which contains constant strings + Set allowlist = new HashSet(); + addNonConstantStringViaLambda(e -> allowlist.add(e)); + if(allowlist.contains(tainted)){ // missing result + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + } + + private static void addNonConstantStringDirectly(Set set) { + set.add(getNonConstantString()); + } + + private static void addNonConstantStringViaLambda(Consumer adder) { + adder.accept(getNonConstantString()); + } + +} diff --git a/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlConcatenated.expected b/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlConcatenated.expected index fc1d87f06b1..1e560f03c3b 100644 --- a/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlConcatenated.expected +++ b/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlConcatenated.expected @@ -1,3 +1,55 @@ +| AllowListSanitizerWithJavaUtilList.java:64:66:64:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:63:8:63:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:70:66:70:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:69:8:69:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:76:66:76:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:75:8:75:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:82:66:82:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:81:8:81:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:88:66:88:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:87:8:87:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:93:8:93:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:99:8:99:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:105:8:105:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:112:66:112:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:111:8:111:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:117:8:117:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:128:66:128:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:127:8:127:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:140:67:140:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:139:9:139:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:148:9:148:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:159:67:159:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:158:9:158:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:168:9:168:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:178:67:178:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:177:9:177:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:186:9:186:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:197:67:197:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:196:9:196:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:207:67:207:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:206:9:206:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:219:67:219:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:218:9:218:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:231:67:231:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:230:9:230:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:242:67:242:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:241:9:241:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:260:67:260:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:259:9:259:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:269:67:269:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:268:9:268:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:278:67:278:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:277:9:277:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:293:67:293:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:292:9:292:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:63:66:63:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:62:8:62:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:69:66:69:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:68:8:68:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:75:66:75:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:74:8:74:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:81:66:81:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:80:8:80:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:87:66:87:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:86:8:86:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:92:8:92:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:98:8:98:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:104:8:104:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:111:66:111:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:110:8:110:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:116:8:116:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:127:66:127:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:126:8:126:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:139:67:139:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:138:9:138:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:147:9:147:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:158:67:158:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:157:9:157:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:167:9:167:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:177:67:177:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:176:9:176:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:185:9:185:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:196:67:196:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:195:9:195:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:206:67:206:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:205:9:205:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:218:67:218:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:217:9:217:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:230:67:230:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:229:9:229:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:241:67:241:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:240:9:240:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:259:67:259:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:258:9:258:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:268:67:268:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:267:9:267:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:277:67:277:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:276:9:276:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:292:67:292:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:291:9:291:15 | tainted | this expression | | Test.java:36:47:36:52 | query1 | Query built by concatenation with $@, which may be untrusted. | Test.java:35:8:35:15 | category | this expression | | Test.java:42:57:42:62 | query2 | Query built by concatenation with $@, which may be untrusted. | Test.java:41:51:41:52 | id | this expression | | Test.java:50:62:50:67 | query3 | Query built by concatenation with $@, which may be untrusted. | Test.java:49:8:49:15 | category | this expression | diff --git a/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlTainted.expected b/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlTainted.expected index d54bbdaec05..82c17206b14 100644 --- a/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlTainted.expected +++ b/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlTainted.expected @@ -1,4 +1,38 @@ #select +| AllowListSanitizerWithJavaUtilList.java:88:66:88:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:88:66:88:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:112:66:112:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:112:66:112:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:128:66:128:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:128:66:128:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:207:67:207:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:207:67:207:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:231:67:231:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:231:67:231:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:242:67:242:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:242:67:242:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:260:67:260:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:260:67:260:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:269:67:269:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:269:67:269:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:278:67:278:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:278:67:278:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:293:67:293:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:293:67:293:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:87:66:87:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:87:66:87:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:111:66:111:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:111:66:111:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:127:66:127:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:127:66:127:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:206:67:206:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:206:67:206:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:230:67:230:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:230:67:230:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:241:67:241:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:241:67:241:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:259:67:259:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:259:67:259:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:268:67:268:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:268:67:268:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:277:67:277:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:277:67:277:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:292:67:292:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:292:67:292:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | | Mongo.java:17:45:17:67 | parse(...) | Mongo.java:10:29:10:41 | args : String[] | Mongo.java:17:45:17:67 | parse(...) | This query depends on a $@. | Mongo.java:10:29:10:41 | args | user-provided value | | Mongo.java:21:49:21:52 | json | Mongo.java:10:29:10:41 | args : String[] | Mongo.java:21:49:21:52 | json | This query depends on a $@. | Mongo.java:10:29:10:41 | args | user-provided value | | Test.java:36:47:36:52 | query1 | Test.java:227:26:227:38 | args : String[] | Test.java:36:47:36:52 | query1 | This query depends on a $@. | Test.java:227:26:227:38 | args | user-provided value | @@ -10,6 +44,60 @@ | Test.java:209:47:209:68 | queryWithUserTableName | Test.java:227:26:227:38 | args : String[] | Test.java:209:47:209:68 | queryWithUserTableName | This query depends on a $@. | Test.java:227:26:227:38 | args | user-provided value | | Test.java:221:81:221:111 | ... + ... | Test.java:227:26:227:38 | args : String[] | Test.java:221:81:221:111 | ... + ... | This query depends on a $@. | Test.java:227:26:227:38 | args | user-provided value | edges +| AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:50:20:50:23 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:51:13:51:16 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:53:25:53:28 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:54:23:54:26 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:55:14:55:17 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilList.java:50:20:50:23 | args : String[] | AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilList.java:51:13:51:16 | args : String[] | AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilList.java:53:25:53:28 | args : String[] | AllowListSanitizerWithJavaUtilList.java:122:35:122:47 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilList.java:54:23:54:26 | args : String[] | AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilList.java:55:14:55:17 | args : String[] | AllowListSanitizerWithJavaUtilList.java:283:33:283:45 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:88:66:88:70 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:112:66:112:70 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilList.java:122:35:122:47 | args : String[] | AllowListSanitizerWithJavaUtilList.java:128:66:128:70 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:207:67:207:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:231:67:231:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:242:67:242:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | AllowListSanitizerWithJavaUtilList.java:260:67:260:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | AllowListSanitizerWithJavaUtilList.java:269:67:269:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | AllowListSanitizerWithJavaUtilList.java:278:67:278:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilList.java:283:33:283:45 | args : String[] | AllowListSanitizerWithJavaUtilList.java:293:67:293:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:49:20:49:23 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:50:13:50:16 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:52:25:52:28 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:53:23:53:26 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:54:14:54:17 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilSet.java:49:20:49:23 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilSet.java:50:13:50:16 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilSet.java:52:25:52:28 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:121:35:121:47 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilSet.java:53:23:53:26 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilSet.java:54:14:54:17 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:282:33:282:45 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:87:66:87:70 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:111:66:111:70 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilSet.java:121:35:121:47 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:127:66:127:70 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:206:67:206:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:230:67:230:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:241:67:241:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:259:67:259:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:268:67:268:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:277:67:277:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilSet.java:282:33:282:45 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:292:67:292:71 | query | provenance | Sink:MaD:6 | | Mongo.java:10:29:10:41 | args : String[] | Mongo.java:17:56:17:66 | stringQuery : String | provenance | | | Mongo.java:10:29:10:41 | args : String[] | Mongo.java:21:49:21:52 | json | provenance | | | Mongo.java:17:56:17:66 | stringQuery : String | Mongo.java:17:45:17:67 | parse(...) | provenance | Config | @@ -40,6 +128,62 @@ models | 6 | Summary: java.lang; AbstractStringBuilder; true; append; ; ; Argument[0]; Argument[this]; taint; manual | | 7 | Summary: java.lang; CharSequence; true; toString; ; ; Argument[this]; ReturnValue; taint; manual | nodes +| AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:50:20:50:23 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:51:13:51:16 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:53:25:53:28 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:54:23:54:26 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:55:14:55:17 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:88:66:88:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:112:66:112:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:122:35:122:47 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:128:66:128:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:207:67:207:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:231:67:231:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:242:67:242:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:260:67:260:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:269:67:269:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:278:67:278:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:283:33:283:45 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:293:67:293:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:49:20:49:23 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:50:13:50:16 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:52:25:52:28 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:53:23:53:26 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:54:14:54:17 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:87:66:87:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:111:66:111:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:121:35:121:47 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:127:66:127:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:206:67:206:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:230:67:230:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:241:67:241:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:259:67:259:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:268:67:268:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:277:67:277:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:282:33:282:45 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:292:67:292:71 | query | semmle.label | query | | Mongo.java:10:29:10:41 | args : String[] | semmle.label | args : String[] | | Mongo.java:17:45:17:67 | parse(...) | semmle.label | parse(...) | | Mongo.java:17:56:17:66 | stringQuery : String | semmle.label | stringQuery : String | From 38eb3e49528f07d21c530513dfd5f084c4996081 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Fri, 22 Nov 2024 10:45:27 +0100 Subject: [PATCH 08/11] Java: Adjust expected output. --- .../AllowListSanitizerWithJavaUtilList.java | 20 +++++++++---------- .../AllowListSanitizerWithJavaUtilSet.java | 20 +++++++++---------- .../semmle/examples/SqlTainted.expected | 20 ------------------- 3 files changed, 20 insertions(+), 40 deletions(-) diff --git a/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilList.java b/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilList.java index 8f97f022a71..285f9bc49cb 100644 --- a/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilList.java +++ b/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilList.java @@ -22,23 +22,23 @@ class AllowListSanitizerWithJavaUtilList { public static final List goodAllowList2 = Collections.unmodifiableList(Arrays.asList("allowed1")); public static final List goodAllowList3; public static final List goodAllowList4; + public static final List goodAllowList5; public static final List badAllowList1 = List.of("allowed1", "allowed2", getNonConstantString()); public static final List badAllowList2 = Collections.unmodifiableList(Arrays.asList("allowed1", getNonConstantString())); public static final List badAllowList3; public static final List badAllowList4; - public static final List badAllowList5; public static List badAllowList6 = List.of("allowed1", "allowed2", "allowed3"); - public final List badAllowList7 = List.of("allowed1", "allowed2", "allowed3"); + public final List goodAllowList7 = List.of("allowed1", "allowed2", "allowed3"); static { goodAllowList3 = List.of("allowed1", "allowed2", "allowed3"); goodAllowList4 = Collections.unmodifiableList(Arrays.asList("allowed1", "allowed2")); badAllowList3 = List.of(getNonConstantString(), "allowed2", "allowed3"); badAllowList4 = Collections.unmodifiableList(Arrays.asList("allowed1", getNonConstantString())); - badAllowList5 = new ArrayList(); - badAllowList5.add("allowed1"); - badAllowList5.add("allowed2"); - badAllowList5.add("allowed3"); + goodAllowList5 = new ArrayList(); + goodAllowList5.add("allowed1"); + goodAllowList5.add("allowed2"); + goodAllowList5.add("allowed3"); } public static String getNonConstantString() { @@ -105,8 +105,8 @@ class AllowListSanitizerWithJavaUtilList { + tainted + "' ORDER BY PRICE"; ResultSet results = connection.createStatement().executeQuery(query); } - // BAD: an allowlist is used with constant strings - if(badAllowList5.contains(tainted)){ + // GOOD: an allowlist is used with constant strings + if(goodAllowList5.contains(tainted)){ String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + tainted + "' ORDER BY PRICE"; ResultSet results = connection.createStatement().executeQuery(query); @@ -121,8 +121,8 @@ class AllowListSanitizerWithJavaUtilList { private void testNonStaticFields(String[] args) throws IOException, SQLException { String tainted = args[0]; - // BAD: the allowlist is in a non-static field - if(badAllowList7.contains(tainted)){ + // GOOD: the allowlist is in a non-static field + if(goodAllowList7.contains(tainted)){ String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + tainted + "' ORDER BY PRICE"; ResultSet results = connection.createStatement().executeQuery(query); diff --git a/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilSet.java b/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilSet.java index a9e1e0f99e5..e1a5f889c6f 100644 --- a/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilSet.java +++ b/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilSet.java @@ -21,23 +21,23 @@ class AllowListSanitizerWithJavaUtilSet { public static final Set goodAllowList2 = Collections.unmodifiableSet(new HashSet(Arrays.asList("allowed1","allowed2"))); public static final Set goodAllowList3; public static final Set goodAllowList4; + public static final Set goodAllowList5; public static final Set badAllowList1 = Set.of("allowed1", "allowed2", getNonConstantString()); public static final Set badAllowList2 = Collections.unmodifiableSet(new HashSet(Arrays.asList("allowed1", getNonConstantString()))); public static final Set badAllowList3; public static final Set badAllowList4; - public static final Set badAllowList5; public static Set badAllowList6 = Set.of("allowed1", "allowed2", "allowed3"); - public final Set badAllowList7 = Set.of("allowed1", "allowed2", "allowed3"); + public final Set goodAllowList7 = Set.of("allowed1", "allowed2", "allowed3"); static { goodAllowList3 = Set.of("allowed1", "allowed2", "allowed3"); goodAllowList4 = Collections.unmodifiableSet(new HashSet(Arrays.asList("allowed1", "allowed2"))); badAllowList3 = Set.of(getNonConstantString(), "allowed2", "allowed3"); badAllowList4 = Collections.unmodifiableSet(new HashSet(Arrays.asList("allowed1", getNonConstantString()))); - badAllowList5 = new HashSet(); - badAllowList5.add("allowed1"); - badAllowList5.add("allowed2"); - badAllowList5.add("allowed3"); + goodAllowList5 = new HashSet(); + goodAllowList5.add("allowed1"); + goodAllowList5.add("allowed2"); + goodAllowList5.add("allowed3"); } public static String getNonConstantString() { @@ -104,8 +104,8 @@ class AllowListSanitizerWithJavaUtilSet { + tainted + "' ORDER BY PRICE"; ResultSet results = connection.createStatement().executeQuery(query); } - // BAD: an allowlist is used with constant strings - if(badAllowList5.contains(tainted)){ + // GOOD: an allowlist is used with constant strings + if(goodAllowList5.contains(tainted)){ String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + tainted + "' ORDER BY PRICE"; ResultSet results = connection.createStatement().executeQuery(query); @@ -120,8 +120,8 @@ class AllowListSanitizerWithJavaUtilSet { private void testNonStaticFields(String[] args) throws IOException, SQLException { String tainted = args[1]; - // BAD: the allowlist is in a non-static field - if(badAllowList7.contains(tainted)){ + // GOOD: the allowlist is in a non-static field + if(goodAllowList7.contains(tainted)){ String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + tainted + "' ORDER BY PRICE"; ResultSet results = connection.createStatement().executeQuery(query); diff --git a/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlTainted.expected b/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlTainted.expected index 82c17206b14..6d1e99e2afb 100644 --- a/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlTainted.expected +++ b/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlTainted.expected @@ -3,9 +3,7 @@ | AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | | AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | | AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | -| AllowListSanitizerWithJavaUtilList.java:112:66:112:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:112:66:112:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | | AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | -| AllowListSanitizerWithJavaUtilList.java:128:66:128:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:128:66:128:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | | AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | | AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | | AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | @@ -20,9 +18,7 @@ | AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | | AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | | AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | -| AllowListSanitizerWithJavaUtilSet.java:111:66:111:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:111:66:111:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | | AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | -| AllowListSanitizerWithJavaUtilSet.java:127:66:127:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:127:66:127:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | | AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | | AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | | AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | @@ -46,21 +42,17 @@ edges | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:50:20:50:23 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:51:13:51:16 | args : String[] | provenance | | -| AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:53:25:53:28 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:54:23:54:26 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:55:14:55:17 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilList.java:50:20:50:23 | args : String[] | AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilList.java:51:13:51:16 | args : String[] | AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | provenance | | -| AllowListSanitizerWithJavaUtilList.java:53:25:53:28 | args : String[] | AllowListSanitizerWithJavaUtilList.java:122:35:122:47 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilList.java:54:23:54:26 | args : String[] | AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilList.java:55:14:55:17 | args : String[] | AllowListSanitizerWithJavaUtilList.java:283:33:283:45 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:88:66:88:70 | query | provenance | Sink:MaD:6 | | AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | provenance | Sink:MaD:6 | | AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | provenance | Sink:MaD:6 | | AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:112:66:112:70 | query | provenance | Sink:MaD:6 | | AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilList.java:122:35:122:47 | args : String[] | AllowListSanitizerWithJavaUtilList.java:128:66:128:70 | query | provenance | Sink:MaD:6 | | AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | provenance | Sink:MaD:6 | | AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | provenance | Sink:MaD:6 | | AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | provenance | Sink:MaD:6 | @@ -73,21 +65,17 @@ edges | AllowListSanitizerWithJavaUtilList.java:283:33:283:45 | args : String[] | AllowListSanitizerWithJavaUtilList.java:293:67:293:71 | query | provenance | Sink:MaD:6 | | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:49:20:49:23 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:50:13:50:16 | args : String[] | provenance | | -| AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:52:25:52:28 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:53:23:53:26 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:54:14:54:17 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilSet.java:49:20:49:23 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilSet.java:50:13:50:16 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | provenance | | -| AllowListSanitizerWithJavaUtilSet.java:52:25:52:28 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:121:35:121:47 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilSet.java:53:23:53:26 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilSet.java:54:14:54:17 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:282:33:282:45 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:87:66:87:70 | query | provenance | Sink:MaD:6 | | AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | provenance | Sink:MaD:6 | | AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | provenance | Sink:MaD:6 | | AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:111:66:111:70 | query | provenance | Sink:MaD:6 | | AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilSet.java:121:35:121:47 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:127:66:127:70 | query | provenance | Sink:MaD:6 | | AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | provenance | Sink:MaD:6 | | AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | provenance | Sink:MaD:6 | | AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | provenance | Sink:MaD:6 | @@ -131,7 +119,6 @@ nodes | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | semmle.label | args : String[] | | AllowListSanitizerWithJavaUtilList.java:50:20:50:23 | args : String[] | semmle.label | args : String[] | | AllowListSanitizerWithJavaUtilList.java:51:13:51:16 | args : String[] | semmle.label | args : String[] | -| AllowListSanitizerWithJavaUtilList.java:53:25:53:28 | args : String[] | semmle.label | args : String[] | | AllowListSanitizerWithJavaUtilList.java:54:23:54:26 | args : String[] | semmle.label | args : String[] | | AllowListSanitizerWithJavaUtilList.java:55:14:55:17 | args : String[] | semmle.label | args : String[] | | AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | semmle.label | args : String[] | @@ -139,10 +126,7 @@ nodes | AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | semmle.label | query | | AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | semmle.label | query | | AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | semmle.label | query | -| AllowListSanitizerWithJavaUtilList.java:112:66:112:70 | query | semmle.label | query | | AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | semmle.label | query | -| AllowListSanitizerWithJavaUtilList.java:122:35:122:47 | args : String[] | semmle.label | args : String[] | -| AllowListSanitizerWithJavaUtilList.java:128:66:128:70 | query | semmle.label | query | | AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | semmle.label | args : String[] | | AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | semmle.label | query | | AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | semmle.label | query | @@ -159,7 +143,6 @@ nodes | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | semmle.label | args : String[] | | AllowListSanitizerWithJavaUtilSet.java:49:20:49:23 | args : String[] | semmle.label | args : String[] | | AllowListSanitizerWithJavaUtilSet.java:50:13:50:16 | args : String[] | semmle.label | args : String[] | -| AllowListSanitizerWithJavaUtilSet.java:52:25:52:28 | args : String[] | semmle.label | args : String[] | | AllowListSanitizerWithJavaUtilSet.java:53:23:53:26 | args : String[] | semmle.label | args : String[] | | AllowListSanitizerWithJavaUtilSet.java:54:14:54:17 | args : String[] | semmle.label | args : String[] | | AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | semmle.label | args : String[] | @@ -167,10 +150,7 @@ nodes | AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | semmle.label | query | | AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | semmle.label | query | | AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | semmle.label | query | -| AllowListSanitizerWithJavaUtilSet.java:111:66:111:70 | query | semmle.label | query | | AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | semmle.label | query | -| AllowListSanitizerWithJavaUtilSet.java:121:35:121:47 | args : String[] | semmle.label | args : String[] | -| AllowListSanitizerWithJavaUtilSet.java:127:66:127:70 | query | semmle.label | query | | AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | semmle.label | args : String[] | | AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | semmle.label | query | | AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | semmle.label | query | From a6fc41ec4b8b703c9082cc94bfdb8c6f3a1243e6 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Fri, 22 Nov 2024 10:48:45 +0100 Subject: [PATCH 09/11] Java: Accept consistency failure. --- .../semmle/examples/CONSISTENCY/typeParametersInScope.expected | 1 + 1 file changed, 1 insertion(+) create mode 100644 java/ql/test/query-tests/security/CWE-089/semmle/examples/CONSISTENCY/typeParametersInScope.expected diff --git a/java/ql/test/query-tests/security/CWE-089/semmle/examples/CONSISTENCY/typeParametersInScope.expected b/java/ql/test/query-tests/security/CWE-089/semmle/examples/CONSISTENCY/typeParametersInScope.expected new file mode 100644 index 00000000000..1f8028eff60 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-089/semmle/examples/CONSISTENCY/typeParametersInScope.expected @@ -0,0 +1 @@ +| Type AllowListSanitizerWithJavaUtilSet uses out-of-scope type variable E. Note the Java extractor is known to sometimes do this; the Kotlin extractor should not. | From 85778f7fea72ecac608466dbc47bfe00733e99bb Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Wed, 27 Nov 2024 08:53:41 +0100 Subject: [PATCH 10/11] Java: Fix semantic merge conflict in expected file. --- .../semmle/examples/SqlTainted.expected | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlTainted.expected b/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlTainted.expected index 6d1e99e2afb..a45f58bd54d 100644 --- a/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlTainted.expected +++ b/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlTainted.expected @@ -48,21 +48,21 @@ edges | AllowListSanitizerWithJavaUtilList.java:51:13:51:16 | args : String[] | AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilList.java:54:23:54:26 | args : String[] | AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilList.java:55:14:55:17 | args : String[] | AllowListSanitizerWithJavaUtilList.java:283:33:283:45 | args : String[] | provenance | | -| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:88:66:88:70 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:207:67:207:71 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:231:67:231:71 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:242:67:242:71 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | AllowListSanitizerWithJavaUtilList.java:260:67:260:71 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | AllowListSanitizerWithJavaUtilList.java:269:67:269:71 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | AllowListSanitizerWithJavaUtilList.java:278:67:278:71 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilList.java:283:33:283:45 | args : String[] | AllowListSanitizerWithJavaUtilList.java:293:67:293:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:88:66:88:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:207:67:207:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:231:67:231:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:242:67:242:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | AllowListSanitizerWithJavaUtilList.java:260:67:260:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | AllowListSanitizerWithJavaUtilList.java:269:67:269:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | AllowListSanitizerWithJavaUtilList.java:278:67:278:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:283:33:283:45 | args : String[] | AllowListSanitizerWithJavaUtilList.java:293:67:293:71 | query | provenance | Sink:MaD:4 | | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:49:20:49:23 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:50:13:50:16 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:53:23:53:26 | args : String[] | provenance | | @@ -71,21 +71,21 @@ edges | AllowListSanitizerWithJavaUtilSet.java:50:13:50:16 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilSet.java:53:23:53:26 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | provenance | | | AllowListSanitizerWithJavaUtilSet.java:54:14:54:17 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:282:33:282:45 | args : String[] | provenance | | -| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:87:66:87:70 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:206:67:206:71 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:230:67:230:71 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:241:67:241:71 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:259:67:259:71 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:268:67:268:71 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:277:67:277:71 | query | provenance | Sink:MaD:6 | -| AllowListSanitizerWithJavaUtilSet.java:282:33:282:45 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:292:67:292:71 | query | provenance | Sink:MaD:6 | +| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:87:66:87:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:206:67:206:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:230:67:230:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:241:67:241:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:259:67:259:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:268:67:268:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:277:67:277:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:282:33:282:45 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:292:67:292:71 | query | provenance | Sink:MaD:4 | | Mongo.java:10:29:10:41 | args : String[] | Mongo.java:17:56:17:66 | stringQuery : String | provenance | | | Mongo.java:10:29:10:41 | args : String[] | Mongo.java:21:49:21:52 | json | provenance | | | Mongo.java:17:56:17:66 | stringQuery : String | Mongo.java:17:45:17:67 | parse(...) | provenance | Config | From 5ef496dd1b2fdc9511a68844f06186608c7b09ae Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Wed, 27 Nov 2024 09:07:35 +0100 Subject: [PATCH 11/11] Java: Add more qldoc. --- java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll | 8 ++++++++ .../ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll b/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll index f9046b1b65e..9e05b69db4a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll @@ -21,6 +21,7 @@ private RefType boxIfNeeded(J::Type t) { result = t } +/** Provides the input types and predicates for instantiation of `UniversalFlow`. */ module FlowStepsInput implements UniversalFlow::UniversalFlowInput { private newtype TFlowNode = TField(Field f) { not f.getType() instanceof PrimitiveType } or @@ -32,6 +33,7 @@ module FlowStepsInput implements UniversalFlow::UniversalFlowInput { * A `Field`, `BaseSsaVariable`, `Expr`, or `Method`. */ class FlowNode extends TFlowNode { + /** Gets a textual representation of this element. */ string toString() { result = this.asField().toString() or result = this.asSsa().toString() or @@ -39,6 +41,7 @@ module FlowStepsInput implements UniversalFlow::UniversalFlowInput { result = this.asMethod().toString() } + /** Gets the source location for this element. */ Location getLocation() { result = this.asField().getLocation() or result = this.asSsa().getLocation() or @@ -46,14 +49,19 @@ module FlowStepsInput implements UniversalFlow::UniversalFlowInput { result = this.asMethod().getLocation() } + /** Gets the field corresponding to this node, if any. */ Field asField() { this = TField(result) } + /** Gets the SSA variable corresponding to this node, if any. */ BaseSsaVariable asSsa() { this = TSsa(result) } + /** Gets the expression corresponding to this node, if any. */ Expr asExpr() { this = TExpr(result) } + /** Gets the method corresponding to this node, if any. */ Method asMethod() { this = TMethod(result) } + /** Gets the type of this node. */ RefType getType() { result = this.asField().getType() or result = this.asSsa().getSourceVariable().getType() or diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll b/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll index f33a6d7195f..79f12e57f6a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll @@ -38,6 +38,7 @@ class BaseSsaSourceVariable extends TBaseSsaSourceVariable { /** Gets the `Callable` in which this `BaseSsaSourceVariable` is defined. */ Callable getEnclosingCallable() { this = TLocalVar(result, _) } + /** Gets a textual representation of this element. */ string toString() { exists(LocalScopeVariable v, Callable c | this = TLocalVar(c, v) | if c = v.getCallable() @@ -46,6 +47,7 @@ class BaseSsaSourceVariable extends TBaseSsaSourceVariable { ) } + /** Gets the source location for this element. */ Location getLocation() { exists(LocalScopeVariable v | this = TLocalVar(_, v) and result = v.getLocation()) } @@ -482,8 +484,10 @@ class BaseSsaVariable extends TBaseSsaVariable { this = TSsaEntryDef(_, result) } + /** Gets a textual representation of this element. */ string toString() { none() } + /** Gets the source location for this element. */ Location getLocation() { result = this.getCfgNode().getLocation() } /** Gets the `BasicBlock` in which this SSA variable is defined. */