Skip to content

Commit 74a6698

Browse files
committed
Add list of constants sanitizer
1 parent 859b99f commit 74a6698

File tree

2 files changed

+80
-6
lines changed

2 files changed

+80
-6
lines changed

java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,3 +665,83 @@ private predicate entrypointFieldStep(DataFlow::Node src, DataFlow::Node sink) {
665665
) and
666666
src.getType().(RefType).getSourceDeclaration() = entrypointType()
667667
}
668+
669+
/**
670+
* A comparison against a list of compile-time constants, sanitizing taint by
671+
* restricting to a set of known values.
672+
*/
673+
class ListOfConstantsComparisonSanitizerGuard extends TaintTracking::DefaultTaintSanitizer {
674+
ListOfConstantsComparisonSanitizerGuard() {
675+
this = DataFlow::BarrierGuard<listOfConstantsComparisonSanitizerGuard/3>::getABarrierNode()
676+
}
677+
}
678+
679+
private predicate listOfConstantsComparisonSanitizerGuard(Guard g, Expr e, boolean outcome) {
680+
exists(ListOfConstantsComparison locc |
681+
g = locc and
682+
e = locc.getExpr() and
683+
outcome = locc.getOutcome()
684+
)
685+
}
686+
687+
/** A comparison against a list of compile-time constants. */
688+
abstract class ListOfConstantsComparison extends Guard {
689+
Expr e;
690+
boolean outcome;
691+
692+
ListOfConstantsComparison() {
693+
exists(this) and
694+
outcome = [true, false]
695+
}
696+
697+
Expr getExpr() { result = e }
698+
699+
boolean getOutcome() { result = outcome }
700+
}
701+
702+
/**
703+
* An invocation of `java.util.List.contains` where the qualifier contains only
704+
* compile-time constants.
705+
*/
706+
private class JavaUtilListOfConstantsContains extends ListOfConstantsComparison {
707+
JavaUtilListOfConstantsContains() {
708+
exists(MethodCall mc, Method m | mc.getMethod() = m |
709+
m.hasName("contains") and
710+
m.getDeclaringType().getSourceDeclaration().hasQualifiedName("java.util", "List") and
711+
DataFlow::localFlow(any(JavaUtilListOfConstants loc), DataFlow::exprNode(mc.getQualifier())) and
712+
this = mc and
713+
e = mc.getArgument(0) and
714+
outcome = true
715+
)
716+
}
717+
}
718+
719+
/**
720+
* An instance of `java.util.List` which contains only compile-time constants.
721+
*/
722+
abstract class JavaUtilListOfConstants extends DataFlow::Node { }
723+
724+
/**
725+
* An invocation of `java.util.List.of` which constructs an (immutable) list
726+
* which contains only compile-time constants.
727+
*/
728+
private class JavaUtilListOfConstantsCreatedWithListOf extends JavaUtilListOfConstants {
729+
JavaUtilListOfConstantsCreatedWithListOf() {
730+
exists(MethodCall mc, Method m |
731+
m.hasName("of") and
732+
m.getDeclaringType().getSourceDeclaration().hasQualifiedName("java.util", "List") and
733+
mc.getMethod() = m and
734+
DataFlow::localFlow(DataFlow::exprNode(mc), this) and
735+
(
736+
// List<String> allowlist = List.of("a", "b", "c")
737+
forall(Expr e | e = mc.getAnArgument() | e.isCompileTimeConstant())
738+
or
739+
// String[] a = {"a", "b", "c"};
740+
// List<String> allowlist = List.of(a)
741+
exists(ArrayInit arr | DataFlow::localExprFlow(arr, mc.getArgument(0)) |
742+
forall(Expr e | e = arr.getAnInit() | e.isCompileTimeConstant())
743+
)
744+
)
745+
)
746+
}
747+
}

java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlTainted.expected

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ edges
1414
| Test.java:60:29:60:46 | toString(...) : String | Test.java:62:47:62:61 | querySbToString | provenance | Sink:MaD:43208 |
1515
| Test.java:183:33:183:45 | args : String[] | Test.java:209:47:209:68 | queryWithUserTableName | provenance | Sink:MaD:43208 |
1616
| Test.java:213:34:213:46 | args : String[] | Test.java:221:81:221:111 | ... + ... | provenance | Sink:MaD:43208 |
17-
| Test.java:227:32:227:44 | args : String[] | Test.java:236:48:236:52 | query | provenance | Sink:MaD:43208 |
1817
| Test.java:227:32:227:44 | args : String[] | Test.java:246:48:246:52 | query | provenance | Sink:MaD:43208 |
19-
| Test.java:227:32:227:44 | args : String[] | Test.java:257:48:257:52 | query | provenance | Sink:MaD:43208 |
2018
| Test.java:227:32:227:44 | args : String[] | Test.java:268:48:268:52 | query | provenance | Sink:MaD:43208 |
2119
| Test.java:227:32:227:44 | args : String[] | Test.java:281:48:281:52 | query | provenance | Sink:MaD:43208 |
2220
| Test.java:286:26:286:38 | args : String[] | Test.java:287:11:287:14 | args : String[] | provenance | |
@@ -48,9 +46,7 @@ nodes
4846
| Test.java:213:34:213:46 | args : String[] | semmle.label | args : String[] |
4947
| Test.java:221:81:221:111 | ... + ... | semmle.label | ... + ... |
5048
| Test.java:227:32:227:44 | args : String[] | semmle.label | args : String[] |
51-
| Test.java:236:48:236:52 | query | semmle.label | query |
5249
| Test.java:246:48:246:52 | query | semmle.label | query |
53-
| Test.java:257:48:257:52 | query | semmle.label | query |
5450
| Test.java:268:48:268:52 | query | semmle.label | query |
5551
| Test.java:281:48:281:52 | query | semmle.label | query |
5652
| Test.java:286:26:286:38 | args : String[] | semmle.label | args : String[] |
@@ -70,8 +66,6 @@ subpaths
7066
| Test.java:78:46:78:50 | query | Test.java:286:26:286:38 | args : String[] | Test.java:78:46:78:50 | query | This query depends on a $@. | Test.java:286:26:286:38 | args | user-provided value |
7167
| Test.java:209:47:209:68 | queryWithUserTableName | Test.java:286:26:286:38 | args : String[] | Test.java:209:47:209:68 | queryWithUserTableName | This query depends on a $@. | Test.java:286:26:286:38 | args | user-provided value |
7268
| Test.java:221:81:221:111 | ... + ... | Test.java:286:26:286:38 | args : String[] | Test.java:221:81:221:111 | ... + ... | This query depends on a $@. | Test.java:286:26:286:38 | args | user-provided value |
73-
| Test.java:236:48:236:52 | query | Test.java:286:26:286:38 | args : String[] | Test.java:236:48:236:52 | query | This query depends on a $@. | Test.java:286:26:286:38 | args | user-provided value |
7469
| Test.java:246:48:246:52 | query | Test.java:286:26:286:38 | args : String[] | Test.java:246:48:246:52 | query | This query depends on a $@. | Test.java:286:26:286:38 | args | user-provided value |
75-
| Test.java:257:48:257:52 | query | Test.java:286:26:286:38 | args : String[] | Test.java:257:48:257:52 | query | This query depends on a $@. | Test.java:286:26:286:38 | args | user-provided value |
7670
| Test.java:268:48:268:52 | query | Test.java:286:26:286:38 | args : String[] | Test.java:268:48:268:52 | query | This query depends on a $@. | Test.java:286:26:286:38 | args | user-provided value |
7771
| Test.java:281:48:281:52 | query | Test.java:286:26:286:38 | args : String[] | Test.java:281:48:281:52 | query | This query depends on a $@. | Test.java:286:26:286:38 | args | user-provided value |

0 commit comments

Comments
 (0)