From 768102ee925be402d4dfcabeeaa8d69b54f4848e Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 16 Mar 2023 14:38:54 -0400 Subject: [PATCH 01/12] Refactor java/android/webview-debugging-enabled --- ...y.qll => WebviewDebuggingEnabledQuery.qll} | 30 +++++++++++++++++-- .../CWE/CWE-489/WebviewDebuggingEnabled.ql | 8 ++--- .../WebviewDebuggingEnabled.ql | 21 +++++++------ 3 files changed, 44 insertions(+), 15 deletions(-) rename java/ql/lib/semmle/code/java/security/{WebviewDubuggingEnabledQuery.qll => WebviewDebuggingEnabledQuery.qll} (59%) diff --git a/java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll b/java/ql/lib/semmle/code/java/security/WebviewDebuggingEnabledQuery.qll similarity index 59% rename from java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll rename to java/ql/lib/semmle/code/java/security/WebviewDebuggingEnabledQuery.qll index 92071c2af1a..858da08ea01 100644 --- a/java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll +++ b/java/ql/lib/semmle/code/java/security/WebviewDebuggingEnabledQuery.qll @@ -18,8 +18,12 @@ private predicate isDebugCheck(Expr ex) { ) } -/** A configuration to find instances of `setWebContentDebuggingEnabled` called with `true` values. */ -class WebviewDebugEnabledConfig extends DataFlow::Configuration { +/** + * DEPRECATED: Use `WebviewDebugEnabledFlow` instead. + * + * A configuration to find instances of `setWebContentDebuggingEnabled` called with `true` values. + */ +deprecated class WebviewDebugEnabledConfig extends DataFlow::Configuration { WebviewDebugEnabledConfig() { this = "WebviewDebugEnabledConfig" } override predicate isSource(DataFlow::Node node) { @@ -39,3 +43,25 @@ class WebviewDebugEnabledConfig extends DataFlow::Configuration { node.getEnclosingCallable().getDeclaringType() instanceof NonSecurityTestClass } } + +/** A configuration to find instances of `setWebContentDebuggingEnabled` called with `true` values. */ +private module WebviewDebugEnabledConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { + node.asExpr().(BooleanLiteral).getBooleanValue() = true + } + + predicate isSink(DataFlow::Node node) { + exists(MethodAccess ma | + ma.getMethod().hasQualifiedName("android.webkit", "WebView", "setWebContentsDebuggingEnabled") and + node.asExpr() = ma.getArgument(0) + ) + } + + predicate isBarrier(DataFlow::Node node) { + exists(Guard debug | isDebugCheck(debug) and debug.controls(node.asExpr().getBasicBlock(), _)) + or + node.getEnclosingCallable().getDeclaringType() instanceof NonSecurityTestClass + } +} + +module WebviewDebugEnabledFlow = DataFlow::Make; diff --git a/java/ql/src/Security/CWE/CWE-489/WebviewDebuggingEnabled.ql b/java/ql/src/Security/CWE/CWE-489/WebviewDebuggingEnabled.ql index a8f7f81d832..cafa616e2d1 100644 --- a/java/ql/src/Security/CWE/CWE-489/WebviewDebuggingEnabled.ql +++ b/java/ql/src/Security/CWE/CWE-489/WebviewDebuggingEnabled.ql @@ -11,9 +11,9 @@ */ import java -import semmle.code.java.security.WebviewDubuggingEnabledQuery -import DataFlow::PathGraph +import semmle.code.java.security.WebviewDebuggingEnabledQuery +import WebviewDebugEnabledFlow::PathGraph -from WebviewDebugEnabledConfig conf, DataFlow::PathNode source, DataFlow::PathNode sink -where conf.hasFlowPath(source, sink) +from WebviewDebugEnabledFlow::PathNode source, WebviewDebugEnabledFlow::PathNode sink +where WebviewDebugEnabledFlow::hasFlowPath(source, sink) select sink, source, sink, "Webview debugging is enabled." diff --git a/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql b/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql index aeceb941e09..35d237bf134 100644 --- a/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql +++ b/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql @@ -1,15 +1,18 @@ import java -import TestUtilities.InlineFlowTest -import semmle.code.java.security.WebviewDubuggingEnabledQuery +import TestUtilities.InlineExpectationsTest +import semmle.code.java.security.WebviewDebuggingEnabledQuery -class EnableLegacy extends EnableLegacyConfiguration { - EnableLegacy() { exists(this) } -} +class HasFlowTest extends InlineExpectationsTest { + HasFlowTest() { this = "HasFlowTest" } -class HasFlowTest extends InlineFlowTest { - override DataFlow::Configuration getTaintFlowConfig() { none() } + override string getARelevantTag() { result = "hasValueFlow" } - override DataFlow::Configuration getValueFlowConfig() { - result = any(WebviewDebugEnabledConfig c) + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasValueFlow" and + exists(DataFlow::Node sink | WebviewDebugEnabledFlow::hasFlowTo(sink) | + location = sink.getLocation() and + element = "sink" and + value = "" + ) } } From 807588a031ff065fbd0335666a7f4699ba4612f2 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 16 Mar 2023 21:52:40 -0400 Subject: [PATCH 02/12] Refactor AndroidCertificatePinningQuery --- .../security/AndroidCertificatePinningQuery.qll | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/AndroidCertificatePinningQuery.qll b/java/ql/lib/semmle/code/java/security/AndroidCertificatePinningQuery.qll index 70dc1a7a328..cd8ccdf6758 100644 --- a/java/ql/lib/semmle/code/java/security/AndroidCertificatePinningQuery.qll +++ b/java/ql/lib/semmle/code/java/security/AndroidCertificatePinningQuery.qll @@ -106,10 +106,8 @@ private class MissingPinningSink extends DataFlow::Node { } /** Configuration for finding uses of non trusted URLs. */ -private class UntrustedUrlConfig extends TaintTracking::Configuration { - UntrustedUrlConfig() { this = "UntrustedUrlConfig" } - - override predicate isSource(DataFlow::Node node) { +private module UntrustedUrlConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { trustedDomain(_) and exists(string lit | lit = node.asExpr().(CompileTimeConstantExpr).getStringValue() | lit.matches("%://%") and // it's a URL @@ -117,9 +115,11 @@ private class UntrustedUrlConfig extends TaintTracking::Configuration { ) } - override predicate isSink(DataFlow::Node node) { node instanceof MissingPinningSink } + predicate isSink(DataFlow::Node node) { node instanceof MissingPinningSink } } +private module UntrustedUrlFlow = TaintTracking::Make; + /** Holds if `node` is a network communication call for which certificate pinning is not implemented. */ predicate missingPinning(DataFlow::Node node, string domain) { isAndroid() and @@ -127,8 +127,8 @@ predicate missingPinning(DataFlow::Node node, string domain) { ( not trustedDomain(_) and domain = "" or - exists(UntrustedUrlConfig conf, DataFlow::Node src | - conf.hasFlow(src, node) and + exists(DataFlow::Node src | + UntrustedUrlFlow::hasFlow(src, node) and domain = getDomain(src.asExpr()) ) ) From 1e0c6811a4f072242d1160d528b41b15403712f5 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 21 Mar 2023 16:36:26 -0400 Subject: [PATCH 03/12] Refactor UnsafeAndroidAccess --- .../java/security/UnsafeAndroidAccessQuery.qll | 14 +++++++++++++- .../Security/CWE/CWE-749/UnsafeAndroidAccess.ql | 6 +++--- .../security/CWE-749/UnsafeAndroidAccessTest.ql | 2 +- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/UnsafeAndroidAccessQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeAndroidAccessQuery.qll index 6bd9833047d..3d4a5bd8057 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeAndroidAccessQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeAndroidAccessQuery.qll @@ -7,9 +7,11 @@ import semmle.code.java.security.RequestForgery import semmle.code.java.security.UnsafeAndroidAccess /** + * DEPRECATED: Use `FetchUntrustedResourceFlow` instead. + * * A taint configuration tracking flow from untrusted inputs to a resource fetching call. */ -class FetchUntrustedResourceConfiguration extends TaintTracking::Configuration { +deprecated class FetchUntrustedResourceConfiguration extends TaintTracking::Configuration { FetchUntrustedResourceConfiguration() { this = "FetchUntrustedResourceConfiguration" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -20,3 +22,13 @@ class FetchUntrustedResourceConfiguration extends TaintTracking::Configuration { sanitizer instanceof RequestForgerySanitizer } } + +private module FetchUntrustedResourceConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof UrlResourceSink } + + predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof RequestForgerySanitizer } +} + +module FetchUntrustedResourceFlow = TaintTracking::Make; diff --git a/java/ql/src/Security/CWE/CWE-749/UnsafeAndroidAccess.ql b/java/ql/src/Security/CWE/CWE-749/UnsafeAndroidAccess.ql index 277b1b5790e..c397bf74b93 100644 --- a/java/ql/src/Security/CWE/CWE-749/UnsafeAndroidAccess.ql +++ b/java/ql/src/Security/CWE/CWE-749/UnsafeAndroidAccess.ql @@ -14,9 +14,9 @@ import java import semmle.code.java.security.UnsafeAndroidAccessQuery -import DataFlow::PathGraph +import FetchUntrustedResourceFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, FetchUntrustedResourceConfiguration conf -where conf.hasFlowPath(source, sink) +from FetchUntrustedResourceFlow::PathNode source, FetchUntrustedResourceFlow::PathNode sink +where FetchUntrustedResourceFlow::hasFlowPath(source, sink) select sink.getNode(), source, sink, "Unsafe resource fetching in Android WebView due to $@.", source.getNode(), sink.getNode().(UrlResourceSink).getSinkType() diff --git a/java/ql/test/query-tests/security/CWE-749/UnsafeAndroidAccessTest.ql b/java/ql/test/query-tests/security/CWE-749/UnsafeAndroidAccessTest.ql index 7305d6aeb6f..158c00e5566 100644 --- a/java/ql/test/query-tests/security/CWE-749/UnsafeAndroidAccessTest.ql +++ b/java/ql/test/query-tests/security/CWE-749/UnsafeAndroidAccessTest.ql @@ -9,7 +9,7 @@ class UnsafeAndroidAccessTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasUnsafeAndroidAccess" and - exists(DataFlow::Node sink, FetchUntrustedResourceConfiguration conf | conf.hasFlowTo(sink) | + exists(DataFlow::Node sink | FetchUntrustedResourceFlow::hasFlowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" From d68bec98bcc952f4935cbbb81aacd84fe5645eb9 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 16 Mar 2023 22:05:20 -0400 Subject: [PATCH 04/12] Refactor CWE-940/AndroidIntentRedirection --- .../AndroidIntentRedirectionQuery.qll | 49 +++++++++++++------ .../CWE/CWE-940/AndroidIntentRedirection.ql | 6 +-- .../CWE-940/AndroidIntentRedirectionTest.ql | 2 +- 3 files changed, 37 insertions(+), 20 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/AndroidIntentRedirectionQuery.qll b/java/ql/lib/semmle/code/java/security/AndroidIntentRedirectionQuery.qll index 9d5a2cb4cf2..5971ab597fa 100644 --- a/java/ql/lib/semmle/code/java/security/AndroidIntentRedirectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/AndroidIntentRedirectionQuery.qll @@ -8,9 +8,11 @@ import semmle.code.java.dataflow.TaintTracking3 import semmle.code.java.security.AndroidIntentRedirection /** + * DEPRECATED: Use `IntentRedirectionFlow` instead. + * * A taint tracking configuration for tainted Intents being used to start Android components. */ -class IntentRedirectionConfiguration extends TaintTracking::Configuration { +deprecated class IntentRedirectionConfiguration extends TaintTracking::Configuration { IntentRedirectionConfiguration() { this = "IntentRedirectionConfiguration" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -26,31 +28,44 @@ class IntentRedirectionConfiguration extends TaintTracking::Configuration { } } +private module IntentRedirectionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof IntentRedirectionSink } + + predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof IntentRedirectionSanitizer } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(IntentRedirectionAdditionalTaintStep c).step(node1, node2) + } +} + +/** A taint tracking configuration for tainted Intents being used to start Android components. */ +module IntentRedirectionFlow = TaintTracking::Make; + /** * A sanitizer for sinks that receive the original incoming Intent, * since its component cannot be arbitrarily set. */ private class OriginalIntentSanitizer extends IntentRedirectionSanitizer { - OriginalIntentSanitizer() { any(SameIntentBeingRelaunchedConfiguration c).hasFlowTo(this) } + OriginalIntentSanitizer() { SameIntentBeingRelaunchedFlow::hasFlowTo(this) } } /** * Data flow configuration used to discard incoming Intents * flowing directly to sinks that start Android components. */ -private class SameIntentBeingRelaunchedConfiguration extends DataFlow2::Configuration { - SameIntentBeingRelaunchedConfiguration() { this = "SameIntentBeingRelaunchedConfiguration" } +private module SameIntentBeingRelaunchedConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSink(DataFlow::Node sink) { sink instanceof IntentRedirectionSink } - override predicate isSink(DataFlow::Node sink) { sink instanceof IntentRedirectionSink } - - override predicate isBarrier(DataFlow::Node barrier) { + predicate isBarrier(DataFlow::Node barrier) { // Don't discard the Intent if its original component is tainted barrier instanceof IntentWithTaintedComponent } - override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { // Intents being built with the copy constructor from the original Intent are discarded too exists(ClassInstanceExpr cie | cie.getConstructedType() instanceof TypeIntent and @@ -61,12 +76,14 @@ private class SameIntentBeingRelaunchedConfiguration extends DataFlow2::Configur } } +private module SameIntentBeingRelaunchedFlow = DataFlow::Make; + /** An `Intent` with a tainted component. */ private class IntentWithTaintedComponent extends DataFlow::Node { IntentWithTaintedComponent() { - exists(IntentSetComponent setExpr, TaintedIntentComponentConf conf | + exists(IntentSetComponent setExpr | setExpr.getQualifier() = this.asExpr() and - conf.hasFlowTo(DataFlow::exprNode(setExpr.getSink())) + TaintedIntentComponentFlow::hasFlowTo(DataFlow::exprNode(setExpr.getSink())) ) } } @@ -74,16 +91,16 @@ private class IntentWithTaintedComponent extends DataFlow::Node { /** * A taint tracking configuration for tainted data flowing to an `Intent`'s component. */ -private class TaintedIntentComponentConf extends TaintTracking3::Configuration { - TaintedIntentComponentConf() { this = "TaintedIntentComponentConf" } +private module TaintedIntentComponentConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { any(IntentSetComponent setComponent).getSink() = sink.asExpr() } } +private module TaintedIntentComponentFlow = TaintTracking::Make; + /** A call to a method that changes the component of an `Intent`. */ private class IntentSetComponent extends MethodAccess { int sinkArg; diff --git a/java/ql/src/Security/CWE/CWE-940/AndroidIntentRedirection.ql b/java/ql/src/Security/CWE/CWE-940/AndroidIntentRedirection.ql index 1ace2fc4fcc..c00915f7172 100644 --- a/java/ql/src/Security/CWE/CWE-940/AndroidIntentRedirection.ql +++ b/java/ql/src/Security/CWE/CWE-940/AndroidIntentRedirection.ql @@ -15,10 +15,10 @@ import java import semmle.code.java.security.AndroidIntentRedirectionQuery -import DataFlow::PathGraph +import IntentRedirectionFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, IntentRedirectionConfiguration conf -where conf.hasFlowPath(source, sink) +from IntentRedirectionFlow::PathNode source, IntentRedirectionFlow::PathNode sink +where IntentRedirectionFlow::hasFlowPath(source, sink) select sink.getNode(), source, sink, "Arbitrary Android activities or services can be started from a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/test/query-tests/security/CWE-940/AndroidIntentRedirectionTest.ql b/java/ql/test/query-tests/security/CWE-940/AndroidIntentRedirectionTest.ql index 62605ed505d..02e69d025ff 100644 --- a/java/ql/test/query-tests/security/CWE-940/AndroidIntentRedirectionTest.ql +++ b/java/ql/test/query-tests/security/CWE-940/AndroidIntentRedirectionTest.ql @@ -9,7 +9,7 @@ class HasAndroidIntentRedirectionTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasAndroidIntentRedirection" and - exists(DataFlow::Node sink, IntentRedirectionConfiguration conf | conf.hasFlowTo(sink) | + exists(DataFlow::Node sink | IntentRedirectionFlow::hasFlowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" From 413a6cbc4f476fc76719ca0977051c1c1dbfdfcd Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 21 Mar 2023 20:16:26 -0400 Subject: [PATCH 05/12] Refactor SensitiveKeyboardCacheQuery --- .../security/SensitiveKeyboardCacheQuery.qll | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/SensitiveKeyboardCacheQuery.qll b/java/ql/lib/semmle/code/java/security/SensitiveKeyboardCacheQuery.qll index 5a78932a7cd..ad4c480e7ad 100644 --- a/java/ql/lib/semmle/code/java/security/SensitiveKeyboardCacheQuery.qll +++ b/java/ql/lib/semmle/code/java/security/SensitiveKeyboardCacheQuery.qll @@ -91,16 +91,14 @@ private predicate inputTypeFieldNotCached(Field f) { } /** Configuration that finds uses of `setInputType` for non cached fields. */ -private class GoodInputTypeConf extends DataFlow::Configuration { - GoodInputTypeConf() { this = "GoodInputTypeConf" } - - override predicate isSource(DataFlow::Node node) { +private module GoodInputTypeConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { inputTypeFieldNotCached(node.asExpr().(FieldAccess).getField()) } - override predicate isSink(DataFlow::Node node) { node.asExpr() = setInputTypeForId(_) } + predicate isSink(DataFlow::Node node) { node.asExpr() = setInputTypeForId(_) } - override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { exists(OrBitwiseExpr bitOr | node1.asExpr() = bitOr.getAChildExpr() and node2.asExpr() = bitOr @@ -108,6 +106,8 @@ private class GoodInputTypeConf extends DataFlow::Configuration { } } +private module GoodInputTypeFlow = DataFlow::Make; + /** Gets a regex indicating that an input field may contain sensitive data. */ private string getInputSensitiveInfoRegex() { result = @@ -130,8 +130,8 @@ AndroidEditableXmlElement getASensitiveCachedInput() { result.getId().regexpMatch(getInputSensitiveInfoRegex()) and ( not inputTypeNotCached(result.getInputType()) and - not exists(GoodInputTypeConf conf, DataFlow::Node sink | - conf.hasFlowTo(sink) and + not exists(DataFlow::Node sink | + GoodInputTypeFlow::hasFlowTo(sink) and sink.asExpr() = setInputTypeForId(result.getId()) ) ) From ef08a9134014cf1faac56a252838841ff7de0301 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 21 Mar 2023 13:15:01 -0400 Subject: [PATCH 06/12] Refactor ImproperIntentVerificationQuery.qll --- .../security/ImproperIntentVerificationQuery.qll | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/ImproperIntentVerificationQuery.qll b/java/ql/lib/semmle/code/java/security/ImproperIntentVerificationQuery.qll index 00a6dae69e9..3f362c42bba 100644 --- a/java/ql/lib/semmle/code/java/security/ImproperIntentVerificationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ImproperIntentVerificationQuery.qll @@ -14,14 +14,12 @@ private class OnReceiveMethod extends Method { } /** A configuration to detect whether the `action` of an `Intent` is checked. */ -private class VerifiedIntentConfig extends DataFlow::Configuration { - VerifiedIntentConfig() { this = "VerifiedIntentConfig" } - - override predicate isSource(DataFlow::Node src) { +private module VerifiedIntentConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asParameter() = any(OnReceiveMethod orm).getIntentParameter() } - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(MethodAccess ma | ma.getMethod().hasQualifiedName("android.content", "Intent", "getAction") and sink.asExpr() = ma.getQualifier() @@ -29,10 +27,12 @@ private class VerifiedIntentConfig extends DataFlow::Configuration { } } +private module VerifiedIntentFlow = DataFlow::Make; + /** An `onReceive` method that doesn't verify the action of the intent it receives. */ private class UnverifiedOnReceiveMethod extends OnReceiveMethod { UnverifiedOnReceiveMethod() { - not any(VerifiedIntentConfig c).hasFlow(DataFlow::parameterNode(this.getIntentParameter()), _) + not VerifiedIntentFlow::hasFlow(DataFlow::parameterNode(this.getIntentParameter()), _) } } From e7f6d5390750894e59045b9e97ccd4377424c599 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Wed, 22 Mar 2023 12:14:11 -0400 Subject: [PATCH 07/12] Deprecate `WebViewDubuggingQuery.qll` --- .../2023-03-22-deprecate-webviewdubuggingenabledquery.md | 4 ++++ .../code/java/security/WebviewDubuggingEnabledQuery.qll | 8 ++++++++ 2 files changed, 12 insertions(+) create mode 100644 java/ql/lib/change-notes/2023-03-22-deprecate-webviewdubuggingenabledquery.md create mode 100644 java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll diff --git a/java/ql/lib/change-notes/2023-03-22-deprecate-webviewdubuggingenabledquery.md b/java/ql/lib/change-notes/2023-03-22-deprecate-webviewdubuggingenabledquery.md new file mode 100644 index 00000000000..e4f2933c04a --- /dev/null +++ b/java/ql/lib/change-notes/2023-03-22-deprecate-webviewdubuggingenabledquery.md @@ -0,0 +1,4 @@ +--- +category: deprecated +--- +* The `WebViewDubuggingQuery` library has been renamed to `WebViewDebuggingQuery` to fix the typo in the file name. `WebViewDubuggingQuery` is now deprecated. diff --git a/java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll b/java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll new file mode 100644 index 00000000000..3c517ef719e --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll @@ -0,0 +1,8 @@ +/** + * DEPRECATED: Use `semmle.code.java.security.WebviewDebuggingEnabledQuery` instead. + * + * Definitions for the Android Webview Debugging Enabled query + */ + +import java +import semmle.code.java.security.WebviewDebuggingEnabledQuery From 58bd2f7fa2636b86267196c8ea01c67eac8566e3 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Wed, 22 Mar 2023 12:17:49 -0400 Subject: [PATCH 08/12] Address code review comments --- .../code/java/security/AndroidIntentRedirectionQuery.qll | 5 +++-- .../code/java/security/UnsafeAndroidAccessQuery.qll | 8 +++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/AndroidIntentRedirectionQuery.qll b/java/ql/lib/semmle/code/java/security/AndroidIntentRedirectionQuery.qll index 5971ab597fa..cc5d6a6004b 100644 --- a/java/ql/lib/semmle/code/java/security/AndroidIntentRedirectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/AndroidIntentRedirectionQuery.qll @@ -28,7 +28,8 @@ deprecated class IntentRedirectionConfiguration extends TaintTracking::Configura } } -private module IntentRedirectionConfig implements DataFlow::ConfigSig { +/** A taint tracking configuration for tainted Intents being used to start Android components. */ +module IntentRedirectionConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } predicate isSink(DataFlow::Node sink) { sink instanceof IntentRedirectionSink } @@ -40,7 +41,7 @@ private module IntentRedirectionConfig implements DataFlow::ConfigSig { } } -/** A taint tracking configuration for tainted Intents being used to start Android components. */ +/** Tracks the flow of tainted Intents being used to start Android components. */ module IntentRedirectionFlow = TaintTracking::Make; /** diff --git a/java/ql/lib/semmle/code/java/security/UnsafeAndroidAccessQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeAndroidAccessQuery.qll index 3d4a5bd8057..9a713ff7dfc 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeAndroidAccessQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeAndroidAccessQuery.qll @@ -23,7 +23,10 @@ deprecated class FetchUntrustedResourceConfiguration extends TaintTracking::Conf } } -private module FetchUntrustedResourceConfig implements DataFlow::ConfigSig { +/** + * A taint configuration tracking flow from untrusted inputs to a resource fetching call. + */ +module FetchUntrustedResourceConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } predicate isSink(DataFlow::Node sink) { sink instanceof UrlResourceSink } @@ -31,4 +34,7 @@ private module FetchUntrustedResourceConfig implements DataFlow::ConfigSig { predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof RequestForgerySanitizer } } +/** + * Detects taint flow from untrusted inputs to a resource fetching call. + */ module FetchUntrustedResourceFlow = TaintTracking::Make; From 8cc2a7329e49306385db1c687e35b6d25c6f32f0 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Wed, 22 Mar 2023 22:55:55 -0400 Subject: [PATCH 09/12] Fix test to use new InlineFlowTest --- .../WebviewDebuggingEnabled.ql | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql b/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql index 35d237bf134..20c38ea52ee 100644 --- a/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql +++ b/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql @@ -1,18 +1,11 @@ import java -import TestUtilities.InlineExpectationsTest +import TestUtilities.InlineFlowTest import semmle.code.java.security.WebviewDebuggingEnabledQuery -class HasFlowTest extends InlineExpectationsTest { - HasFlowTest() { this = "HasFlowTest" } +class HasFlowTest extends InlineFlowTest { + override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { none() } - override string getARelevantTag() { result = "hasValueFlow" } - - override predicate hasActualResult(Location location, string element, string tag, string value) { - tag = "hasValueFlow" and - exists(DataFlow::Node sink | WebviewDebugEnabledFlow::hasFlowTo(sink) | - location = sink.getLocation() and - element = "sink" and - value = "" - ) + override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { + WebviewDebugEnabledFlow::hasFlow(src, sink) } } From c62eaba60171053a234f02d322baf2c57bbd0d78 Mon Sep 17 00:00:00 2001 From: Edward Minnix III Date: Thu, 23 Mar 2023 10:04:24 -0400 Subject: [PATCH 10/12] Simulate deprecated import Co-authored-by: Anders Schack-Mulligen --- .../code/java/security/WebviewDubuggingEnabledQuery.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll b/java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll index 3c517ef719e..70180d651bf 100644 --- a/java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll +++ b/java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll @@ -5,4 +5,6 @@ */ import java -import semmle.code.java.security.WebviewDebuggingEnabledQuery +private import semmle.code.java.security.WebviewDebuggingEnabledQuery as WebviewDebuggingEnabledQuery + +deprecated class WebviewDebugEnabledConfig = WebviewDebuggingEnabledQuery:: WebviewDebugEnabledConfig; From 2eea34dc4a884eff69c1040987a5c505a69cf229 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 23 Mar 2023 10:08:22 -0400 Subject: [PATCH 11/12] Apply suggestions from code review --- .../code/java/security/WebviewDebuggingEnabledQuery.qll | 5 ++++- .../code/java/security/WebviewDubuggingEnabledQuery.qll | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/WebviewDebuggingEnabledQuery.qll b/java/ql/lib/semmle/code/java/security/WebviewDebuggingEnabledQuery.qll index 858da08ea01..daeb0790121 100644 --- a/java/ql/lib/semmle/code/java/security/WebviewDebuggingEnabledQuery.qll +++ b/java/ql/lib/semmle/code/java/security/WebviewDebuggingEnabledQuery.qll @@ -45,7 +45,7 @@ deprecated class WebviewDebugEnabledConfig extends DataFlow::Configuration { } /** A configuration to find instances of `setWebContentDebuggingEnabled` called with `true` values. */ -private module WebviewDebugEnabledConfig implements DataFlow::ConfigSig { +module WebviewDebugEnabledConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node node) { node.asExpr().(BooleanLiteral).getBooleanValue() = true } @@ -64,4 +64,7 @@ private module WebviewDebugEnabledConfig implements DataFlow::ConfigSig { } } +/** + * Tracks instances of `setWebContentDebuggingEnabled` with `true` values. + */ module WebviewDebugEnabledFlow = DataFlow::Make; diff --git a/java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll b/java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll index 70180d651bf..f315c55291e 100644 --- a/java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll +++ b/java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll @@ -7,4 +7,5 @@ import java private import semmle.code.java.security.WebviewDebuggingEnabledQuery as WebviewDebuggingEnabledQuery -deprecated class WebviewDebugEnabledConfig = WebviewDebuggingEnabledQuery:: WebviewDebugEnabledConfig; +deprecated class WebviewDebugEnabledConfig = + WebviewDebuggingEnabledQuery::WebviewDebugEnabledConfig; From 1bf4dd964995b9eae06cbe5e844bfa8cffd1be8e Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Fri, 24 Mar 2023 09:54:53 -0400 Subject: [PATCH 12/12] Update to DataFlow::Global --- .../java/security/AndroidCertificatePinningQuery.qll | 4 ++-- .../java/security/AndroidIntentRedirectionQuery.qll | 10 +++++----- .../java/security/ImproperIntentVerificationQuery.qll | 4 ++-- .../code/java/security/SensitiveKeyboardCacheQuery.qll | 4 ++-- .../code/java/security/UnsafeAndroidAccessQuery.qll | 2 +- .../java/security/WebviewDebuggingEnabledQuery.qll | 2 +- .../Security/CWE/CWE-489/WebviewDebuggingEnabled.ql | 2 +- .../ql/src/Security/CWE/CWE-749/UnsafeAndroidAccess.ql | 2 +- .../Security/CWE/CWE-940/AndroidIntentRedirection.ql | 2 +- .../webview-debugging/WebviewDebuggingEnabled.ql | 2 +- .../security/CWE-749/UnsafeAndroidAccessTest.ql | 2 +- .../security/CWE-940/AndroidIntentRedirectionTest.ql | 2 +- 12 files changed, 19 insertions(+), 19 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/AndroidCertificatePinningQuery.qll b/java/ql/lib/semmle/code/java/security/AndroidCertificatePinningQuery.qll index cd8ccdf6758..86779a4a911 100644 --- a/java/ql/lib/semmle/code/java/security/AndroidCertificatePinningQuery.qll +++ b/java/ql/lib/semmle/code/java/security/AndroidCertificatePinningQuery.qll @@ -118,7 +118,7 @@ private module UntrustedUrlConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node node) { node instanceof MissingPinningSink } } -private module UntrustedUrlFlow = TaintTracking::Make; +private module UntrustedUrlFlow = TaintTracking::Global; /** Holds if `node` is a network communication call for which certificate pinning is not implemented. */ predicate missingPinning(DataFlow::Node node, string domain) { @@ -128,7 +128,7 @@ predicate missingPinning(DataFlow::Node node, string domain) { not trustedDomain(_) and domain = "" or exists(DataFlow::Node src | - UntrustedUrlFlow::hasFlow(src, node) and + UntrustedUrlFlow::flow(src, node) and domain = getDomain(src.asExpr()) ) ) diff --git a/java/ql/lib/semmle/code/java/security/AndroidIntentRedirectionQuery.qll b/java/ql/lib/semmle/code/java/security/AndroidIntentRedirectionQuery.qll index cc5d6a6004b..87fd5003afb 100644 --- a/java/ql/lib/semmle/code/java/security/AndroidIntentRedirectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/AndroidIntentRedirectionQuery.qll @@ -42,14 +42,14 @@ module IntentRedirectionConfig implements DataFlow::ConfigSig { } /** Tracks the flow of tainted Intents being used to start Android components. */ -module IntentRedirectionFlow = TaintTracking::Make; +module IntentRedirectionFlow = TaintTracking::Global; /** * A sanitizer for sinks that receive the original incoming Intent, * since its component cannot be arbitrarily set. */ private class OriginalIntentSanitizer extends IntentRedirectionSanitizer { - OriginalIntentSanitizer() { SameIntentBeingRelaunchedFlow::hasFlowTo(this) } + OriginalIntentSanitizer() { SameIntentBeingRelaunchedFlow::flowTo(this) } } /** @@ -77,14 +77,14 @@ private module SameIntentBeingRelaunchedConfig implements DataFlow::ConfigSig { } } -private module SameIntentBeingRelaunchedFlow = DataFlow::Make; +private module SameIntentBeingRelaunchedFlow = DataFlow::Global; /** An `Intent` with a tainted component. */ private class IntentWithTaintedComponent extends DataFlow::Node { IntentWithTaintedComponent() { exists(IntentSetComponent setExpr | setExpr.getQualifier() = this.asExpr() and - TaintedIntentComponentFlow::hasFlowTo(DataFlow::exprNode(setExpr.getSink())) + TaintedIntentComponentFlow::flowTo(DataFlow::exprNode(setExpr.getSink())) ) } } @@ -100,7 +100,7 @@ private module TaintedIntentComponentConfig implements DataFlow::ConfigSig { } } -private module TaintedIntentComponentFlow = TaintTracking::Make; +private module TaintedIntentComponentFlow = TaintTracking::Global; /** A call to a method that changes the component of an `Intent`. */ private class IntentSetComponent extends MethodAccess { diff --git a/java/ql/lib/semmle/code/java/security/ImproperIntentVerificationQuery.qll b/java/ql/lib/semmle/code/java/security/ImproperIntentVerificationQuery.qll index 3f362c42bba..db59c5c5291 100644 --- a/java/ql/lib/semmle/code/java/security/ImproperIntentVerificationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ImproperIntentVerificationQuery.qll @@ -27,12 +27,12 @@ private module VerifiedIntentConfig implements DataFlow::ConfigSig { } } -private module VerifiedIntentFlow = DataFlow::Make; +private module VerifiedIntentFlow = DataFlow::Global; /** An `onReceive` method that doesn't verify the action of the intent it receives. */ private class UnverifiedOnReceiveMethod extends OnReceiveMethod { UnverifiedOnReceiveMethod() { - not VerifiedIntentFlow::hasFlow(DataFlow::parameterNode(this.getIntentParameter()), _) + not VerifiedIntentFlow::flow(DataFlow::parameterNode(this.getIntentParameter()), _) } } diff --git a/java/ql/lib/semmle/code/java/security/SensitiveKeyboardCacheQuery.qll b/java/ql/lib/semmle/code/java/security/SensitiveKeyboardCacheQuery.qll index ad4c480e7ad..2a41d2da08c 100644 --- a/java/ql/lib/semmle/code/java/security/SensitiveKeyboardCacheQuery.qll +++ b/java/ql/lib/semmle/code/java/security/SensitiveKeyboardCacheQuery.qll @@ -106,7 +106,7 @@ private module GoodInputTypeConfig implements DataFlow::ConfigSig { } } -private module GoodInputTypeFlow = DataFlow::Make; +private module GoodInputTypeFlow = DataFlow::Global; /** Gets a regex indicating that an input field may contain sensitive data. */ private string getInputSensitiveInfoRegex() { @@ -131,7 +131,7 @@ AndroidEditableXmlElement getASensitiveCachedInput() { ( not inputTypeNotCached(result.getInputType()) and not exists(DataFlow::Node sink | - GoodInputTypeFlow::hasFlowTo(sink) and + GoodInputTypeFlow::flowTo(sink) and sink.asExpr() = setInputTypeForId(result.getId()) ) ) diff --git a/java/ql/lib/semmle/code/java/security/UnsafeAndroidAccessQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeAndroidAccessQuery.qll index 9a713ff7dfc..267bfd6bf39 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeAndroidAccessQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeAndroidAccessQuery.qll @@ -37,4 +37,4 @@ module FetchUntrustedResourceConfig implements DataFlow::ConfigSig { /** * Detects taint flow from untrusted inputs to a resource fetching call. */ -module FetchUntrustedResourceFlow = TaintTracking::Make; +module FetchUntrustedResourceFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/WebviewDebuggingEnabledQuery.qll b/java/ql/lib/semmle/code/java/security/WebviewDebuggingEnabledQuery.qll index daeb0790121..d5aaf92f412 100644 --- a/java/ql/lib/semmle/code/java/security/WebviewDebuggingEnabledQuery.qll +++ b/java/ql/lib/semmle/code/java/security/WebviewDebuggingEnabledQuery.qll @@ -67,4 +67,4 @@ module WebviewDebugEnabledConfig implements DataFlow::ConfigSig { /** * Tracks instances of `setWebContentDebuggingEnabled` with `true` values. */ -module WebviewDebugEnabledFlow = DataFlow::Make; +module WebviewDebugEnabledFlow = DataFlow::Global; diff --git a/java/ql/src/Security/CWE/CWE-489/WebviewDebuggingEnabled.ql b/java/ql/src/Security/CWE/CWE-489/WebviewDebuggingEnabled.ql index cafa616e2d1..c34a40358d9 100644 --- a/java/ql/src/Security/CWE/CWE-489/WebviewDebuggingEnabled.ql +++ b/java/ql/src/Security/CWE/CWE-489/WebviewDebuggingEnabled.ql @@ -15,5 +15,5 @@ import semmle.code.java.security.WebviewDebuggingEnabledQuery import WebviewDebugEnabledFlow::PathGraph from WebviewDebugEnabledFlow::PathNode source, WebviewDebugEnabledFlow::PathNode sink -where WebviewDebugEnabledFlow::hasFlowPath(source, sink) +where WebviewDebugEnabledFlow::flowPath(source, sink) select sink, source, sink, "Webview debugging is enabled." diff --git a/java/ql/src/Security/CWE/CWE-749/UnsafeAndroidAccess.ql b/java/ql/src/Security/CWE/CWE-749/UnsafeAndroidAccess.ql index c397bf74b93..6cdcab9d4cc 100644 --- a/java/ql/src/Security/CWE/CWE-749/UnsafeAndroidAccess.ql +++ b/java/ql/src/Security/CWE/CWE-749/UnsafeAndroidAccess.ql @@ -17,6 +17,6 @@ import semmle.code.java.security.UnsafeAndroidAccessQuery import FetchUntrustedResourceFlow::PathGraph from FetchUntrustedResourceFlow::PathNode source, FetchUntrustedResourceFlow::PathNode sink -where FetchUntrustedResourceFlow::hasFlowPath(source, sink) +where FetchUntrustedResourceFlow::flowPath(source, sink) select sink.getNode(), source, sink, "Unsafe resource fetching in Android WebView due to $@.", source.getNode(), sink.getNode().(UrlResourceSink).getSinkType() diff --git a/java/ql/src/Security/CWE/CWE-940/AndroidIntentRedirection.ql b/java/ql/src/Security/CWE/CWE-940/AndroidIntentRedirection.ql index c00915f7172..5fac8c7ecc1 100644 --- a/java/ql/src/Security/CWE/CWE-940/AndroidIntentRedirection.ql +++ b/java/ql/src/Security/CWE/CWE-940/AndroidIntentRedirection.ql @@ -18,7 +18,7 @@ import semmle.code.java.security.AndroidIntentRedirectionQuery import IntentRedirectionFlow::PathGraph from IntentRedirectionFlow::PathNode source, IntentRedirectionFlow::PathNode sink -where IntentRedirectionFlow::hasFlowPath(source, sink) +where IntentRedirectionFlow::flowPath(source, sink) select sink.getNode(), source, sink, "Arbitrary Android activities or services can be started from a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql b/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql index 20c38ea52ee..5bd19fb5b9e 100644 --- a/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql +++ b/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql @@ -6,6 +6,6 @@ class HasFlowTest extends InlineFlowTest { override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { none() } override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { - WebviewDebugEnabledFlow::hasFlow(src, sink) + WebviewDebugEnabledFlow::flow(src, sink) } } diff --git a/java/ql/test/query-tests/security/CWE-749/UnsafeAndroidAccessTest.ql b/java/ql/test/query-tests/security/CWE-749/UnsafeAndroidAccessTest.ql index 158c00e5566..4da1ca7fd5f 100644 --- a/java/ql/test/query-tests/security/CWE-749/UnsafeAndroidAccessTest.ql +++ b/java/ql/test/query-tests/security/CWE-749/UnsafeAndroidAccessTest.ql @@ -9,7 +9,7 @@ class UnsafeAndroidAccessTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasUnsafeAndroidAccess" and - exists(DataFlow::Node sink | FetchUntrustedResourceFlow::hasFlowTo(sink) | + exists(DataFlow::Node sink | FetchUntrustedResourceFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" diff --git a/java/ql/test/query-tests/security/CWE-940/AndroidIntentRedirectionTest.ql b/java/ql/test/query-tests/security/CWE-940/AndroidIntentRedirectionTest.ql index 02e69d025ff..7b74855caa5 100644 --- a/java/ql/test/query-tests/security/CWE-940/AndroidIntentRedirectionTest.ql +++ b/java/ql/test/query-tests/security/CWE-940/AndroidIntentRedirectionTest.ql @@ -9,7 +9,7 @@ class HasAndroidIntentRedirectionTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasAndroidIntentRedirection" and - exists(DataFlow::Node sink | IntentRedirectionFlow::hasFlowTo(sink) | + exists(DataFlow::Node sink | IntentRedirectionFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = ""