diff --git a/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp b/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp
index 9ee9234770e..1ebf32750a1 100644
--- a/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp
+++ b/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp
@@ -40,11 +40,11 @@ to arbitrary objects, this is inherently unsafe.
In the example below, you can see safe and unsafe methods get called by a remote user input. You can give correct authorization to users, or you can use safe methods for loading yaml documents.
-
+
In the example below, you can see safe and unsafe Plist dangerous method calls that can be abused by a remote user input. You can use "marshal: false" as an arugument for Plist.parse_xml to use it safe.
-
+
Using JSON.parse and YAML.safe_load instead, as in the
From d727d573d5ce139e8356bfca8765fc4dbcc9caa4 Mon Sep 17 00:00:00 2001
From: amammad
Date: Thu, 27 Apr 2023 06:48:15 +0200
Subject: [PATCH 069/219] v4.2 write exact version of yaml.load default loader
change
---
.../ruby/security/UnsafeDeserializationCustomizations.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ruby/ql/lib/codeql/ruby/security/UnsafeDeserializationCustomizations.qll b/ruby/ql/lib/codeql/ruby/security/UnsafeDeserializationCustomizations.qll
index fcaceed1b3a..9dea66252e5 100644
--- a/ruby/ql/lib/codeql/ruby/security/UnsafeDeserializationCustomizations.qll
+++ b/ruby/ql/lib/codeql/ruby/security/UnsafeDeserializationCustomizations.qll
@@ -79,7 +79,7 @@ module UnsafeDeserialization {
* for unsafe deserialization. The `YAML` module is an alias of `Psych` in
* recent versions of Ruby.
* the `this = yamlNode().getAMethodCall("load").getArgument(0)` is safe
- * in recent versions of YAML library, so it will be removed in future.
+ * in psych/yaml library after [v4.0.0](https://github.com/ruby/psych/releases/tag/v4.0.0), so it will be removed in future.
*/
class YamlLoadArgument extends Sink {
YamlLoadArgument() {
From b8c3cba4ff0fa9819982425cca1bf41dcbd0e2c0 Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Fri, 26 May 2023 14:48:16 +0000
Subject: [PATCH 070/219] Ruby: Consolidate unsafe deserialization queries
Merge the experimental YAMLUnsafeDeserialization and
PlistUnsafeDeserialization queries into the generate
UnsafeDeserialization query in the default suite.
These queries look for some specific sinks that we now find in the
general query.
Also apply some small code and comment refactors.
---
ruby/ql/lib/codeql/ruby/frameworks/Yaml.qll | 34 +++----
.../UnsafeDeserializationCustomizations.qll | 25 +++---
.../cwe-502/PlistUnsafeDeserialization.qhelp | 24 -----
.../cwe-502/PlistUnsafeDeserialization.ql | 57 ------------
.../cwe-502/PlistUnsafeDeserialization.rb | 17 ----
.../cwe-502/YAMLUnsafeDeserialization.qhelp | 26 ------
.../cwe-502/YAMLUnsafeDeserialization.ql | 88 -------------------
.../cwe-502/UnsafeDeserialization.qhelp | 22 +++--
.../PlistUnsafeDeserialization.expected | 12 ---
.../cwe-502/PlistUnsafeDeserialization.qlref | 1 -
.../YAMLUnsafeDeserialization.expected | 34 -------
.../cwe-502/YAMLUnsafeDeserialization.qlref | 1 -
.../cwe-502/YAMLUnsafeDeserialization.rb | 22 -----
.../PlistUnsafeDeserialization.rb | 0
.../UnsafeDeserialization.expected | 42 +++++++++
.../YAMLUnsafeDeserialization.rb | 0
16 files changed, 75 insertions(+), 330 deletions(-)
delete mode 100644 ruby/ql/src/experimental/cwe-502/PlistUnsafeDeserialization.qhelp
delete mode 100644 ruby/ql/src/experimental/cwe-502/PlistUnsafeDeserialization.ql
delete mode 100644 ruby/ql/src/experimental/cwe-502/PlistUnsafeDeserialization.rb
delete mode 100644 ruby/ql/src/experimental/cwe-502/YAMLUnsafeDeserialization.qhelp
delete mode 100644 ruby/ql/src/experimental/cwe-502/YAMLUnsafeDeserialization.ql
delete mode 100644 ruby/ql/test/query-tests/experimental/Security/cwe-502/PlistUnsafeDeserialization.expected
delete mode 100644 ruby/ql/test/query-tests/experimental/Security/cwe-502/PlistUnsafeDeserialization.qlref
delete mode 100644 ruby/ql/test/query-tests/experimental/Security/cwe-502/YAMLUnsafeDeserialization.expected
delete mode 100644 ruby/ql/test/query-tests/experimental/Security/cwe-502/YAMLUnsafeDeserialization.qlref
delete mode 100644 ruby/ql/test/query-tests/experimental/Security/cwe-502/YAMLUnsafeDeserialization.rb
rename ruby/ql/test/query-tests/{experimental/Security/cwe-502 => security/cwe-502/unsafe-deserialization}/PlistUnsafeDeserialization.rb (100%)
rename ruby/ql/{src/experimental/cwe-502 => test/query-tests/security/cwe-502/unsafe-deserialization}/YAMLUnsafeDeserialization.rb (100%)
diff --git a/ruby/ql/lib/codeql/ruby/frameworks/Yaml.qll b/ruby/ql/lib/codeql/ruby/frameworks/Yaml.qll
index 81afdcbed7b..65596df7fe2 100644
--- a/ruby/ql/lib/codeql/ruby/frameworks/Yaml.qll
+++ b/ruby/ql/lib/codeql/ruby/frameworks/Yaml.qll
@@ -8,36 +8,28 @@ private import codeql.ruby.ApiGraphs
/**
* A taint step related to the result of `YAML.parse` calls, or similar.
- *In the following example, this step will propagate taint from
- *`source` to `sink`:
+ * In the following example, this step will propagate taint from
+ * `source` to `sink`:
*
- *```rb
- *x = source
- *result = YAML.parse(x)
- *sink result.to_ruby # Unsafe call
+ * ```rb
+ * x = source
+ * result = YAML.parse(x)
+ * sink result.to_ruby # Unsafe call
* ```
*/
private class YamlParseStep extends AdditionalTaintStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
exists(DataFlow::CallNode yamlParserMethod |
- yamlParserMethod = yamlNode().getAMethodCall(["parse", "parse_stream"]) and
+ succ = yamlParserMethod.getAMethodCall("to_ruby") and
(
- pred = yamlParserMethod.getArgument(0) or
- pred = yamlParserMethod.getKeywordArgument("yaml")
- ) and
- succ = yamlParserMethod.getAMethodCall("to_ruby")
- or
- yamlParserMethod = yamlNode().getAMethodCall("parse_file") and
- (
- pred = yamlParserMethod.getArgument(0) or
- pred = yamlParserMethod.getKeywordArgument("filename")
- ) and
- succ = yamlParserMethod.getAMethodCall("to_ruby")
+ yamlParserMethod = yamlNode().getAMethodCall(["parse", "parse_stream"]) and
+ pred = [yamlParserMethod.getArgument(0), yamlParserMethod.getKeywordArgument("yaml")]
+ or
+ yamlParserMethod = yamlNode().getAMethodCall("parse_file") and
+ pred = [yamlParserMethod.getArgument(0), yamlParserMethod.getKeywordArgument("filename")]
+ )
)
}
}
-/**
- * YAML/Psych Top level Class member
- */
private API::Node yamlNode() { result = API::getTopLevelMember(["YAML", "Psych"]) }
diff --git a/ruby/ql/lib/codeql/ruby/security/UnsafeDeserializationCustomizations.qll b/ruby/ql/lib/codeql/ruby/security/UnsafeDeserializationCustomizations.qll
index 9dea66252e5..e38a38af2dc 100644
--- a/ruby/ql/lib/codeql/ruby/security/UnsafeDeserializationCustomizations.qll
+++ b/ruby/ql/lib/codeql/ruby/security/UnsafeDeserializationCustomizations.qll
@@ -75,14 +75,13 @@ module UnsafeDeserialization {
}
/**
- * An argument in a call to `YAML.unsafe_*` and `YAML.load_stream` , considered sinks
+ * An argument in a call to `YAML.unsafe_*` and `YAML.load_stream` , considered a sink
* for unsafe deserialization. The `YAML` module is an alias of `Psych` in
* recent versions of Ruby.
- * the `this = yamlNode().getAMethodCall("load").getArgument(0)` is safe
- * in psych/yaml library after [v4.0.0](https://github.com/ruby/psych/releases/tag/v4.0.0), so it will be removed in future.
*/
class YamlLoadArgument extends Sink {
YamlLoadArgument() {
+ // Note: this is safe in psych/yaml >= 4.0.0.
this = yamlNode().getAMethodCall("load").getArgument(0)
or
this =
@@ -94,16 +93,11 @@ module UnsafeDeserialization {
}
}
- /**
- * YAML/Psych Top level Class member
- */
private API::Node yamlNode() { result = API::getTopLevelMember(["YAML", "Psych"]) }
/**
- * An argument in a call to `YAML.parse*`, considered sinks
- * for unsafe deserialization if there is a call to `to_ruby` on returned value of them,
- * so this need some additional taint steps. The `YAML` module is an alias of `Psych` in
- * recent versions of Ruby.
+ * An argument in a call to `YAML.parse*`, considered a sink for unsafe deserialization
+ * if there is a call to `to_ruby` on the returned value.
*/
class YamlParseArgument extends Sink {
YamlParseArgument() {
@@ -237,7 +231,7 @@ module UnsafeDeserialization {
}
/**
- * An argument in a call to `Plist.parse_xml` where the marshal is `true` (which is
+ * An argument in a call to `Plist.parse_xml` where `marshal` is `true` (which is
* the default), considered a sink for unsafe deserialization.
*/
class UnsafePlistParsexmlArgument extends Sink {
@@ -246,10 +240,11 @@ module UnsafeDeserialization {
plistParseXml = API::getTopLevelMember("Plist").getAMethodCall("parse_xml")
|
this = [plistParseXml.getArgument(0), plistParseXml.getKeywordArgument("filename_or_xml")] and
- plistParseXml.getKeywordArgument("marshal").getConstantValue().isBoolean(true)
- or
- this = [plistParseXml.getArgument(0), plistParseXml.getKeywordArgument("filename_or_xml")] and
- plistParseXml.getNumberOfArguments() = 1
+ (
+ plistParseXml.getKeywordArgument("marshal").getConstantValue().isBoolean(true)
+ or
+ plistParseXml.getNumberOfArguments() = 1
+ )
)
}
}
diff --git a/ruby/ql/src/experimental/cwe-502/PlistUnsafeDeserialization.qhelp b/ruby/ql/src/experimental/cwe-502/PlistUnsafeDeserialization.qhelp
deleted file mode 100644
index 9863402d583..00000000000
--- a/ruby/ql/src/experimental/cwe-502/PlistUnsafeDeserialization.qhelp
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
- Processing an unvalidated user input can allow an attacker to execute arbitrary code in your application.
- Unsafe deserializing the malicious serialized xml document through the Plist library, making it possible to execute some code or execute arbitrary code with the help of a complete gadget chain.
-
-
-
-
- This vulnerability in Plist can be prevented by calling Plist.parse_xml FileOrXmlString, marshal: false.
-
-
-
- In the example below, you can see safe and unsafe Plist dangerous method calls that can be abused by a remote user input. You can use "marshal: false" as an arugument for Plist.parse_xml to use it safe.
-
-
-
-
-
- Security considerations from library documentation: patsplat/plist Repository.
-
-
-
\ No newline at end of file
diff --git a/ruby/ql/src/experimental/cwe-502/PlistUnsafeDeserialization.ql b/ruby/ql/src/experimental/cwe-502/PlistUnsafeDeserialization.ql
deleted file mode 100644
index 4ba55824598..00000000000
--- a/ruby/ql/src/experimental/cwe-502/PlistUnsafeDeserialization.ql
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * @name Unsafe Deserialization of user-controlled data by Plist
- * @description Deserializing user-controlled data may allow attackers to
- * execute arbitrary code.
- * @kind path-problem
- * @problem.severity warning
- * @security-severity 9.8
- * @precision high
- * @id rb/plist-unsafe-deserialization
- * @tags security
- * experimental
- * external/cwe/cwe-502
- */
-
-import codeql.ruby.ApiGraphs
-import codeql.ruby.DataFlow
-import codeql.ruby.TaintTracking
-import codeql.ruby.CFG
-import DataFlow::PathGraph
-import codeql.ruby.security.UnsafeDeserializationCustomizations
-
-abstract class PlistUnsafeSinks extends DataFlow::Node { }
-
-/**
- * An argument in a call to `Plist.parse_xml` where the marshal is `true` (which is
- * the default), considered a sink for unsafe deserialization.
- */
-class UnsafePlistParsexmlArgument extends PlistUnsafeSinks {
- UnsafePlistParsexmlArgument() {
- exists(DataFlow::CallNode plistParseXml |
- plistParseXml = API::getTopLevelMember("Plist").getAMethodCall("parse_xml")
- |
- this = [plistParseXml.getArgument(0), plistParseXml.getKeywordArgument("filename_or_xml")] and
- plistParseXml.getKeywordArgument("marshal").getConstantValue().isBoolean(true)
- or
- this = [plistParseXml.getArgument(0), plistParseXml.getKeywordArgument("filename_or_xml")] and
- plistParseXml.getNumberOfArguments() = 1
- )
- }
-}
-
-class Configuration extends TaintTracking::Configuration {
- Configuration() { this = "PlistUnsafeDeserialization" }
-
- override predicate isSource(DataFlow::Node source) {
- // to detect CVE-2021-33575, we should uncomment following line instead of current UnsafeDeserialization::Source
- // source instanceof DataFlow::LocalSourceNode
- source instanceof UnsafeDeserialization::Source
- }
-
- override predicate isSink(DataFlow::Node sink) { sink instanceof PlistUnsafeSinks }
-}
-
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
-select sink.getNode(), source, sink, "Unsafe deserialization depends on a $@.", source.getNode(),
- "potentially untrusted source"
diff --git a/ruby/ql/src/experimental/cwe-502/PlistUnsafeDeserialization.rb b/ruby/ql/src/experimental/cwe-502/PlistUnsafeDeserialization.rb
deleted file mode 100644
index 433873d6fa0..00000000000
--- a/ruby/ql/src/experimental/cwe-502/PlistUnsafeDeserialization.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require 'plist'
-class UsersController < ActionController::Base
- def example
- # not safe
- config = true
- result = Plist.parse_xml(params[:yaml_string])
- result = Plist.parse_xml(params[:yaml_string], marshal: config)
- result = Plist.parse_xml(params[:yaml_string], marshal: true)
-
- # safe
- config = false
- result = Plist.parse_xml(params[:yaml_string], marshal: false)
- result = Plist.parse_xml(params[:yaml_string], marshal: config)
- end
-end
-
-
diff --git a/ruby/ql/src/experimental/cwe-502/YAMLUnsafeDeserialization.qhelp b/ruby/ql/src/experimental/cwe-502/YAMLUnsafeDeserialization.qhelp
deleted file mode 100644
index c644f495271..00000000000
--- a/ruby/ql/src/experimental/cwe-502/YAMLUnsafeDeserialization.qhelp
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
- Processing an unvalidated user input can allow an attacker to execute arbitrary code in your application.
- Unsafe deserializing the malicious serialized yaml document through the Psych (YAML) library, making it possible to execute some code or execute arbitrary code with the help of a complete gadget chain.
-
-
-
-
- After Psych(YAML) 4.0.0, the load method is same as safe_load method.
- This vulnerability can be prevented by using YAML.load (same as YAML.safe_load), YAML.load_file (same as YAML.safe_load_file) instead of YAML.unsafe_* methods.
- Be careful that YAML.load_stream don't use safe_load method, Also Be careful the to_ruby method of Psych get called on a trusted parsed (YAML.parse*) yaml document.
-
-
-
- In the example below, you can see safe and unsafe methods get called by a remote user input. You can give correct authorization to users, or you can use safe methods for loading yaml documents.
-
-
-
-
- You can read that how unsafe yaml load methods can lead to code executions.
- Universal Deserialisation Gadget for Ruby 2.x-3.x .
-
-
-
\ No newline at end of file
diff --git a/ruby/ql/src/experimental/cwe-502/YAMLUnsafeDeserialization.ql b/ruby/ql/src/experimental/cwe-502/YAMLUnsafeDeserialization.ql
deleted file mode 100644
index 5cb720d19da..00000000000
--- a/ruby/ql/src/experimental/cwe-502/YAMLUnsafeDeserialization.ql
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * @name Unsafe Deserialization of user-controlled data by YAML
- * @description Deserializing user-controlled data may allow attackers to
- * execute arbitrary code.
- * @kind path-problem
- * @problem.severity warning
- * @security-severity 9.8
- * @precision high
- * @id rb/YAML-unsafe-deserialization
- * @tags security
- * experimental
- * external/cwe/cwe-502
- */
-
-import codeql.ruby.ApiGraphs
-import codeql.ruby.DataFlow
-import codeql.ruby.TaintTracking
-import DataFlow::PathGraph
-import codeql.ruby.security.UnsafeDeserializationCustomizations
-
-abstract class YamlUnsafeSinks extends DataFlow::Node { }
-
-class YamlUnsafeArgument extends YamlUnsafeSinks {
- YamlUnsafeArgument() {
- this =
- API::getTopLevelMember(["YAML", "Psych"])
- .getAMethodCall(["unsafe_load_file", "unsafe_load", "load_stream"])
- .getArgument(0)
- or
- this =
- API::getTopLevelMember(["YAML", "Psych"])
- .getAMethodCall(["unsafe_load", "load_stream"])
- .getKeywordArgument("yaml")
- or
- this =
- API::getTopLevelMember(["YAML", "Psych"])
- .getAMethodCall("unsafe_load_file")
- .getKeywordArgument("filename")
- or
- this =
- API::getTopLevelMember(["YAML", "Psych"])
- .getAMethodCall(["parse", "parse_stream", "parse_file"])
- .getAMethodCall("to_ruby")
- }
-}
-
-class Configuration extends TaintTracking::Configuration {
- Configuration() { this = "YamlUnsafeDeserialization" }
-
- override predicate isSource(DataFlow::Node source) {
- // to detect CVE-2022-32224, we should uncomment following line instead of current UnsafeDeserialization::Source
- // source instanceof DataFlow::LocalSourceNode
- source instanceof UnsafeDeserialization::Source
- }
-
- override predicate isSink(DataFlow::Node sink) {
- // after changing the isSource for detecting CVE-2022-32224
- // uncomment the following line only see the CVE sink not other files similar sinks
- // sink.getLocation().getFile().toString().matches("%yaml_column%") and
- sink instanceof YamlUnsafeSinks
- }
-
- override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
- exists(DataFlow::CallNode yaml_parser_methods |
- yaml_parser_methods =
- API::getTopLevelMember(["YAML", "Psych"]).getAMethodCall(["parse", "parse_stream"]) and
- (
- nodeFrom = yaml_parser_methods.getArgument(0) or
- nodeFrom = yaml_parser_methods.getKeywordArgument("yaml")
- ) and
- nodeTo = yaml_parser_methods.getAMethodCall("to_ruby")
- )
- or
- exists(DataFlow::CallNode yaml_parser_methods |
- yaml_parser_methods = API::getTopLevelMember(["YAML", "Psych"]).getAMethodCall("parse_file") and
- (
- nodeFrom = yaml_parser_methods.getArgument(0) or
- nodeFrom = yaml_parser_methods.getKeywordArgument("filename")
- ) and
- nodeTo = yaml_parser_methods.getAMethodCall("to_ruby")
- )
- }
-}
-
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
-select sink.getNode(), source, sink, "Unsafe deserialization depends on a $@.", source.getNode(),
- "potentially untrusted source"
diff --git a/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp b/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp
index 1ebf32750a1..17f03853570 100644
--- a/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp
+++ b/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp
@@ -19,14 +19,19 @@ deserialization of arbitrary objects.
-YAML/Psych recommendation:
-After Psych(YAML) 4.0.0, the load method is same as safe_load method.
-This vulnerability can be prevented by using YAML.load (same as YAML.safe_load), YAML.load_file (same as YAML.safe_load_file) instead of YAML.unsafe_* methods.
-Be careful that YAML.load_stream don't use safe_load method, Also Be careful the to_ruby method of Psych get called on a trusted parsed (YAML.parse*) yaml document.
+If deserializing an untrusted YAML document using the psych gem
+prior to version 4.0.0, the load method is vulnerable. Use
+safe_load instead. With psych version 4.0.0 and later,
+the load is safe. The same applies to load_file.
+load_stream is vulnerable in all versions. The safe versions of these
+methods (safe_load and safe_load_file) are not vulnerable
+in any known version.
-This vulnerability in Plist can be prevented by calling Plist.parse_xml FileOrXmlString, marshal: false.
+To safely deserialize Property List
+files using the plist gem, ensure that you pass marshal: false
+when calling Plist.parse_xml.
@@ -39,13 +44,6 @@ to arbitrary objects, this is inherently unsafe.
-In the example below, you can see safe and unsafe methods get called by a remote user input. You can give correct authorization to users, or you can use safe methods for loading yaml documents.
-
-
-In the example below, you can see safe and unsafe Plist dangerous method calls that can be abused by a remote user input. You can use "marshal: false" as an arugument for Plist.parse_xml to use it safe.
-
-
-
Using JSON.parse and YAML.safe_load instead, as in the
following example, removes the vulnerability. Similarly, calling
diff --git a/ruby/ql/test/query-tests/experimental/Security/cwe-502/PlistUnsafeDeserialization.expected b/ruby/ql/test/query-tests/experimental/Security/cwe-502/PlistUnsafeDeserialization.expected
deleted file mode 100644
index 967ef978a3b..00000000000
--- a/ruby/ql/test/query-tests/experimental/Security/cwe-502/PlistUnsafeDeserialization.expected
+++ /dev/null
@@ -1,12 +0,0 @@
-edges
-| PlistUnsafeDeserialization.rb:5:30:5:35 | call to params : | PlistUnsafeDeserialization.rb:5:30:5:49 | ...[...] |
-| PlistUnsafeDeserialization.rb:6:30:6:35 | call to params : | PlistUnsafeDeserialization.rb:6:30:6:49 | ...[...] |
-nodes
-| PlistUnsafeDeserialization.rb:5:30:5:35 | call to params : | semmle.label | call to params : |
-| PlistUnsafeDeserialization.rb:5:30:5:49 | ...[...] | semmle.label | ...[...] |
-| PlistUnsafeDeserialization.rb:6:30:6:35 | call to params : | semmle.label | call to params : |
-| PlistUnsafeDeserialization.rb:6:30:6:49 | ...[...] | semmle.label | ...[...] |
-subpaths
-#select
-| PlistUnsafeDeserialization.rb:5:30:5:49 | ...[...] | PlistUnsafeDeserialization.rb:5:30:5:35 | call to params : | PlistUnsafeDeserialization.rb:5:30:5:49 | ...[...] | Unsafe deserialization depends on a $@. | PlistUnsafeDeserialization.rb:5:30:5:35 | call to params | potentially untrusted source |
-| PlistUnsafeDeserialization.rb:6:30:6:49 | ...[...] | PlistUnsafeDeserialization.rb:6:30:6:35 | call to params : | PlistUnsafeDeserialization.rb:6:30:6:49 | ...[...] | Unsafe deserialization depends on a $@. | PlistUnsafeDeserialization.rb:6:30:6:35 | call to params | potentially untrusted source |
diff --git a/ruby/ql/test/query-tests/experimental/Security/cwe-502/PlistUnsafeDeserialization.qlref b/ruby/ql/test/query-tests/experimental/Security/cwe-502/PlistUnsafeDeserialization.qlref
deleted file mode 100644
index f7bfbada7b5..00000000000
--- a/ruby/ql/test/query-tests/experimental/Security/cwe-502/PlistUnsafeDeserialization.qlref
+++ /dev/null
@@ -1 +0,0 @@
-experimental/cwe-502/PlistUnsafeDeserialization.ql
\ No newline at end of file
diff --git a/ruby/ql/test/query-tests/experimental/Security/cwe-502/YAMLUnsafeDeserialization.expected b/ruby/ql/test/query-tests/experimental/Security/cwe-502/YAMLUnsafeDeserialization.expected
deleted file mode 100644
index 9a9bd05e514..00000000000
--- a/ruby/ql/test/query-tests/experimental/Security/cwe-502/YAMLUnsafeDeserialization.expected
+++ /dev/null
@@ -1,34 +0,0 @@
-edges
-| YAMLUnsafeDeserialization.rb:11:23:11:28 | call to params : | YAMLUnsafeDeserialization.rb:11:23:11:42 | ...[...] |
-| YAMLUnsafeDeserialization.rb:12:28:12:33 | call to params : | YAMLUnsafeDeserialization.rb:12:28:12:45 | ...[...] |
-| YAMLUnsafeDeserialization.rb:13:23:13:28 | call to params : | YAMLUnsafeDeserialization.rb:13:23:13:42 | ...[...] |
-| YAMLUnsafeDeserialization.rb:14:39:14:44 | call to params : | YAMLUnsafeDeserialization.rb:14:39:14:58 | ...[...] : |
-| YAMLUnsafeDeserialization.rb:14:39:14:58 | ...[...] : | YAMLUnsafeDeserialization.rb:15:5:15:24 | call to to_ruby |
-| YAMLUnsafeDeserialization.rb:16:17:16:22 | call to params : | YAMLUnsafeDeserialization.rb:16:17:16:36 | ...[...] : |
-| YAMLUnsafeDeserialization.rb:16:17:16:36 | ...[...] : | YAMLUnsafeDeserialization.rb:16:5:16:45 | call to to_ruby |
-| YAMLUnsafeDeserialization.rb:17:22:17:27 | call to params : | YAMLUnsafeDeserialization.rb:17:22:17:39 | ...[...] : |
-| YAMLUnsafeDeserialization.rb:17:22:17:39 | ...[...] : | YAMLUnsafeDeserialization.rb:17:5:17:48 | call to to_ruby |
-nodes
-| YAMLUnsafeDeserialization.rb:11:23:11:28 | call to params : | semmle.label | call to params : |
-| YAMLUnsafeDeserialization.rb:11:23:11:42 | ...[...] | semmle.label | ...[...] |
-| YAMLUnsafeDeserialization.rb:12:28:12:33 | call to params : | semmle.label | call to params : |
-| YAMLUnsafeDeserialization.rb:12:28:12:45 | ...[...] | semmle.label | ...[...] |
-| YAMLUnsafeDeserialization.rb:13:23:13:28 | call to params : | semmle.label | call to params : |
-| YAMLUnsafeDeserialization.rb:13:23:13:42 | ...[...] | semmle.label | ...[...] |
-| YAMLUnsafeDeserialization.rb:14:39:14:44 | call to params : | semmle.label | call to params : |
-| YAMLUnsafeDeserialization.rb:14:39:14:58 | ...[...] : | semmle.label | ...[...] : |
-| YAMLUnsafeDeserialization.rb:15:5:15:24 | call to to_ruby | semmle.label | call to to_ruby |
-| YAMLUnsafeDeserialization.rb:16:5:16:45 | call to to_ruby | semmle.label | call to to_ruby |
-| YAMLUnsafeDeserialization.rb:16:17:16:22 | call to params : | semmle.label | call to params : |
-| YAMLUnsafeDeserialization.rb:16:17:16:36 | ...[...] : | semmle.label | ...[...] : |
-| YAMLUnsafeDeserialization.rb:17:5:17:48 | call to to_ruby | semmle.label | call to to_ruby |
-| YAMLUnsafeDeserialization.rb:17:22:17:27 | call to params : | semmle.label | call to params : |
-| YAMLUnsafeDeserialization.rb:17:22:17:39 | ...[...] : | semmle.label | ...[...] : |
-subpaths
-#select
-| YAMLUnsafeDeserialization.rb:11:23:11:42 | ...[...] | YAMLUnsafeDeserialization.rb:11:23:11:28 | call to params : | YAMLUnsafeDeserialization.rb:11:23:11:42 | ...[...] | Unsafe deserialization depends on a $@. | YAMLUnsafeDeserialization.rb:11:23:11:28 | call to params | potentially untrusted source |
-| YAMLUnsafeDeserialization.rb:12:28:12:45 | ...[...] | YAMLUnsafeDeserialization.rb:12:28:12:33 | call to params : | YAMLUnsafeDeserialization.rb:12:28:12:45 | ...[...] | Unsafe deserialization depends on a $@. | YAMLUnsafeDeserialization.rb:12:28:12:33 | call to params | potentially untrusted source |
-| YAMLUnsafeDeserialization.rb:13:23:13:42 | ...[...] | YAMLUnsafeDeserialization.rb:13:23:13:28 | call to params : | YAMLUnsafeDeserialization.rb:13:23:13:42 | ...[...] | Unsafe deserialization depends on a $@. | YAMLUnsafeDeserialization.rb:13:23:13:28 | call to params | potentially untrusted source |
-| YAMLUnsafeDeserialization.rb:15:5:15:24 | call to to_ruby | YAMLUnsafeDeserialization.rb:14:39:14:44 | call to params : | YAMLUnsafeDeserialization.rb:15:5:15:24 | call to to_ruby | Unsafe deserialization depends on a $@. | YAMLUnsafeDeserialization.rb:14:39:14:44 | call to params | potentially untrusted source |
-| YAMLUnsafeDeserialization.rb:16:5:16:45 | call to to_ruby | YAMLUnsafeDeserialization.rb:16:17:16:22 | call to params : | YAMLUnsafeDeserialization.rb:16:5:16:45 | call to to_ruby | Unsafe deserialization depends on a $@. | YAMLUnsafeDeserialization.rb:16:17:16:22 | call to params | potentially untrusted source |
-| YAMLUnsafeDeserialization.rb:17:5:17:48 | call to to_ruby | YAMLUnsafeDeserialization.rb:17:22:17:27 | call to params : | YAMLUnsafeDeserialization.rb:17:5:17:48 | call to to_ruby | Unsafe deserialization depends on a $@. | YAMLUnsafeDeserialization.rb:17:22:17:27 | call to params | potentially untrusted source |
diff --git a/ruby/ql/test/query-tests/experimental/Security/cwe-502/YAMLUnsafeDeserialization.qlref b/ruby/ql/test/query-tests/experimental/Security/cwe-502/YAMLUnsafeDeserialization.qlref
deleted file mode 100644
index e06e0921159..00000000000
--- a/ruby/ql/test/query-tests/experimental/Security/cwe-502/YAMLUnsafeDeserialization.qlref
+++ /dev/null
@@ -1 +0,0 @@
-experimental/cwe-502/YAMLUnsafeDeserialization.ql
\ No newline at end of file
diff --git a/ruby/ql/test/query-tests/experimental/Security/cwe-502/YAMLUnsafeDeserialization.rb b/ruby/ql/test/query-tests/experimental/Security/cwe-502/YAMLUnsafeDeserialization.rb
deleted file mode 100644
index 6e836a0a049..00000000000
--- a/ruby/ql/test/query-tests/experimental/Security/cwe-502/YAMLUnsafeDeserialization.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require 'yaml'
-class UsersController < ActionController::Base
- def example
- # safe
- Psych.load(params[:yaml_string])
- Psych.load_file(params[:yaml_file])
- Psych.parse_stream(params[:yaml_string])
- Psych.parse(params[:yaml_string])
- Psych.parse_file(params[:yaml_file])
- # unsafe
- Psych.unsafe_load(params[:yaml_string])
- Psych.unsafe_load_file(params[:yaml_file])
- Psych.load_stream(params[:yaml_string])
- parse_output = Psych.parse_stream(params[:yaml_string])
- parse_output.to_ruby
- Psych.parse(params[:yaml_string]).to_ruby
- Psych.parse_file(params[:yaml_file]).to_ruby
-
- end
-end
-
-
diff --git a/ruby/ql/test/query-tests/experimental/Security/cwe-502/PlistUnsafeDeserialization.rb b/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/PlistUnsafeDeserialization.rb
similarity index 100%
rename from ruby/ql/test/query-tests/experimental/Security/cwe-502/PlistUnsafeDeserialization.rb
rename to ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/PlistUnsafeDeserialization.rb
diff --git a/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.expected b/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.expected
index 6fbbb14ef8a..b1f1d701a73 100644
--- a/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.expected
+++ b/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.expected
@@ -1,4 +1,6 @@
edges
+| PlistUnsafeDeserialization.rb:5:30:5:35 | call to params | PlistUnsafeDeserialization.rb:5:30:5:49 | ...[...] |
+| PlistUnsafeDeserialization.rb:6:30:6:35 | call to params | PlistUnsafeDeserialization.rb:6:30:6:49 | ...[...] |
| UnsafeDeserialization.rb:10:5:10:19 | serialized_data | UnsafeDeserialization.rb:11:27:11:41 | serialized_data |
| UnsafeDeserialization.rb:10:23:10:50 | call to decode64 | UnsafeDeserialization.rb:10:5:10:19 | serialized_data |
| UnsafeDeserialization.rb:10:39:10:44 | call to params | UnsafeDeserialization.rb:10:39:10:50 | ...[...] |
@@ -29,7 +31,21 @@ edges
| UnsafeDeserialization.rb:87:5:87:13 | yaml_data | UnsafeDeserialization.rb:88:25:88:33 | yaml_data |
| UnsafeDeserialization.rb:87:17:87:22 | call to params | UnsafeDeserialization.rb:87:17:87:28 | ...[...] |
| UnsafeDeserialization.rb:87:17:87:28 | ...[...] | UnsafeDeserialization.rb:87:5:87:13 | yaml_data |
+| YAMLUnsafeDeserialization.rb:5:16:5:21 | call to params | YAMLUnsafeDeserialization.rb:5:16:5:35 | ...[...] |
+| YAMLUnsafeDeserialization.rb:11:23:11:28 | call to params | YAMLUnsafeDeserialization.rb:11:23:11:42 | ...[...] |
+| YAMLUnsafeDeserialization.rb:12:28:12:33 | call to params | YAMLUnsafeDeserialization.rb:12:28:12:45 | ...[...] |
+| YAMLUnsafeDeserialization.rb:13:23:13:28 | call to params | YAMLUnsafeDeserialization.rb:13:23:13:42 | ...[...] |
+| YAMLUnsafeDeserialization.rb:14:39:14:44 | call to params | YAMLUnsafeDeserialization.rb:14:39:14:58 | ...[...] |
+| YAMLUnsafeDeserialization.rb:14:39:14:58 | ...[...] | YAMLUnsafeDeserialization.rb:15:5:15:24 | call to to_ruby |
+| YAMLUnsafeDeserialization.rb:16:17:16:22 | call to params | YAMLUnsafeDeserialization.rb:16:17:16:36 | ...[...] |
+| YAMLUnsafeDeserialization.rb:16:17:16:36 | ...[...] | YAMLUnsafeDeserialization.rb:16:5:16:45 | call to to_ruby |
+| YAMLUnsafeDeserialization.rb:17:22:17:27 | call to params | YAMLUnsafeDeserialization.rb:17:22:17:39 | ...[...] |
+| YAMLUnsafeDeserialization.rb:17:22:17:39 | ...[...] | YAMLUnsafeDeserialization.rb:17:5:17:48 | call to to_ruby |
nodes
+| PlistUnsafeDeserialization.rb:5:30:5:35 | call to params | semmle.label | call to params |
+| PlistUnsafeDeserialization.rb:5:30:5:49 | ...[...] | semmle.label | ...[...] |
+| PlistUnsafeDeserialization.rb:6:30:6:35 | call to params | semmle.label | call to params |
+| PlistUnsafeDeserialization.rb:6:30:6:49 | ...[...] | semmle.label | ...[...] |
| UnsafeDeserialization.rb:10:5:10:19 | serialized_data | semmle.label | serialized_data |
| UnsafeDeserialization.rb:10:23:10:50 | call to decode64 | semmle.label | call to decode64 |
| UnsafeDeserialization.rb:10:39:10:44 | call to params | semmle.label | call to params |
@@ -74,8 +90,27 @@ nodes
| UnsafeDeserialization.rb:98:24:98:32 | call to read | semmle.label | call to read |
| UnsafeDeserialization.rb:101:24:101:27 | call to gets | semmle.label | call to gets |
| UnsafeDeserialization.rb:104:24:104:32 | call to readlines | semmle.label | call to readlines |
+| YAMLUnsafeDeserialization.rb:5:16:5:21 | call to params | semmle.label | call to params |
+| YAMLUnsafeDeserialization.rb:5:16:5:35 | ...[...] | semmle.label | ...[...] |
+| YAMLUnsafeDeserialization.rb:11:23:11:28 | call to params | semmle.label | call to params |
+| YAMLUnsafeDeserialization.rb:11:23:11:42 | ...[...] | semmle.label | ...[...] |
+| YAMLUnsafeDeserialization.rb:12:28:12:33 | call to params | semmle.label | call to params |
+| YAMLUnsafeDeserialization.rb:12:28:12:45 | ...[...] | semmle.label | ...[...] |
+| YAMLUnsafeDeserialization.rb:13:23:13:28 | call to params | semmle.label | call to params |
+| YAMLUnsafeDeserialization.rb:13:23:13:42 | ...[...] | semmle.label | ...[...] |
+| YAMLUnsafeDeserialization.rb:14:39:14:44 | call to params | semmle.label | call to params |
+| YAMLUnsafeDeserialization.rb:14:39:14:58 | ...[...] | semmle.label | ...[...] |
+| YAMLUnsafeDeserialization.rb:15:5:15:24 | call to to_ruby | semmle.label | call to to_ruby |
+| YAMLUnsafeDeserialization.rb:16:5:16:45 | call to to_ruby | semmle.label | call to to_ruby |
+| YAMLUnsafeDeserialization.rb:16:17:16:22 | call to params | semmle.label | call to params |
+| YAMLUnsafeDeserialization.rb:16:17:16:36 | ...[...] | semmle.label | ...[...] |
+| YAMLUnsafeDeserialization.rb:17:5:17:48 | call to to_ruby | semmle.label | call to to_ruby |
+| YAMLUnsafeDeserialization.rb:17:22:17:27 | call to params | semmle.label | call to params |
+| YAMLUnsafeDeserialization.rb:17:22:17:39 | ...[...] | semmle.label | ...[...] |
subpaths
#select
+| PlistUnsafeDeserialization.rb:5:30:5:49 | ...[...] | PlistUnsafeDeserialization.rb:5:30:5:35 | call to params | PlistUnsafeDeserialization.rb:5:30:5:49 | ...[...] | Unsafe deserialization depends on a $@. | PlistUnsafeDeserialization.rb:5:30:5:35 | call to params | user-provided value |
+| PlistUnsafeDeserialization.rb:6:30:6:49 | ...[...] | PlistUnsafeDeserialization.rb:6:30:6:35 | call to params | PlistUnsafeDeserialization.rb:6:30:6:49 | ...[...] | Unsafe deserialization depends on a $@. | PlistUnsafeDeserialization.rb:6:30:6:35 | call to params | user-provided value |
| UnsafeDeserialization.rb:11:27:11:41 | serialized_data | UnsafeDeserialization.rb:10:39:10:44 | call to params | UnsafeDeserialization.rb:11:27:11:41 | serialized_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:10:39:10:44 | call to params | user-provided value |
| UnsafeDeserialization.rb:17:30:17:44 | serialized_data | UnsafeDeserialization.rb:16:39:16:44 | call to params | UnsafeDeserialization.rb:17:30:17:44 | serialized_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:16:39:16:44 | call to params | user-provided value |
| UnsafeDeserialization.rb:23:24:23:32 | json_data | UnsafeDeserialization.rb:22:17:22:22 | call to params | UnsafeDeserialization.rb:23:24:23:32 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:22:17:22:22 | call to params | user-provided value |
@@ -91,3 +126,10 @@ subpaths
| UnsafeDeserialization.rb:98:24:98:32 | call to read | UnsafeDeserialization.rb:98:24:98:32 | call to read | UnsafeDeserialization.rb:98:24:98:32 | call to read | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:98:24:98:32 | call to read | value from stdin |
| UnsafeDeserialization.rb:101:24:101:27 | call to gets | UnsafeDeserialization.rb:101:24:101:27 | call to gets | UnsafeDeserialization.rb:101:24:101:27 | call to gets | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:101:24:101:27 | call to gets | value from stdin |
| UnsafeDeserialization.rb:104:24:104:32 | call to readlines | UnsafeDeserialization.rb:104:24:104:32 | call to readlines | UnsafeDeserialization.rb:104:24:104:32 | call to readlines | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:104:24:104:32 | call to readlines | value from stdin |
+| YAMLUnsafeDeserialization.rb:5:16:5:35 | ...[...] | YAMLUnsafeDeserialization.rb:5:16:5:21 | call to params | YAMLUnsafeDeserialization.rb:5:16:5:35 | ...[...] | Unsafe deserialization depends on a $@. | YAMLUnsafeDeserialization.rb:5:16:5:21 | call to params | user-provided value |
+| YAMLUnsafeDeserialization.rb:11:23:11:42 | ...[...] | YAMLUnsafeDeserialization.rb:11:23:11:28 | call to params | YAMLUnsafeDeserialization.rb:11:23:11:42 | ...[...] | Unsafe deserialization depends on a $@. | YAMLUnsafeDeserialization.rb:11:23:11:28 | call to params | user-provided value |
+| YAMLUnsafeDeserialization.rb:12:28:12:45 | ...[...] | YAMLUnsafeDeserialization.rb:12:28:12:33 | call to params | YAMLUnsafeDeserialization.rb:12:28:12:45 | ...[...] | Unsafe deserialization depends on a $@. | YAMLUnsafeDeserialization.rb:12:28:12:33 | call to params | user-provided value |
+| YAMLUnsafeDeserialization.rb:13:23:13:42 | ...[...] | YAMLUnsafeDeserialization.rb:13:23:13:28 | call to params | YAMLUnsafeDeserialization.rb:13:23:13:42 | ...[...] | Unsafe deserialization depends on a $@. | YAMLUnsafeDeserialization.rb:13:23:13:28 | call to params | user-provided value |
+| YAMLUnsafeDeserialization.rb:15:5:15:24 | call to to_ruby | YAMLUnsafeDeserialization.rb:14:39:14:44 | call to params | YAMLUnsafeDeserialization.rb:15:5:15:24 | call to to_ruby | Unsafe deserialization depends on a $@. | YAMLUnsafeDeserialization.rb:14:39:14:44 | call to params | user-provided value |
+| YAMLUnsafeDeserialization.rb:16:5:16:45 | call to to_ruby | YAMLUnsafeDeserialization.rb:16:17:16:22 | call to params | YAMLUnsafeDeserialization.rb:16:5:16:45 | call to to_ruby | Unsafe deserialization depends on a $@. | YAMLUnsafeDeserialization.rb:16:17:16:22 | call to params | user-provided value |
+| YAMLUnsafeDeserialization.rb:17:5:17:48 | call to to_ruby | YAMLUnsafeDeserialization.rb:17:22:17:27 | call to params | YAMLUnsafeDeserialization.rb:17:5:17:48 | call to to_ruby | Unsafe deserialization depends on a $@. | YAMLUnsafeDeserialization.rb:17:22:17:27 | call to params | user-provided value |
diff --git a/ruby/ql/src/experimental/cwe-502/YAMLUnsafeDeserialization.rb b/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/YAMLUnsafeDeserialization.rb
similarity index 100%
rename from ruby/ql/src/experimental/cwe-502/YAMLUnsafeDeserialization.rb
rename to ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/YAMLUnsafeDeserialization.rb
From 562065f29e6fd387534e517942e89f907117a290 Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Sat, 27 May 2023 00:59:36 +0000
Subject: [PATCH 071/219] Ruby: Add change note
---
ruby/ql/lib/change-notes/2023-05-27-unsafe-deserialization.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 ruby/ql/lib/change-notes/2023-05-27-unsafe-deserialization.md
diff --git a/ruby/ql/lib/change-notes/2023-05-27-unsafe-deserialization.md b/ruby/ql/lib/change-notes/2023-05-27-unsafe-deserialization.md
new file mode 100644
index 00000000000..4039e7c90dc
--- /dev/null
+++ b/ruby/ql/lib/change-notes/2023-05-27-unsafe-deserialization.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* Additional sinks for `rb/unsafe-deserialization` have been added. This includes various methods from the `yaml` and `plist` gems, which deserialize YAML and Property List data, respectively.
From e515981c81d1fd82d586de9bc4afa8f5e4988470 Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Sat, 27 May 2023 12:01:00 +0000
Subject: [PATCH 072/219] Ruby: Remove unused examples
---
.../examples/PlistUnsafeDeserialization.rb | 17 --------------
.../examples/YAMLUnsafeDeserialization.rb | 22 -------------------
2 files changed, 39 deletions(-)
delete mode 100644 ruby/ql/src/queries/security/cwe-502/examples/PlistUnsafeDeserialization.rb
delete mode 100644 ruby/ql/src/queries/security/cwe-502/examples/YAMLUnsafeDeserialization.rb
diff --git a/ruby/ql/src/queries/security/cwe-502/examples/PlistUnsafeDeserialization.rb b/ruby/ql/src/queries/security/cwe-502/examples/PlistUnsafeDeserialization.rb
deleted file mode 100644
index 433873d6fa0..00000000000
--- a/ruby/ql/src/queries/security/cwe-502/examples/PlistUnsafeDeserialization.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require 'plist'
-class UsersController < ActionController::Base
- def example
- # not safe
- config = true
- result = Plist.parse_xml(params[:yaml_string])
- result = Plist.parse_xml(params[:yaml_string], marshal: config)
- result = Plist.parse_xml(params[:yaml_string], marshal: true)
-
- # safe
- config = false
- result = Plist.parse_xml(params[:yaml_string], marshal: false)
- result = Plist.parse_xml(params[:yaml_string], marshal: config)
- end
-end
-
-
diff --git a/ruby/ql/src/queries/security/cwe-502/examples/YAMLUnsafeDeserialization.rb b/ruby/ql/src/queries/security/cwe-502/examples/YAMLUnsafeDeserialization.rb
deleted file mode 100644
index 6e836a0a049..00000000000
--- a/ruby/ql/src/queries/security/cwe-502/examples/YAMLUnsafeDeserialization.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require 'yaml'
-class UsersController < ActionController::Base
- def example
- # safe
- Psych.load(params[:yaml_string])
- Psych.load_file(params[:yaml_file])
- Psych.parse_stream(params[:yaml_string])
- Psych.parse(params[:yaml_string])
- Psych.parse_file(params[:yaml_file])
- # unsafe
- Psych.unsafe_load(params[:yaml_string])
- Psych.unsafe_load_file(params[:yaml_file])
- Psych.load_stream(params[:yaml_string])
- parse_output = Psych.parse_stream(params[:yaml_string])
- parse_output.to_ruby
- Psych.parse(params[:yaml_string]).to_ruby
- Psych.parse_file(params[:yaml_file]).to_ruby
-
- end
-end
-
-
From ca1024e2858c6f541c5adef4e0405dbc6b7625f1 Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Mon, 29 May 2023 03:46:30 +0000
Subject: [PATCH 073/219] Ruby: Reword unsafe deserialization qhelp
---
.../security/cwe-502/UnsafeDeserialization.qhelp | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp b/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp
index 17f03853570..8bacb266423 100644
--- a/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp
+++ b/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp
@@ -19,13 +19,12 @@ deserialization of arbitrary objects.
-If deserializing an untrusted YAML document using the psych gem
-prior to version 4.0.0, the load method is vulnerable. Use
-safe_load instead. With psych version 4.0.0 and later,
-the load is safe. The same applies to load_file.
-load_stream is vulnerable in all versions. The safe versions of these
-methods (safe_load and safe_load_file) are not vulnerable
-in any known version.
+If deserializing an untrusted YAML document using the psych gem,
+prefer the safe_load and safe_load_file methods over
+load and load_file, as the former will safely
+handle untrusted data. Avoid passing untrusted data to the load_stream
+method. In psych version 4.0.0 and above, the load can
+safely be used.
From e70e3e52dcf7456465fdc6f59e687f08293c40d2 Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Mon, 29 May 2023 04:05:42 +0000
Subject: [PATCH 074/219] Ruby: fix typo in qhelp
---
.../ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp b/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp
index 8bacb266423..e361b62338e 100644
--- a/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp
+++ b/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp
@@ -23,7 +23,7 @@ If deserializing an untrusted YAML document using the psych gem,
prefer the safe_load and safe_load_file methods over
load and load_file, as the former will safely
handle untrusted data. Avoid passing untrusted data to the load_stream
-method. In psych version 4.0.0 and above, the load can
+method. In psych version 4.0.0 and above, the load method can
safely be used.
From d50617202746b8cbb8558f8486975a804e9a71fd Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Tue, 30 May 2023 09:11:00 +0100
Subject: [PATCH 075/219] Swift: Change note.
---
swift/ql/lib/change-notes/2023-05-30-shared-sensitive.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 swift/ql/lib/change-notes/2023-05-30-shared-sensitive.md
diff --git a/swift/ql/lib/change-notes/2023-05-30-shared-sensitive.md b/swift/ql/lib/change-notes/2023-05-30-shared-sensitive.md
new file mode 100644
index 00000000000..03de16f4269
--- /dev/null
+++ b/swift/ql/lib/change-notes/2023-05-30-shared-sensitive.md
@@ -0,0 +1,4 @@
+---
+category: majorAnalysis
+---
+* Incorporated the cross-language `SensitiveDataHeuristics.qll` heuristics library into the Swift `SensitiveExprs.qll` library. This adds a number of new heuristics enhancing detection from the library.
\ No newline at end of file
From 560aa43953a14843f0661420c40f13c1c66b0dae Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Tue, 30 May 2023 14:20:17 +0100
Subject: [PATCH 076/219] Swift: Repair for AccountID / AccountKey.
---
swift/ql/lib/codeql/swift/security/SensitiveExprs.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll b/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll
index 71a250229e7..d750e673121 100644
--- a/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll
+++ b/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll
@@ -35,7 +35,7 @@ class SensitiveCredential extends SensitiveDataType, TCredential {
result = HeuristicNames::maybeSensitiveRegexp(classification)
)
or
- result = "(?is).*(license.?key).*"
+ result = "(?is).*(account|accnt|license).?(id|key).*"
}
}
From b343dcaadd01e19b610269b2bbbb1e709e509f57 Mon Sep 17 00:00:00 2001
From: erik-krogh
Date: Wed, 31 May 2023 08:06:04 +0200
Subject: [PATCH 077/219] put string/object in the alert-message for
sql-injection
---
.../ql/src/Security/CWE-089/SqlInjection.ql | 9 +-
.../ql/src/Security/CWE-089/SqlInjection.ql | 12 +-
.../CWE-089/typed/SqlInjection.expected | 6 +-
.../CWE-089/untyped/SqlInjection.expected | 250 +++++++++---------
4 files changed, 139 insertions(+), 138 deletions(-)
diff --git a/javascript/ql/src/Security/CWE-089/SqlInjection.ql b/javascript/ql/src/Security/CWE-089/SqlInjection.ql
index 6b0502f611f..f7a40bb91f9 100644
--- a/javascript/ql/src/Security/CWE-089/SqlInjection.ql
+++ b/javascript/ql/src/Security/CWE-089/SqlInjection.ql
@@ -18,12 +18,13 @@ import semmle.javascript.security.dataflow.SqlInjectionQuery as SqlInjection
import semmle.javascript.security.dataflow.NosqlInjectionQuery as NosqlInjection
import DataFlow::PathGraph
-from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, string type
where
(
- cfg instanceof SqlInjection::Configuration or
- cfg instanceof NosqlInjection::Configuration
+ cfg instanceof SqlInjection::Configuration and type = "string"
+ or
+ cfg instanceof NosqlInjection::Configuration and type = "object"
) and
cfg.hasFlowPath(source, sink)
-select sink.getNode(), source, sink, "This query depends on a $@.", source.getNode(),
+select sink.getNode(), source, sink, "This query " + type + " depends on a $@.", source.getNode(),
"user-provided value"
diff --git a/javascript/ql/src/experimental/heuristics/ql/src/Security/CWE-089/SqlInjection.ql b/javascript/ql/src/experimental/heuristics/ql/src/Security/CWE-089/SqlInjection.ql
index a2c4a4158bc..e82b9d40d5b 100644
--- a/javascript/ql/src/experimental/heuristics/ql/src/Security/CWE-089/SqlInjection.ql
+++ b/javascript/ql/src/experimental/heuristics/ql/src/Security/CWE-089/SqlInjection.ql
@@ -20,13 +20,13 @@ import semmle.javascript.security.dataflow.NosqlInjectionQuery as NosqlInjection
import DataFlow::PathGraph
import semmle.javascript.heuristics.AdditionalSources
-from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, string type
where
(
- cfg instanceof SqlInjection::Configuration or
- cfg instanceof NosqlInjection::Configuration
+ cfg instanceof SqlInjection::Configuration and type = "string"
+ or
+ cfg instanceof NosqlInjection::Configuration and type = "object"
) and
- cfg.hasFlowPath(source, sink) and
- source.getNode() instanceof HeuristicSource
-select sink.getNode(), source, sink, "This query depends on a $@.", source.getNode(),
+ cfg.hasFlowPath(source, sink)
+select sink.getNode(), source, sink, "This query " + type + " depends on a $@.", source.getNode(),
"user-provided value"
diff --git a/javascript/ql/test/query-tests/Security/CWE-089/typed/SqlInjection.expected b/javascript/ql/test/query-tests/Security/CWE-089/typed/SqlInjection.expected
index f6a8d8862f6..acf7e712ee2 100644
--- a/javascript/ql/test/query-tests/Security/CWE-089/typed/SqlInjection.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-089/typed/SqlInjection.expected
@@ -37,6 +37,6 @@ edges
| typedClient.ts:23:33:23:33 | v | typedClient.ts:23:27:23:35 | { id: v } |
| typedClient.ts:23:33:23:33 | v | typedClient.ts:23:27:23:35 | { id: v } |
#select
-| typedClient.ts:14:24:14:32 | { id: v } | typedClient.ts:13:22:13:29 | req.body | typedClient.ts:14:24:14:32 | { id: v } | This query depends on a $@. | typedClient.ts:13:22:13:29 | req.body | user-provided value |
-| typedClient.ts:22:27:22:35 | { id: v } | typedClient.ts:21:22:21:29 | req.body | typedClient.ts:22:27:22:35 | { id: v } | This query depends on a $@. | typedClient.ts:21:22:21:29 | req.body | user-provided value |
-| typedClient.ts:23:27:23:35 | { id: v } | typedClient.ts:21:22:21:29 | req.body | typedClient.ts:23:27:23:35 | { id: v } | This query depends on a $@. | typedClient.ts:21:22:21:29 | req.body | user-provided value |
+| typedClient.ts:14:24:14:32 | { id: v } | typedClient.ts:13:22:13:29 | req.body | typedClient.ts:14:24:14:32 | { id: v } | This query object depends on a $@. | typedClient.ts:13:22:13:29 | req.body | user-provided value |
+| typedClient.ts:22:27:22:35 | { id: v } | typedClient.ts:21:22:21:29 | req.body | typedClient.ts:22:27:22:35 | { id: v } | This query object depends on a $@. | typedClient.ts:21:22:21:29 | req.body | user-provided value |
+| typedClient.ts:23:27:23:35 | { id: v } | typedClient.ts:21:22:21:29 | req.body | typedClient.ts:23:27:23:35 | { id: v } | This query object depends on a $@. | typedClient.ts:21:22:21:29 | req.body | user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected b/javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected
index be40ab490ad..6eba7711032 100644
--- a/javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected
@@ -928,128 +928,128 @@ edges
| tst.js:10:46:10:58 | req.params.id | tst.js:10:10:10:64 | 'SELECT ... d + '"' |
| tst.js:10:46:10:58 | req.params.id | tst.js:10:10:10:64 | 'SELECT ... d + '"' |
#select
-| graphql.js:10:34:20:5 | `\\n ... }\\n ` | graphql.js:8:16:8:28 | req.params.id | graphql.js:10:34:20:5 | `\\n ... }\\n ` | This query depends on a $@. | graphql.js:8:16:8:28 | req.params.id | user-provided value |
-| graphql.js:27:30:27:40 | `foo ${id}` | graphql.js:26:16:26:28 | req.params.id | graphql.js:27:30:27:40 | `foo ${id}` | This query depends on a $@. | graphql.js:26:16:26:28 | req.params.id | user-provided value |
-| graphql.js:30:32:30:42 | `foo ${id}` | graphql.js:26:16:26:28 | req.params.id | graphql.js:30:32:30:42 | `foo ${id}` | This query depends on a $@. | graphql.js:26:16:26:28 | req.params.id | user-provided value |
-| graphql.js:33:18:33:28 | `foo ${id}` | graphql.js:26:16:26:28 | req.params.id | graphql.js:33:18:33:28 | `foo ${id}` | This query depends on a $@. | graphql.js:26:16:26:28 | req.params.id | user-provided value |
-| graphql.js:44:14:44:24 | `foo ${id}` | graphql.js:39:16:39:28 | req.params.id | graphql.js:44:14:44:24 | `foo ${id}` | This query depends on a $@. | graphql.js:39:16:39:28 | req.params.id | user-provided value |
-| graphql.js:48:44:48:54 | `foo ${id}` | graphql.js:39:16:39:28 | req.params.id | graphql.js:48:44:48:54 | `foo ${id}` | This query depends on a $@. | graphql.js:39:16:39:28 | req.params.id | user-provided value |
-| graphql.js:56:39:56:49 | `foo ${id}` | graphql.js:55:16:55:28 | req.params.id | graphql.js:56:39:56:49 | `foo ${id}` | This query depends on a $@. | graphql.js:55:16:55:28 | req.params.id | user-provided value |
-| graphql.js:58:66:58:76 | `foo ${id}` | graphql.js:55:16:55:28 | req.params.id | graphql.js:58:66:58:76 | `foo ${id}` | This query depends on a $@. | graphql.js:55:16:55:28 | req.params.id | user-provided value |
-| graphql.js:75:46:75:64 | "{ foo" + id + " }" | graphql.js:74:14:74:25 | req.query.id | graphql.js:75:46:75:64 | "{ foo" + id + " }" | This query depends on a $@. | graphql.js:74:14:74:25 | req.query.id | user-provided value |
-| graphql.js:84:14:90:8 | `{\\n ... }` | graphql.js:74:14:74:25 | req.query.id | graphql.js:84:14:90:8 | `{\\n ... }` | This query depends on a $@. | graphql.js:74:14:74:25 | req.query.id | user-provided value |
-| graphql.js:120:38:120:48 | `foo ${id}` | graphql.js:119:16:119:28 | req.params.id | graphql.js:120:38:120:48 | `foo ${id}` | This query depends on a $@. | graphql.js:119:16:119:28 | req.params.id | user-provided value |
-| html-sanitizer.js:16:9:16:59 | `SELECT ... param1 | html-sanitizer.js:13:39:13:44 | param1 | html-sanitizer.js:16:9:16:59 | `SELECT ... param1 | This query depends on a $@. | html-sanitizer.js:13:39:13:44 | param1 | user-provided value |
-| json-schema-validator.js:33:22:33:26 | query | json-schema-validator.js:25:34:25:47 | req.query.data | json-schema-validator.js:33:22:33:26 | query | This query depends on a $@. | json-schema-validator.js:25:34:25:47 | req.query.data | user-provided value |
-| json-schema-validator.js:35:18:35:22 | query | json-schema-validator.js:25:34:25:47 | req.query.data | json-schema-validator.js:35:18:35:22 | query | This query depends on a $@. | json-schema-validator.js:25:34:25:47 | req.query.data | user-provided value |
-| json-schema-validator.js:55:22:55:26 | query | json-schema-validator.js:50:34:50:47 | req.query.data | json-schema-validator.js:55:22:55:26 | query | This query depends on a $@. | json-schema-validator.js:50:34:50:47 | req.query.data | user-provided value |
-| json-schema-validator.js:59:22:59:26 | query | json-schema-validator.js:50:34:50:47 | req.query.data | json-schema-validator.js:59:22:59:26 | query | This query depends on a $@. | json-schema-validator.js:50:34:50:47 | req.query.data | user-provided value |
-| json-schema-validator.js:61:22:61:26 | query | json-schema-validator.js:50:34:50:47 | req.query.data | json-schema-validator.js:61:22:61:26 | query | This query depends on a $@. | json-schema-validator.js:50:34:50:47 | req.query.data | user-provided value |
-| ldap.js:28:30:28:34 | opts1 | ldap.js:20:21:20:27 | req.url | ldap.js:28:30:28:34 | opts1 | This query depends on a $@. | ldap.js:20:21:20:27 | req.url | user-provided value |
-| ldap.js:32:5:32:61 | { filte ... e}))` } | ldap.js:20:21:20:27 | req.url | ldap.js:32:5:32:61 | { filte ... e}))` } | This query depends on a $@. | ldap.js:20:21:20:27 | req.url | user-provided value |
-| ldap.js:66:30:66:53 | { filte ... ilter } | ldap.js:20:21:20:27 | req.url | ldap.js:66:30:66:53 | { filte ... ilter } | This query depends on a $@. | ldap.js:20:21:20:27 | req.url | user-provided value |
-| ldap.js:68:27:68:42 | `cn=${username}` | ldap.js:20:21:20:27 | req.url | ldap.js:68:27:68:42 | `cn=${username}` | This query depends on a $@. | ldap.js:20:21:20:27 | req.url | user-provided value |
-| marsdb-flow-to.js:14:17:14:21 | query | marsdb-flow-to.js:11:17:11:24 | req.body | marsdb-flow-to.js:14:17:14:21 | query | This query depends on a $@. | marsdb-flow-to.js:11:17:11:24 | req.body | user-provided value |
-| marsdb.js:16:12:16:16 | query | marsdb.js:13:17:13:24 | req.body | marsdb.js:16:12:16:16 | query | This query depends on a $@. | marsdb.js:13:17:13:24 | req.body | user-provided value |
-| minimongo.js:18:12:18:16 | query | minimongo.js:15:17:15:24 | req.body | minimongo.js:18:12:18:16 | query | This query depends on a $@. | minimongo.js:15:17:15:24 | req.body | user-provided value |
-| mongodb.js:18:16:18:20 | query | mongodb.js:13:19:13:26 | req.body | mongodb.js:18:16:18:20 | query | This query depends on a $@. | mongodb.js:13:19:13:26 | req.body | user-provided value |
-| mongodb.js:32:18:32:45 | { title ... itle) } | mongodb.js:26:19:26:26 | req.body | mongodb.js:32:18:32:45 | { title ... itle) } | This query depends on a $@. | mongodb.js:26:19:26:26 | req.body | user-provided value |
-| mongodb.js:54:16:54:20 | query | mongodb.js:49:19:49:33 | req.query.title | mongodb.js:54:16:54:20 | query | This query depends on a $@. | mongodb.js:49:19:49:33 | req.query.title | user-provided value |
-| mongodb.js:65:12:65:16 | query | mongodb.js:60:16:60:30 | req.query.title | mongodb.js:65:12:65:16 | query | This query depends on a $@. | mongodb.js:60:16:60:30 | req.query.title | user-provided value |
-| mongodb.js:77:14:77:26 | { tags: tag } | mongodb.js:70:13:70:25 | req.query.tag | mongodb.js:77:14:77:26 | { tags: tag } | This query depends on a $@. | mongodb.js:70:13:70:25 | req.query.tag | user-provided value |
-| mongodb.js:85:12:85:24 | { tags: tag } | mongodb.js:70:13:70:25 | req.query.tag | mongodb.js:85:12:85:24 | { tags: tag } | This query depends on a $@. | mongodb.js:70:13:70:25 | req.query.tag | user-provided value |
-| mongodb.js:112:14:112:18 | query | mongodb.js:107:17:107:29 | queries.title | mongodb.js:112:14:112:18 | query | This query depends on a $@. | mongodb.js:107:17:107:29 | queries.title | user-provided value |
-| mongodb_bodySafe.js:29:16:29:20 | query | mongodb_bodySafe.js:24:19:24:33 | req.query.title | mongodb_bodySafe.js:29:16:29:20 | query | This query depends on a $@. | mongodb_bodySafe.js:24:19:24:33 | req.query.title | user-provided value |
-| mongoose.js:24:24:24:30 | [query] | mongoose.js:21:19:21:26 | req.body | mongoose.js:24:24:24:30 | [query] | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:27:20:27:24 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:27:20:27:24 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:30:25:30:29 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:30:25:30:29 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:33:24:33:28 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:33:24:33:28 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:36:31:36:35 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:36:31:36:35 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:39:19:39:23 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:39:19:39:23 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:42:22:42:26 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:42:22:42:26 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:45:31:45:35 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:45:31:45:35 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:48:31:48:35 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:48:31:48:35 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:51:31:51:35 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:51:31:51:35 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:54:25:54:29 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:54:25:54:29 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:57:21:57:25 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:57:21:57:25 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:60:25:60:29 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:60:25:60:29 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:63:21:63:25 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:63:21:63:25 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:65:32:65:36 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:65:32:65:36 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:67:27:67:31 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:67:27:67:31 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:68:8:68:12 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:68:8:68:12 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:71:20:71:24 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:71:20:71:24 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:72:16:72:20 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:72:16:72:20 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:73:8:73:12 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:73:8:73:12 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:74:7:74:11 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:74:7:74:11 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:75:16:75:20 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:75:16:75:20 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:77:10:77:14 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:77:10:77:14 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:82:46:82:50 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:82:46:82:50 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:83:47:83:51 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:83:47:83:51 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:85:46:85:50 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:85:46:85:50 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:87:51:87:55 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:87:51:87:55 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:89:46:89:50 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:89:46:89:50 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:92:46:92:50 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:92:46:92:50 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:94:51:94:55 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:94:51:94:55 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:96:46:96:50 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:96:46:96:50 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:111:14:111:18 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:111:14:111:18 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:113:31:113:35 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:113:31:113:35 | query | This query depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
-| mongoose.js:116:22:116:25 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:116:22:116:25 | cond | This query depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
-| mongoose.js:117:21:117:24 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:117:21:117:24 | cond | This query depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
-| mongoose.js:118:21:118:24 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:118:21:118:24 | cond | This query depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
-| mongoose.js:119:18:119:21 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:119:18:119:21 | cond | This query depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
-| mongoose.js:120:22:120:25 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:120:22:120:25 | cond | This query depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
-| mongoose.js:121:16:121:19 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:121:16:121:19 | cond | This query depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
-| mongoose.js:122:19:122:22 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:122:19:122:22 | cond | This query depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
-| mongoose.js:123:20:123:21 | id | mongoose.js:115:11:115:22 | req.query.id | mongoose.js:123:20:123:21 | id | This query depends on a $@. | mongoose.js:115:11:115:22 | req.query.id | user-provided value |
-| mongoose.js:124:28:124:31 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:124:28:124:31 | cond | This query depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
-| mongoose.js:125:28:125:31 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:125:28:125:31 | cond | This query depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
-| mongoose.js:126:28:126:31 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:126:28:126:31 | cond | This query depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
-| mongoose.js:127:18:127:21 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:127:18:127:21 | cond | This query depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
-| mongoose.js:128:22:128:25 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:128:22:128:25 | cond | This query depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
-| mongoose.js:129:21:129:24 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:129:21:129:24 | cond | This query depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
-| mongoose.js:130:16:130:26 | { _id: id } | mongoose.js:115:11:115:22 | req.query.id | mongoose.js:130:16:130:26 | { _id: id } | This query depends on a $@. | mongoose.js:115:11:115:22 | req.query.id | user-provided value |
-| mongooseJsonParse.js:23:19:23:23 | query | mongooseJsonParse.js:20:30:20:43 | req.query.data | mongooseJsonParse.js:23:19:23:23 | query | This query depends on a $@. | mongooseJsonParse.js:20:30:20:43 | req.query.data | user-provided value |
-| mongooseModelClient.js:11:16:11:24 | { id: v } | mongooseModelClient.js:10:22:10:29 | req.body | mongooseModelClient.js:11:16:11:24 | { id: v } | This query depends on a $@. | mongooseModelClient.js:10:22:10:29 | req.body | user-provided value |
-| mongooseModelClient.js:12:16:12:34 | { id: req.body.id } | mongooseModelClient.js:12:22:12:29 | req.body | mongooseModelClient.js:12:16:12:34 | { id: req.body.id } | This query depends on a $@. | mongooseModelClient.js:12:22:12:29 | req.body | user-provided value |
-| mysql.js:15:18:15:65 | 'SELECT ... + temp | mysql.js:6:16:6:31 | req.params.value | mysql.js:15:18:15:65 | 'SELECT ... + temp | This query depends on a $@. | mysql.js:6:16:6:31 | req.params.value | user-provided value |
-| mysql.js:19:26:19:73 | 'SELECT ... + temp | mysql.js:6:16:6:31 | req.params.value | mysql.js:19:26:19:73 | 'SELECT ... + temp | This query depends on a $@. | mysql.js:6:16:6:31 | req.params.value | user-provided value |
-| pg-promise-types.ts:8:17:8:21 | taint | pg-promise-types.ts:7:17:7:28 | req.params.x | pg-promise-types.ts:8:17:8:21 | taint | This query depends on a $@. | pg-promise-types.ts:7:17:7:28 | req.params.x | user-provided value |
-| pg-promise.js:9:10:9:14 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:9:10:9:14 | query | This query depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
-| pg-promise.js:10:11:10:15 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:10:11:10:15 | query | This query depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
-| pg-promise.js:11:17:11:21 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:11:17:11:21 | query | This query depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
-| pg-promise.js:12:10:12:14 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:12:10:12:14 | query | This query depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
-| pg-promise.js:13:12:13:16 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:13:12:13:16 | query | This query depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
-| pg-promise.js:14:18:14:22 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:14:18:14:22 | query | This query depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
-| pg-promise.js:15:11:15:15 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:15:11:15:15 | query | This query depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
-| pg-promise.js:16:10:16:14 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:16:10:16:14 | query | This query depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
-| pg-promise.js:17:16:17:20 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:17:16:17:20 | query | This query depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
-| pg-promise.js:18:12:18:16 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:18:12:18:16 | query | This query depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
-| pg-promise.js:19:13:19:17 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:19:13:19:17 | query | This query depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
-| pg-promise.js:22:11:22:15 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:22:11:22:15 | query | This query depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
-| pg-promise.js:30:13:30:25 | req.params.id | pg-promise.js:30:13:30:25 | req.params.id | pg-promise.js:30:13:30:25 | req.params.id | This query depends on a $@. | pg-promise.js:30:13:30:25 | req.params.id | user-provided value |
-| pg-promise.js:34:13:34:25 | req.params.id | pg-promise.js:34:13:34:25 | req.params.id | pg-promise.js:34:13:34:25 | req.params.id | This query depends on a $@. | pg-promise.js:34:13:34:25 | req.params.id | user-provided value |
-| pg-promise.js:38:13:42:5 | [\\n ... n\\n ] | pg-promise.js:39:7:39:19 | req.params.id | pg-promise.js:38:13:42:5 | [\\n ... n\\n ] | This query depends on a $@. | pg-promise.js:39:7:39:19 | req.params.id | user-provided value |
-| pg-promise.js:38:13:42:5 | [\\n ... n\\n ] | pg-promise.js:40:7:40:21 | req.params.name | pg-promise.js:38:13:42:5 | [\\n ... n\\n ] | This query depends on a $@. | pg-promise.js:40:7:40:21 | req.params.name | user-provided value |
-| pg-promise.js:38:13:42:5 | [\\n ... n\\n ] | pg-promise.js:41:7:41:20 | req.params.foo | pg-promise.js:38:13:42:5 | [\\n ... n\\n ] | This query depends on a $@. | pg-promise.js:41:7:41:20 | req.params.foo | user-provided value |
-| pg-promise.js:39:7:39:19 | req.params.id | pg-promise.js:39:7:39:19 | req.params.id | pg-promise.js:39:7:39:19 | req.params.id | This query depends on a $@. | pg-promise.js:39:7:39:19 | req.params.id | user-provided value |
-| pg-promise.js:40:7:40:21 | req.params.name | pg-promise.js:40:7:40:21 | req.params.name | pg-promise.js:40:7:40:21 | req.params.name | This query depends on a $@. | pg-promise.js:40:7:40:21 | req.params.name | user-provided value |
-| pg-promise.js:47:11:47:23 | req.params.id | pg-promise.js:47:11:47:23 | req.params.id | pg-promise.js:47:11:47:23 | req.params.id | This query depends on a $@. | pg-promise.js:47:11:47:23 | req.params.id | user-provided value |
-| pg-promise.js:54:11:54:23 | req.params.id | pg-promise.js:54:11:54:23 | req.params.id | pg-promise.js:54:11:54:23 | req.params.id | This query depends on a $@. | pg-promise.js:54:11:54:23 | req.params.id | user-provided value |
-| pg-promise.js:56:14:56:29 | req.params.title | pg-promise.js:56:14:56:29 | req.params.title | pg-promise.js:56:14:56:29 | req.params.title | This query depends on a $@. | pg-promise.js:56:14:56:29 | req.params.title | user-provided value |
-| pg-promise.js:60:20:60:24 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:60:20:60:24 | query | This query depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
-| pg-promise.js:63:23:63:27 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:63:23:63:27 | query | This query depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
-| pg-promise.js:64:16:64:20 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:64:16:64:20 | query | This query depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
-| redis.js:10:16:10:27 | req.body.key | redis.js:10:16:10:23 | req.body | redis.js:10:16:10:27 | req.body.key | This query depends on a $@. | redis.js:10:16:10:23 | req.body | user-provided value |
-| redis.js:18:16:18:18 | key | redis.js:12:15:12:22 | req.body | redis.js:18:16:18:18 | key | This query depends on a $@. | redis.js:12:15:12:22 | req.body | user-provided value |
-| redis.js:19:43:19:45 | key | redis.js:12:15:12:22 | req.body | redis.js:19:43:19:45 | key | This query depends on a $@. | redis.js:12:15:12:22 | req.body | user-provided value |
-| redis.js:25:14:25:16 | key | redis.js:12:15:12:22 | req.body | redis.js:25:14:25:16 | key | This query depends on a $@. | redis.js:12:15:12:22 | req.body | user-provided value |
-| redis.js:30:23:30:25 | key | redis.js:12:15:12:22 | req.body | redis.js:30:23:30:25 | key | This query depends on a $@. | redis.js:12:15:12:22 | req.body | user-provided value |
-| redis.js:32:28:32:30 | key | redis.js:12:15:12:22 | req.body | redis.js:32:28:32:30 | key | This query depends on a $@. | redis.js:12:15:12:22 | req.body | user-provided value |
-| redis.js:39:16:39:18 | key | redis.js:38:17:38:24 | req.body | redis.js:39:16:39:18 | key | This query depends on a $@. | redis.js:38:17:38:24 | req.body | user-provided value |
-| redis.js:43:27:43:29 | key | redis.js:38:17:38:24 | req.body | redis.js:43:27:43:29 | key | This query depends on a $@. | redis.js:38:17:38:24 | req.body | user-provided value |
-| redis.js:46:34:46:36 | key | redis.js:38:17:38:24 | req.body | redis.js:46:34:46:36 | key | This query depends on a $@. | redis.js:38:17:38:24 | req.body | user-provided value |
-| socketio.js:11:12:11:53 | `INSERT ... andle}` | socketio.js:10:25:10:30 | handle | socketio.js:11:12:11:53 | `INSERT ... andle}` | This query depends on a $@. | socketio.js:10:25:10:30 | handle | user-provided value |
-| tst2.js:9:27:9:84 | "select ... d + "'" | tst2.js:9:66:9:78 | req.params.id | tst2.js:9:27:9:84 | "select ... d + "'" | This query depends on a $@. | tst2.js:9:66:9:78 | req.params.id | user-provided value |
-| tst3.js:9:14:9:19 | query1 | tst3.js:8:16:8:34 | req.params.category | tst3.js:9:14:9:19 | query1 | This query depends on a $@. | tst3.js:8:16:8:34 | req.params.category | user-provided value |
-| tst4.js:8:10:8:66 | 'SELECT ... d + '"' | tst4.js:8:46:8:60 | $routeParams.id | tst4.js:8:10:8:66 | 'SELECT ... d + '"' | This query depends on a $@. | tst4.js:8:46:8:60 | $routeParams.id | user-provided value |
-| tst.js:10:10:10:64 | 'SELECT ... d + '"' | tst.js:10:46:10:58 | req.params.id | tst.js:10:10:10:64 | 'SELECT ... d + '"' | This query depends on a $@. | tst.js:10:46:10:58 | req.params.id | user-provided value |
+| graphql.js:10:34:20:5 | `\\n ... }\\n ` | graphql.js:8:16:8:28 | req.params.id | graphql.js:10:34:20:5 | `\\n ... }\\n ` | This query string depends on a $@. | graphql.js:8:16:8:28 | req.params.id | user-provided value |
+| graphql.js:27:30:27:40 | `foo ${id}` | graphql.js:26:16:26:28 | req.params.id | graphql.js:27:30:27:40 | `foo ${id}` | This query string depends on a $@. | graphql.js:26:16:26:28 | req.params.id | user-provided value |
+| graphql.js:30:32:30:42 | `foo ${id}` | graphql.js:26:16:26:28 | req.params.id | graphql.js:30:32:30:42 | `foo ${id}` | This query string depends on a $@. | graphql.js:26:16:26:28 | req.params.id | user-provided value |
+| graphql.js:33:18:33:28 | `foo ${id}` | graphql.js:26:16:26:28 | req.params.id | graphql.js:33:18:33:28 | `foo ${id}` | This query string depends on a $@. | graphql.js:26:16:26:28 | req.params.id | user-provided value |
+| graphql.js:44:14:44:24 | `foo ${id}` | graphql.js:39:16:39:28 | req.params.id | graphql.js:44:14:44:24 | `foo ${id}` | This query string depends on a $@. | graphql.js:39:16:39:28 | req.params.id | user-provided value |
+| graphql.js:48:44:48:54 | `foo ${id}` | graphql.js:39:16:39:28 | req.params.id | graphql.js:48:44:48:54 | `foo ${id}` | This query string depends on a $@. | graphql.js:39:16:39:28 | req.params.id | user-provided value |
+| graphql.js:56:39:56:49 | `foo ${id}` | graphql.js:55:16:55:28 | req.params.id | graphql.js:56:39:56:49 | `foo ${id}` | This query string depends on a $@. | graphql.js:55:16:55:28 | req.params.id | user-provided value |
+| graphql.js:58:66:58:76 | `foo ${id}` | graphql.js:55:16:55:28 | req.params.id | graphql.js:58:66:58:76 | `foo ${id}` | This query string depends on a $@. | graphql.js:55:16:55:28 | req.params.id | user-provided value |
+| graphql.js:75:46:75:64 | "{ foo" + id + " }" | graphql.js:74:14:74:25 | req.query.id | graphql.js:75:46:75:64 | "{ foo" + id + " }" | This query string depends on a $@. | graphql.js:74:14:74:25 | req.query.id | user-provided value |
+| graphql.js:84:14:90:8 | `{\\n ... }` | graphql.js:74:14:74:25 | req.query.id | graphql.js:84:14:90:8 | `{\\n ... }` | This query string depends on a $@. | graphql.js:74:14:74:25 | req.query.id | user-provided value |
+| graphql.js:120:38:120:48 | `foo ${id}` | graphql.js:119:16:119:28 | req.params.id | graphql.js:120:38:120:48 | `foo ${id}` | This query string depends on a $@. | graphql.js:119:16:119:28 | req.params.id | user-provided value |
+| html-sanitizer.js:16:9:16:59 | `SELECT ... param1 | html-sanitizer.js:13:39:13:44 | param1 | html-sanitizer.js:16:9:16:59 | `SELECT ... param1 | This query string depends on a $@. | html-sanitizer.js:13:39:13:44 | param1 | user-provided value |
+| json-schema-validator.js:33:22:33:26 | query | json-schema-validator.js:25:34:25:47 | req.query.data | json-schema-validator.js:33:22:33:26 | query | This query object depends on a $@. | json-schema-validator.js:25:34:25:47 | req.query.data | user-provided value |
+| json-schema-validator.js:35:18:35:22 | query | json-schema-validator.js:25:34:25:47 | req.query.data | json-schema-validator.js:35:18:35:22 | query | This query object depends on a $@. | json-schema-validator.js:25:34:25:47 | req.query.data | user-provided value |
+| json-schema-validator.js:55:22:55:26 | query | json-schema-validator.js:50:34:50:47 | req.query.data | json-schema-validator.js:55:22:55:26 | query | This query object depends on a $@. | json-schema-validator.js:50:34:50:47 | req.query.data | user-provided value |
+| json-schema-validator.js:59:22:59:26 | query | json-schema-validator.js:50:34:50:47 | req.query.data | json-schema-validator.js:59:22:59:26 | query | This query object depends on a $@. | json-schema-validator.js:50:34:50:47 | req.query.data | user-provided value |
+| json-schema-validator.js:61:22:61:26 | query | json-schema-validator.js:50:34:50:47 | req.query.data | json-schema-validator.js:61:22:61:26 | query | This query object depends on a $@. | json-schema-validator.js:50:34:50:47 | req.query.data | user-provided value |
+| ldap.js:28:30:28:34 | opts1 | ldap.js:20:21:20:27 | req.url | ldap.js:28:30:28:34 | opts1 | This query string depends on a $@. | ldap.js:20:21:20:27 | req.url | user-provided value |
+| ldap.js:32:5:32:61 | { filte ... e}))` } | ldap.js:20:21:20:27 | req.url | ldap.js:32:5:32:61 | { filte ... e}))` } | This query string depends on a $@. | ldap.js:20:21:20:27 | req.url | user-provided value |
+| ldap.js:66:30:66:53 | { filte ... ilter } | ldap.js:20:21:20:27 | req.url | ldap.js:66:30:66:53 | { filte ... ilter } | This query string depends on a $@. | ldap.js:20:21:20:27 | req.url | user-provided value |
+| ldap.js:68:27:68:42 | `cn=${username}` | ldap.js:20:21:20:27 | req.url | ldap.js:68:27:68:42 | `cn=${username}` | This query string depends on a $@. | ldap.js:20:21:20:27 | req.url | user-provided value |
+| marsdb-flow-to.js:14:17:14:21 | query | marsdb-flow-to.js:11:17:11:24 | req.body | marsdb-flow-to.js:14:17:14:21 | query | This query object depends on a $@. | marsdb-flow-to.js:11:17:11:24 | req.body | user-provided value |
+| marsdb.js:16:12:16:16 | query | marsdb.js:13:17:13:24 | req.body | marsdb.js:16:12:16:16 | query | This query object depends on a $@. | marsdb.js:13:17:13:24 | req.body | user-provided value |
+| minimongo.js:18:12:18:16 | query | minimongo.js:15:17:15:24 | req.body | minimongo.js:18:12:18:16 | query | This query object depends on a $@. | minimongo.js:15:17:15:24 | req.body | user-provided value |
+| mongodb.js:18:16:18:20 | query | mongodb.js:13:19:13:26 | req.body | mongodb.js:18:16:18:20 | query | This query object depends on a $@. | mongodb.js:13:19:13:26 | req.body | user-provided value |
+| mongodb.js:32:18:32:45 | { title ... itle) } | mongodb.js:26:19:26:26 | req.body | mongodb.js:32:18:32:45 | { title ... itle) } | This query object depends on a $@. | mongodb.js:26:19:26:26 | req.body | user-provided value |
+| mongodb.js:54:16:54:20 | query | mongodb.js:49:19:49:33 | req.query.title | mongodb.js:54:16:54:20 | query | This query object depends on a $@. | mongodb.js:49:19:49:33 | req.query.title | user-provided value |
+| mongodb.js:65:12:65:16 | query | mongodb.js:60:16:60:30 | req.query.title | mongodb.js:65:12:65:16 | query | This query object depends on a $@. | mongodb.js:60:16:60:30 | req.query.title | user-provided value |
+| mongodb.js:77:14:77:26 | { tags: tag } | mongodb.js:70:13:70:25 | req.query.tag | mongodb.js:77:14:77:26 | { tags: tag } | This query object depends on a $@. | mongodb.js:70:13:70:25 | req.query.tag | user-provided value |
+| mongodb.js:85:12:85:24 | { tags: tag } | mongodb.js:70:13:70:25 | req.query.tag | mongodb.js:85:12:85:24 | { tags: tag } | This query object depends on a $@. | mongodb.js:70:13:70:25 | req.query.tag | user-provided value |
+| mongodb.js:112:14:112:18 | query | mongodb.js:107:17:107:29 | queries.title | mongodb.js:112:14:112:18 | query | This query object depends on a $@. | mongodb.js:107:17:107:29 | queries.title | user-provided value |
+| mongodb_bodySafe.js:29:16:29:20 | query | mongodb_bodySafe.js:24:19:24:33 | req.query.title | mongodb_bodySafe.js:29:16:29:20 | query | This query object depends on a $@. | mongodb_bodySafe.js:24:19:24:33 | req.query.title | user-provided value |
+| mongoose.js:24:24:24:30 | [query] | mongoose.js:21:19:21:26 | req.body | mongoose.js:24:24:24:30 | [query] | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:27:20:27:24 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:27:20:27:24 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:30:25:30:29 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:30:25:30:29 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:33:24:33:28 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:33:24:33:28 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:36:31:36:35 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:36:31:36:35 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:39:19:39:23 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:39:19:39:23 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:42:22:42:26 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:42:22:42:26 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:45:31:45:35 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:45:31:45:35 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:48:31:48:35 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:48:31:48:35 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:51:31:51:35 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:51:31:51:35 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:54:25:54:29 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:54:25:54:29 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:57:21:57:25 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:57:21:57:25 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:60:25:60:29 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:60:25:60:29 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:63:21:63:25 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:63:21:63:25 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:65:32:65:36 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:65:32:65:36 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:67:27:67:31 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:67:27:67:31 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:68:8:68:12 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:68:8:68:12 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:71:20:71:24 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:71:20:71:24 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:72:16:72:20 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:72:16:72:20 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:73:8:73:12 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:73:8:73:12 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:74:7:74:11 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:74:7:74:11 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:75:16:75:20 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:75:16:75:20 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:77:10:77:14 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:77:10:77:14 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:82:46:82:50 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:82:46:82:50 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:83:47:83:51 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:83:47:83:51 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:85:46:85:50 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:85:46:85:50 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:87:51:87:55 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:87:51:87:55 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:89:46:89:50 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:89:46:89:50 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:92:46:92:50 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:92:46:92:50 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:94:51:94:55 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:94:51:94:55 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:96:46:96:50 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:96:46:96:50 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:111:14:111:18 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:111:14:111:18 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:113:31:113:35 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:113:31:113:35 | query | This query object depends on a $@. | mongoose.js:21:19:21:26 | req.body | user-provided value |
+| mongoose.js:116:22:116:25 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:116:22:116:25 | cond | This query object depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
+| mongoose.js:117:21:117:24 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:117:21:117:24 | cond | This query object depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
+| mongoose.js:118:21:118:24 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:118:21:118:24 | cond | This query object depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
+| mongoose.js:119:18:119:21 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:119:18:119:21 | cond | This query object depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
+| mongoose.js:120:22:120:25 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:120:22:120:25 | cond | This query object depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
+| mongoose.js:121:16:121:19 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:121:16:121:19 | cond | This query object depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
+| mongoose.js:122:19:122:22 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:122:19:122:22 | cond | This query object depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
+| mongoose.js:123:20:123:21 | id | mongoose.js:115:11:115:22 | req.query.id | mongoose.js:123:20:123:21 | id | This query object depends on a $@. | mongoose.js:115:11:115:22 | req.query.id | user-provided value |
+| mongoose.js:124:28:124:31 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:124:28:124:31 | cond | This query object depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
+| mongoose.js:125:28:125:31 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:125:28:125:31 | cond | This query object depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
+| mongoose.js:126:28:126:31 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:126:28:126:31 | cond | This query object depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
+| mongoose.js:127:18:127:21 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:127:18:127:21 | cond | This query object depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
+| mongoose.js:128:22:128:25 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:128:22:128:25 | cond | This query object depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
+| mongoose.js:129:21:129:24 | cond | mongoose.js:115:32:115:45 | req.query.cond | mongoose.js:129:21:129:24 | cond | This query object depends on a $@. | mongoose.js:115:32:115:45 | req.query.cond | user-provided value |
+| mongoose.js:130:16:130:26 | { _id: id } | mongoose.js:115:11:115:22 | req.query.id | mongoose.js:130:16:130:26 | { _id: id } | This query object depends on a $@. | mongoose.js:115:11:115:22 | req.query.id | user-provided value |
+| mongooseJsonParse.js:23:19:23:23 | query | mongooseJsonParse.js:20:30:20:43 | req.query.data | mongooseJsonParse.js:23:19:23:23 | query | This query object depends on a $@. | mongooseJsonParse.js:20:30:20:43 | req.query.data | user-provided value |
+| mongooseModelClient.js:11:16:11:24 | { id: v } | mongooseModelClient.js:10:22:10:29 | req.body | mongooseModelClient.js:11:16:11:24 | { id: v } | This query object depends on a $@. | mongooseModelClient.js:10:22:10:29 | req.body | user-provided value |
+| mongooseModelClient.js:12:16:12:34 | { id: req.body.id } | mongooseModelClient.js:12:22:12:29 | req.body | mongooseModelClient.js:12:16:12:34 | { id: req.body.id } | This query object depends on a $@. | mongooseModelClient.js:12:22:12:29 | req.body | user-provided value |
+| mysql.js:15:18:15:65 | 'SELECT ... + temp | mysql.js:6:16:6:31 | req.params.value | mysql.js:15:18:15:65 | 'SELECT ... + temp | This query string depends on a $@. | mysql.js:6:16:6:31 | req.params.value | user-provided value |
+| mysql.js:19:26:19:73 | 'SELECT ... + temp | mysql.js:6:16:6:31 | req.params.value | mysql.js:19:26:19:73 | 'SELECT ... + temp | This query string depends on a $@. | mysql.js:6:16:6:31 | req.params.value | user-provided value |
+| pg-promise-types.ts:8:17:8:21 | taint | pg-promise-types.ts:7:17:7:28 | req.params.x | pg-promise-types.ts:8:17:8:21 | taint | This query string depends on a $@. | pg-promise-types.ts:7:17:7:28 | req.params.x | user-provided value |
+| pg-promise.js:9:10:9:14 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:9:10:9:14 | query | This query string depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
+| pg-promise.js:10:11:10:15 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:10:11:10:15 | query | This query string depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
+| pg-promise.js:11:17:11:21 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:11:17:11:21 | query | This query string depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
+| pg-promise.js:12:10:12:14 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:12:10:12:14 | query | This query string depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
+| pg-promise.js:13:12:13:16 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:13:12:13:16 | query | This query string depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
+| pg-promise.js:14:18:14:22 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:14:18:14:22 | query | This query string depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
+| pg-promise.js:15:11:15:15 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:15:11:15:15 | query | This query string depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
+| pg-promise.js:16:10:16:14 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:16:10:16:14 | query | This query string depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
+| pg-promise.js:17:16:17:20 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:17:16:17:20 | query | This query string depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
+| pg-promise.js:18:12:18:16 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:18:12:18:16 | query | This query string depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
+| pg-promise.js:19:13:19:17 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:19:13:19:17 | query | This query string depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
+| pg-promise.js:22:11:22:15 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:22:11:22:15 | query | This query string depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
+| pg-promise.js:30:13:30:25 | req.params.id | pg-promise.js:30:13:30:25 | req.params.id | pg-promise.js:30:13:30:25 | req.params.id | This query string depends on a $@. | pg-promise.js:30:13:30:25 | req.params.id | user-provided value |
+| pg-promise.js:34:13:34:25 | req.params.id | pg-promise.js:34:13:34:25 | req.params.id | pg-promise.js:34:13:34:25 | req.params.id | This query string depends on a $@. | pg-promise.js:34:13:34:25 | req.params.id | user-provided value |
+| pg-promise.js:38:13:42:5 | [\\n ... n\\n ] | pg-promise.js:39:7:39:19 | req.params.id | pg-promise.js:38:13:42:5 | [\\n ... n\\n ] | This query string depends on a $@. | pg-promise.js:39:7:39:19 | req.params.id | user-provided value |
+| pg-promise.js:38:13:42:5 | [\\n ... n\\n ] | pg-promise.js:40:7:40:21 | req.params.name | pg-promise.js:38:13:42:5 | [\\n ... n\\n ] | This query string depends on a $@. | pg-promise.js:40:7:40:21 | req.params.name | user-provided value |
+| pg-promise.js:38:13:42:5 | [\\n ... n\\n ] | pg-promise.js:41:7:41:20 | req.params.foo | pg-promise.js:38:13:42:5 | [\\n ... n\\n ] | This query string depends on a $@. | pg-promise.js:41:7:41:20 | req.params.foo | user-provided value |
+| pg-promise.js:39:7:39:19 | req.params.id | pg-promise.js:39:7:39:19 | req.params.id | pg-promise.js:39:7:39:19 | req.params.id | This query string depends on a $@. | pg-promise.js:39:7:39:19 | req.params.id | user-provided value |
+| pg-promise.js:40:7:40:21 | req.params.name | pg-promise.js:40:7:40:21 | req.params.name | pg-promise.js:40:7:40:21 | req.params.name | This query string depends on a $@. | pg-promise.js:40:7:40:21 | req.params.name | user-provided value |
+| pg-promise.js:47:11:47:23 | req.params.id | pg-promise.js:47:11:47:23 | req.params.id | pg-promise.js:47:11:47:23 | req.params.id | This query string depends on a $@. | pg-promise.js:47:11:47:23 | req.params.id | user-provided value |
+| pg-promise.js:54:11:54:23 | req.params.id | pg-promise.js:54:11:54:23 | req.params.id | pg-promise.js:54:11:54:23 | req.params.id | This query string depends on a $@. | pg-promise.js:54:11:54:23 | req.params.id | user-provided value |
+| pg-promise.js:56:14:56:29 | req.params.title | pg-promise.js:56:14:56:29 | req.params.title | pg-promise.js:56:14:56:29 | req.params.title | This query string depends on a $@. | pg-promise.js:56:14:56:29 | req.params.title | user-provided value |
+| pg-promise.js:60:20:60:24 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:60:20:60:24 | query | This query string depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
+| pg-promise.js:63:23:63:27 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:63:23:63:27 | query | This query string depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
+| pg-promise.js:64:16:64:20 | query | pg-promise.js:7:16:7:34 | req.params.category | pg-promise.js:64:16:64:20 | query | This query string depends on a $@. | pg-promise.js:7:16:7:34 | req.params.category | user-provided value |
+| redis.js:10:16:10:27 | req.body.key | redis.js:10:16:10:23 | req.body | redis.js:10:16:10:27 | req.body.key | This query object depends on a $@. | redis.js:10:16:10:23 | req.body | user-provided value |
+| redis.js:18:16:18:18 | key | redis.js:12:15:12:22 | req.body | redis.js:18:16:18:18 | key | This query object depends on a $@. | redis.js:12:15:12:22 | req.body | user-provided value |
+| redis.js:19:43:19:45 | key | redis.js:12:15:12:22 | req.body | redis.js:19:43:19:45 | key | This query object depends on a $@. | redis.js:12:15:12:22 | req.body | user-provided value |
+| redis.js:25:14:25:16 | key | redis.js:12:15:12:22 | req.body | redis.js:25:14:25:16 | key | This query object depends on a $@. | redis.js:12:15:12:22 | req.body | user-provided value |
+| redis.js:30:23:30:25 | key | redis.js:12:15:12:22 | req.body | redis.js:30:23:30:25 | key | This query object depends on a $@. | redis.js:12:15:12:22 | req.body | user-provided value |
+| redis.js:32:28:32:30 | key | redis.js:12:15:12:22 | req.body | redis.js:32:28:32:30 | key | This query object depends on a $@. | redis.js:12:15:12:22 | req.body | user-provided value |
+| redis.js:39:16:39:18 | key | redis.js:38:17:38:24 | req.body | redis.js:39:16:39:18 | key | This query object depends on a $@. | redis.js:38:17:38:24 | req.body | user-provided value |
+| redis.js:43:27:43:29 | key | redis.js:38:17:38:24 | req.body | redis.js:43:27:43:29 | key | This query object depends on a $@. | redis.js:38:17:38:24 | req.body | user-provided value |
+| redis.js:46:34:46:36 | key | redis.js:38:17:38:24 | req.body | redis.js:46:34:46:36 | key | This query object depends on a $@. | redis.js:38:17:38:24 | req.body | user-provided value |
+| socketio.js:11:12:11:53 | `INSERT ... andle}` | socketio.js:10:25:10:30 | handle | socketio.js:11:12:11:53 | `INSERT ... andle}` | This query string depends on a $@. | socketio.js:10:25:10:30 | handle | user-provided value |
+| tst2.js:9:27:9:84 | "select ... d + "'" | tst2.js:9:66:9:78 | req.params.id | tst2.js:9:27:9:84 | "select ... d + "'" | This query string depends on a $@. | tst2.js:9:66:9:78 | req.params.id | user-provided value |
+| tst3.js:9:14:9:19 | query1 | tst3.js:8:16:8:34 | req.params.category | tst3.js:9:14:9:19 | query1 | This query string depends on a $@. | tst3.js:8:16:8:34 | req.params.category | user-provided value |
+| tst4.js:8:10:8:66 | 'SELECT ... d + '"' | tst4.js:8:46:8:60 | $routeParams.id | tst4.js:8:10:8:66 | 'SELECT ... d + '"' | This query string depends on a $@. | tst4.js:8:46:8:60 | $routeParams.id | user-provided value |
+| tst.js:10:10:10:64 | 'SELECT ... d + '"' | tst.js:10:46:10:58 | req.params.id | tst.js:10:10:10:64 | 'SELECT ... d + '"' | This query string depends on a $@. | tst.js:10:46:10:58 | req.params.id | user-provided value |
From e24b45b4233724e6756057f87c04593bed583c5f Mon Sep 17 00:00:00 2001
From: erik-krogh
Date: Wed, 31 May 2023 09:57:38 +0200
Subject: [PATCH 078/219] elaborate on both SQL and NoSQL injection in the
js/sql-injection qhelp
---
.../Security/CWE-089/SqlInjection.inc.qhelp | 48 ++++++++++++++-----
.../CWE-089/examples/NoSqlInjection.js | 18 +++++++
.../CWE-089/examples/NoSqlInjectionFix.js | 21 ++++++++
.../Security/CWE-089/examples/SqlInjection.js | 7 ---
.../CWE-089/examples/SqlInjectionFix.js | 12 +++++
5 files changed, 86 insertions(+), 20 deletions(-)
create mode 100644 javascript/ql/src/Security/CWE-089/examples/NoSqlInjection.js
create mode 100644 javascript/ql/src/Security/CWE-089/examples/NoSqlInjectionFix.js
create mode 100644 javascript/ql/src/Security/CWE-089/examples/SqlInjectionFix.js
diff --git a/javascript/ql/src/Security/CWE-089/SqlInjection.inc.qhelp b/javascript/ql/src/Security/CWE-089/SqlInjection.inc.qhelp
index 8cdc2419d47..1d99428b718 100644
--- a/javascript/ql/src/Security/CWE-089/SqlInjection.inc.qhelp
+++ b/javascript/ql/src/Security/CWE-089/SqlInjection.inc.qhelp
@@ -20,7 +20,13 @@ or prepared statements.
For NoSQL queries, make use of an operator like MongoDB's $eq
to ensure that untrusted data is interpreted as a literal value and not as
-a query object.
+a query object. Alternatively, check that the untrusted data is a literal
+value and not a query object before using it in a query.
+
+
+For SQL queries, use query parameters or prepared statements to
+embed untrusted data into the query string, or use a library like
+sqlstring to escape untrusted data.
@@ -32,31 +38,47 @@ an HTTP request handler in a web application, whose parameter
-The handler constructs two copies of the same SQL query involving
-user input taken from the request object, once unsafely using
-string concatenation, and once safely using query parameters.
+The handler constructs constructs an SQL query string from user input
+and executes it as a database query using the pg library.
+THe user input may contain quote characters, so this code is vulnerable
+to a SQL injection attack.
-
-In the first case, the query string query1 is built by
-directly concatenating a user-supplied request parameter with some
-string literals. The parameter may include quote characters, so this
-code is vulnerable to a SQL injection attack.
-
+
-In the second case, the parameter is embedded into the query string
-query2 using query parameters. In this example, we use
+To fix this vulnerability, we can use query parameters to embed the
+user input into the query string. In this example, we use
the API offered by the pg Postgres database connector
library, but other libraries offer similar features. This version is
immune to injection attacks.
-
+
+