}
+ * * @return {!Array<string>}
* */
* Object.keys = function(obj) {};
*
@@ -214,7 +214,7 @@ class ExternalGlobalVarDecl extends ExternalGlobalDecl, VariableDeclarator {
*
* /**
* * @param {!Object} obj
- * * @return {!Array}
+ * * @return {!Array<string>}
* */
* Object.keys = function(obj) {};
*
@@ -273,7 +273,7 @@ class ExternalMemberDecl extends ExternalVarDecl, ExprStmt {
*
* /**
* * @param {!Object} obj
- * * @return {!Array}
+ * * @return {!Array<string>}
* */
* Object.keys = function(obj) {};
*
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll
index f46570b7434..676d4a41f10 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll
@@ -273,7 +273,7 @@ module UnsafeShellCommandConstruction {
}
/**
- * A guard of the form `typeof x === ""`, where is "number", or "boolean",
+ * A guard of the form `typeof x === ""`, where `` is "number", or "boolean",
* which sanitizes `x` in its "then" branch.
*/
class TypeOfSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode {
From 0aa1251ffe47a396224db32e8d72a5d7beaf42ad Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Fri, 29 Apr 2022 02:31:43 +0000
Subject: [PATCH 0163/1274] Add more test cases
---
.../Security/CWE/CWE-552/UnsafeUrlForward.qll | 6 +-
.../semmle/code/java/frameworks/Jsf.qll | 2 +-
.../security/CWE-552/UnsafeResourceGet.java | 64 ++++++++++++++++-
.../security/CWE-552/UnsafeResourceGet2.java | 58 +++++++++++++++
.../CWE-552/UnsafeUrlForward.expected | 70 +++++++++++--------
.../query-tests/security/CWE-552/options | 2 +-
.../jboss-vfs-3.2/org/jboss/vfs/VFS.java | 19 +++++
.../org/jboss/vfs/VirtualFile.java | 29 ++++++++
.../resource/FileResourceManager.java | 31 ++++++++
.../server/handlers/resource/Resource.java | 33 +++++++++
10 files changed, 281 insertions(+), 33 deletions(-)
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-552/UnsafeResourceGet2.java
create mode 100644 java/ql/test/stubs/jboss-vfs-3.2/org/jboss/vfs/VFS.java
create mode 100644 java/ql/test/stubs/jboss-vfs-3.2/org/jboss/vfs/VirtualFile.java
create mode 100644 java/ql/test/stubs/undertow-io-2.2/io/undertow/server/handlers/resource/FileResourceManager.java
create mode 100644 java/ql/test/stubs/undertow-io-2.2/io/undertow/server/handlers/resource/Resource.java
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
index 2ee7188f313..c741eabcaa5 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
@@ -160,7 +160,7 @@ private class ServletGetPathSource extends SourceModelCsv {
}
}
-/** Taint model related to `java.nio.file.Path`. */
+/** Taint model related to `java.nio.file.Path` and `io.undertow.server.handlers.resource.Resource`. */
private class FilePathFlowStep extends SummaryModelCsv {
override predicate row(string row) {
row =
@@ -168,7 +168,9 @@ private class FilePathFlowStep extends SummaryModelCsv {
"java.nio.file;Paths;true;get;;;Argument[0..1];ReturnValue;taint",
"java.nio.file;Path;true;resolve;;;Argument[-1..0];ReturnValue;taint",
"java.nio.file;Path;true;normalize;;;Argument[-1];ReturnValue;taint",
- "java.nio.file;Path;true;toString;;;Argument[-1];ReturnValue;taint"
+ "io.undertow.server.handlers.resource;Resource;true;getFile;;;Argument[-1];ReturnValue;taint",
+ "io.undertow.server.handlers.resource;Resource;true;getFilePath;;;Argument[-1];ReturnValue;taint",
+ "io.undertow.server.handlers.resource;Resource;true;getPath;;;Argument[-1];ReturnValue;taint"
]
}
}
diff --git a/java/ql/src/experimental/semmle/code/java/frameworks/Jsf.qll b/java/ql/src/experimental/semmle/code/java/frameworks/Jsf.qll
index 4701d6ca565..a013c341c67 100644
--- a/java/ql/src/experimental/semmle/code/java/frameworks/Jsf.qll
+++ b/java/ql/src/experimental/semmle/code/java/frameworks/Jsf.qll
@@ -2,7 +2,7 @@
* Provides classes and predicates for working with the Java Server Faces (JSF).
*/
-import semmle.code.java.Type
+import java
/**
* The JSF class `ExternalContext` for processing HTTP requests.
diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeResourceGet.java b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeResourceGet.java
index ae22a7e7d0f..64c23334f18 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeResourceGet.java
+++ b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeResourceGet.java
@@ -5,7 +5,9 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.net.URI;
import java.net.URL;
+import java.net.URISyntaxException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@@ -15,6 +17,11 @@ import javax.servlet.ServletException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
+import io.undertow.server.handlers.resource.FileResourceManager;
+import io.undertow.server.handlers.resource.Resource;
+import org.jboss.vfs.VFS;
+import org.jboss.vfs.VirtualFile;
+
public class UnsafeResourceGet extends HttpServlet {
private static final String BASE_PATH = "/pages";
@@ -137,7 +144,7 @@ public class UnsafeResourceGet extends HttpServlet {
ServletOutputStream out = response.getOutputStream();
// A sample request /fake.jsp/../../../WEB-INF/web.xml can load the web.xml file
- // Note the class is in two levels of subpackages and `Class.loadResource` starts from its own directory
+ // Note the class is in two levels of subpackages and `Class.getResource` starts from its own directory
URL url = getClass().getResource(requestUrl);
InputStream in = url.openStream();
@@ -205,4 +212,59 @@ public class UnsafeResourceGet extends HttpServlet {
}
}
}
+
+ // BAD: getResource constructed from `ClassLoader` without input validation
+ protected void doPutBad(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ String requestUrl = request.getParameter("requestURL");
+ ServletOutputStream out = response.getOutputStream();
+
+ // A sample request /fake.jsp/../../../WEB-INF/web.xml can load the web.xml file
+ // Note the class is in two levels of subpackages and `ClassLoader.getResource` starts from its own directory
+ URL url = getClass().getClassLoader().getResource(requestUrl);
+
+ InputStream in = url.openStream();
+ byte[] buf = new byte[4 * 1024]; // 4K buffer
+ int bytesRead;
+ while ((bytesRead = in.read(buf)) != -1) {
+ out.write(buf, 0, bytesRead);
+ }
+ }
+
+ // BAD: getResource constructed using Undertow IO without input validation
+ protected void doPutBad2(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ String requestPath = request.getParameter("requestPath");
+
+ try {
+ FileResourceManager rm = new FileResourceManager(VFS.getChild(new URI("/usr/share")).getPhysicalFile());
+ Resource rs = rm.getResource(requestPath);
+
+ VirtualFile overlay = VFS.getChild(new URI("EAP_HOME/modules/"));
+ // Do file operations
+ overlay.getChild(rs.getPath());
+ } catch (URISyntaxException ue) {
+ throw new IOException("Cannot parse the URI");
+ }
+ }
+
+ // GOOD: getResource constructed using Undertow IO with input validation
+ protected void doPutGood2(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ String requestPath = request.getParameter("requestPath");
+
+ try {
+ FileResourceManager rm = new FileResourceManager(VFS.getChild(new URI("/usr/share")).getPhysicalFile());
+ Resource rs = rm.getResource(requestPath);
+
+ VirtualFile overlay = VFS.getChild(new URI("EAP_HOME/modules/"));
+ String path = rs.getPath();
+ if (path.startsWith("/trusted_path") && !path.contains("..")) {
+ // Do file operations
+ overlay.getChild(path);
+ }
+ } catch (URISyntaxException ue) {
+ throw new IOException("Cannot parse the URI");
+ }
+ }
}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeResourceGet2.java b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeResourceGet2.java
new file mode 100644
index 00000000000..b3d041d024c
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeResourceGet2.java
@@ -0,0 +1,58 @@
+package com.example;
+
+import javax.faces.context.FacesContext;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Map;
+
+/** Sample class of JSF managed bean */
+public class UnsafeResourceGet2 {
+ // BAD: getResourceAsStream constructed from `ExternalContext` without input validation
+ public String parameterActionBad1() throws IOException {
+ FacesContext fc = FacesContext.getCurrentInstance();
+ Map params = fc.getExternalContext().getRequestParameterMap();
+ String loadUrl = params.get("loadUrl");
+
+ InputStreamReader isr = new InputStreamReader(fc.getExternalContext().getResourceAsStream(loadUrl));
+ BufferedReader br = new BufferedReader(isr);
+ if(br.ready()) {
+ //Do Stuff
+ return "result";
+ }
+
+ return "home";
+ }
+
+ // BAD: getResource constructed from `ExternalContext` without input validation
+ public String parameterActionBad2() throws IOException {
+ FacesContext fc = FacesContext.getCurrentInstance();
+ Map params = fc.getExternalContext().getRequestParameterMap();
+ String loadUrl = params.get("loadUrl");
+
+ URL url = fc.getExternalContext().getResource(loadUrl);
+
+ InputStream in = url.openStream();
+ //Do Stuff
+ return "result";
+ }
+
+ // GOOD: getResource constructed from `ExternalContext` with input validation
+ public String parameterActionGood1() throws IOException {
+ FacesContext fc = FacesContext.getCurrentInstance();
+ Map params = fc.getExternalContext().getRequestParameterMap();
+ String loadUrl = params.get("loadUrl");
+
+ if (loadUrl.equals("/public/crossdomain.xml")) {
+ URL url = fc.getExternalContext().getResource(loadUrl);
+
+ InputStream in = url.openStream();
+ //Do Stuff
+ return "result";
+ }
+
+ return "home";
+ }
+}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected
index 2f136732fdc..202ce9d0cd8 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected
+++ b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected
@@ -1,17 +1,21 @@
edges
| UnsafeRequestPath.java:20:17:20:63 | getServletPath(...) : String | UnsafeRequestPath.java:23:33:23:36 | path |
-| UnsafeResourceGet.java:25:23:25:56 | getParameter(...) : String | UnsafeResourceGet.java:34:20:34:22 | url |
-| UnsafeResourceGet.java:104:24:104:58 | getParameter(...) : String | UnsafeResourceGet.java:108:68:108:78 | requestPath |
-| UnsafeResourceGet.java:136:23:136:56 | getParameter(...) : String | UnsafeResourceGet.java:143:20:143:22 | url |
-| UnsafeResourceGet.java:174:24:174:58 | getParameter(...) : String | UnsafeResourceGet.java:182:68:182:78 | requestPath |
+| UnsafeResourceGet2.java:16:32:16:79 | getRequestParameterMap(...) : Map | UnsafeResourceGet2.java:17:20:17:25 | params : Map |
+| UnsafeResourceGet2.java:17:20:17:25 | params : Map | UnsafeResourceGet2.java:17:20:17:40 | get(...) : Object |
+| UnsafeResourceGet2.java:17:20:17:40 | get(...) : Object | UnsafeResourceGet2.java:19:93:19:99 | loadUrl |
+| UnsafeResourceGet2.java:32:32:32:79 | getRequestParameterMap(...) : Map | UnsafeResourceGet2.java:33:20:33:25 | params : Map |
+| UnsafeResourceGet2.java:33:20:33:25 | params : Map | UnsafeResourceGet2.java:33:20:33:40 | get(...) : Object |
+| UnsafeResourceGet2.java:33:20:33:40 | get(...) : Object | UnsafeResourceGet2.java:37:20:37:22 | url |
+| UnsafeResourceGet.java:32:23:32:56 | getParameter(...) : String | UnsafeResourceGet.java:41:20:41:22 | url |
+| UnsafeResourceGet.java:111:24:111:58 | getParameter(...) : String | UnsafeResourceGet.java:115:68:115:78 | requestPath |
+| UnsafeResourceGet.java:143:23:143:56 | getParameter(...) : String | UnsafeResourceGet.java:150:20:150:22 | url |
+| UnsafeResourceGet.java:181:24:181:58 | getParameter(...) : String | UnsafeResourceGet.java:189:68:189:78 | requestPath |
+| UnsafeResourceGet.java:219:23:219:56 | getParameter(...) : String | UnsafeResourceGet.java:226:20:226:22 | url |
+| UnsafeResourceGet.java:237:24:237:58 | getParameter(...) : String | UnsafeResourceGet.java:245:21:245:22 | rs : Resource |
+| UnsafeResourceGet.java:245:21:245:22 | rs : Resource | UnsafeResourceGet.java:245:21:245:32 | getPath(...) |
| UnsafeServletRequestDispatch.java:23:22:23:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:32:51:32:59 | returnURL |
| UnsafeServletRequestDispatch.java:42:22:42:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL |
| UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:76:53:76:56 | path |
-| UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:107:53:107:56 | path : String |
-| UnsafeServletRequestDispatch.java:107:24:107:57 | resolve(...) : Path | UnsafeServletRequestDispatch.java:107:24:107:69 | normalize(...) : Path |
-| UnsafeServletRequestDispatch.java:107:24:107:69 | normalize(...) : Path | UnsafeServletRequestDispatch.java:110:53:110:65 | requestedPath : Path |
-| UnsafeServletRequestDispatch.java:107:53:107:56 | path : String | UnsafeServletRequestDispatch.java:107:24:107:57 | resolve(...) : Path |
-| UnsafeServletRequestDispatch.java:110:53:110:65 | requestedPath : Path | UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) |
| UnsafeUrlForward.java:13:27:13:36 | url : String | UnsafeUrlForward.java:14:27:14:29 | url |
| UnsafeUrlForward.java:18:27:18:36 | url : String | UnsafeUrlForward.java:20:28:20:30 | url |
| UnsafeUrlForward.java:25:21:25:30 | url : String | UnsafeUrlForward.java:26:23:26:25 | url |
@@ -23,26 +27,33 @@ edges
nodes
| UnsafeRequestPath.java:20:17:20:63 | getServletPath(...) : String | semmle.label | getServletPath(...) : String |
| UnsafeRequestPath.java:23:33:23:36 | path | semmle.label | path |
-| UnsafeResourceGet.java:25:23:25:56 | getParameter(...) : String | semmle.label | getParameter(...) : String |
-| UnsafeResourceGet.java:34:20:34:22 | url | semmle.label | url |
-| UnsafeResourceGet.java:104:24:104:58 | getParameter(...) : String | semmle.label | getParameter(...) : String |
-| UnsafeResourceGet.java:108:68:108:78 | requestPath | semmle.label | requestPath |
-| UnsafeResourceGet.java:136:23:136:56 | getParameter(...) : String | semmle.label | getParameter(...) : String |
-| UnsafeResourceGet.java:143:20:143:22 | url | semmle.label | url |
-| UnsafeResourceGet.java:174:24:174:58 | getParameter(...) : String | semmle.label | getParameter(...) : String |
-| UnsafeResourceGet.java:182:68:182:78 | requestPath | semmle.label | requestPath |
+| UnsafeResourceGet2.java:16:32:16:79 | getRequestParameterMap(...) : Map | semmle.label | getRequestParameterMap(...) : Map |
+| UnsafeResourceGet2.java:17:20:17:25 | params : Map | semmle.label | params : Map |
+| UnsafeResourceGet2.java:17:20:17:40 | get(...) : Object | semmle.label | get(...) : Object |
+| UnsafeResourceGet2.java:19:93:19:99 | loadUrl | semmle.label | loadUrl |
+| UnsafeResourceGet2.java:32:32:32:79 | getRequestParameterMap(...) : Map | semmle.label | getRequestParameterMap(...) : Map |
+| UnsafeResourceGet2.java:33:20:33:25 | params : Map | semmle.label | params : Map |
+| UnsafeResourceGet2.java:33:20:33:40 | get(...) : Object | semmle.label | get(...) : Object |
+| UnsafeResourceGet2.java:37:20:37:22 | url | semmle.label | url |
+| UnsafeResourceGet.java:32:23:32:56 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| UnsafeResourceGet.java:41:20:41:22 | url | semmle.label | url |
+| UnsafeResourceGet.java:111:24:111:58 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| UnsafeResourceGet.java:115:68:115:78 | requestPath | semmle.label | requestPath |
+| UnsafeResourceGet.java:143:23:143:56 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| UnsafeResourceGet.java:150:20:150:22 | url | semmle.label | url |
+| UnsafeResourceGet.java:181:24:181:58 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| UnsafeResourceGet.java:189:68:189:78 | requestPath | semmle.label | requestPath |
+| UnsafeResourceGet.java:219:23:219:56 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| UnsafeResourceGet.java:226:20:226:22 | url | semmle.label | url |
+| UnsafeResourceGet.java:237:24:237:58 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| UnsafeResourceGet.java:245:21:245:22 | rs : Resource | semmle.label | rs : Resource |
+| UnsafeResourceGet.java:245:21:245:32 | getPath(...) | semmle.label | getPath(...) |
| UnsafeServletRequestDispatch.java:23:22:23:54 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| UnsafeServletRequestDispatch.java:32:51:32:59 | returnURL | semmle.label | returnURL |
| UnsafeServletRequestDispatch.java:42:22:42:54 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL | semmle.label | returnURL |
| UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| UnsafeServletRequestDispatch.java:76:53:76:56 | path | semmle.label | path |
-| UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
-| UnsafeServletRequestDispatch.java:107:24:107:57 | resolve(...) : Path | semmle.label | resolve(...) : Path |
-| UnsafeServletRequestDispatch.java:107:24:107:69 | normalize(...) : Path | semmle.label | normalize(...) : Path |
-| UnsafeServletRequestDispatch.java:107:53:107:56 | path : String | semmle.label | path : String |
-| UnsafeServletRequestDispatch.java:110:53:110:65 | requestedPath : Path | semmle.label | requestedPath : Path |
-| UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) | semmle.label | toString(...) |
| UnsafeUrlForward.java:13:27:13:36 | url : String | semmle.label | url : String |
| UnsafeUrlForward.java:14:27:14:29 | url | semmle.label | url |
| UnsafeUrlForward.java:18:27:18:36 | url : String | semmle.label | url : String |
@@ -61,14 +72,17 @@ nodes
subpaths
#select
| UnsafeRequestPath.java:23:33:23:36 | path | UnsafeRequestPath.java:20:17:20:63 | getServletPath(...) : String | UnsafeRequestPath.java:23:33:23:36 | path | Potentially untrusted URL forward due to $@. | UnsafeRequestPath.java:20:17:20:63 | getServletPath(...) | user-provided value |
-| UnsafeResourceGet.java:34:20:34:22 | url | UnsafeResourceGet.java:25:23:25:56 | getParameter(...) : String | UnsafeResourceGet.java:34:20:34:22 | url | Potentially untrusted URL forward due to $@. | UnsafeResourceGet.java:25:23:25:56 | getParameter(...) | user-provided value |
-| UnsafeResourceGet.java:108:68:108:78 | requestPath | UnsafeResourceGet.java:104:24:104:58 | getParameter(...) : String | UnsafeResourceGet.java:108:68:108:78 | requestPath | Potentially untrusted URL forward due to $@. | UnsafeResourceGet.java:104:24:104:58 | getParameter(...) | user-provided value |
-| UnsafeResourceGet.java:143:20:143:22 | url | UnsafeResourceGet.java:136:23:136:56 | getParameter(...) : String | UnsafeResourceGet.java:143:20:143:22 | url | Potentially untrusted URL forward due to $@. | UnsafeResourceGet.java:136:23:136:56 | getParameter(...) | user-provided value |
-| UnsafeResourceGet.java:182:68:182:78 | requestPath | UnsafeResourceGet.java:174:24:174:58 | getParameter(...) : String | UnsafeResourceGet.java:182:68:182:78 | requestPath | Potentially untrusted URL forward due to $@. | UnsafeResourceGet.java:174:24:174:58 | getParameter(...) | user-provided value |
+| UnsafeResourceGet2.java:19:93:19:99 | loadUrl | UnsafeResourceGet2.java:16:32:16:79 | getRequestParameterMap(...) : Map | UnsafeResourceGet2.java:19:93:19:99 | loadUrl | Potentially untrusted URL forward due to $@. | UnsafeResourceGet2.java:16:32:16:79 | getRequestParameterMap(...) | user-provided value |
+| UnsafeResourceGet2.java:37:20:37:22 | url | UnsafeResourceGet2.java:32:32:32:79 | getRequestParameterMap(...) : Map | UnsafeResourceGet2.java:37:20:37:22 | url | Potentially untrusted URL forward due to $@. | UnsafeResourceGet2.java:32:32:32:79 | getRequestParameterMap(...) | user-provided value |
+| UnsafeResourceGet.java:41:20:41:22 | url | UnsafeResourceGet.java:32:23:32:56 | getParameter(...) : String | UnsafeResourceGet.java:41:20:41:22 | url | Potentially untrusted URL forward due to $@. | UnsafeResourceGet.java:32:23:32:56 | getParameter(...) | user-provided value |
+| UnsafeResourceGet.java:115:68:115:78 | requestPath | UnsafeResourceGet.java:111:24:111:58 | getParameter(...) : String | UnsafeResourceGet.java:115:68:115:78 | requestPath | Potentially untrusted URL forward due to $@. | UnsafeResourceGet.java:111:24:111:58 | getParameter(...) | user-provided value |
+| UnsafeResourceGet.java:150:20:150:22 | url | UnsafeResourceGet.java:143:23:143:56 | getParameter(...) : String | UnsafeResourceGet.java:150:20:150:22 | url | Potentially untrusted URL forward due to $@. | UnsafeResourceGet.java:143:23:143:56 | getParameter(...) | user-provided value |
+| UnsafeResourceGet.java:189:68:189:78 | requestPath | UnsafeResourceGet.java:181:24:181:58 | getParameter(...) : String | UnsafeResourceGet.java:189:68:189:78 | requestPath | Potentially untrusted URL forward due to $@. | UnsafeResourceGet.java:181:24:181:58 | getParameter(...) | user-provided value |
+| UnsafeResourceGet.java:226:20:226:22 | url | UnsafeResourceGet.java:219:23:219:56 | getParameter(...) : String | UnsafeResourceGet.java:226:20:226:22 | url | Potentially untrusted URL forward due to $@. | UnsafeResourceGet.java:219:23:219:56 | getParameter(...) | user-provided value |
+| UnsafeResourceGet.java:245:21:245:32 | getPath(...) | UnsafeResourceGet.java:237:24:237:58 | getParameter(...) : String | UnsafeResourceGet.java:245:21:245:32 | getPath(...) | Potentially untrusted URL forward due to $@. | UnsafeResourceGet.java:237:24:237:58 | getParameter(...) | user-provided value |
| UnsafeServletRequestDispatch.java:32:51:32:59 | returnURL | UnsafeServletRequestDispatch.java:23:22:23:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:32:51:32:59 | returnURL | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:23:22:23:54 | getParameter(...) | user-provided value |
| UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL | UnsafeServletRequestDispatch.java:42:22:42:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:42:22:42:54 | getParameter(...) | user-provided value |
| UnsafeServletRequestDispatch.java:76:53:76:56 | path | UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:76:53:76:56 | path | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) | user-provided value |
-| UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) | UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) | user-provided value |
| UnsafeUrlForward.java:14:27:14:29 | url | UnsafeUrlForward.java:13:27:13:36 | url : String | UnsafeUrlForward.java:14:27:14:29 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:13:27:13:36 | url | user-provided value |
| UnsafeUrlForward.java:20:28:20:30 | url | UnsafeUrlForward.java:18:27:18:36 | url : String | UnsafeUrlForward.java:20:28:20:30 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:18:27:18:36 | url | user-provided value |
| UnsafeUrlForward.java:26:23:26:25 | url | UnsafeUrlForward.java:25:21:25:30 | url : String | UnsafeUrlForward.java:26:23:26:25 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:25:21:25:30 | url | user-provided value |
diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/options b/java/ql/test/experimental/query-tests/security/CWE-552/options
index ba166b547a0..095b86c3e9a 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-552/options
+++ b/java/ql/test/experimental/query-tests/security/CWE-552/options
@@ -1 +1 @@
-//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/springframework-5.3.8/
\ No newline at end of file
+//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/springframework-5.3.8/:${testdir}/../../../../stubs/javax-faces-2.3/:${testdir}/../../../../stubs/undertow-io-2.2/:${testdir}/../../../../stubs/jboss-vfs-3.2/
diff --git a/java/ql/test/stubs/jboss-vfs-3.2/org/jboss/vfs/VFS.java b/java/ql/test/stubs/jboss-vfs-3.2/org/jboss/vfs/VFS.java
new file mode 100644
index 00000000000..e3528239558
--- /dev/null
+++ b/java/ql/test/stubs/jboss-vfs-3.2/org/jboss/vfs/VFS.java
@@ -0,0 +1,19 @@
+package org.jboss.vfs;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+public class VFS {
+ public static VirtualFile getChild(URL url) throws URISyntaxException {
+ return null;
+ }
+
+ public static VirtualFile getChild(URI uri) {
+ return null;
+ }
+
+ public static VirtualFile getChild(String path) {
+ return null;
+ }
+}
diff --git a/java/ql/test/stubs/jboss-vfs-3.2/org/jboss/vfs/VirtualFile.java b/java/ql/test/stubs/jboss-vfs-3.2/org/jboss/vfs/VirtualFile.java
new file mode 100644
index 00000000000..ff6c17caff6
--- /dev/null
+++ b/java/ql/test/stubs/jboss-vfs-3.2/org/jboss/vfs/VirtualFile.java
@@ -0,0 +1,29 @@
+package org.jboss.vfs;
+
+import java.io.File;
+import java.io.IOException;
+
+public class VirtualFile {
+ VirtualFile(String name, VirtualFile parent) {
+ }
+
+ public String getName() {
+ return null;
+ }
+
+ public String getPathName() {
+ return null;
+ }
+
+ String getPathName(boolean url) {
+ return null;
+ }
+
+ public File getPhysicalFile() throws IOException {
+ return null;
+ }
+
+ public VirtualFile getChild(String path) {
+ return null;
+ }
+}
diff --git a/java/ql/test/stubs/undertow-io-2.2/io/undertow/server/handlers/resource/FileResourceManager.java b/java/ql/test/stubs/undertow-io-2.2/io/undertow/server/handlers/resource/FileResourceManager.java
new file mode 100644
index 00000000000..815222f2f9f
--- /dev/null
+++ b/java/ql/test/stubs/undertow-io-2.2/io/undertow/server/handlers/resource/FileResourceManager.java
@@ -0,0 +1,31 @@
+package io.undertow.server.handlers.resource;
+
+import java.io.File;
+
+public class FileResourceManager {
+ public FileResourceManager(final File base) {
+ }
+
+ public FileResourceManager(final File base, long transferMinSize) {
+ }
+
+ public FileResourceManager(final File base, long transferMinSize, boolean caseSensitive) {
+ }
+
+ public FileResourceManager(final File base, long transferMinSize, boolean followLinks, final String... safePaths) {
+ }
+
+ protected FileResourceManager(long transferMinSize, boolean caseSensitive, boolean followLinks, final String... safePaths) {
+ }
+
+ public FileResourceManager(final File base, long transferMinSize, boolean caseSensitive, boolean followLinks, final String... safePaths) {
+ }
+
+ public File getBase() {
+ return null;
+ }
+
+ public Resource getResource(final String p) {
+ return null;
+ }
+}
diff --git a/java/ql/test/stubs/undertow-io-2.2/io/undertow/server/handlers/resource/Resource.java b/java/ql/test/stubs/undertow-io-2.2/io/undertow/server/handlers/resource/Resource.java
new file mode 100644
index 00000000000..579e08107c6
--- /dev/null
+++ b/java/ql/test/stubs/undertow-io-2.2/io/undertow/server/handlers/resource/Resource.java
@@ -0,0 +1,33 @@
+package io.undertow.server.handlers.resource;
+
+import java.io.File;
+import java.net.URL;
+import java.nio.file.Path;
+import java.util.Date;
+import java.util.List;
+
+public interface Resource {
+ String getPath();
+
+ Date getLastModified();
+
+ String getLastModifiedString();
+
+ String getName();
+
+ boolean isDirectory();
+
+ List list();
+
+ Long getContentLength();
+
+ File getFile();
+
+ Path getFilePath();
+
+ File getResourceManagerRoot();
+
+ Path getResourceManagerRootPath();
+
+ URL getUrl();
+}
From 33d499c12db1c7b2c19eff664beb72677c048d51 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Fri, 29 Apr 2022 08:50:11 +0100
Subject: [PATCH 0164/1274] C++: Address review comments.
---
cpp/ql/src/Security/CWE/CWE-611/XXE.ql | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/cpp/ql/src/Security/CWE/CWE-611/XXE.ql b/cpp/ql/src/Security/CWE/CWE-611/XXE.ql
index 20d979fd8c8..be626795db4 100644
--- a/cpp/ql/src/Security/CWE/CWE-611/XXE.ql
+++ b/cpp/ql/src/Security/CWE/CWE-611/XXE.ql
@@ -59,8 +59,8 @@ class XercesDOMParserClass extends Class {
/**
* The `SAXParser` class.
*/
-class SAXParser extends Class {
- SAXParser() { this.hasName("SAXParser") }
+class SAXParserClass extends Class {
+ SAXParserClass() { this.hasName("SAXParser") }
}
/**
@@ -112,7 +112,7 @@ class DisableDefaultEntityResolutionTranformer extends XXEFlowStateTranformer {
call.getTarget() = f and
(
f.getDeclaringType() instanceof AbstractDOMParserClass or
- f.getDeclaringType() instanceof SAXParser
+ f.getDeclaringType() instanceof SAXParserClass
) and
f.hasName("setDisableDefaultEntityResolution") and
this = call.getQualifier() and
@@ -172,7 +172,7 @@ class CreateEntityReferenceNodesTranformer extends XXEFlowStateTranformer {
class ParseFunction extends Function {
ParseFunction() {
this.getClassAndName("parse") instanceof AbstractDOMParserClass or
- this.getClassAndName("parse") instanceof SAXParser
+ this.getClassAndName("parse") instanceof SAXParserClass
}
}
@@ -213,9 +213,9 @@ class XXEConfiguration extends DataFlow::Configuration {
// source is the write on `this` of a call to the `SAXParser`
// constructor.
exists(CallInstruction call |
+ call.getStaticCallTarget() = any(SAXParserClass c).getAConstructor() and
node.asInstruction().(WriteSideEffectInstruction).getDestinationAddress() =
call.getThisArgument() and
- call.getStaticCallTarget().(Constructor).getDeclaringType() instanceof SAXParser and
encodeXercesFlowState(flowstate, 0, 1) // default configuration
)
}
From 215453e4db951b8d6e858cac8e5494d5ac1756ed Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Fri, 29 Apr 2022 09:07:25 +0100
Subject: [PATCH 0165/1274] Update cpp/ql/src/Security/CWE/CWE-611/XXE.ql
Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com>
---
cpp/ql/src/Security/CWE/CWE-611/XXE.ql | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cpp/ql/src/Security/CWE/CWE-611/XXE.ql b/cpp/ql/src/Security/CWE/CWE-611/XXE.ql
index be626795db4..76247cf7c49 100644
--- a/cpp/ql/src/Security/CWE/CWE-611/XXE.ql
+++ b/cpp/ql/src/Security/CWE/CWE-611/XXE.ql
@@ -91,7 +91,7 @@ predicate encodeXercesFlowState(
}
/**
- * A flow state representing the configuration of a `AbstractDOMParser` or
+ * A flow state representing the configuration of an `AbstractDOMParser` or
* `SAXParser` object.
*/
class XercesFlowState extends XXEFlowState {
From 7fb1069d69b0cff278250c7d05de52f6c13f2e2a Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Fri, 29 Apr 2022 09:54:47 +0100
Subject: [PATCH 0166/1274] C++: Use GVN on the values passed into set*
functions.
---
cpp/ql/src/Security/CWE/CWE-611/XXE.ql | 9 +++++----
.../test/query-tests/Security/CWE/CWE-611/XXE.expected | 4 ----
cpp/ql/test/query-tests/Security/CWE/CWE-611/tests2.cpp | 2 +-
3 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/cpp/ql/src/Security/CWE/CWE-611/XXE.ql b/cpp/ql/src/Security/CWE/CWE-611/XXE.ql
index 76247cf7c49..805f3a61277 100644
--- a/cpp/ql/src/Security/CWE/CWE-611/XXE.ql
+++ b/cpp/ql/src/Security/CWE/CWE-611/XXE.ql
@@ -16,6 +16,7 @@ import cpp
import semmle.code.cpp.ir.dataflow.DataFlow
import DataFlow::PathGraph
import semmle.code.cpp.ir.IR
+import semmle.code.cpp.valuenumbering.GlobalValueNumbering
/**
* A flow state representing a possible configuration of an XML object.
@@ -124,10 +125,10 @@ class DisableDefaultEntityResolutionTranformer extends XXEFlowStateTranformer {
exists(int createEntityReferenceNodes |
encodeXercesFlowState(flowstate, _, createEntityReferenceNodes) and
(
- newValue.getValue().toInt() = 1 and // true
+ globalValueNumber(newValue).getAnExpr().getValue().toInt() = 1 and // true
encodeXercesFlowState(result, 1, createEntityReferenceNodes)
or
- not newValue.getValue().toInt() = 1 and // false or unknown
+ not globalValueNumber(newValue).getAnExpr().getValue().toInt() = 1 and // false or unknown
encodeXercesFlowState(result, 0, createEntityReferenceNodes)
)
)
@@ -156,10 +157,10 @@ class CreateEntityReferenceNodesTranformer extends XXEFlowStateTranformer {
exists(int disabledDefaultEntityResolution |
encodeXercesFlowState(flowstate, disabledDefaultEntityResolution, _) and
(
- newValue.getValue().toInt() = 1 and // true
+ globalValueNumber(newValue).getAnExpr().getValue().toInt() = 1 and // true
encodeXercesFlowState(result, disabledDefaultEntityResolution, 1)
or
- not newValue.getValue().toInt() = 1 and // false or unknown
+ not globalValueNumber(newValue).getAnExpr().getValue().toInt() = 1 and // false or unknown
encodeXercesFlowState(result, disabledDefaultEntityResolution, 0)
)
)
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected
index f6360956a5f..25f1ad8e1ab 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected
@@ -1,7 +1,6 @@
edges
| tests2.cpp:20:17:20:31 | SAXParser output argument | tests2.cpp:22:2:22:2 | p |
| tests2.cpp:33:17:33:31 | SAXParser output argument | tests2.cpp:37:2:37:2 | p |
-| tests2.cpp:41:17:41:31 | SAXParser output argument | tests2.cpp:45:2:45:2 | p |
| tests.cpp:33:23:33:43 | XercesDOMParser output argument | tests.cpp:35:2:35:2 | p |
| tests.cpp:46:23:46:43 | XercesDOMParser output argument | tests.cpp:49:2:49:2 | p |
| tests.cpp:53:19:53:19 | VariableAddress [post update] | tests.cpp:55:2:55:2 | p |
@@ -34,8 +33,6 @@ nodes
| tests2.cpp:22:2:22:2 | p | semmle.label | p |
| tests2.cpp:33:17:33:31 | SAXParser output argument | semmle.label | SAXParser output argument |
| tests2.cpp:37:2:37:2 | p | semmle.label | p |
-| tests2.cpp:41:17:41:31 | SAXParser output argument | semmle.label | SAXParser output argument |
-| tests2.cpp:45:2:45:2 | p | semmle.label | p |
| tests.cpp:33:23:33:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:35:2:35:2 | p | semmle.label | p |
| tests.cpp:46:23:46:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
@@ -77,7 +74,6 @@ subpaths
#select
| tests2.cpp:22:2:22:2 | p | tests2.cpp:20:17:20:31 | SAXParser output argument | tests2.cpp:22:2:22:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:20:17:20:31 | SAXParser output argument | XML parser |
| tests2.cpp:37:2:37:2 | p | tests2.cpp:33:17:33:31 | SAXParser output argument | tests2.cpp:37:2:37:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:33:17:33:31 | SAXParser output argument | XML parser |
-| tests2.cpp:45:2:45:2 | p | tests2.cpp:41:17:41:31 | SAXParser output argument | tests2.cpp:45:2:45:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:41:17:41:31 | SAXParser output argument | XML parser |
| tests.cpp:35:2:35:2 | p | tests.cpp:33:23:33:43 | XercesDOMParser output argument | tests.cpp:35:2:35:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:33:23:33:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:49:2:49:2 | p | tests.cpp:46:23:46:43 | XercesDOMParser output argument | tests.cpp:49:2:49:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:46:23:46:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:57:2:57:2 | p | tests.cpp:53:23:53:43 | XercesDOMParser output argument | tests.cpp:57:2:57:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:53:23:53:43 | XercesDOMParser output argument | XML parser |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests2.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests2.cpp
index d5a495b29aa..758cb57b26e 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests2.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests2.cpp
@@ -42,5 +42,5 @@ void test2_4(InputSource &data) {
bool v = true;
p->setDisableDefaultEntityResolution(v);
- p->parse(data); // GOOD [FALSE POSITIVE]
+ p->parse(data); // GOOD
}
From a1542322e279225a326313cb936e150f91fbe04a Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 28 Apr 2022 09:39:33 +0100
Subject: [PATCH 0167/1274] C++: Add test cases for SAX2XMLReader.
---
.../Security/CWE/CWE-611/tests3.cpp | 65 +++++++++++++++++++
1 file changed, 65 insertions(+)
create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-611/tests3.cpp
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests3.cpp
new file mode 100644
index 00000000000..bcece961d56
--- /dev/null
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests3.cpp
@@ -0,0 +1,65 @@
+// test cases for rule CWE-611
+
+#include "tests.h"
+
+// ---
+
+typedef unsigned int XMLCh;
+
+class XMLUni
+{
+public:
+ static const XMLCh fgXercesDisableDefaultEntityResolution[];
+};
+
+class SAX2XMLReader
+{
+public:
+ void setFeature(const XMLCh *feature, bool value);
+ void parse(const InputSource &data);
+};
+
+class XMLReaderFactory
+{
+public:
+ static SAX2XMLReader *createXMLReader();
+};
+
+// ---
+
+void test3_1(InputSource &data) {
+ SAX2XMLReader *p = XMLReaderFactory::createXMLReader();
+
+ p->parse(data); // BAD (parser not correctly configured) [NOT DETECTED]
+}
+
+void test3_2(InputSource &data) {
+ SAX2XMLReader *p = XMLReaderFactory::createXMLReader();
+
+ p->setFeature(XMLUni::fgXercesDisableDefaultEntityResolution, true);
+ p->parse(data); // GOOD
+}
+
+SAX2XMLReader *p_3_3 = XMLReaderFactory::createXMLReader();
+
+void test3_3(InputSource &data) {
+ p_3_3->parse(data); // BAD (parser not correctly configured) [NOT DETECTED]
+}
+
+SAX2XMLReader *p_3_4 = XMLReaderFactory::createXMLReader();
+
+void test3_4(InputSource &data) {
+ p_3_4->setFeature(XMLUni::fgXercesDisableDefaultEntityResolution, true);
+ p_3_4->parse(data); // GOOD
+}
+
+SAX2XMLReader *p_3_5 = XMLReaderFactory::createXMLReader();
+
+void test3_5_init() {
+ p_3_5->setFeature(XMLUni::fgXercesDisableDefaultEntityResolution, true);
+}
+
+void test3_5(InputSource &data) {
+ test3_5_init();
+ p_3_5->parse(data); // GOOD
+}
From b02519bf0bb9c6d79ed01387466673c559a84293 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 28 Apr 2022 16:35:31 +0100
Subject: [PATCH 0168/1274] C++: Make the createLSParser test a bit closer to
real life.
---
.../Security/CWE/CWE-611/XXE.expected | 6 ++--
.../Security/CWE/CWE-611/tests.cpp | 30 ++++++++++++-------
2 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected
index 25f1ad8e1ab..083fa5f673e 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected
@@ -27,7 +27,7 @@ edges
| tests.cpp:140:23:140:43 | XercesDOMParser output argument | tests.cpp:146:18:146:18 | q |
| tests.cpp:144:18:144:18 | q | tests.cpp:130:39:130:39 | p |
| tests.cpp:146:18:146:18 | q | tests.cpp:134:39:134:39 | p |
-| tests.cpp:150:19:150:32 | call to createLSParser | tests.cpp:152:2:152:2 | p |
+| tests.cpp:150:25:150:38 | call to createLSParser | tests.cpp:152:2:152:2 | p |
nodes
| tests2.cpp:20:17:20:31 | SAXParser output argument | semmle.label | SAXParser output argument |
| tests2.cpp:22:2:22:2 | p | semmle.label | p |
@@ -68,7 +68,7 @@ nodes
| tests.cpp:140:23:140:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:144:18:144:18 | q | semmle.label | q |
| tests.cpp:146:18:146:18 | q | semmle.label | q |
-| tests.cpp:150:19:150:32 | call to createLSParser | semmle.label | call to createLSParser |
+| tests.cpp:150:25:150:38 | call to createLSParser | semmle.label | call to createLSParser |
| tests.cpp:152:2:152:2 | p | semmle.label | p |
subpaths
#select
@@ -85,4 +85,4 @@ subpaths
| tests.cpp:122:3:122:3 | q | tests.cpp:118:24:118:44 | XercesDOMParser output argument | tests.cpp:122:3:122:3 | q | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:118:24:118:44 | XercesDOMParser output argument | XML parser |
| tests.cpp:131:2:131:2 | p | tests.cpp:140:23:140:43 | XercesDOMParser output argument | tests.cpp:131:2:131:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:140:23:140:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:135:2:135:2 | p | tests.cpp:140:23:140:43 | XercesDOMParser output argument | tests.cpp:135:2:135:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:140:23:140:43 | XercesDOMParser output argument | XML parser |
-| tests.cpp:152:2:152:2 | p | tests.cpp:150:19:150:32 | call to createLSParser | tests.cpp:152:2:152:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:150:19:150:32 | call to createLSParser | XML parser |
+| tests.cpp:152:2:152:2 | p | tests.cpp:150:25:150:38 | call to createLSParser | tests.cpp:152:2:152:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:150:25:150:38 | call to createLSParser | XML parser |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.cpp
index 76ceb7b7556..ec822b44a20 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.cpp
@@ -4,9 +4,6 @@
// ---
-
-
-
class AbstractDOMParser {
public:
AbstractDOMParser();
@@ -25,7 +22,10 @@ public:
class DOMLSParser : public AbstractDOMParser {
};
-DOMLSParser *createLSParser();
+class DOMImplementationLS {
+public:
+ DOMLSParser *createLSParser();
+};
// ---
@@ -146,25 +146,33 @@ void test10(InputSource &data) {
test10_doParseC(q, data);
}
-void test11(InputSource &data) {
- DOMLSParser *p = createLSParser();
+void test11(DOMImplementationLS *impl, InputSource &data) {
+ DOMLSParser *p = impl->createLSParser();
p->parse(data); // BAD (parser not correctly configured)
}
-void test12(InputSource &data) {
- DOMLSParser *p = createLSParser();
+void test12(DOMImplementationLS *impl, InputSource &data) {
+ DOMLSParser *p = impl->createLSParser();
p->setDisableDefaultEntityResolution(true);
p->parse(data); // GOOD
}
-DOMLSParser *g_p1 = createLSParser();
-DOMLSParser *g_p2 = createLSParser();
+DOMImplementationLS *g_impl;
+DOMLSParser *g_p1, *g_p2;
InputSource *g_data;
-void test13() {
+void test13_init() {
+ g_p1 = g_impl->createLSParser();
g_p1->setDisableDefaultEntityResolution(true);
+
+ g_p2 = g_impl->createLSParser();
+}
+
+void test13() {
+ test13_init();
+
g_p1->parse(*g_data); // GOOD
g_p2->parse(*g_data); // BAD (parser not correctly configured) [NOT DETECTED]
}
From 397efd1648e66342b3accacddbdc1448893ee3b1 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 28 Apr 2022 16:56:00 +0100
Subject: [PATCH 0169/1274] C++: Split off the createLSParser tests into their
own file.
---
.../Security/CWE/CWE-611/XXE.expected | 8 +--
.../Security/CWE/CWE-611/tests.cpp | 65 +++++--------------
.../query-tests/Security/CWE/CWE-611/tests.h | 10 +++
.../Security/CWE/CWE-611/tests5.cpp | 46 +++++++++++++
4 files changed, 77 insertions(+), 52 deletions(-)
create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-611/tests5.cpp
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected
index 083fa5f673e..d5353ff057a 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected
@@ -1,6 +1,7 @@
edges
| tests2.cpp:20:17:20:31 | SAXParser output argument | tests2.cpp:22:2:22:2 | p |
| tests2.cpp:33:17:33:31 | SAXParser output argument | tests2.cpp:37:2:37:2 | p |
+| tests5.cpp:18:25:18:38 | call to createLSParser | tests5.cpp:20:2:20:2 | p |
| tests.cpp:33:23:33:43 | XercesDOMParser output argument | tests.cpp:35:2:35:2 | p |
| tests.cpp:46:23:46:43 | XercesDOMParser output argument | tests.cpp:49:2:49:2 | p |
| tests.cpp:53:19:53:19 | VariableAddress [post update] | tests.cpp:55:2:55:2 | p |
@@ -27,12 +28,13 @@ edges
| tests.cpp:140:23:140:43 | XercesDOMParser output argument | tests.cpp:146:18:146:18 | q |
| tests.cpp:144:18:144:18 | q | tests.cpp:130:39:130:39 | p |
| tests.cpp:146:18:146:18 | q | tests.cpp:134:39:134:39 | p |
-| tests.cpp:150:25:150:38 | call to createLSParser | tests.cpp:152:2:152:2 | p |
nodes
| tests2.cpp:20:17:20:31 | SAXParser output argument | semmle.label | SAXParser output argument |
| tests2.cpp:22:2:22:2 | p | semmle.label | p |
| tests2.cpp:33:17:33:31 | SAXParser output argument | semmle.label | SAXParser output argument |
| tests2.cpp:37:2:37:2 | p | semmle.label | p |
+| tests5.cpp:18:25:18:38 | call to createLSParser | semmle.label | call to createLSParser |
+| tests5.cpp:20:2:20:2 | p | semmle.label | p |
| tests.cpp:33:23:33:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:35:2:35:2 | p | semmle.label | p |
| tests.cpp:46:23:46:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
@@ -68,12 +70,11 @@ nodes
| tests.cpp:140:23:140:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:144:18:144:18 | q | semmle.label | q |
| tests.cpp:146:18:146:18 | q | semmle.label | q |
-| tests.cpp:150:25:150:38 | call to createLSParser | semmle.label | call to createLSParser |
-| tests.cpp:152:2:152:2 | p | semmle.label | p |
subpaths
#select
| tests2.cpp:22:2:22:2 | p | tests2.cpp:20:17:20:31 | SAXParser output argument | tests2.cpp:22:2:22:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:20:17:20:31 | SAXParser output argument | XML parser |
| tests2.cpp:37:2:37:2 | p | tests2.cpp:33:17:33:31 | SAXParser output argument | tests2.cpp:37:2:37:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:33:17:33:31 | SAXParser output argument | XML parser |
+| tests5.cpp:20:2:20:2 | p | tests5.cpp:18:25:18:38 | call to createLSParser | tests5.cpp:20:2:20:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:18:25:18:38 | call to createLSParser | XML parser |
| tests.cpp:35:2:35:2 | p | tests.cpp:33:23:33:43 | XercesDOMParser output argument | tests.cpp:35:2:35:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:33:23:33:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:49:2:49:2 | p | tests.cpp:46:23:46:43 | XercesDOMParser output argument | tests.cpp:49:2:49:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:46:23:46:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:57:2:57:2 | p | tests.cpp:53:23:53:43 | XercesDOMParser output argument | tests.cpp:57:2:57:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:53:23:53:43 | XercesDOMParser output argument | XML parser |
@@ -85,4 +86,3 @@ subpaths
| tests.cpp:122:3:122:3 | q | tests.cpp:118:24:118:44 | XercesDOMParser output argument | tests.cpp:122:3:122:3 | q | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:118:24:118:44 | XercesDOMParser output argument | XML parser |
| tests.cpp:131:2:131:2 | p | tests.cpp:140:23:140:43 | XercesDOMParser output argument | tests.cpp:131:2:131:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:140:23:140:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:135:2:135:2 | p | tests.cpp:140:23:140:43 | XercesDOMParser output argument | tests.cpp:135:2:135:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:140:23:140:43 | XercesDOMParser output argument | XML parser |
-| tests.cpp:152:2:152:2 | p | tests.cpp:150:25:150:38 | call to createLSParser | tests.cpp:152:2:152:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:150:25:150:38 | call to createLSParser | XML parser |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.cpp
index ec822b44a20..a2d767e19bd 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.cpp
@@ -1,31 +1,31 @@
-// test cases for rule CWE-611
+// test cases for rule CWE-611 (XercesDOMParser)
#include "tests.h"
// ---
-class AbstractDOMParser {
-public:
- AbstractDOMParser();
-
- void setDisableDefaultEntityResolution(bool); // default is false
- void setCreateEntityReferenceNodes(bool); // default is true
- void setSecurityManager(SecurityManager *const manager);
- void parse(const InputSource &data);
-};
-
class XercesDOMParser: public AbstractDOMParser {
public:
XercesDOMParser();
};
-class DOMLSParser : public AbstractDOMParser {
-};
-class DOMImplementationLS {
-public:
- DOMLSParser *createLSParser();
-};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
// ---
@@ -145,34 +145,3 @@ void test10(InputSource &data) {
test10_doParseC(p, data);
test10_doParseC(q, data);
}
-
-void test11(DOMImplementationLS *impl, InputSource &data) {
- DOMLSParser *p = impl->createLSParser();
-
- p->parse(data); // BAD (parser not correctly configured)
-}
-
-void test12(DOMImplementationLS *impl, InputSource &data) {
- DOMLSParser *p = impl->createLSParser();
-
- p->setDisableDefaultEntityResolution(true);
- p->parse(data); // GOOD
-}
-
-DOMImplementationLS *g_impl;
-DOMLSParser *g_p1, *g_p2;
-InputSource *g_data;
-
-void test13_init() {
- g_p1 = g_impl->createLSParser();
- g_p1->setDisableDefaultEntityResolution(true);
-
- g_p2 = g_impl->createLSParser();
-}
-
-void test13() {
- test13_init();
-
- g_p1->parse(*g_data); // GOOD
- g_p2->parse(*g_data); // BAD (parser not correctly configured) [NOT DETECTED]
-}
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.h b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.h
index aa4c539bbd9..4e5c5b4e6fb 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.h
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.h
@@ -2,3 +2,13 @@
class SecurityManager;
class InputSource;
+
+class AbstractDOMParser {
+public:
+ AbstractDOMParser();
+
+ void setDisableDefaultEntityResolution(bool); // default is false
+ void setCreateEntityReferenceNodes(bool); // default is true
+ void setSecurityManager(SecurityManager *const manager);
+ void parse(const InputSource &data);
+};
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests5.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests5.cpp
new file mode 100644
index 00000000000..3f3bfad92df
--- /dev/null
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests5.cpp
@@ -0,0 +1,46 @@
+// test cases for rule CWE-611 (createLSParser)
+
+#include "tests.h"
+
+// ---
+
+class DOMLSParser : public AbstractDOMParser {
+};
+
+class DOMImplementationLS {
+public:
+ DOMLSParser *createLSParser();
+};
+
+// ---
+
+void test5_1(DOMImplementationLS *impl, InputSource &data) {
+ DOMLSParser *p = impl->createLSParser();
+
+ p->parse(data); // BAD (parser not correctly configured)
+}
+
+void test5_2(DOMImplementationLS *impl, InputSource &data) {
+ DOMLSParser *p = impl->createLSParser();
+
+ p->setDisableDefaultEntityResolution(true);
+ p->parse(data); // GOOD
+}
+
+DOMImplementationLS *g_impl;
+DOMLSParser *g_p1, *g_p2;
+InputSource *g_data;
+
+void test5_3_init() {
+ g_p1 = g_impl->createLSParser();
+ g_p1->setDisableDefaultEntityResolution(true);
+
+ g_p2 = g_impl->createLSParser();
+}
+
+void test5_3() {
+ test5_3_init();
+
+ g_p1->parse(*g_data); // GOOD
+ g_p2->parse(*g_data); // BAD (parser not correctly configured) [NOT DETECTED]
+}
From 4be31618917f67716e32c12ed51c80e82a46f172 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 28 Apr 2022 17:02:26 +0100
Subject: [PATCH 0170/1274] C++: Move some stuff from tests3.cpp to common
tests.h
---
.../query-tests/Security/CWE/CWE-611/tests.h | 8 ++++++++
.../Security/CWE/CWE-611/tests3.cpp | 18 +++++++++---------
2 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.h b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.h
index 4e5c5b4e6fb..0e0d1c9d8c5 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.h
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.h
@@ -12,3 +12,11 @@ public:
void setSecurityManager(SecurityManager *const manager);
void parse(const InputSource &data);
};
+
+typedef unsigned int XMLCh;
+
+class XMLUni
+{
+public:
+ static const XMLCh fgXercesDisableDefaultEntityResolution[];
+};
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests3.cpp
index bcece961d56..3bff5d77866 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests3.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests3.cpp
@@ -1,17 +1,9 @@
-// test cases for rule CWE-611
+// test cases for rule CWE-611 (SAX2XMLReader)
#include "tests.h"
// ---
-typedef unsigned int XMLCh;
-
-class XMLUni
-{
-public:
- static const XMLCh fgXercesDisableDefaultEntityResolution[];
-};
-
class SAX2XMLReader
{
public:
@@ -25,6 +17,14 @@ public:
static SAX2XMLReader *createXMLReader();
};
+
+
+
+
+
+
+
+
// ---
void test3_1(InputSource &data) {
From c6deddb2904f72a713d7f5d172c39fad70800188 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 28 Apr 2022 17:09:32 +0100
Subject: [PATCH 0171/1274] C++: For consistency.
---
cpp/ql/test/query-tests/Security/CWE/CWE-611/tests2.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests2.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests2.cpp
index 758cb57b26e..147be557844 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests2.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests2.cpp
@@ -1,4 +1,4 @@
-// test cases for rule CWE-611
+// test cases for rule CWE-611 (SAXParser)
#include "tests.h"
From 1d71f042db20cc0e59e9c5d95f1c52079b74c337 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 28 Apr 2022 17:14:39 +0100
Subject: [PATCH 0172/1274] C++: Turns out DOMLSParser is not an
AbstractDOMParser and works a little differently than I'd thought.
---
.../Security/CWE/CWE-611/XXE.expected | 4 ----
.../query-tests/Security/CWE/CWE-611/tests5.cpp | 17 +++++++++++++----
2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected
index d5353ff057a..dcf334d5bfe 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected
@@ -1,7 +1,6 @@
edges
| tests2.cpp:20:17:20:31 | SAXParser output argument | tests2.cpp:22:2:22:2 | p |
| tests2.cpp:33:17:33:31 | SAXParser output argument | tests2.cpp:37:2:37:2 | p |
-| tests5.cpp:18:25:18:38 | call to createLSParser | tests5.cpp:20:2:20:2 | p |
| tests.cpp:33:23:33:43 | XercesDOMParser output argument | tests.cpp:35:2:35:2 | p |
| tests.cpp:46:23:46:43 | XercesDOMParser output argument | tests.cpp:49:2:49:2 | p |
| tests.cpp:53:19:53:19 | VariableAddress [post update] | tests.cpp:55:2:55:2 | p |
@@ -33,8 +32,6 @@ nodes
| tests2.cpp:22:2:22:2 | p | semmle.label | p |
| tests2.cpp:33:17:33:31 | SAXParser output argument | semmle.label | SAXParser output argument |
| tests2.cpp:37:2:37:2 | p | semmle.label | p |
-| tests5.cpp:18:25:18:38 | call to createLSParser | semmle.label | call to createLSParser |
-| tests5.cpp:20:2:20:2 | p | semmle.label | p |
| tests.cpp:33:23:33:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
| tests.cpp:35:2:35:2 | p | semmle.label | p |
| tests.cpp:46:23:46:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument |
@@ -74,7 +71,6 @@ subpaths
#select
| tests2.cpp:22:2:22:2 | p | tests2.cpp:20:17:20:31 | SAXParser output argument | tests2.cpp:22:2:22:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:20:17:20:31 | SAXParser output argument | XML parser |
| tests2.cpp:37:2:37:2 | p | tests2.cpp:33:17:33:31 | SAXParser output argument | tests2.cpp:37:2:37:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:33:17:33:31 | SAXParser output argument | XML parser |
-| tests5.cpp:20:2:20:2 | p | tests5.cpp:18:25:18:38 | call to createLSParser | tests5.cpp:20:2:20:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:18:25:18:38 | call to createLSParser | XML parser |
| tests.cpp:35:2:35:2 | p | tests.cpp:33:23:33:43 | XercesDOMParser output argument | tests.cpp:35:2:35:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:33:23:33:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:49:2:49:2 | p | tests.cpp:46:23:46:43 | XercesDOMParser output argument | tests.cpp:49:2:49:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:46:23:46:43 | XercesDOMParser output argument | XML parser |
| tests.cpp:57:2:57:2 | p | tests.cpp:53:23:53:43 | XercesDOMParser output argument | tests.cpp:57:2:57:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:53:23:53:43 | XercesDOMParser output argument | XML parser |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests5.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests5.cpp
index 3f3bfad92df..477107d97fe 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests5.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests5.cpp
@@ -4,7 +4,16 @@
// ---
-class DOMLSParser : public AbstractDOMParser {
+class DOMConfiguration {
+public:
+ void setParameter(const XMLCh *parameter, bool value);
+};
+
+class DOMLSParser {
+public:
+ DOMConfiguration *getDomConfig();
+
+ void parse(const InputSource &data);
};
class DOMImplementationLS {
@@ -17,13 +26,13 @@ public:
void test5_1(DOMImplementationLS *impl, InputSource &data) {
DOMLSParser *p = impl->createLSParser();
- p->parse(data); // BAD (parser not correctly configured)
+ p->parse(data); // BAD (parser not correctly configured) [NOT DETECTED]
}
void test5_2(DOMImplementationLS *impl, InputSource &data) {
DOMLSParser *p = impl->createLSParser();
- p->setDisableDefaultEntityResolution(true);
+ p->getDomConfig()->setParameter(XMLUni::fgXercesDisableDefaultEntityResolution, true);
p->parse(data); // GOOD
}
@@ -33,7 +42,7 @@ InputSource *g_data;
void test5_3_init() {
g_p1 = g_impl->createLSParser();
- g_p1->setDisableDefaultEntityResolution(true);
+ g_p1->getDomConfig()->setParameter(XMLUni::fgXercesDisableDefaultEntityResolution, true);
g_p2 = g_impl->createLSParser();
}
From dd258781ed9c4eaa6dd452a913cdc640a9aad470 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 28 Apr 2022 18:14:39 +0100
Subject: [PATCH 0173/1274] C++: More test cases.
---
.../Security/CWE/CWE-611/tests5.cpp | 29 +++++++++++++++++--
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests5.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests5.cpp
index 477107d97fe..e98d5a99e60 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests5.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests5.cpp
@@ -36,19 +36,42 @@ void test5_2(DOMImplementationLS *impl, InputSource &data) {
p->parse(data); // GOOD
}
+void test5_3(DOMImplementationLS *impl, InputSource &data) {
+ DOMLSParser *p = impl->createLSParser();
+
+ p->getDomConfig()->setParameter(XMLUni::fgXercesDisableDefaultEntityResolution, false);
+ p->parse(data); // BAD (parser not correctly configured) [NOT DETECTED]
+}
+
+void test5_4(DOMImplementationLS *impl, InputSource &data) {
+ DOMLSParser *p = impl->createLSParser();
+ DOMConfiguration *cfg = p->getDomConfig();
+
+ cfg->setParameter(XMLUni::fgXercesDisableDefaultEntityResolution, true);
+ p->parse(data); // GOOD
+}
+
+void test5_5(DOMImplementationLS *impl, InputSource &data) {
+ DOMLSParser *p = impl->createLSParser();
+ DOMConfiguration *cfg = p->getDomConfig();
+
+ cfg->setParameter(XMLUni::fgXercesDisableDefaultEntityResolution, false);
+ p->parse(data); // BAD (parser not correctly configured) [NOT DETECTED]
+}
+
DOMImplementationLS *g_impl;
DOMLSParser *g_p1, *g_p2;
InputSource *g_data;
-void test5_3_init() {
+void test5_6_init() {
g_p1 = g_impl->createLSParser();
g_p1->getDomConfig()->setParameter(XMLUni::fgXercesDisableDefaultEntityResolution, true);
g_p2 = g_impl->createLSParser();
}
-void test5_3() {
- test5_3_init();
+void test5_6() {
+ test5_6_init();
g_p1->parse(*g_data); // GOOD
g_p2->parse(*g_data); // BAD (parser not correctly configured) [NOT DETECTED]
From 812a24fc1846af1247abc7e2710a9b0cb7a871c9 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 28 Apr 2022 12:53:00 +0100
Subject: [PATCH 0174/1274] C++: Add test cases for libxml2.
---
.../query-tests/Security/CWE/CWE-611/tests.h | 2 +
.../Security/CWE/CWE-611/tests4.cpp | 135 ++++++++++++++++++
2 files changed, 137 insertions(+)
create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-611/tests4.cpp
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.h b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.h
index aa4c539bbd9..fa67239a8bc 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.h
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests.h
@@ -2,3 +2,5 @@
class SecurityManager;
class InputSource;
+
+#define NULL (0)
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests4.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests4.cpp
new file mode 100644
index 00000000000..40197d2c0ee
--- /dev/null
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests4.cpp
@@ -0,0 +1,135 @@
+// test cases for rule CWE-611 (libxml2)
+
+#include "tests.h"
+
+// ---
+
+enum xmlParserOption
+{
+ XML_PARSE_NOENT = 2,
+ XML_PARSE_DTDLOAD = 4,
+ XML_PARSE_OPTION_HARMLESS = 8
+};
+
+class xmlDoc;
+
+xmlDoc *xmlReadFile(const char *fileName, const char *encoding, int flags);
+xmlDoc *xmlReadMemory(const char *ptr, int sz, const char *url, const char *encoding, int flags);
+
+void xmlFreeDoc(xmlDoc *ptr);
+
+// ---
+
+void test4_1(const char *fileName) {
+ xmlDoc *p;
+
+ p = xmlReadFile(fileName, NULL, XML_PARSE_NOENT); // BAD (parser not correctly configured) [NOT DETECTED]
+ if (p != NULL)
+ {
+ xmlFreeDoc(p);
+ }
+}
+
+void test4_2(const char *fileName) {
+ xmlDoc *p;
+
+ p = xmlReadFile(fileName, NULL, XML_PARSE_DTDLOAD); // BAD (parser not correctly configured) [NOT DETECTED]
+ if (p != NULL)
+ {
+ xmlFreeDoc(p);
+ }
+}
+
+void test4_3(const char *fileName) {
+ xmlDoc *p;
+
+ p = xmlReadFile(fileName, NULL, XML_PARSE_NOENT | XML_PARSE_DTDLOAD); // BAD (parser not correctly configured) [NOT DETECTED]
+ if (p != NULL)
+ {
+ xmlFreeDoc(p);
+ }
+}
+
+void test4_4(const char *fileName) {
+ xmlDoc *p;
+
+ p = xmlReadFile(fileName, NULL, 0); // GOOD
+ if (p != NULL)
+ {
+ xmlFreeDoc(p);
+ }
+}
+
+void test4_5(const char *fileName) {
+ xmlDoc *p;
+
+ p = xmlReadFile(fileName, NULL, XML_PARSE_OPTION_HARMLESS); // GOOD
+ if (p != NULL)
+ {
+ xmlFreeDoc(p);
+ }
+}
+
+void test4_6(const char *fileName) {
+ xmlDoc *p;
+ int flags = XML_PARSE_NOENT;
+
+ p = xmlReadFile(fileName, NULL, flags); // BAD (parser not correctly configured) [NOT DETECTED]
+ if (p != NULL)
+ {
+ xmlFreeDoc(p);
+ }
+}
+
+void test4_7(const char *fileName) {
+ xmlDoc *p;
+ int flags = 0;
+
+ p = xmlReadFile(fileName, NULL, flags); // GOOD
+ if (p != NULL)
+ {
+ xmlFreeDoc(p);
+ }
+}
+
+void test4_8(const char *fileName) {
+ xmlDoc *p;
+ int flags = XML_PARSE_OPTION_HARMLESS;
+
+ p = xmlReadFile(fileName, NULL, flags | XML_PARSE_NOENT); // BAD (parser not correctly configured) [NOT DETECTED]
+ if (p != NULL)
+ {
+ xmlFreeDoc(p);
+ }
+}
+
+void test4_9(const char *fileName) {
+ xmlDoc *p;
+ int flags = XML_PARSE_NOENT;
+
+ p = xmlReadFile(fileName, NULL, flags | XML_PARSE_OPTION_HARMLESS); // BAD (parser not correctly configured) [NOT DETECTED]
+ if (p != NULL)
+ {
+ xmlFreeDoc(p);
+ }
+}
+
+void test4_10(const char *ptr, int sz) {
+ xmlDoc *p;
+
+ p = xmlReadMemory(ptr, sz, "", NULL, 0); // GOOD
+ if (p != NULL)
+ {
+ xmlFreeDoc(p);
+ }
+}
+
+void test4_11(const char *ptr, int sz) {
+ xmlDoc *p;
+
+ p = xmlReadMemory(ptr, sz, "", NULL, XML_PARSE_DTDLOAD); // BAD (parser not correctly configured) [NOT DETECTED]
+ if (p != NULL)
+ {
+ xmlFreeDoc(p);
+ }
+}
From cf4325c86f7f1fb8d0f4701c483b5dc84a10b6a2 Mon Sep 17 00:00:00 2001
From: Arthur Baars
Date: Fri, 29 Apr 2022 16:19:11 +0200
Subject: [PATCH 0175/1274] Add change note
---
ruby/ql/lib/change-notes/2022-04-30-update-grammar.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 ruby/ql/lib/change-notes/2022-04-30-update-grammar.md
diff --git a/ruby/ql/lib/change-notes/2022-04-30-update-grammar.md b/ruby/ql/lib/change-notes/2022-04-30-update-grammar.md
new file mode 100644
index 00000000000..34a485c94e6
--- /dev/null
+++ b/ruby/ql/lib/change-notes/2022-04-30-update-grammar.md
@@ -0,0 +1,4 @@
+---
+category: fix
+---
+The TreeSitter Ruby grammar has been updated; this fixes several issues where Ruby code was parsed incorrectly.
From c8e0d7f8472557dd8cb8eda2f3169d2d6aebfbdb Mon Sep 17 00:00:00 2001
From: Jonathan Leitschuh
Date: Fri, 29 Apr 2022 14:51:26 -0400
Subject: [PATCH 0176/1274] Summary model for `File` should include overriden
methods
---
java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll
index e5e4c582a66..c1fbbdb275e 100644
--- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll
+++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll
@@ -298,8 +298,8 @@ private predicate summaryModelCsv(string row) {
"java.net;URI;false;toURL;;;Argument[-1];ReturnValue;taint",
"java.net;URI;false;toString;;;Argument[-1];ReturnValue;taint",
"java.net;URI;false;toAsciiString;;;Argument[-1];ReturnValue;taint",
- "java.io;File;false;toURI;;;Argument[-1];ReturnValue;taint",
- "java.io;File;false;toPath;;;Argument[-1];ReturnValue;taint",
+ "java.io;File;true;toURI;;;Argument[-1];ReturnValue;taint",
+ "java.io;File;true;toPath;;;Argument[-1];ReturnValue;taint",
"java.io;File;true;getAbsoluteFile;;;Argument[-1];ReturnValue;taint",
"java.io;File;true;getCanonicalFile;;;Argument[-1];ReturnValue;taint",
"java.io;File;true;getAbsolutePath;;;Argument[-1];ReturnValue;taint",
From 920a7cd2e62e69886516e67e55a7b4295b7725e1 Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Fri, 29 Apr 2022 20:29:04 +0000
Subject: [PATCH 0177/1274] Put back the taint step removed during merge
---
.../Security/CWE/CWE-552/UnsafeUrlForward.qll | 1 +
.../security/CWE-552/UnsafeUrlForward.expected | 12 ++++++++++++
2 files changed, 13 insertions(+)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
index c741eabcaa5..5471f55b212 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
@@ -168,6 +168,7 @@ private class FilePathFlowStep extends SummaryModelCsv {
"java.nio.file;Paths;true;get;;;Argument[0..1];ReturnValue;taint",
"java.nio.file;Path;true;resolve;;;Argument[-1..0];ReturnValue;taint",
"java.nio.file;Path;true;normalize;;;Argument[-1];ReturnValue;taint",
+ "java.nio.file;Path;true;toString;;;Argument[-1];ReturnValue;taint",
"io.undertow.server.handlers.resource;Resource;true;getFile;;;Argument[-1];ReturnValue;taint",
"io.undertow.server.handlers.resource;Resource;true;getFilePath;;;Argument[-1];ReturnValue;taint",
"io.undertow.server.handlers.resource;Resource;true;getPath;;;Argument[-1];ReturnValue;taint"
diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected
index 202ce9d0cd8..179d2b37265 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected
+++ b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected
@@ -16,6 +16,11 @@ edges
| UnsafeServletRequestDispatch.java:23:22:23:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:32:51:32:59 | returnURL |
| UnsafeServletRequestDispatch.java:42:22:42:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL |
| UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:76:53:76:56 | path |
+| UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:107:53:107:56 | path : String |
+| UnsafeServletRequestDispatch.java:107:24:107:57 | resolve(...) : Path | UnsafeServletRequestDispatch.java:107:24:107:69 | normalize(...) : Path |
+| UnsafeServletRequestDispatch.java:107:24:107:69 | normalize(...) : Path | UnsafeServletRequestDispatch.java:110:53:110:65 | requestedPath : Path |
+| UnsafeServletRequestDispatch.java:107:53:107:56 | path : String | UnsafeServletRequestDispatch.java:107:24:107:57 | resolve(...) : Path |
+| UnsafeServletRequestDispatch.java:110:53:110:65 | requestedPath : Path | UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) |
| UnsafeUrlForward.java:13:27:13:36 | url : String | UnsafeUrlForward.java:14:27:14:29 | url |
| UnsafeUrlForward.java:18:27:18:36 | url : String | UnsafeUrlForward.java:20:28:20:30 | url |
| UnsafeUrlForward.java:25:21:25:30 | url : String | UnsafeUrlForward.java:26:23:26:25 | url |
@@ -54,6 +59,12 @@ nodes
| UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL | semmle.label | returnURL |
| UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| UnsafeServletRequestDispatch.java:76:53:76:56 | path | semmle.label | path |
+| UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| UnsafeServletRequestDispatch.java:107:24:107:57 | resolve(...) : Path | semmle.label | resolve(...) : Path |
+| UnsafeServletRequestDispatch.java:107:24:107:69 | normalize(...) : Path | semmle.label | normalize(...) : Path |
+| UnsafeServletRequestDispatch.java:107:53:107:56 | path : String | semmle.label | path : String |
+| UnsafeServletRequestDispatch.java:110:53:110:65 | requestedPath : Path | semmle.label | requestedPath : Path |
+| UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) | semmle.label | toString(...) |
| UnsafeUrlForward.java:13:27:13:36 | url : String | semmle.label | url : String |
| UnsafeUrlForward.java:14:27:14:29 | url | semmle.label | url |
| UnsafeUrlForward.java:18:27:18:36 | url : String | semmle.label | url : String |
@@ -83,6 +94,7 @@ subpaths
| UnsafeServletRequestDispatch.java:32:51:32:59 | returnURL | UnsafeServletRequestDispatch.java:23:22:23:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:32:51:32:59 | returnURL | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:23:22:23:54 | getParameter(...) | user-provided value |
| UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL | UnsafeServletRequestDispatch.java:42:22:42:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:42:22:42:54 | getParameter(...) | user-provided value |
| UnsafeServletRequestDispatch.java:76:53:76:56 | path | UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:76:53:76:56 | path | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) | user-provided value |
+| UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) | UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) | user-provided value |
| UnsafeUrlForward.java:14:27:14:29 | url | UnsafeUrlForward.java:13:27:13:36 | url : String | UnsafeUrlForward.java:14:27:14:29 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:13:27:13:36 | url | user-provided value |
| UnsafeUrlForward.java:20:28:20:30 | url | UnsafeUrlForward.java:18:27:18:36 | url : String | UnsafeUrlForward.java:20:28:20:30 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:18:27:18:36 | url | user-provided value |
| UnsafeUrlForward.java:26:23:26:25 | url | UnsafeUrlForward.java:25:21:25:30 | url : String | UnsafeUrlForward.java:26:23:26:25 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:25:21:25:30 | url | user-provided value |
From f87312d4ba97570f39fe6adb87c38e1760590e45 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Sat, 30 Apr 2022 20:29:44 +0200
Subject: [PATCH 0178/1274] have ApiGraphModelsSpecific.qll mention all the
required predicates/types
---
.../data/internal/ApiGraphModelsSpecific.qll | 10 ++++++++--
.../data/internal/ApiGraphModelsSpecific.qll | 4 ++++
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll
index 752acea10c6..9e08e8ed619 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll
@@ -4,12 +4,18 @@
* It must export the following members:
* ```ql
* class Unit // a unit type
+ * module AccessPathSyntax // a re-export of the AccessPathSyntax module
+ * class InvokeNode // a type representing an invocation connected to the API graph
* module API // the API graph module
* predicate isPackageUsed(string package)
* API::Node getExtraNodeFromPath(string package, string type, string path, int n)
* API::Node getExtraSuccessorFromNode(API::Node node, AccessPathToken token)
- * API::Node getExtraSuccessorFromInvoke(API::InvokeNode node, AccessPathToken token)
- * predicate invocationMatchesExtraCallSiteFilter(API::InvokeNode invoke, AccessPathToken token)
+ * API::Node getExtraSuccessorFromInvoke(InvokeNode node, AccessPathToken token)
+ * predicate invocationMatchesExtraCallSiteFilter(InvokeNode invoke, AccessPathToken token)
+ * InvokeNode getAnInvocationOf(API::Node node)
+ * predicate isExtraValidTokenNameInIdentifyingAccessPath(string name)
+ * predicate isExtraValidNoArgumentTokenInIdentifyingAccessPath(string name)
+ * predicate isExtraValidTokenArgumentInIdentifyingAccessPath(string name, string argument)
* ```
*/
diff --git a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsSpecific.qll b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsSpecific.qll
index 3bd595b44b8..381623d557e 100644
--- a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsSpecific.qll
+++ b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsSpecific.qll
@@ -4,6 +4,7 @@
* It must export the following members:
* ```ql
* class Unit // a unit type
+ * module AccessPathSyntax // a re-export of the AccessPathSyntax module
* class InvokeNode // a type representing an invocation connected to the API graph
* module API // the API graph module
* predicate isPackageUsed(string package)
@@ -12,6 +13,9 @@
* API::Node getExtraSuccessorFromInvoke(InvokeNode node, AccessPathToken token)
* predicate invocationMatchesExtraCallSiteFilter(InvokeNode invoke, AccessPathToken token)
* InvokeNode getAnInvocationOf(API::Node node)
+ * predicate isExtraValidTokenNameInIdentifyingAccessPath(string name)
+ * predicate isExtraValidNoArgumentTokenInIdentifyingAccessPath(string name)
+ * predicate isExtraValidTokenArgumentInIdentifyingAccessPath(string name, string argument)
* ```
*/
From 57ae07017f6bc97f139222508eacb7e8f57db7f7 Mon Sep 17 00:00:00 2001
From: bananabr
Date: Sat, 30 Apr 2022 18:27:31 -0500
Subject: [PATCH 0179/1274] adds the Selection API as a new DOM text source
---
.../2022-04-30-xss-selection-source.md | 4 ++++
.../dataflow/XssThroughDomCustomizations.qll | 22 +++++++++++++++++++
.../XssThroughDom/XssThroughDom.expected | 12 ++++++++++
.../CWE-079/XssThroughDom/xss-through-dom.js | 8 +++++++
4 files changed, 46 insertions(+)
create mode 100644 javascript/ql/lib/change-notes/2022-04-30-xss-selection-source.md
diff --git a/javascript/ql/lib/change-notes/2022-04-30-xss-selection-source.md b/javascript/ql/lib/change-notes/2022-04-30-xss-selection-source.md
new file mode 100644
index 00000000000..4b7ed054b74
--- /dev/null
+++ b/javascript/ql/lib/change-notes/2022-04-30-xss-selection-source.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* Added the `Selection` api as a DOM text source in the `XssThroughDomCustomizations` library.
\ No newline at end of file
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
index 80c28c03513..cc9535e054e 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
@@ -216,4 +216,26 @@ module XssThroughDom {
}
}
}
+
+
+ /**
+ * A source for text from the DOM from a Selection object toString method call
+ * https://developer.mozilla.org/en-US/docs/Web/API/Selection
+ */
+ DataFlow::SourceNode getSelectionCall(DataFlow::TypeTracker t) {
+ t.start() and
+ exists(DataFlow::CallNode call |
+ call = DataFlow::globalVarRef("getSelection").getACall()
+ |
+ result = call
+ )
+ or
+ exists(DataFlow::TypeTracker t2 | result = getSelectionCall(t2).track(t2, t))
+ }
+
+ class SelectionSource extends Source {
+ SelectionSource() {
+ this = getSelectionCall(DataFlow::TypeTracker::end()).getAMethodCall("toString")
+ }
+ }
}
diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected
index 104a3055e40..0cf59fe99c1 100644
--- a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected
@@ -139,6 +139,12 @@ nodes
| xss-through-dom.js:122:53:122:67 | ev.target.files |
| xss-through-dom.js:122:53:122:67 | ev.target.files |
| xss-through-dom.js:122:53:122:70 | ev.target.files[0] |
+| xss-through-dom.js:129:6:129:42 | linkText |
+| xss-through-dom.js:129:17:129:36 | selection.toString() |
+| xss-through-dom.js:129:17:129:36 | selection.toString() |
+| xss-through-dom.js:129:17:129:42 | selecti ... ) \|\| '' |
+| xss-through-dom.js:130:19:130:26 | linkText |
+| xss-through-dom.js:130:19:130:26 | linkText |
edges
| forms.js:8:23:8:28 | values | forms.js:9:31:9:36 | values |
| forms.js:8:23:8:28 | values | forms.js:9:31:9:36 | values |
@@ -225,6 +231,11 @@ edges
| xss-through-dom.js:122:53:122:67 | ev.target.files | xss-through-dom.js:122:53:122:70 | ev.target.files[0] |
| xss-through-dom.js:122:53:122:70 | ev.target.files[0] | xss-through-dom.js:122:33:122:71 | URL.cre ... les[0]) |
| xss-through-dom.js:122:53:122:70 | ev.target.files[0] | xss-through-dom.js:122:33:122:71 | URL.cre ... les[0]) |
+| xss-through-dom.js:129:6:129:42 | linkText | xss-through-dom.js:130:19:130:26 | linkText |
+| xss-through-dom.js:129:6:129:42 | linkText | xss-through-dom.js:130:19:130:26 | linkText |
+| xss-through-dom.js:129:17:129:36 | selection.toString() | xss-through-dom.js:129:17:129:42 | selecti ... ) \|\| '' |
+| xss-through-dom.js:129:17:129:36 | selection.toString() | xss-through-dom.js:129:17:129:42 | selecti ... ) \|\| '' |
+| xss-through-dom.js:129:17:129:42 | selecti ... ) \|\| '' | xss-through-dom.js:129:6:129:42 | linkText |
#select
| forms.js:9:31:9:40 | values.foo | forms.js:8:23:8:28 | values | forms.js:9:31:9:40 | values.foo | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:8:23:8:28 | values | DOM text |
| forms.js:12:31:12:40 | values.bar | forms.js:11:24:11:29 | values | forms.js:12:31:12:40 | values.bar | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:11:24:11:29 | values | DOM text |
@@ -262,3 +273,4 @@ edges
| xss-through-dom.js:115:16:115:18 | src | xss-through-dom.js:114:17:114:52 | documen ... k").src | xss-through-dom.js:115:16:115:18 | src | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:114:17:114:52 | documen ... k").src | DOM text |
| xss-through-dom.js:120:23:120:45 | ev.targ ... 0].name | xss-through-dom.js:120:23:120:37 | ev.target.files | xss-through-dom.js:120:23:120:45 | ev.targ ... 0].name | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:120:23:120:37 | ev.target.files | DOM text |
| xss-through-dom.js:122:33:122:71 | URL.cre ... les[0]) | xss-through-dom.js:122:53:122:67 | ev.target.files | xss-through-dom.js:122:33:122:71 | URL.cre ... les[0]) | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:122:53:122:67 | ev.target.files | DOM text |
+| xss-through-dom.js:130:19:130:26 | linkText | xss-through-dom.js:129:17:129:36 | selection.toString() | xss-through-dom.js:130:19:130:26 | linkText | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:129:17:129:36 | selection.toString() | DOM text |
diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/xss-through-dom.js b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/xss-through-dom.js
index 6fcf9e2a13f..55f4e80436c 100644
--- a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/xss-through-dom.js
+++ b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/xss-through-dom.js
@@ -122,3 +122,11 @@ class Sub extends Super {
$("img#id").attr("src", URL.createObjectURL(ev.target.files[0])); // NOT OK
}
})();
+
+(function () {
+ let elem = document.createElement('a');
+ const selection = getSelection();
+ let linkText = selection.toString() || '';
+ elem.innerHTML = linkText; // NOT OK
+ elem.innerText = linkText; // OK
+})();
\ No newline at end of file
From ed58ee86fe426fffa60e6698f4d5dd9c05460c4f Mon Sep 17 00:00:00 2001
From: bananabr
Date: Sun, 1 May 2022 20:41:43 -0500
Subject: [PATCH 0180/1274] documented getSelectionCall
---
.../security/dataflow/XssThroughDomCustomizations.qll | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
index cc9535e054e..a387607229a 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
@@ -219,7 +219,7 @@ module XssThroughDom {
/**
- * A source for text from the DOM from a Selection object toString method call
+ * A call to window.getSelection
* https://developer.mozilla.org/en-US/docs/Web/API/Selection
*/
DataFlow::SourceNode getSelectionCall(DataFlow::TypeTracker t) {
@@ -233,6 +233,10 @@ module XssThroughDom {
exists(DataFlow::TypeTracker t2 | result = getSelectionCall(t2).track(t2, t))
}
+ /**
+ * A source for text from the DOM from a Selection object toString method call
+ * https://developer.mozilla.org/en-US/docs/Web/API/Selection
+ */
class SelectionSource extends Source {
SelectionSource() {
this = getSelectionCall(DataFlow::TypeTracker::end()).getAMethodCall("toString")
From 714465bf39d97e31aa6f0a7aa01c57e16f3c3078 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Mon, 2 May 2022 11:29:00 +0200
Subject: [PATCH 0181/1274] Python: Refactor `SaxParserSetFeatureCall`
Originally made by @erik-krogh in
https://github.com/github/codeql/pull/8693/files#diff-9627c1fb9a1cc77fb93e6b7e31af1a4fa908f2a60362cfb34377d24debb97398
Could not be applied directly to this PR, since this PR deletes the file.
---
.../lib/semmle/python/frameworks/Stdlib.qll | 38 ++++---------------
1 file changed, 7 insertions(+), 31 deletions(-)
diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll
index 10eaa9dc3b6..bf2b01930d2 100644
--- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll
@@ -3408,7 +3408,7 @@ private module StdlibPrivate {
*
* See https://docs.python.org/3.10/library/xml.sax.reader.html#xml.sax.xmlreader.XMLReader.setFeature
*/
- private class SaxParserSetFeatureCall extends DataFlow::MethodCallNode {
+ private class SaxParserSetFeatureCall extends API::CallNode, DataFlow::MethodCallNode {
SaxParserSetFeatureCall() {
this =
API::moduleImport("xml")
@@ -3421,27 +3421,9 @@ private module StdlibPrivate {
// The keyword argument names does not match documentation. I checked (with Python
// 3.9.5) that the names used here actually works.
- DataFlow::Node getFeatureArg() { result in [this.getArg(0), this.getArgByName("name")] }
+ API::Node getFeatureArg() { result = this.getParameter(0, "name") }
- DataFlow::Node getStateArg() { result in [this.getArg(1), this.getArgByName("state")] }
- }
-
- /** Gets a back-reference to the `setFeature` state argument `arg`. */
- private DataFlow::TypeTrackingNode saxParserSetFeatureStateArgBacktracker(
- DataFlow::TypeBackTracker t, DataFlow::Node arg
- ) {
- t.start() and
- arg = any(SaxParserSetFeatureCall c).getStateArg() and
- result = arg.getALocalSource()
- or
- exists(DataFlow::TypeBackTracker t2 |
- result = saxParserSetFeatureStateArgBacktracker(t2, arg).backtrack(t2, t)
- )
- }
-
- /** Gets a back-reference to the `setFeature` state argument `arg`. */
- DataFlow::LocalSourceNode saxParserSetFeatureStateArgBacktracker(DataFlow::Node arg) {
- result = saxParserSetFeatureStateArgBacktracker(DataFlow::TypeBackTracker::end(), arg)
+ API::Node getStateArg() { result = this.getParameter(1, "state") }
}
/**
@@ -3452,16 +3434,13 @@ private module StdlibPrivate {
private DataFlow::Node saxParserWithFeatureExternalGesTurnedOn(DataFlow::TypeTracker t) {
t.start() and
exists(SaxParserSetFeatureCall call |
- call.getFeatureArg() =
+ call.getFeatureArg().getARhs() =
API::moduleImport("xml")
.getMember("sax")
.getMember("handler")
.getMember("feature_external_ges")
.getAUse() and
- saxParserSetFeatureStateArgBacktracker(call.getStateArg())
- .asExpr()
- .(BooleanLiteral)
- .booleanValue() = true and
+ call.getStateArg().getAValueReachingRhs().asExpr().(BooleanLiteral).booleanValue() = true and
result = call.getObject()
)
or
@@ -3471,16 +3450,13 @@ private module StdlibPrivate {
// take account of that we can set the feature to False, which makes the parser safe again
not exists(SaxParserSetFeatureCall call |
call.getObject() = result and
- call.getFeatureArg() =
+ call.getFeatureArg().getARhs() =
API::moduleImport("xml")
.getMember("sax")
.getMember("handler")
.getMember("feature_external_ges")
.getAUse() and
- saxParserSetFeatureStateArgBacktracker(call.getStateArg())
- .asExpr()
- .(BooleanLiteral)
- .booleanValue() = false
+ call.getStateArg().getAValueReachingRhs().asExpr().(BooleanLiteral).booleanValue() = false
)
}
From 0c62916af5d42aaf88667dc2d04f82ec12537b37 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Mon, 2 May 2022 14:05:35 +0200
Subject: [PATCH 0182/1274] Python: Highlight problem with Flask
`request.files` modeling
---
python/ql/test/library-tests/frameworks/flask/taint_test.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/python/ql/test/library-tests/frameworks/flask/taint_test.py b/python/ql/test/library-tests/frameworks/flask/taint_test.py
index 1c1f88eab68..609e4caf091 100644
--- a/python/ql/test/library-tests/frameworks/flask/taint_test.py
+++ b/python/ql/test/library-tests/frameworks/flask/taint_test.py
@@ -189,6 +189,7 @@ def test_taint(name = "World!", number="0", foo="foo"): # $requestHandler route
a = request.args
b = a
gl = b.getlist
+ files = request.files
ensure_tainted(
request.args, # $ tainted
a, # $ tainted
@@ -202,6 +203,8 @@ def test_taint(name = "World!", number="0", foo="foo"): # $requestHandler route
a.getlist('key'), # $ tainted
b.getlist('key'), # $ tainted
gl('key'), # $ tainted
+
+ files.get('key').filename, # $ MISSING: tainted
)
# aliasing tests
From fb0133d276c2f8c62f79bcea3f3d1087ebbfcdd7 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Mon, 2 May 2022 14:14:29 +0200
Subject: [PATCH 0183/1274] Python: Fix Flask `request.files` modeling
---
python/ql/lib/semmle/python/frameworks/Flask.qll | 2 +-
python/ql/test/library-tests/frameworks/flask/taint_test.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/python/ql/lib/semmle/python/frameworks/Flask.qll b/python/ql/lib/semmle/python/frameworks/Flask.qll
index 8fe9e9bdd4b..19400aba739 100644
--- a/python/ql/lib/semmle/python/frameworks/Flask.qll
+++ b/python/ql/lib/semmle/python/frameworks/Flask.qll
@@ -418,7 +418,7 @@ module Flask {
// TODO: This approach for identifying member-access is very adhoc, and we should
// be able to do something more structured for providing modeling of the members
// of a container-object.
- exists(DataFlow::AttrRead files | files = request().getMember("files").getAnImmediateUse() |
+ exists(DataFlow::Node files | files = request().getMember("files").getAUse() |
this.asCfgNode().(SubscriptNode).getObject() = files.asCfgNode()
or
this.(DataFlow::MethodCallNode).calls(files, "get")
diff --git a/python/ql/test/library-tests/frameworks/flask/taint_test.py b/python/ql/test/library-tests/frameworks/flask/taint_test.py
index 609e4caf091..dcca8ff6681 100644
--- a/python/ql/test/library-tests/frameworks/flask/taint_test.py
+++ b/python/ql/test/library-tests/frameworks/flask/taint_test.py
@@ -204,7 +204,7 @@ def test_taint(name = "World!", number="0", foo="foo"): # $requestHandler route
b.getlist('key'), # $ tainted
gl('key'), # $ tainted
- files.get('key').filename, # $ MISSING: tainted
+ files.get('key').filename, # $ tainted
)
# aliasing tests
From de4390cdf6500f352591e69ad4568243cc7408d1 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Mon, 2 May 2022 14:19:45 +0200
Subject: [PATCH 0184/1274] Python: Improve Flask `request.files` handling even
more
---
python/ql/lib/semmle/python/frameworks/Flask.qll | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/python/ql/lib/semmle/python/frameworks/Flask.qll b/python/ql/lib/semmle/python/frameworks/Flask.qll
index 19400aba739..02331ed316e 100644
--- a/python/ql/lib/semmle/python/frameworks/Flask.qll
+++ b/python/ql/lib/semmle/python/frameworks/Flask.qll
@@ -411,21 +411,16 @@ module Flask {
/** An `FileStorage` instance that originates from a flask request. */
private class FlaskRequestFileStorageInstances extends Werkzeug::FileStorage::InstanceSource {
FlaskRequestFileStorageInstances() {
- // TODO: this currently only works in local-scope, since writing type-trackers for
- // this is a little too much effort. Once API-graphs are available for more
- // things, we can rewrite this.
- //
// TODO: This approach for identifying member-access is very adhoc, and we should
// be able to do something more structured for providing modeling of the members
// of a container-object.
- exists(DataFlow::Node files | files = request().getMember("files").getAUse() |
- this.asCfgNode().(SubscriptNode).getObject() = files.asCfgNode()
+ exists(API::Node files | files = request().getMember("files") |
+ this.asCfgNode().(SubscriptNode).getObject() = files.getAUse().asCfgNode()
or
- this.(DataFlow::MethodCallNode).calls(files, "get")
+ this = files.getMember("get").getACall()
or
- exists(DataFlow::MethodCallNode getlistCall | getlistCall.calls(files, "getlist") |
- this.asCfgNode().(SubscriptNode).getObject() = getlistCall.asCfgNode()
- )
+ this.asCfgNode().(SubscriptNode).getObject() =
+ files.getMember("getlist").getReturn().getAUse().asCfgNode()
)
}
}
From 7e1be3172e946da4620eb52c112391ad6241b36b Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Mon, 2 May 2022 14:24:13 +0200
Subject: [PATCH 0185/1274] Python: Add change-note
---
.../change-notes/2022-05-02-flask-request-files-modeling.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 python/ql/lib/change-notes/2022-05-02-flask-request-files-modeling.md
diff --git a/python/ql/lib/change-notes/2022-05-02-flask-request-files-modeling.md b/python/ql/lib/change-notes/2022-05-02-flask-request-files-modeling.md
new file mode 100644
index 00000000000..9b80811a608
--- /dev/null
+++ b/python/ql/lib/change-notes/2022-05-02-flask-request-files-modeling.md
@@ -0,0 +1,5 @@
+---
+category: minorAnalysis
+---
+The modeling of `request.files` in Flask has been fixed, so we now properly handle
+assignments to local variables (such as `files = request.files; files['key'].filename`).
From 8602a6f6c98f5a9f46db2c099ff7451b64f9b550 Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Mon, 2 May 2022 15:38:28 +0200
Subject: [PATCH 0186/1274] Add models for OkHttp and Retrofit
---
.../code/java/dataflow/ExternalFlow.qll | 2 +
.../semmle/code/java/frameworks/OkHttp.qll | 55 ++
.../semmle/code/java/frameworks/Retrofit.qll | 12 +
.../library-tests/frameworks/okhttp/Test.java | 237 ++++++++
.../library-tests/frameworks/okhttp/options | 1 +
.../frameworks/okhttp/test.expected | 0
.../library-tests/frameworks/okhttp/test.ql | 6 +
.../frameworks/retrofit/Test.java | 16 +
.../library-tests/frameworks/retrofit/options | 1 +
.../frameworks/retrofit/test.expected | 0
.../library-tests/frameworks/retrofit/test.ql | 6 +
.../stubs/okhttp-4.9.3/kotlin/Function.java | 8 +
.../test/stubs/okhttp-4.9.3/kotlin/Pair.java | 19 +
.../test/stubs/okhttp-4.9.3/kotlin/Unit.java | 11 +
.../collections/AbstractCollection.java | 26 +
.../kotlin/collections/AbstractList.java | 40 ++
.../kotlin/jvm/functions/Function0.java | 10 +
.../jvm/internal/markers/KMappedMarker.java | 8 +
.../stubs/okhttp-4.9.3/okhttp3/Address.java | 84 +++
.../okhttp-4.9.3/okhttp3/Authenticator.java | 19 +
.../stubs/okhttp-4.9.3/okhttp3/Cache.java | 137 +++++
.../okhttp-4.9.3/okhttp3/CacheControl.java | 78 +++
.../test/stubs/okhttp-4.9.3/okhttp3/Call.java | 24 +
.../stubs/okhttp-4.9.3/okhttp3/Callback.java | 13 +
.../okhttp3/CertificatePinner.java | 51 ++
.../stubs/okhttp-4.9.3/okhttp3/Challenge.java | 46 ++
.../okhttp-4.9.3/okhttp3/CipherSuite.java | 155 +++++
.../okhttp-4.9.3/okhttp3/Connection.java | 16 +
.../okhttp-4.9.3/okhttp3/ConnectionPool.java | 17 +
.../okhttp-4.9.3/okhttp3/ConnectionSpec.java | 58 ++
.../stubs/okhttp-4.9.3/okhttp3/Cookie.java | 93 +++
.../stubs/okhttp-4.9.3/okhttp3/CookieJar.java | 19 +
.../okhttp-4.9.3/okhttp3/Dispatcher.java | 62 ++
.../test/stubs/okhttp-4.9.3/okhttp3/Dns.java | 17 +
.../okhttp-4.9.3/okhttp3/EventListener.java | 60 ++
.../stubs/okhttp-4.9.3/okhttp3/Handshake.java | 78 +++
.../stubs/okhttp-4.9.3/okhttp3/Headers.java | 161 ++++++
.../stubs/okhttp-4.9.3/okhttp3/HttpUrl.java | 390 +++++++++++++
.../okhttp-4.9.3/okhttp3/Interceptor.java | 34 ++
.../stubs/okhttp-4.9.3/okhttp3/MediaType.java | 63 +++
.../okhttp-4.9.3/okhttp3/OkHttpClient.java | 528 ++++++++++++++++++
.../stubs/okhttp-4.9.3/okhttp3/Protocol.java | 18 +
.../stubs/okhttp-4.9.3/okhttp3/Request.java | 182 ++++++
.../okhttp-4.9.3/okhttp3/RequestBody.java | 49 ++
.../stubs/okhttp-4.9.3/okhttp3/Response.java | 270 +++++++++
.../okhttp-4.9.3/okhttp3/ResponseBody.java | 45 ++
.../stubs/okhttp-4.9.3/okhttp3/Route.java | 41 ++
.../okhttp-4.9.3/okhttp3/TlsVersion.java | 28 +
.../stubs/okhttp-4.9.3/okhttp3/WebSocket.java | 21 +
.../okhttp3/WebSocketListener.java | 18 +
.../okhttp3/internal/cache/CacheRequest.java | 11 +
.../okhttp3/internal/cache/CacheStrategy.java | 20 +
.../okhttp3/internal/cache/DiskLruCache.java | 106 ++++
.../okhttp3/internal/concurrent/Task.java | 20 +
.../internal/concurrent/TaskQueue.java | 35 ++
.../internal/concurrent/TaskRunner.java | 35 ++
.../okhttp3/internal/connection/Exchange.java | 44 ++
.../internal/connection/ExchangeFinder.java | 24 +
.../okhttp3/internal/connection/RealCall.java | 63 +++
.../internal/connection/RealConnection.java | 65 +++
.../connection/RealConnectionPool.java | 31 +
.../internal/connection/RouteDatabase.java | 13 +
.../okhttp3/internal/http/ExchangeCodec.java | 31 +
.../internal/http/RealInterceptorChain.java | 36 ++
.../okhttp3/internal/http2/ErrorCode.java | 17 +
.../okhttp3/internal/http2/Header.java | 38 ++
.../okhttp3/internal/http2/Hpack.java | 34 ++
.../internal/http2/Http2Connection.java | 153 +++++
.../okhttp3/internal/http2/Http2Reader.java | 42 ++
.../okhttp3/internal/http2/Http2Stream.java | 104 ++++
.../okhttp3/internal/http2/Http2Writer.java | 39 ++
.../okhttp3/internal/http2/PushObserver.java | 22 +
.../okhttp3/internal/http2/Settings.java | 34 ++
.../okhttp3/internal/io/FileSystem.java | 25 +
.../internal/tls/CertificateChainCleaner.java | 21 +
.../okhttp3/internal/ws/RealWebSocket.java | 66 +++
.../internal/ws/WebSocketExtensions.java | 34 ++
.../okhttp3/internal/ws/WebSocketReader.java | 24 +
.../stubs/okhttp-4.9.3/okio/AsyncTimeout.java | 28 +
.../test/stubs/okhttp-4.9.3/okio/Buffer.java | 469 ++++++++++++++++
.../stubs/okhttp-4.9.3/okio/BufferedSink.java | 41 ++
.../okhttp-4.9.3/okio/BufferedSource.java | 60 ++
.../stubs/okhttp-4.9.3/okio/ByteString.java | 284 ++++++++++
.../test/stubs/okhttp-4.9.3/okio/Options.java | 28 +
.../test/stubs/okhttp-4.9.3/okio/Segment.java | 31 +
.../ql/test/stubs/okhttp-4.9.3/okio/Sink.java | 16 +
.../test/stubs/okhttp-4.9.3/okio/Source.java | 14 +
.../test/stubs/okhttp-4.9.3/okio/Timeout.java | 30 +
.../stubs/retrofit-2.9.0/kotlin/Function.java | 8 +
.../stubs/retrofit-2.9.0/kotlin/Pair.java | 19 +
.../stubs/retrofit-2.9.0/kotlin/Unit.java | 11 +
.../collections/AbstractCollection.java | 26 +
.../kotlin/collections/AbstractList.java | 40 ++
.../kotlin/collections/IntIterator.java | 14 +
.../kotlin/jvm/functions/Function0.java | 10 +
.../kotlin/jvm/functions/Function1.java | 10 +
.../jvm/internal/markers/KMappedMarker.java | 8 +
.../kotlin/ranges/ClosedRange.java | 12 +
.../kotlin/ranges/IntProgression.java | 26 +
.../kotlin/ranges/IntRange.java | 26 +
.../kotlin/sequences/Sequence.java | 10 +
.../retrofit-2.9.0/kotlin/text/FlagEnum.java | 10 +
.../kotlin/text/MatchGroup.java | 19 +
.../kotlin/text/MatchGroupCollection.java | 12 +
.../kotlin/text/MatchResult.java | 24 +
.../retrofit-2.9.0/kotlin/text/Regex.java | 42 ++
.../kotlin/text/RegexOption.java | 12 +
.../stubs/retrofit-2.9.0/retrofit2/Call.java | 20 +
.../retrofit-2.9.0/retrofit2/CallAdapter.java | 22 +
.../retrofit-2.9.0/retrofit2/Callback.java | 12 +
.../retrofit-2.9.0/retrofit2/Converter.java | 24 +
.../retrofit-2.9.0/retrofit2/Response.java | 25 +
.../retrofit-2.9.0/retrofit2/Retrofit.java | 51 ++
113 files changed, 6014 insertions(+)
create mode 100644 java/ql/lib/semmle/code/java/frameworks/OkHttp.qll
create mode 100644 java/ql/lib/semmle/code/java/frameworks/Retrofit.qll
create mode 100644 java/ql/test/library-tests/frameworks/okhttp/Test.java
create mode 100644 java/ql/test/library-tests/frameworks/okhttp/options
create mode 100644 java/ql/test/library-tests/frameworks/okhttp/test.expected
create mode 100644 java/ql/test/library-tests/frameworks/okhttp/test.ql
create mode 100644 java/ql/test/library-tests/frameworks/retrofit/Test.java
create mode 100644 java/ql/test/library-tests/frameworks/retrofit/options
create mode 100644 java/ql/test/library-tests/frameworks/retrofit/test.expected
create mode 100644 java/ql/test/library-tests/frameworks/retrofit/test.ql
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/kotlin/Function.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/kotlin/Pair.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/kotlin/Unit.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/kotlin/collections/AbstractCollection.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/kotlin/collections/AbstractList.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/kotlin/jvm/functions/Function0.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/kotlin/jvm/internal/markers/KMappedMarker.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/Address.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/Authenticator.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/Cache.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/CacheControl.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/Call.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/Callback.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/CertificatePinner.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/Challenge.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/CipherSuite.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/Connection.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/ConnectionPool.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/ConnectionSpec.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/Cookie.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/CookieJar.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/Dispatcher.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/Dns.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/EventListener.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/Handshake.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/Headers.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/HttpUrl.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/Interceptor.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/MediaType.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/OkHttpClient.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/Protocol.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/Request.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/RequestBody.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/Response.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/ResponseBody.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/Route.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/TlsVersion.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/WebSocket.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/WebSocketListener.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/cache/CacheRequest.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/cache/CacheStrategy.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/cache/DiskLruCache.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/concurrent/Task.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/concurrent/TaskQueue.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/concurrent/TaskRunner.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/connection/Exchange.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/connection/ExchangeFinder.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/connection/RealCall.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/connection/RealConnection.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/connection/RealConnectionPool.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/connection/RouteDatabase.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/http/ExchangeCodec.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/http/RealInterceptorChain.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/http2/ErrorCode.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/http2/Header.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/http2/Hpack.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/http2/Http2Connection.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/http2/Http2Reader.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/http2/Http2Stream.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/http2/Http2Writer.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/http2/PushObserver.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/http2/Settings.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/io/FileSystem.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/tls/CertificateChainCleaner.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/ws/RealWebSocket.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/ws/WebSocketExtensions.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okhttp3/internal/ws/WebSocketReader.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okio/AsyncTimeout.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okio/Buffer.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okio/BufferedSink.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okio/BufferedSource.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okio/ByteString.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okio/Options.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okio/Segment.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okio/Sink.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okio/Source.java
create mode 100644 java/ql/test/stubs/okhttp-4.9.3/okio/Timeout.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/Function.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/Pair.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/Unit.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/collections/AbstractCollection.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/collections/AbstractList.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/collections/IntIterator.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/jvm/functions/Function0.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/jvm/functions/Function1.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/jvm/internal/markers/KMappedMarker.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/ranges/ClosedRange.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/ranges/IntProgression.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/ranges/IntRange.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/sequences/Sequence.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/text/FlagEnum.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/text/MatchGroup.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/text/MatchGroupCollection.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/text/MatchResult.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/text/Regex.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/kotlin/text/RegexOption.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/retrofit2/Call.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/retrofit2/CallAdapter.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/retrofit2/Callback.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/retrofit2/Converter.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/retrofit2/Response.java
create mode 100644 java/ql/test/stubs/retrofit-2.9.0/retrofit2/Retrofit.java
diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll
index f3ac4a041b6..f3101c208db 100644
--- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll
+++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll
@@ -102,8 +102,10 @@ private module Frameworks {
private import semmle.code.java.frameworks.JsonJava
private import semmle.code.java.frameworks.Logging
private import semmle.code.java.frameworks.Objects
+ private import semmle.code.java.frameworks.OkHttp
private import semmle.code.java.frameworks.Optional
private import semmle.code.java.frameworks.Regex
+ private import semmle.code.java.frameworks.Retrofit
private import semmle.code.java.frameworks.Stream
private import semmle.code.java.frameworks.Strings
private import semmle.code.java.frameworks.ratpack.Ratpack
diff --git a/java/ql/lib/semmle/code/java/frameworks/OkHttp.qll b/java/ql/lib/semmle/code/java/frameworks/OkHttp.qll
new file mode 100644
index 00000000000..36e23d45881
--- /dev/null
+++ b/java/ql/lib/semmle/code/java/frameworks/OkHttp.qll
@@ -0,0 +1,55 @@
+/**
+ * Provides classes and predicates for working with the OkHttp client.
+ */
+
+import java
+import semmle.code.java.dataflow.ExternalFlow
+
+private class OkHttpOpenUrlSinks extends SinkModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "okhttp3;Request;true;Request;;;Argument[0];open-url",
+ "okhttp3;Request$Builder;true;url;;;Argument[0];open-url"
+ ]
+ }
+}
+
+private class OKHttpSummaries extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "okhttp3;HttpUrl;false;parse;;;Argument[0];ReturnValue;taint",
+ "okhttp3;HttpUrl;false;uri;;;Argument[-1];ReturnValue;taint",
+ "okhttp3;HttpUrl;false;url;;;Argument[-1];ReturnValue;taint",
+ "okhttp3;HttpUrl$Builder;false;addEncodedPathSegment;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;addEncodedPathSegments;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;addEncodedQueryParameter;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;addPathSegment;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;addPathSegments;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;addQueryParameter;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;build;;;Argument[-1];ReturnValue;taint",
+ "okhttp3;HttpUrl$Builder;false;encodedFragment;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;encodedPassword;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;encodedPath;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;encodedQuery;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;encodedUsername;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;fragment;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;fragment;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;host;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;password;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;port;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;query;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;removeAllEncodedQueryParameters;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;removeAllQueryParameters;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;removePathSegment;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;scheme;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;scheme;;;Argument[0];Argument[-1];taint",
+ "okhttp3;HttpUrl$Builder;false;setEncodedPathSegment;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;setEncodedQueryParameter;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;setPathSegment;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;setQueryParameter;;;Argument[-1];ReturnValue;value",
+ "okhttp3;HttpUrl$Builder;false;username;;;Argument[-1];ReturnValue;value",
+ ]
+ }
+}
diff --git a/java/ql/lib/semmle/code/java/frameworks/Retrofit.qll b/java/ql/lib/semmle/code/java/frameworks/Retrofit.qll
new file mode 100644
index 00000000000..cb1aaa87667
--- /dev/null
+++ b/java/ql/lib/semmle/code/java/frameworks/Retrofit.qll
@@ -0,0 +1,12 @@
+/**
+ * Provides classes and predicates for working with the Retrofit API client.
+ */
+
+import java
+import semmle.code.java.dataflow.ExternalFlow
+
+private class RetrofitOpenUrlSinks extends SinkModelCsv {
+ override predicate row(string row) {
+ row = "retrofit2;Retrofit$Builder;true;baseUrl;;;Argument[0];open-url"
+ }
+}
diff --git a/java/ql/test/library-tests/frameworks/okhttp/Test.java b/java/ql/test/library-tests/frameworks/okhttp/Test.java
new file mode 100644
index 00000000000..02950ccaa30
--- /dev/null
+++ b/java/ql/test/library-tests/frameworks/okhttp/Test.java
@@ -0,0 +1,237 @@
+package generatedtest;
+
+import java.net.URI;
+import java.net.URL;
+import okhttp3.HttpUrl;
+import okhttp3.Request;
+
+// Test case generated by GenerateFlowTestCase.ql
+public class Test {
+
+ Object source() {
+ return null;
+ }
+
+ void sink(Object o) {}
+
+ public void testSinks() {
+ new Request((HttpUrl) source(), null, null, null, null); // $ hasValueFlow
+ new Request.Builder().url((String) source()); // $ hasValueFlow
+ }
+
+ public void test() throws Exception {
+
+ {
+ // "okhttp3;HttpUrl$Builder;false;addEncodedPathSegment;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.addEncodedPathSegment(null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;addEncodedPathSegments;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.addEncodedPathSegments(null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;addEncodedQueryParameter;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.addEncodedQueryParameter(null, null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;addPathSegment;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.addPathSegment(null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;addPathSegments;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.addPathSegments(null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;addQueryParameter;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.addQueryParameter(null, null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;build;;;Argument[-1];ReturnValue;taint"
+ HttpUrl out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.build();
+ sink(out); // $ hasTaintFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;encodedFragment;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.encodedFragment(null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;encodedPassword;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.encodedPassword(null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;encodedPath;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.encodedPath(null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;encodedQuery;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.encodedQuery(null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;encodedUsername;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.encodedUsername(null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;fragment;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.fragment(null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;host;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.host(null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;password;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.password(null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;port;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.port(0);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;query;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.query(null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;removeAllEncodedQueryParameters;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.removeAllEncodedQueryParameters(null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;removeAllQueryParameters;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.removeAllQueryParameters(null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;removePathSegment;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.removePathSegment(0);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;scheme;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.scheme(null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;scheme;;;Argument[0];Argument[-1];taint"
+ HttpUrl.Builder out = null;
+ String in = (String) source();
+ out.scheme(in);
+ sink(out); // $ hasTaintFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;setEncodedPathSegment;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.setEncodedPathSegment(0, null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;setEncodedQueryParameter;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.setEncodedQueryParameter(null, null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;setPathSegment;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.setPathSegment(0, null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;setQueryParameter;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.setQueryParameter(null, null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl$Builder;false;username;;;Argument[-1];ReturnValue;value"
+ HttpUrl.Builder out = null;
+ HttpUrl.Builder in = (HttpUrl.Builder) source();
+ out = in.username(null);
+ sink(out); // $ hasValueFlow
+ }
+ {
+ // "okhttp3;HttpUrl;false;parse;;;Argument[0];ReturnValue;taint"
+ HttpUrl out = null;
+ String in = (String) source();
+ out = HttpUrl.parse(in);
+ sink(out); // $ hasTaintFlow
+ }
+ {
+ // "okhttp3;HttpUrl;false;uri;;;Argument[-1];ReturnValue;taint"
+ URI out = null;
+ HttpUrl in = (HttpUrl) source();
+ out = in.uri();
+ sink(out); // $ hasTaintFlow
+ }
+ {
+ // "okhttp3;HttpUrl;false;url;;;Argument[-1];ReturnValue;taint"
+ URL out = null;
+ HttpUrl in = (HttpUrl) source();
+ out = in.url();
+ sink(out); // $ hasTaintFlow
+ }
+
+ }
+
+}
diff --git a/java/ql/test/library-tests/frameworks/okhttp/options b/java/ql/test/library-tests/frameworks/okhttp/options
new file mode 100644
index 00000000000..597cc3181f0
--- /dev/null
+++ b/java/ql/test/library-tests/frameworks/okhttp/options
@@ -0,0 +1 @@
+//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/okhttp-4.9.3
diff --git a/java/ql/test/library-tests/frameworks/okhttp/test.expected b/java/ql/test/library-tests/frameworks/okhttp/test.expected
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/java/ql/test/library-tests/frameworks/okhttp/test.ql b/java/ql/test/library-tests/frameworks/okhttp/test.ql
new file mode 100644
index 00000000000..e78af7d25bf
--- /dev/null
+++ b/java/ql/test/library-tests/frameworks/okhttp/test.ql
@@ -0,0 +1,6 @@
+import java
+import TestUtilities.InlineFlowTest
+
+class FlowConf extends DefaultValueFlowConf {
+ override predicate isSink(DataFlow::Node n) { super.isSink(n) or sinkNode(n, "open-url") }
+}
diff --git a/java/ql/test/library-tests/frameworks/retrofit/Test.java b/java/ql/test/library-tests/frameworks/retrofit/Test.java
new file mode 100644
index 00000000000..a5513298230
--- /dev/null
+++ b/java/ql/test/library-tests/frameworks/retrofit/Test.java
@@ -0,0 +1,16 @@
+import java.net.URL;
+import okhttp3.HttpUrl;
+import retrofit2.Retrofit;
+
+public class Test {
+ public Object source() {
+ return null;
+ }
+
+ public void test() {
+ Retrofit.Builder builder = new Retrofit.Builder();
+ builder.baseUrl((String) source()); // $ hasValueFlow
+ builder.baseUrl((URL) source()); // $ hasValueFlow
+ builder.baseUrl((HttpUrl) source()); // $ hasValueFlow
+ }
+}
diff --git a/java/ql/test/library-tests/frameworks/retrofit/options b/java/ql/test/library-tests/frameworks/retrofit/options
new file mode 100644
index 00000000000..87371f0fe2a
--- /dev/null
+++ b/java/ql/test/library-tests/frameworks/retrofit/options
@@ -0,0 +1 @@
+//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/okhttp-4.9.3:${testdir}/../../../stubs/retrofit-2.9.0
diff --git a/java/ql/test/library-tests/frameworks/retrofit/test.expected b/java/ql/test/library-tests/frameworks/retrofit/test.expected
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/java/ql/test/library-tests/frameworks/retrofit/test.ql b/java/ql/test/library-tests/frameworks/retrofit/test.ql
new file mode 100644
index 00000000000..e78af7d25bf
--- /dev/null
+++ b/java/ql/test/library-tests/frameworks/retrofit/test.ql
@@ -0,0 +1,6 @@
+import java
+import TestUtilities.InlineFlowTest
+
+class FlowConf extends DefaultValueFlowConf {
+ override predicate isSink(DataFlow::Node n) { super.isSink(n) or sinkNode(n, "open-url") }
+}
diff --git a/java/ql/test/stubs/okhttp-4.9.3/kotlin/Function.java b/java/ql/test/stubs/okhttp-4.9.3/kotlin/Function.java
new file mode 100644
index 00000000000..ec16743fa7a
--- /dev/null
+++ b/java/ql/test/stubs/okhttp-4.9.3/kotlin/Function.java
@@ -0,0 +1,8 @@
+// Generated automatically from kotlin.Function for testing purposes
+
+package kotlin;
+
+
+public interface Function
+{
+}
diff --git a/java/ql/test/stubs/okhttp-4.9.3/kotlin/Pair.java b/java/ql/test/stubs/okhttp-4.9.3/kotlin/Pair.java
new file mode 100644
index 00000000000..74869657cb4
--- /dev/null
+++ b/java/ql/test/stubs/okhttp-4.9.3/kotlin/Pair.java
@@ -0,0 +1,19 @@
+// Generated automatically from kotlin.Pair for testing purposes
+
+package kotlin;
+
+import java.io.Serializable;
+
+public class Pair implements Serializable
+{
+ protected Pair() {}
+ public Pair(A p0, B p1){}
+ public String toString(){ return null; }
+ public boolean equals(Object p0){ return false; }
+ public final A component1(){ return null; }
+ public final A getFirst(){ return null; }
+ public final B component2(){ return null; }
+ public final B getSecond(){ return null; }
+ public final Pair copy(A p0, B p1){ return null; }
+ public int hashCode(){ return 0; }
+}
diff --git a/java/ql/test/stubs/okhttp-4.9.3/kotlin/Unit.java b/java/ql/test/stubs/okhttp-4.9.3/kotlin/Unit.java
new file mode 100644
index 00000000000..c2aeb7e3616
--- /dev/null
+++ b/java/ql/test/stubs/okhttp-4.9.3/kotlin/Unit.java
@@ -0,0 +1,11 @@
+// Generated automatically from kotlin.Unit for testing purposes
+
+package kotlin;
+
+
+public class Unit
+{
+ protected Unit() {}
+ public String toString(){ return null; }
+ public static Unit INSTANCE = null;
+}
diff --git a/java/ql/test/stubs/okhttp-4.9.3/kotlin/collections/AbstractCollection.java b/java/ql/test/stubs/okhttp-4.9.3/kotlin/collections/AbstractCollection.java
new file mode 100644
index 00000000000..48555f6818e
--- /dev/null
+++ b/java/ql/test/stubs/okhttp-4.9.3/kotlin/collections/AbstractCollection.java
@@ -0,0 +1,26 @@
+// Generated automatically from kotlin.collections.AbstractCollection for testing purposes
+
+package kotlin.collections;
+
+import java.util.Collection;
+import java.util.Iterator;
+import kotlin.jvm.internal.markers.KMappedMarker;
+
+abstract public class AbstractCollection implements Collection, KMappedMarker
+{
+ protected AbstractCollection(){}
+ public T[] toArray(T[] p0){ return null; }
+ public Object[] toArray(){ return null; }
+ public String toString(){ return null; }
+ public abstract Iterator iterator();
+ public abstract int getSize();
+ public boolean add(E p0){ return false; }
+ public boolean addAll(Collection extends E> p0){ return false; }
+ public boolean contains(Object p0){ return false; }
+ public boolean containsAll(Collection extends Object> p0){ return false; }
+ public boolean isEmpty(){ return false; }
+ public boolean remove(Object p0){ return false; }
+ public boolean removeAll(Collection extends Object> p0){ return false; }
+ public boolean retainAll(Collection extends Object> p0){ return false; }
+ public void clear(){}
+}
diff --git a/java/ql/test/stubs/okhttp-4.9.3/kotlin/collections/AbstractList.java b/java/ql/test/stubs/okhttp-4.9.3/kotlin/collections/AbstractList.java
new file mode 100644
index 00000000000..1a11dbf9132
--- /dev/null
+++ b/java/ql/test/stubs/okhttp-4.9.3/kotlin/collections/AbstractList.java
@@ -0,0 +1,40 @@
+// Generated automatically from kotlin.collections.AbstractList for testing purposes
+
+package kotlin.collections;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import kotlin.collections.AbstractCollection;
+import kotlin.jvm.internal.markers.KMappedMarker;
+
+abstract public class AbstractList extends AbstractCollection implements KMappedMarker, List
+{
+ protected AbstractList(){}
+ public E remove(int p0){ return null; }
+ public E set(int p0, E p1){ return null; }
+ public Iterator