diff --git a/java/ql/test/TestUtilities/ProvenancePathGraph.ql b/java/ql/test/TestUtilities/ProvenancePathGraph.ql new file mode 100644 index 0000000000000..79442c4439516 --- /dev/null +++ b/java/ql/test/TestUtilities/ProvenancePathGraph.ql @@ -0,0 +1,18 @@ +/** + * @kind test-postprocess + */ + +import codeql.dataflow.test.ProvenancePathGraph +import semmle.code.java.dataflow.ExternalFlow + +external predicate queryResults(string relation, int row, int column, string data); + +external predicate queryRelations(string relation); + +query predicate resultRelations(string relation) { queryRelations(relation) } + +module Res = TranslateProvenanceResults; + +from string relation, int row, int column, string data +where Res::results(relation, row, column, data) +select relation, row, column, data diff --git a/java/ql/test/query-tests/security/CWE-078/ExecTainted.expected b/java/ql/test/query-tests/security/CWE-078/ExecTainted.expected index 6e71e15445406..8cff41743e99f 100644 --- a/java/ql/test/query-tests/security/CWE-078/ExecTainted.expected +++ b/java/ql/test/query-tests/security/CWE-078/ExecTainted.expected @@ -1,23 +1,33 @@ +#select +| Test.java:7:44:7:69 | ... + ... | Test.java:57:27:57:39 | args : String[] | Test.java:7:25:7:70 | new ..[] { .. } | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value | +| Test.java:10:29:10:74 | new String[] | Test.java:57:27:57:39 | args : String[] | Test.java:10:29:10:74 | new String[] | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value | +| Test.java:18:29:18:31 | cmd | Test.java:57:27:57:39 | args : String[] | Test.java:18:29:18:31 | cmd | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value | +| Test.java:24:29:24:32 | cmd1 | Test.java:57:27:57:39 | args : String[] | Test.java:24:29:24:32 | cmd1 | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value | +| Test.java:29:44:29:64 | ... + ... | Test.java:57:27:57:39 | args : String[] | Test.java:29:25:29:65 | new ..[] { .. } | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value | edges | Test.java:6:35:6:44 | arg : String | Test.java:7:44:7:69 | ... + ... : String | provenance | | | Test.java:6:35:6:44 | arg : String | Test.java:10:61:10:73 | ... + ... : String | provenance | | | Test.java:6:35:6:44 | arg : String | Test.java:16:13:16:25 | ... + ... : String | provenance | | | Test.java:6:35:6:44 | arg : String | Test.java:22:15:22:27 | ... + ... : String | provenance | | -| Test.java:7:25:7:70 | new ..[] { .. } : String[] [[]] : String | Test.java:7:25:7:70 | new ..[] { .. } | provenance | Sink:MaD:42682 | +| Test.java:7:25:7:70 | new ..[] { .. } : String[] [[]] : String | Test.java:7:25:7:70 | new ..[] { .. } | provenance | Sink:MaD:2 | | Test.java:7:44:7:69 | ... + ... : String | Test.java:7:25:7:70 | new ..[] { .. } : String[] [[]] : String | provenance | | -| Test.java:10:29:10:74 | {...} : String[] [[]] : String | Test.java:10:29:10:74 | new String[] | provenance | Sink:MaD:42682 | +| Test.java:10:29:10:74 | {...} : String[] [[]] : String | Test.java:10:29:10:74 | new String[] | provenance | Sink:MaD:2 | | Test.java:10:61:10:73 | ... + ... : String | Test.java:10:29:10:74 | {...} : String[] [[]] : String | provenance | | -| Test.java:16:5:16:7 | cmd [post update] : ArrayList [] : String | Test.java:18:29:18:31 | cmd | provenance | Sink:MaD:42681 | -| Test.java:16:13:16:25 | ... + ... : String | Test.java:16:5:16:7 | cmd [post update] : ArrayList [] : String | provenance | MaD:43744 | -| Test.java:22:5:22:8 | cmd1 [post update] : String[] [[]] : String | Test.java:24:29:24:32 | cmd1 | provenance | Sink:MaD:42682 | +| Test.java:16:5:16:7 | cmd [post update] : ArrayList [] : String | Test.java:18:29:18:31 | cmd | provenance | Sink:MaD:1 | +| Test.java:16:13:16:25 | ... + ... : String | Test.java:16:5:16:7 | cmd [post update] : ArrayList [] : String | provenance | MaD:3 | +| Test.java:22:5:22:8 | cmd1 [post update] : String[] [[]] : String | Test.java:24:29:24:32 | cmd1 | provenance | Sink:MaD:2 | | Test.java:22:15:22:27 | ... + ... : String | Test.java:22:5:22:8 | cmd1 [post update] : String[] [[]] : String | provenance | | | Test.java:28:38:28:47 | arg : String | Test.java:29:44:29:64 | ... + ... : String | provenance | | -| Test.java:29:25:29:65 | new ..[] { .. } : String[] [[]] : String | Test.java:29:25:29:65 | new ..[] { .. } | provenance | Sink:MaD:42682 | +| Test.java:29:25:29:65 | new ..[] { .. } : String[] [[]] : String | Test.java:29:25:29:65 | new ..[] { .. } | provenance | Sink:MaD:2 | | Test.java:29:44:29:64 | ... + ... : String | Test.java:29:25:29:65 | new ..[] { .. } : String[] [[]] : String | provenance | | | Test.java:57:27:57:39 | args : String[] | Test.java:60:20:60:22 | arg : String | provenance | | | Test.java:57:27:57:39 | args : String[] | Test.java:61:23:61:25 | arg : String | provenance | | | Test.java:60:20:60:22 | arg : String | Test.java:6:35:6:44 | arg : String | provenance | | | Test.java:61:23:61:25 | arg : String | Test.java:28:38:28:47 | arg : String | provenance | | +models +| 1 | Sink: java.lang; ProcessBuilder; false; ProcessBuilder; (List); ; Argument[0]; command-injection; ai-manual | +| 2 | Sink: java.lang; ProcessBuilder; false; ProcessBuilder; (String[]); ; Argument[0]; command-injection; ai-manual | +| 3 | Summary: java.util; Collection; true; add; ; ; Argument[0]; Argument[this].Element; value; manual | nodes | Test.java:6:35:6:44 | arg : String | semmle.label | arg : String | | Test.java:7:25:7:70 | new ..[] { .. } | semmle.label | new ..[] { .. } | @@ -40,9 +50,3 @@ nodes | Test.java:60:20:60:22 | arg : String | semmle.label | arg : String | | Test.java:61:23:61:25 | arg : String | semmle.label | arg : String | subpaths -#select -| Test.java:7:44:7:69 | ... + ... | Test.java:57:27:57:39 | args : String[] | Test.java:7:25:7:70 | new ..[] { .. } | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value | -| Test.java:10:29:10:74 | new String[] | Test.java:57:27:57:39 | args : String[] | Test.java:10:29:10:74 | new String[] | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value | -| Test.java:18:29:18:31 | cmd | Test.java:57:27:57:39 | args : String[] | Test.java:18:29:18:31 | cmd | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value | -| Test.java:24:29:24:32 | cmd1 | Test.java:57:27:57:39 | args : String[] | Test.java:24:29:24:32 | cmd1 | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value | -| Test.java:29:44:29:64 | ... + ... | Test.java:57:27:57:39 | args : String[] | Test.java:29:25:29:65 | new ..[] { .. } | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value | diff --git a/java/ql/test/query-tests/security/CWE-078/ExecTainted.qlref b/java/ql/test/query-tests/security/CWE-078/ExecTainted.qlref index 1de765a2fdf1f..d7045a37d9cfc 100644 --- a/java/ql/test/query-tests/security/CWE-078/ExecTainted.qlref +++ b/java/ql/test/query-tests/security/CWE-078/ExecTainted.qlref @@ -1 +1,2 @@ -Security/CWE/CWE-078/ExecTainted.ql +query: Security/CWE/CWE-078/ExecTainted.ql +postprocess: TestUtilities/ProvenancePathGraph.ql diff --git a/java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.ql b/java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.ql deleted file mode 100644 index 1175b67693961..0000000000000 --- a/java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.ql +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @kind path-problem - */ - -import java -import semmle.code.java.security.HttpsUrlsQuery -import codeql.dataflow.test.ProvenancePathGraph -import semmle.code.java.dataflow.ExternalFlow -import ShowProvenance - -from HttpStringToUrlOpenMethodFlow::PathNode source, HttpStringToUrlOpenMethodFlow::PathNode sink -where HttpStringToUrlOpenMethodFlow::flowPath(source, sink) -select sink.getNode(), source, sink, "URL may have been constructed with HTTP protocol, using $@.", - source.getNode(), "this HTTP URL" diff --git a/java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.qlref b/java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.qlref new file mode 100644 index 0000000000000..6c0d22195aa65 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.qlref @@ -0,0 +1,2 @@ +query: Security/CWE/CWE-319/HttpsUrls.ql +postprocess: TestUtilities/ProvenancePathGraph.ql diff --git a/shared/dataflow/codeql/dataflow/test/ProvenancePathGraph.qll b/shared/dataflow/codeql/dataflow/test/ProvenancePathGraph.qll index 0b606dc98dcb1..8a5bdb15be55f 100644 --- a/shared/dataflow/codeql/dataflow/test/ProvenancePathGraph.qll +++ b/shared/dataflow/codeql/dataflow/test/ProvenancePathGraph.qll @@ -9,6 +9,8 @@ module; signature predicate interpretModelForTestSig(QlBuiltins::ExtensionId madId, string model); +signature predicate queryResultsSig(string relation, int row, int column, string data); + signature class PathNodeSig { string toString(); } @@ -28,14 +30,14 @@ signature module PathGraphSig { predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out); } -/** Transforms a `PathGraph` by printing the provenance information. */ -module ShowProvenance< - interpretModelForTestSig/2 interpretModelForTest, PathNodeSig PathNode, - PathGraphSig PathGraph> +private signature predicate provenanceSig(string model); + +private module TranslateModels< + interpretModelForTestSig/2 interpretModelForTest, provenanceSig/1 provenance> { private predicate madIds(string madId) { exists(string model | - PathGraph::edges(_, _, _, model) and + provenance(model) and model.regexpFind("(?<=MaD:)[0-9]*", _, _) = madId ) } @@ -44,14 +46,15 @@ module ShowProvenance< madId = rank[r](string madId0 | madIds(madId0) | madId0 order by madId0.toInt()) } - query predicate models(int r, string model) { + /** Lists the renumbered and pretty-printed models used in the edges relation. */ + predicate models(int r, string model) { exists(QlBuiltins::ExtensionId madId | rankedMadIds(madId.toString(), r) and interpretModelForTest(madId, model) ) } private predicate translateModelsPart(string model1, string model2, int i) { - PathGraph::edges(_, _, _, model1) and + provenance(model1) and exists(string s | model1.splitAt("MaD:", i) = s | model2 = s and i = 0 or @@ -65,17 +68,29 @@ module ShowProvenance< ) } - private predicate translateModels(string model1, string model2) { + predicate translateModels(string model1, string model2) { exists(int i | translateModelsPart(model1, model2, i) and not translateModelsPart(model1, _, i + 1) ) } +} + +/** Transforms a `PathGraph` by printing the provenance information. */ +module ShowProvenance< + interpretModelForTestSig/2 interpretModelForTest, PathNodeSig PathNode, + PathGraphSig PathGraph> +{ + private predicate provenance(string model) { PathGraph::edges(_, _, _, model) } + + private module Models = TranslateModels; + + query predicate models(int r, string model) { Models::models(r, model) } query predicate edges(PathNode a, PathNode b, string key, string val) { exists(string model | PathGraph::edges(a, b, key, model) and - translateModels(model, val) + Models::translateModels(model, val) ) } @@ -83,3 +98,36 @@ module ShowProvenance< query predicate subpaths = PathGraph::subpaths/4; } + +/** Transforms a `PathGraph` by printing the provenance information. */ +module TranslateProvenanceResults< + interpretModelForTestSig/2 interpretModelForTest, queryResultsSig/4 queryResults> +{ + private int provenanceColumn() { result = 5 } + + private predicate provenance(string model) { queryResults("edges", _, provenanceColumn(), model) } + + private module Models = TranslateModels; + + predicate results(string relation, int row, int column, string data) { + queryResults(relation, row, column, data) and + (relation != "edges" or column != provenanceColumn()) + or + exists(string model | + relation = "edges" and + column = provenanceColumn() and + queryResults(relation, row, column, model) and + Models::translateModels(model, data) + ) + or + exists(int r, string model | + Models::models(r, model) and + relation = "models" and + row = r + | + column = 0 and data = r.toString() + or + column = 1 and data = model + ) + } +}