From e536628a66f88e33fe13f3eab8b611f152fd4400 Mon Sep 17 00:00:00 2001
From: Porcuiney Hairs
Date: Fri, 21 May 2021 02:09:30 +0530
Subject: [PATCH 1/6] Java : Add SSTI query
---
.../Security/CWE/CWE-094/SSTIBad.java | 19 ++
.../Security/CWE/CWE-094/SSTIGood.java | 17 ++
.../CWE/CWE-094/TemplateInjection.qhelp | 31 +++
.../Security/CWE/CWE-094/TemplateInjection.ql | 18 ++
.../CWE/CWE-094/TemplateInjection.qll | 209 ++++++++++++++++++
.../code/java/frameworks/FreeMarker.qll | 29 +++
.../semmle/code/java/frameworks/JinJava.qll | 24 ++
.../semmle/code/java/frameworks/Pebble.qll | 16 ++
.../semmle/code/java/frameworks/Thymeleaf.qll | 25 +++
.../semmle/code/java/frameworks/Velocity.qll | 119 ++++++++++
.../security/CWE-094/FreemarkerSSTI.java | 132 +++++++++++
.../security/CWE-094/JinJavaSSTI.java | 48 ++++
.../security/CWE-094/PebbleSSTI.java | 30 +++
.../CWE-094/TemplateInjection.expected | 24 ++
.../security/CWE-094/TemplateInjection.qlref | 1 +
.../security/CWE-094/ThymeleafSSTI.java | 31 +++
.../security/CWE-094/VelocitySSTI.java | 126 +++++++++++
.../query-tests/security/CWE-094/options | 2 +-
.../cache/StringTemplateLoader.java | 7 +
.../freemarker/template/Configuration.java | 9 +
.../freemarker/template/ObjectWrapper.java | 3 +
.../template/ParserConfiguration.java | 3 +
.../freemarker/template/Template.java | 55 +++++
.../template/TemplateNodeModel.java | 3 +
.../org/apache/velocity/Template.java | 13 ++
.../org/apache/velocity/VelocityContext.java | 10 +
.../org/apache/velocity/VelocityEngine.java | 20 ++
.../org/apache/velocity/app/Velocity.java | 15 ++
.../apache/velocity/app/VelocityEngine.java | 20 ++
.../velocity/context/AbstractContext.java | 14 ++
.../org/apache/velocity/context/Context.java | 7 +
.../velocity/runtime/RuntimeServices.java | 25 +++
.../velocity/runtime/RuntimeSingleton.java | 8 +
.../runtime/parser/node/SimpleNode.java | 5 +
.../util/StringResourceRepository.java | 7 +
.../util/StringResourceRepositoryImpl.java | 9 +
.../com/hubspot/jinjava/Jinjava.java | 24 ++
.../com/hubspot/jinjava/JinjavaConfig.java | 5 +
.../jinjava/interpret/RenderResult.java | 6 +
.../mitchellbosecke/pebble/PebbleEngine.java | 27 +++
.../pebble/template/PebbleTemplate.java | 3 +
.../org/thymeleaf/ITemplateEngine.java | 28 +++
.../IThrottledTemplateProcessor.java | 5 +
.../org/thymeleaf/TemplateEngine.java | 51 +++++
.../org/thymeleaf/TemplateSpec.java | 5 +
.../org/thymeleaf/context/Context.java | 7 +
.../org/thymeleaf/context/IContext.java | 5 +
47 files changed, 1299 insertions(+), 1 deletion(-)
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-094/SSTIBad.java
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-094/SSTIGood.java
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.qhelp
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.ql
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.qll
create mode 100644 java/ql/src/experimental/semmle/code/java/frameworks/FreeMarker.qll
create mode 100644 java/ql/src/experimental/semmle/code/java/frameworks/JinJava.qll
create mode 100644 java/ql/src/experimental/semmle/code/java/frameworks/Pebble.qll
create mode 100644 java/ql/src/experimental/semmle/code/java/frameworks/Thymeleaf.qll
create mode 100644 java/ql/src/experimental/semmle/code/java/frameworks/Velocity.qll
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/FreemarkerSSTI.java
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/JinJavaSSTI.java
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/PebbleSSTI.java
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/TemplateInjection.expected
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/TemplateInjection.qlref
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/ThymeleafSSTI.java
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/VelocitySSTI.java
create mode 100644 java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/cache/StringTemplateLoader.java
create mode 100644 java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/Configuration.java
create mode 100644 java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/ObjectWrapper.java
create mode 100644 java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/ParserConfiguration.java
create mode 100644 java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/Template.java
create mode 100644 java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateNodeModel.java
create mode 100644 java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/Template.java
create mode 100644 java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/VelocityContext.java
create mode 100644 java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/VelocityEngine.java
create mode 100644 java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/app/Velocity.java
create mode 100644 java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/app/VelocityEngine.java
create mode 100644 java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/context/AbstractContext.java
create mode 100644 java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/context/Context.java
create mode 100644 java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/RuntimeServices.java
create mode 100644 java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/RuntimeSingleton.java
create mode 100644 java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/parser/node/SimpleNode.java
create mode 100644 java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/resource/util/StringResourceRepository.java
create mode 100644 java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/resource/util/StringResourceRepositoryImpl.java
create mode 100644 java/ql/test/experimental/stubs/jinjava-2.6.0/com/hubspot/jinjava/Jinjava.java
create mode 100644 java/ql/test/experimental/stubs/jinjava-2.6.0/com/hubspot/jinjava/JinjavaConfig.java
create mode 100644 java/ql/test/experimental/stubs/jinjava-2.6.0/com/hubspot/jinjava/interpret/RenderResult.java
create mode 100644 java/ql/test/experimental/stubs/pebble-3.1.5/com/mitchellbosecke/pebble/PebbleEngine.java
create mode 100644 java/ql/test/experimental/stubs/pebble-3.1.5/com/mitchellbosecke/pebble/template/PebbleTemplate.java
create mode 100644 java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/ITemplateEngine.java
create mode 100644 java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/IThrottledTemplateProcessor.java
create mode 100644 java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/TemplateEngine.java
create mode 100644 java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/TemplateSpec.java
create mode 100644 java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/context/Context.java
create mode 100644 java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/context/IContext.java
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/SSTIBad.java b/java/ql/src/experimental/Security/CWE/CWE-094/SSTIBad.java
new file mode 100644
index 000000000000..33210448e189
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/SSTIBad.java
@@ -0,0 +1,19 @@
+@Controller
+public class VelocitySSTI {
+
+ @GetMapping(value = "bad")
+ public void bad(HttpServletRequest request) {
+ Velocity.init();
+
+ String code = request.getParameter("code");
+
+ VelocityContext context = new VelocityContext();
+
+ context.put("name", "Velocity");
+ context.put("project", "Jakarta");
+
+ StringWriter w = new StringWriter();
+ // evaluate( Context context, Writer out, String logTag, String instring )
+ Velocity.evaluate(context, w, "mystring", code);
+ }
+}
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/SSTIGood.java b/java/ql/src/experimental/Security/CWE/CWE-094/SSTIGood.java
new file mode 100644
index 000000000000..be4120539d5c
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/SSTIGood.java
@@ -0,0 +1,17 @@
+@Controller
+public class VelocitySSTI {
+
+ @GetMapping(value = "good")
+ public void good(HttpServletRequest request) {
+ Velocity.init();
+ VelocityContext context = new VelocityContext();
+
+ context.put("name", "Velocity");
+ context.put("project", "Jakarta");
+
+ String s = "We are using $project $name to render this.";
+ StringWriter w = new StringWriter();
+ Velocity.evaluate(context, w, "mystring", s);
+ System.out.println(" string : " + w);
+ }
+}
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.qhelp b/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.qhelp
new file mode 100644
index 000000000000..86d821b85205
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.qhelp
@@ -0,0 +1,31 @@
+
+
+
+
+ Template Injection occurs when user input is embedded in a template in an unsafe manner.
+ An attacker can use native template syntax to inject a malicious payload into a template, which is then executed server-side. This permits the attacker to run arbitrary code in the server's context.
+
+
+
+ To fix this, ensure that an untrusted value is not used as a template. If the application requirements do not allow this, use a sandboxed environment where access to unsafe attributes and methods is prohibited.
+
+
+
+
+ In the example given below, an untrusted HTTP parameter
+ code
+ is used as a Velocity template string. This can lead to remote code execution.
+
+
+
+
+ In the next example the problem is avoided by using a fixed template string
+ s
+ . Since, the template is not attacker controlled in this case, we prevent untrusted code execution.
+
+
+
+
+ Portswigger : [Server Side Template Injection](https://portswigger.net/web-security/server-side-template-injection)
+
+
\ No newline at end of file
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.ql
new file mode 100644
index 000000000000..d4dc0c3952ef
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.ql
@@ -0,0 +1,18 @@
+/**
+ * @name Server Side Template Injection
+ * @description Untrusted input used as a template parameter can lead to remote code execution.
+ * @kind path-problem
+ * @problem.severity error
+ * @precision high
+ * @id java/server-side-template-injection
+ * @tags security
+ * external/cwe/cwe-094
+ */
+
+import java
+import TemplateInjection
+
+from TemplateInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
+where config.hasFlowPath(source, sink)
+select sink.getNode(), source, sink, "Potential arbitrary code execution due to $@.",
+ source.getNode(), "a template value loaded from a remote source."
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.qll b/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.qll
new file mode 100644
index 000000000000..2f3113123aac
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.qll
@@ -0,0 +1,209 @@
+/** Definitions related to the Server Side Template Injection (SSTI) query. */
+
+import java
+import semmle.code.java.dataflow.TaintTracking
+import semmle.code.java.dataflow.FlowSources
+import experimental.semmle.code.java.frameworks.FreeMarker
+import experimental.semmle.code.java.frameworks.Velocity
+import experimental.semmle.code.java.frameworks.JinJava
+import experimental.semmle.code.java.frameworks.Pebble
+import experimental.semmle.code.java.frameworks.Thymeleaf
+
+/** A taint tracking configuration to reason about Server Side Template Injection (SSTI) vulnerabilities */
+class TemplateInjectionFlowConfig extends TaintTracking::Configuration {
+ TemplateInjectionFlowConfig() { this = "TemplateInjectionFlowConfig" }
+
+ override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
+
+ override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
+
+ override predicate isSanitizer(DataFlow::Node node) {
+ node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
+ }
+
+ override predicate isAdditionalTaintStep(DataFlow::Node prev, DataFlow::Node succ) {
+ exists(AdditionalFlowStep a | a.isAdditionalTaintStep(prev, succ))
+ }
+}
+
+/**
+ * A data flow sink for Server Side Template Injection (SSTI) vulnerabilities
+ */
+abstract private class Sink extends DataFlow::ExprNode { }
+
+/**
+ * A data flow step for Server Side Template Injection (SSTI) vulnerabilities
+ */
+private class AdditionalFlowStep extends Unit {
+ abstract predicate isAdditionalTaintStep(DataFlow::Node prev, DataFlow::Node succ);
+}
+
+/**
+ * An argument to FreeMarker template engine's `process` method call.
+ */
+private class FreeMarkerProcessSink extends Sink {
+ FreeMarkerProcessSink() {
+ exists(MethodAccess m |
+ m.getCallee() instanceof MethodFreeMarkerTemplateProcess and
+ m.getArgument(0) = this.getExpr()
+ )
+ }
+}
+
+/**
+ * An reader passed an argument to FreeMarker template engine's `Template`
+ * construtor call.
+ */
+private class FreeMarkerConstructorSink extends Sink {
+ FreeMarkerConstructorSink() {
+ // Template(java.lang.String name, java.io.Reader reader)
+ // Template(java.lang.String name, java.io.Reader reader, Configuration cfg)
+ // Template(java.lang.String name, java.io.Reader reader, Configuration cfg, java.lang.String encoding)
+ // Template(java.lang.String name, java.lang.String sourceName, java.io.Reader reader, Configuration cfg)
+ // Template(java.lang.String name, java.lang.String sourceName, java.io.Reader reader, Configuration cfg, ParserConfiguration customParserConfiguration, java.lang.String encoding)
+ // Template(java.lang.String name, java.lang.String sourceName, java.io.Reader reader, Configuration cfg, java.lang.String encoding)
+ exists(ConstructorCall cc, Expr e |
+ cc.getConstructor().getDeclaringType() instanceof TypeFreeMarkerTemplate and
+ e = cc.getAnArgument() and
+ (
+ e.getType().(RefType).hasQualifiedName("java.io", "Reader") and
+ this.asExpr() = e
+ )
+ )
+ or
+ exists(ConstructorCall cc |
+ cc.getConstructor().getDeclaringType() instanceof TypeFreeMarkerTemplate and
+ // Template(java.lang.String name, java.lang.String sourceCode, Configuration cfg)
+ cc.getNumArgument() = 3 and
+ cc.getArgument(1).getType() instanceof TypeString and
+ this.asExpr() = cc.getArgument(1)
+ )
+ }
+}
+
+/**
+ * An argument to FreeMarker template engine's `putTemplate` method call.
+ */
+private class FreeMarkerStringTemplateLoaderPutTemplateSink extends Sink {
+ FreeMarkerStringTemplateLoaderPutTemplateSink() {
+ exists(MethodAccess ma |
+ this.asExpr() = ma.getArgument(1) and
+ ma.getMethod() instanceof MethodFreeMarkerStringTemplateLoaderPutTemplate
+ )
+ }
+}
+
+/**
+ * An argument to Pebble template engine's `getLiteralTemplate` or `getTemplate` method call.
+ */
+private class PebbleGetTemplateSinkTemplateSink extends Sink {
+ PebbleGetTemplateSinkTemplateSink() {
+ exists(MethodAccess ma |
+ this.asExpr() = ma.getArgument(0) and
+ ma.getMethod() instanceof MethodPebbleGetTemplate
+ )
+ }
+}
+
+/**
+ * An argument to JinJava template engine's `render` or `renderForResult` method call.
+ */
+private class JinjavaRenderSink extends Sink {
+ JinjavaRenderSink() {
+ exists(MethodAccess ma |
+ this.asExpr() = ma.getArgument(0) and
+ (
+ ma.getMethod() instanceof MethodJinjavaRenderForResult
+ or
+ ma.getMethod() instanceof MethodJinjavaRender
+ )
+ )
+ }
+}
+
+/**
+ * An argument to ThymeLeaf template engine's `process` method call.
+ */
+private class ThymeLeafRenderSink extends Sink {
+ ThymeLeafRenderSink() {
+ exists(MethodAccess ma |
+ this.asExpr() = ma.getArgument(0) and
+ ma.getMethod() instanceof MethodThymeleafProcess
+ )
+ }
+}
+
+/**
+ * Tainted data flowing into a Velocity Context through `put` method taints the context.
+ */
+private class VelocityContextFlow extends AdditionalFlowStep {
+ override predicate isAdditionalTaintStep(DataFlow::Node prev, DataFlow::Node succ) {
+ exists(MethodAccess m | m.getMethod() instanceof MethodVelocityContextPut |
+ m.getArgument(1) = prev.asExpr() and
+ succ.asExpr() = m.getQualifier()
+ )
+ }
+}
+
+/**
+ * An argument to Velocity template engine's `mergeTemplate` method call.
+ */
+private class VelocityMergeTempSink extends Sink {
+ VelocityMergeTempSink() {
+ exists(MethodAccess m |
+ // static boolean mergeTemplate(String templateName, String encoding, Context context, Writer writer)
+ m.getCallee() instanceof MethodVelocityMergeTemplate and
+ m.getArgument(2) = this.getExpr()
+ )
+ }
+}
+
+/**
+ * An argument to Velocity template engine's `mergeTemplate` method call.
+ */
+private class VelocityMergeSink extends Sink {
+ VelocityMergeSink() {
+ exists(MethodAccess m |
+ m.getCallee() instanceof MethodVelocityMerge and
+ // public void merge(Context context, Writer writer)
+ // public void merge(Context context, Writer writer, List macroLibraries)
+ m.getArgument(0) = this.getExpr()
+ )
+ }
+}
+
+/**
+ * An argument to Velocity template engine's `evaluate` method call.
+ */
+private class VelocityEvaluateSink extends Sink {
+ VelocityEvaluateSink() {
+ exists(MethodAccess m |
+ m.getCallee() instanceof MethodVelocityEvaluate and
+ m.getArgument([0, 3]) = this.getExpr()
+ )
+ }
+}
+
+/**
+ * An argument to Velocity template engine's `parse` method call.
+ */
+private class VelocityParseSink extends Sink {
+ VelocityParseSink() {
+ exists(MethodAccess ma |
+ this.asExpr() = ma.getArgument(0) and
+ ma.getMethod() instanceof MethodVelocityParse
+ )
+ }
+}
+
+/**
+ * An argument to Velocity template engine's `putStringResource` method call.
+ */
+private class VelocityPutStringResSink extends Sink {
+ VelocityPutStringResSink() {
+ exists(MethodAccess ma |
+ this.asExpr() = ma.getArgument(1) and
+ ma.getMethod() instanceof MethodVelocityPutStringResource
+ )
+ }
+}
diff --git a/java/ql/src/experimental/semmle/code/java/frameworks/FreeMarker.qll b/java/ql/src/experimental/semmle/code/java/frameworks/FreeMarker.qll
new file mode 100644
index 000000000000..84cea7f013ef
--- /dev/null
+++ b/java/ql/src/experimental/semmle/code/java/frameworks/FreeMarker.qll
@@ -0,0 +1,29 @@
+/** Definitions related to the FreeMarker Templating library. */
+
+import java
+
+/** The `Template` class of the FreeMarker Template Engine */
+class TypeFreeMarkerTemplate extends Class {
+ TypeFreeMarkerTemplate() { this.hasQualifiedName("freemarker.template", "Template") }
+}
+
+/** The `process` method of the FreeMarker Template Engine's `Template` class */
+class MethodFreeMarkerTemplateProcess extends Method {
+ MethodFreeMarkerTemplateProcess() {
+ this.getDeclaringType() instanceof TypeFreeMarkerTemplate and
+ this.hasName("process")
+ }
+}
+
+/** The `StringTemplateLoader` class of the FreeMarker Template Engine */
+class TypeFreeMarkerStringLoader extends Class {
+ TypeFreeMarkerStringLoader() { this.hasQualifiedName("freemarker.cache", "StringTemplateLoader") }
+}
+
+/** The `process` method of the FreeMarker Template Engine's `StringTemplateLoader` class */
+class MethodFreeMarkerStringTemplateLoaderPutTemplate extends Method {
+ MethodFreeMarkerStringTemplateLoaderPutTemplate() {
+ this.getDeclaringType() instanceof TypeFreeMarkerStringLoader and
+ this.hasName("putTemplate")
+ }
+}
diff --git a/java/ql/src/experimental/semmle/code/java/frameworks/JinJava.qll b/java/ql/src/experimental/semmle/code/java/frameworks/JinJava.qll
new file mode 100644
index 000000000000..f0f3bcf603bd
--- /dev/null
+++ b/java/ql/src/experimental/semmle/code/java/frameworks/JinJava.qll
@@ -0,0 +1,24 @@
+/** Definitions related to the Jinjava Templating library. */
+
+import java
+
+/** The `Jinjava` class of the Jinjava Templating Engine. */
+class TypeJinjava extends Class {
+ TypeJinjava() { this.hasQualifiedName("com.hubspot.jinjava", "Jinjava") }
+}
+
+/** The `render` method of the Jinjava Templating Engine. */
+class MethodJinjavaRender extends Method {
+ MethodJinjavaRender() {
+ this.getDeclaringType() instanceof TypeJinjava and
+ this.hasName("render")
+ }
+}
+
+/** The `render` method of the Jinjava Templating Engine. */
+class MethodJinjavaRenderForResult extends Method {
+ MethodJinjavaRenderForResult() {
+ this.getDeclaringType() instanceof TypeJinjava and
+ this.hasName("renderForResult")
+ }
+}
diff --git a/java/ql/src/experimental/semmle/code/java/frameworks/Pebble.qll b/java/ql/src/experimental/semmle/code/java/frameworks/Pebble.qll
new file mode 100644
index 000000000000..9850e5dbf4d9
--- /dev/null
+++ b/java/ql/src/experimental/semmle/code/java/frameworks/Pebble.qll
@@ -0,0 +1,16 @@
+/** Definitions related to the Pebble Templating library. */
+
+import java
+
+/** The `PebbleEngine` class of the Pebble Templating Engine. */
+class TypePebbleEngine extends Class {
+ TypePebbleEngine() { this.hasQualifiedName("com.mitchellbosecke.pebble", "PebbleEngine") }
+}
+
+/** The `getTemplate` method of the Pebble Templating Engine. */
+class MethodPebbleGetTemplate extends Method {
+ MethodPebbleGetTemplate() {
+ this.getDeclaringType() instanceof TypePebbleEngine and
+ this.hasName(["getTemplate", "getLiteralTemplate"])
+ }
+}
diff --git a/java/ql/src/experimental/semmle/code/java/frameworks/Thymeleaf.qll b/java/ql/src/experimental/semmle/code/java/frameworks/Thymeleaf.qll
new file mode 100644
index 000000000000..18235257be1d
--- /dev/null
+++ b/java/ql/src/experimental/semmle/code/java/frameworks/Thymeleaf.qll
@@ -0,0 +1,25 @@
+/** Definitions related to the Thymeleaf Templating library. */
+
+import java
+
+/**
+ * A class implementing the `ITemplateEngine` interface of the Thymeleaf
+ * Templating Engine such as the `TemplateEngine` class.
+ * */
+class TypeThymeleafTemplateEngine extends Class {
+ TypeThymeleafTemplateEngine() {
+ this.hasQualifiedName("org.thymeleaf", "TemplateEngine")
+ or
+ exists(Type t | this.getASupertype*().extendsOrImplements(t) |
+ t.hasName("org.thymeleaf.ITemplateEngine")
+ )
+ }
+}
+
+/** The `process` or `processThrottled` method of the Thymeleaf Templating Engine. */
+class MethodThymeleafProcess extends Method {
+ MethodThymeleafProcess() {
+ this.getDeclaringType() instanceof TypeThymeleafTemplateEngine and
+ this.hasName(["process", "processThrottled"])
+ }
+}
diff --git a/java/ql/src/experimental/semmle/code/java/frameworks/Velocity.qll b/java/ql/src/experimental/semmle/code/java/frameworks/Velocity.qll
new file mode 100644
index 000000000000..f2d298833c6a
--- /dev/null
+++ b/java/ql/src/experimental/semmle/code/java/frameworks/Velocity.qll
@@ -0,0 +1,119 @@
+/** Definitions related to the Apache Velocity Templating library. */
+
+import java
+
+/** The `org.apache.velocity.context.AbstractContext` class of the Velocity Templating Engine. */
+class TypeVelocityAbstractContext extends Class {
+ TypeVelocityAbstractContext() {
+ this.hasQualifiedName("org.apache.velocity.context", "AbstractContext")
+ }
+}
+
+/** The `org.apache.velocity.runtime.RuntimeServices` class of the Velocity Templating Engine. */
+class TypeVelocityRuntimeRuntimeServices extends Class {
+ TypeVelocityRuntimeRuntimeServices() {
+ this.hasQualifiedName("org.apache.velocity.runtime", "RuntimeServices")
+ }
+}
+
+/** The `org.apache.velocity.Template` class of the Velocity Templating Engine. */
+class TypeVelocityTemplate extends Class {
+ TypeVelocityTemplate() { this.hasQualifiedName("org.apache.velocity", "Template") }
+}
+
+/** The `org.apache.velocity.runtime.RuntimeSingleton` classTemplating Engine. */
+class TypeVelocityRuntimeRuntimeSingleton extends Class {
+ TypeVelocityRuntimeRuntimeSingleton() {
+ this.hasQualifiedName("org.apache.velocity.runtime", "RuntimeSingleton")
+ }
+}
+
+/** The `org.apache.velocity.VelocityEngine` class of the Velocity Templating Engine. */
+class TypeVelocityVelocityEngine extends Class {
+ TypeVelocityVelocityEngine() { this.hasQualifiedName("org.apache.velocity", "VelocityEngine") }
+}
+
+/** The `org.apache.velocity.app.VelocityEngine` class of the Velocity Templating Engine. */
+class TypeVelocityAppVelocityEngine extends RefType {
+ TypeVelocityAppVelocityEngine() {
+ this.hasQualifiedName("org.apache.velocity.app", "VelocityEngine")
+ }
+}
+
+/** The `org.apache.velocity.app.Velocity` class of the Velocity Templating Engine. */
+class TypeVelocityAppVelocity extends RefType {
+ TypeVelocityAppVelocity() { this.hasQualifiedName("org.apache.velocity.app", "Velocity") }
+}
+
+/**
+ * The `org.apache.velocity.runtime.resource.util.StringResourceRepository` interface
+ * of the Velocity Templating Engine.
+ */
+class TypeVelocityStringResourceRepo extends RefType {
+ TypeVelocityStringResourceRepo() {
+ this.hasQualifiedName("org.apache.velocity.runtime.resource.util", "StringResourceRepository")
+ }
+}
+
+/** The `internalPut` and `put` methods of the Velocity Templating Engine. */
+class MethodVelocityContextPut extends Method {
+ MethodVelocityContextPut() {
+ this.getDeclaringType().getASupertype*() instanceof TypeVelocityAbstractContext and
+ this.hasName(["put", "internalPut"])
+ }
+}
+
+/** The `evaluate` method of the Velocity Templating Engine. */
+class MethodVelocityEvaluate extends Method {
+ MethodVelocityEvaluate() {
+ // static boolean evaluate(Context context, Writer out, String logTag, String instring)
+ // static boolean evaluate(Context context, Writer writer, String logTag, Reader reader)
+ (
+ this.getDeclaringType() instanceof TypeVelocityAppVelocity or
+ this.getDeclaringType() instanceof TypeVelocityAppVelocityEngine or
+ this.getDeclaringType().getASupertype*() instanceof TypeVelocityRuntimeRuntimeServices
+ ) and
+ this.hasName("evaluate")
+ }
+}
+
+/** The `mergeTemplate` method of the Velocity Templating Engine. */
+class MethodVelocityMergeTemplate extends Method {
+ MethodVelocityMergeTemplate() {
+ // static boolean mergeTemplate(String templateName, String encoding, Context context, Writer writer)
+ (
+ this.getDeclaringType() instanceof TypeVelocityAppVelocity or
+ this.getDeclaringType() instanceof TypeVelocityAppVelocityEngine
+ ) and
+ this.hasName("mergeTemplate")
+ }
+}
+
+/** The `merge` method of the Velocity Templating Engine. */
+class MethodVelocityMerge extends Method {
+ MethodVelocityMerge() {
+ // void merge(Context context, Writer writer)
+ // void merge(Context context, Writer writer, List macroLibraries)
+ this.getDeclaringType() instanceof TypeVelocityTemplate and
+ this.hasName("merge")
+ }
+}
+
+/** The `parse` method of the Velocity Templating Engine. */
+class MethodVelocityParse extends Method {
+ MethodVelocityParse() {
+ (
+ this.getDeclaringType().getASupertype*() instanceof TypeVelocityRuntimeRuntimeSingleton or
+ this.getDeclaringType().getASupertype*() instanceof TypeVelocityRuntimeRuntimeServices
+ ) and
+ this.hasName("parse")
+ }
+}
+
+/** The `putStringResource` method of the Velocity Templating Engine. */
+class MethodVelocityPutStringResource extends Method {
+ MethodVelocityPutStringResource() {
+ this.getDeclaringType().getASupertype*() instanceof TypeVelocityStringResourceRepo and
+ this.hasName("putStringResource")
+ }
+}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/FreemarkerSSTI.java b/java/ql/test/experimental/query-tests/security/CWE-094/FreemarkerSSTI.java
new file mode 100644
index 000000000000..3ac93749616f
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/FreemarkerSSTI.java
@@ -0,0 +1,132 @@
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+
+import java.lang.String;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.OutputStreamWriter;
+import java.util.HashMap;
+
+import freemarker.template.Template;
+import freemarker.template.Configuration;
+import freemarker.cache.StringTemplateLoader;
+import freemarker.template.ParserConfiguration;
+
+@Controller
+public class FreemarkerSSTI {
+ String sourceName = "sourceName";
+
+ @GetMapping(value = "bad1")
+ public void bad1(HttpServletRequest request) {
+ String name = "ttemplate";
+ String code = request.getParameter("code");
+ Reader reader = new StringReader(code);
+
+ // Template(java.lang.String name, java.io.Reader reader)
+ Template t = new Template(name, reader);
+ }
+
+ @GetMapping(value = "bad2")
+ public void bad2(HttpServletRequest request) {
+ String name = "ttemplate";
+ String code = request.getParameter("code");
+ Reader reader = new StringReader(code);
+ Configuration cfg = new Configuration();
+
+ // Template(java.lang.String name, java.io.Reader reader, Configuration cfg)
+ Template t = new Template(name, reader, cfg);
+ }
+
+ @GetMapping(value = "bad3")
+ public void bad3(HttpServletRequest request) {
+ String name = "ttemplate";
+ String code = request.getParameter("code");
+ Reader reader = new StringReader(code);
+ Configuration cfg = new Configuration();
+
+ // Template(java.lang.String name, java.io.Reader reader, Configuration cfg,
+ // java.lang.String encoding)
+ Template t = new Template(name, reader, cfg, "UTF-8");
+ }
+
+ @GetMapping(value = "bad4")
+ public void bad4(HttpServletRequest request) {
+ String name = "ttemplate";
+ String sourceCode = request.getParameter("sourceCode");
+ Configuration cfg = new Configuration();
+
+ // Template(java.lang.String name, java.lang.String sourceCode, Configuration
+ // cfg)
+ Template t = new Template(name, sourceCode, cfg);
+ }
+
+ @GetMapping(value = "bad5")
+ public void bad5(HttpServletRequest request) {
+ String name = "ttemplate";
+ String code = request.getParameter("code");
+ Configuration cfg = new Configuration();
+ Reader reader = new StringReader(code);
+
+ // Template(java.lang.String name, java.lang.String sourceName, java.io.Reader
+ // reader, Configuration cfg)
+ Template t = new Template(name, sourceName, reader, cfg);
+ }
+
+ @GetMapping(value = "bad6")
+ public void bad6(HttpServletRequest request) {
+ String name = "ttemplate";
+ String code = request.getParameter("code");
+ Configuration cfg = new Configuration();
+ ParserConfiguration customParserConfiguration = new Configuration();
+ Reader reader = new StringReader(code);
+
+ // Template(java.lang.String name, java.lang.String sourceName, java.io.Reader
+ // reader, Configuration cfg, ParserConfiguration customParserConfiguration,
+ // java.lang.String encoding)
+ Template t = new Template(name, sourceName, reader, cfg, customParserConfiguration, "UTF-8");
+ }
+
+ @GetMapping(value = "bad7")
+ public void bad7(HttpServletRequest request) {
+ String name = "ttemplate";
+ String code = request.getParameter("code");
+ Configuration cfg = new Configuration();
+ ParserConfiguration customParserConfiguration = new Configuration();
+ Reader reader = new StringReader(code);
+
+ // Template(java.lang.String name, java.lang.String sourceName, java.io.Reader
+ // reader, Configuration cfg, java.lang.String encoding)
+ Template t = new Template(name, sourceName, reader, cfg, "UTF-8");
+ }
+
+ @GetMapping(value = "bad8")
+ public void bad8(HttpServletRequest request) {
+ String code = request.getParameter("code");
+ StringTemplateLoader stringLoader = new StringTemplateLoader();
+
+ // void putTemplate(java.lang.String name, java.lang.String templateContent)
+ stringLoader.putTemplate("myTemplate", code);
+ }
+
+ @GetMapping(value = "bad9")
+ public void bad9(HttpServletRequest request) {
+ String code = request.getParameter("code");
+ StringTemplateLoader stringLoader = new StringTemplateLoader();
+
+ // void putTemplate(java.lang.String name, java.lang.String templateContent,
+ // long lastModified)
+ stringLoader.putTemplate("myTemplate", code, 0);
+ }
+
+ @GetMapping(value = "bad10")
+ public void bad10(HttpServletRequest request) {
+ HashMap root = new HashMap();
+ String code = request.getParameter("code");
+ root.put("code", code);
+ Configuration cfg = new Configuration();
+ Template temp = cfg.getTemplate("test.ftlh");
+ OutputStreamWriter out = new OutputStreamWriter(System.out);
+ temp.process(root, out);
+ }
+}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/JinJavaSSTI.java b/java/ql/test/experimental/query-tests/security/CWE-094/JinJavaSSTI.java
new file mode 100644
index 000000000000..5f0d932678d7
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/JinJavaSSTI.java
@@ -0,0 +1,48 @@
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+
+import java.lang.String;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.hubspot.jinjava.*;
+import com.hubspot.jinjava.JinjavaConfig;
+import com.hubspot.jinjava.interpret.*;
+
+@Controller
+public class JinJavaSSTI {
+ String sourceName = "sourceName";
+
+ @GetMapping(value = "bad1")
+ public void bad1(HttpServletRequest request) {
+ String template = request.getParameter("template");
+ Jinjava jinjava = new Jinjava();
+ Map context = new HashMap<>();
+ // String render(String template, Map bindings)
+ String renderedTemplate = jinjava.render(template, context);
+ }
+
+ @GetMapping(value = "bad2")
+ public void bad2(HttpServletRequest request) {
+ String template = request.getParameter("template");
+ Jinjava jinjava = new Jinjava();
+ Map bindings = new HashMap<>();
+ // RenderResult renderForResult(String template, Map bindings)
+ RenderResult renderResult = jinjava.renderForResult(template, bindings);
+ }
+
+ @GetMapping(value = "bad3")
+ public void bad3(HttpServletRequest request) {
+ String template = request.getParameter("template");
+ Jinjava jinjava = new Jinjava();
+ Map bindings = new HashMap<>();
+ JinjavaConfig renderConfig = new JinjavaConfig();
+
+ // RenderResult renderForResult(String template, Map bindings,
+ // JinjavaConfig renderConfig)
+ RenderResult renderResult = jinjava.renderForResult(template, bindings, renderConfig);
+ }
+}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/PebbleSSTI.java b/java/ql/test/experimental/query-tests/security/CWE-094/PebbleSSTI.java
new file mode 100644
index 000000000000..13ed42a9b261
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/PebbleSSTI.java
@@ -0,0 +1,30 @@
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+
+import java.lang.String;
+import java.io.Reader;
+import java.io.StringReader;
+
+import com.mitchellbosecke.pebble.PebbleEngine;
+import com.mitchellbosecke.pebble.template.*;
+
+@Controller
+public class PebbleSSTI {
+ String sourceName = "sourceName";
+
+ @GetMapping(value = "bad1")
+ public void bad1(HttpServletRequest request) {
+ String code = request.getParameter("code");
+ PebbleEngine engine = new PebbleEngine.Builder().build();
+ // public PebbleTemplate getTemplate(String templateName)
+ PebbleTemplate compiledTemplate = engine.getTemplate(code);
+ }
+ @GetMapping(value = "bad2")
+ public void bad2(HttpServletRequest request) {
+ String code = request.getParameter("code");
+ PebbleEngine engine = new PebbleEngine.Builder().build();
+ // public PebbleTemplate getLiteralTemplate(String templateName)
+ PebbleTemplate compiledTemplate = engine.getLiteralTemplate(code);
+ }
+}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/TemplateInjection.expected b/java/ql/test/experimental/query-tests/security/CWE-094/TemplateInjection.expected
new file mode 100644
index 000000000000..dc884612625e
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/TemplateInjection.expected
@@ -0,0 +1,24 @@
+| FreemarkerSSTI.java:27:35:27:40 | reader | FreemarkerSSTI.java:23:17:23:44 | getParameter(...) : String | FreemarkerSSTI.java:27:35:27:40 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:23:17:23:44 | getParameter(...) | a template value loaded from a remote source. |
+| FreemarkerSSTI.java:38:35:38:40 | reader | FreemarkerSSTI.java:33:17:33:44 | getParameter(...) : String | FreemarkerSSTI.java:38:35:38:40 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:33:17:33:44 | getParameter(...) | a template value loaded from a remote source. |
+| FreemarkerSSTI.java:50:35:50:40 | reader | FreemarkerSSTI.java:44:17:44:44 | getParameter(...) : String | FreemarkerSSTI.java:50:35:50:40 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:44:17:44:44 | getParameter(...) | a template value loaded from a remote source. |
+| FreemarkerSSTI.java:61:35:61:44 | sourceCode | FreemarkerSSTI.java:56:23:56:56 | getParameter(...) : String | FreemarkerSSTI.java:61:35:61:44 | sourceCode | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:56:23:56:56 | getParameter(...) | a template value loaded from a remote source. |
+| FreemarkerSSTI.java:73:47:73:52 | reader | FreemarkerSSTI.java:67:17:67:44 | getParameter(...) : String | FreemarkerSSTI.java:73:47:73:52 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:67:17:67:44 | getParameter(...) | a template value loaded from a remote source. |
+| FreemarkerSSTI.java:87:47:87:52 | reader | FreemarkerSSTI.java:79:17:79:44 | getParameter(...) : String | FreemarkerSSTI.java:87:47:87:52 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:79:17:79:44 | getParameter(...) | a template value loaded from a remote source. |
+| FreemarkerSSTI.java:100:47:100:52 | reader | FreemarkerSSTI.java:93:17:93:44 | getParameter(...) : String | FreemarkerSSTI.java:100:47:100:52 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:93:17:93:44 | getParameter(...) | a template value loaded from a remote source. |
+| FreemarkerSSTI.java:109:42:109:45 | code | FreemarkerSSTI.java:105:17:105:44 | getParameter(...) : String | FreemarkerSSTI.java:109:42:109:45 | code | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:105:17:105:44 | getParameter(...) | a template value loaded from a remote source. |
+| FreemarkerSSTI.java:119:42:119:45 | code | FreemarkerSSTI.java:114:17:114:44 | getParameter(...) : String | FreemarkerSSTI.java:119:42:119:45 | code | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:114:17:114:44 | getParameter(...) | a template value loaded from a remote source. |
+| FreemarkerSSTI.java:130:22:130:25 | root | FreemarkerSSTI.java:125:17:125:44 | getParameter(...) : String | FreemarkerSSTI.java:130:22:130:25 | root | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:125:17:125:44 | getParameter(...) | a template value loaded from a remote source. |
+| JinJavaSSTI.java:25:44:25:51 | template | JinJavaSSTI.java:21:21:21:52 | getParameter(...) : String | JinJavaSSTI.java:25:44:25:51 | template | Potential arbitrary code execution due to $@. | JinJavaSSTI.java:21:21:21:52 | getParameter(...) | a template value loaded from a remote source. |
+| JinJavaSSTI.java:34:55:34:62 | template | JinJavaSSTI.java:30:21:30:52 | getParameter(...) : String | JinJavaSSTI.java:34:55:34:62 | template | Potential arbitrary code execution due to $@. | JinJavaSSTI.java:30:21:30:52 | getParameter(...) | a template value loaded from a remote source. |
+| JinJavaSSTI.java:46:55:46:62 | template | JinJavaSSTI.java:39:21:39:52 | getParameter(...) : String | JinJavaSSTI.java:46:55:46:62 | template | Potential arbitrary code execution due to $@. | JinJavaSSTI.java:39:21:39:52 | getParameter(...) | a template value loaded from a remote source. |
+| PebbleSSTI.java:21:56:21:59 | code | PebbleSSTI.java:18:17:18:44 | getParameter(...) : String | PebbleSSTI.java:21:56:21:59 | code | Potential arbitrary code execution due to $@. | PebbleSSTI.java:18:17:18:44 | getParameter(...) | a template value loaded from a remote source. |
+| PebbleSSTI.java:28:63:28:66 | code | PebbleSSTI.java:25:17:25:44 | getParameter(...) : String | PebbleSSTI.java:28:63:28:66 | code | Potential arbitrary code execution due to $@. | PebbleSSTI.java:25:17:25:44 | getParameter(...) | a template value loaded from a remote source. |
+| ThymeleafSSTI.java:27:27:27:30 | code | ThymeleafSSTI.java:22:17:22:44 | getParameter(...) : String | ThymeleafSSTI.java:27:27:27:30 | code | Potential arbitrary code execution due to $@. | ThymeleafSSTI.java:22:17:22:44 | getParameter(...) | a template value loaded from a remote source. |
+| VelocitySSTI.java:38:45:38:48 | code | VelocitySSTI.java:31:17:31:44 | getParameter(...) : String | VelocitySSTI.java:38:45:38:48 | code | Potential arbitrary code execution due to $@. | VelocitySSTI.java:31:17:31:44 | getParameter(...) | a template value loaded from a remote source. |
+| VelocitySSTI.java:53:45:53:50 | reader | VelocitySSTI.java:44:17:44:44 | getParameter(...) : String | VelocitySSTI.java:53:45:53:50 | reader | Potential arbitrary code execution due to $@. | VelocitySSTI.java:44:17:44:44 | getParameter(...) | a template value loaded from a remote source. |
+| VelocitySSTI.java:63:25:63:30 | reader | VelocitySSTI.java:59:17:59:44 | getParameter(...) : String | VelocitySSTI.java:63:25:63:30 | reader | Potential arbitrary code execution due to $@. | VelocitySSTI.java:59:17:59:44 | getParameter(...) | a template value loaded from a remote source. |
+| VelocitySSTI.java:77:21:77:27 | context | VelocitySSTI.java:69:17:69:44 | getParameter(...) : String | VelocitySSTI.java:77:21:77:27 | context | Potential arbitrary code execution due to $@. | VelocitySSTI.java:69:17:69:44 | getParameter(...) | a template value loaded from a remote source. |
+| VelocitySSTI.java:89:60:89:66 | context | VelocitySSTI.java:83:17:83:44 | getParameter(...) : String | VelocitySSTI.java:89:60:89:66 | context | Potential arbitrary code execution due to $@. | VelocitySSTI.java:83:17:83:44 | getParameter(...) | a template value loaded from a remote source. |
+| VelocitySSTI.java:102:11:102:17 | context | VelocitySSTI.java:95:17:95:44 | getParameter(...) : String | VelocitySSTI.java:102:11:102:17 | context | Potential arbitrary code execution due to $@. | VelocitySSTI.java:95:17:95:44 | getParameter(...) | a template value loaded from a remote source. |
+| VelocitySSTI.java:115:11:115:17 | context | VelocitySSTI.java:108:17:108:44 | getParameter(...) : String | VelocitySSTI.java:115:11:115:17 | context | Potential arbitrary code execution due to $@. | VelocitySSTI.java:108:17:108:44 | getParameter(...) | a template value loaded from a remote source. |
+| VelocitySSTI.java:123:37:123:40 | code | VelocitySSTI.java:120:17:120:44 | getParameter(...) : String | VelocitySSTI.java:123:37:123:40 | code | Potential arbitrary code execution due to $@. | VelocitySSTI.java:120:17:120:44 | getParameter(...) | a template value loaded from a remote source. |
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/TemplateInjection.qlref b/java/ql/test/experimental/query-tests/security/CWE-094/TemplateInjection.qlref
new file mode 100644
index 000000000000..2febc9b780f6
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/TemplateInjection.qlref
@@ -0,0 +1 @@
+experimental/Security/CWE/CWE-094/TemplateInjection.ql
\ No newline at end of file
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/ThymeleafSSTI.java b/java/ql/test/experimental/query-tests/security/CWE-094/ThymeleafSSTI.java
new file mode 100644
index 000000000000..2b32a4603c79
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/ThymeleafSSTI.java
@@ -0,0 +1,31 @@
+import javax.imageio.stream.FileImageInputStream;
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+
+import java.lang.String;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.Writer;
+
+import org.thymeleaf.*;
+import org.thymeleaf.context.Context;
+
+@Controller
+public class ThymeleafSSTI {
+ String sourceName = "sourceName";
+
+ @GetMapping(value = "bad1")
+ public void bad1(HttpServletRequest request) {
+ String code = request.getParameter("code");
+ Context ctx = new Context();
+ try {
+ FileWriter fw = new FileWriter(new File("as"));
+ TemplateEngine templateEngine = new TemplateEngine();
+ templateEngine.process(code, ctx, fw);
+ } catch (Exception e) {
+ }
+ }
+}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/VelocitySSTI.java b/java/ql/test/experimental/query-tests/security/CWE-094/VelocitySSTI.java
new file mode 100644
index 000000000000..c35dd9b0aae9
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/VelocitySSTI.java
@@ -0,0 +1,126 @@
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+
+import java.lang.String;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.OutputStreamWriter;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.LinkedList;
+
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.context.AbstractContext;
+import org.apache.velocity.context.Context;
+import org.apache.velocity.Template;
+import org.apache.velocity.app.Velocity;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.runtime.RuntimeServices;
+import org.apache.velocity.runtime.resource.util.StringResourceRepository;
+import org.apache.velocity.runtime.resource.util.StringResourceRepositoryImpl;
+
+@Controller
+public class VelocitySSTI {
+ String sourceName = "sourceName";
+
+ @GetMapping(value = "bad1")
+ public void bad1(HttpServletRequest request) {
+ String name = "ttemplate";
+ String code = request.getParameter("code");
+
+ VelocityContext context = null;
+
+ String s = "We are using $project $name to render this.";
+ StringWriter w = new StringWriter();
+ // evaluate( Context context, Writer out, String logTag, String instring )
+ Velocity.evaluate(context, w, "mystring", code);
+ }
+
+ @GetMapping(value = "bad2")
+ public void bad2(HttpServletRequest request) {
+ String name = "ttemplate";
+ String code = request.getParameter("code");
+
+ VelocityContext context = null;
+
+ String s = "We are using $project $name to render this.";
+ StringWriter w = new StringWriter();
+ StringReader reader = new StringReader(code);
+
+ // evaluate(Context context, Writer writer, String logTag, Reader reader)
+ Velocity.evaluate(context, w, "mystring", reader);
+ }
+
+ @GetMapping(value = "bad3")
+ public void bad3(HttpServletRequest request) {
+ String name = "ttemplate";
+ String code = request.getParameter("code");
+
+ RuntimeServices runtimeServices = new RuntimeServices();
+ StringReader reader = new StringReader(code);
+ runtimeServices.parse(reader, new Template());
+ }
+
+ @GetMapping(value = "bad4")
+ public void bad4(HttpServletRequest request) {
+ String name = "ttemplate";
+ String code = request.getParameter("code");
+
+ VelocityContext context = new VelocityContext();
+ context.put("code", code);
+
+ StringWriter w = new StringWriter();
+ StringReader reader = new StringReader("test");
+
+ Velocity.evaluate(context, w, "mystring", reader);
+ }
+
+ @GetMapping(value = "bad5")
+ public void bad5(HttpServletRequest request) {
+ String name = "ttemplate";
+ String code = request.getParameter("code");
+
+ VelocityContext context = new VelocityContext();
+ context.put("code", code);
+
+ StringWriter w = new StringWriter();
+ VelocityEngine.mergeTemplate("testtemplate.vm", "UTF-8", context, w);
+ }
+
+ @GetMapping(value = "bad6")
+ public void bad6(HttpServletRequest request) {
+ String name = "ttemplate";
+ String code = request.getParameter("code");
+
+ VelocityContext context = new VelocityContext();
+ context.put("code", code);
+
+ StringWriter w = new StringWriter();
+ Template t = new Template();
+ t.merge(context, w);
+ }
+
+ @GetMapping(value = "bad7")
+ public void bad7(HttpServletRequest request) {
+ String name = "ttemplate";
+ String code = request.getParameter("code");
+
+ VelocityContext context = new VelocityContext();
+ context.put("code", code);
+
+ StringWriter w = new StringWriter();
+ Template t = new Template();
+ t.merge(context, w, new LinkedList());
+ }
+
+ @GetMapping(value = "bad8")
+ public void bad8(HttpServletRequest request) {
+ String code = request.getParameter("code");
+
+ StringResourceRepository repo = new StringResourceRepositoryImpl();
+ repo.putStringResource("woogie2", code);
+
+ }
+}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/options b/java/ql/test/experimental/query-tests/security/CWE-094/options
index 606b83a6dcc9..d527e41cc4db 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-094/options
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/options
@@ -1 +1 @@
-//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.3.8:${testdir}/../../../../stubs/jsr223-api:${testdir}/../../../../stubs/scriptengine:${testdir}/../../../../stubs/java-ee-el:${testdir}/../../../../stubs/juel-2.2:${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/jython-2.7.2:${testdir}/../../../../experimental/stubs/rhino-1.7.13:${testdir}/../../../../stubs/bsh-2.0b5:${testdir}/../../../../experimental/stubs/jshell
+//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.3.8:${testdir}/../../../../stubs/jsr223-api:${testdir}/../../../../stubs/scriptengine:${testdir}/../../../../stubs/java-ee-el:${testdir}/../../../../stubs/juel-2.2:${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/jython-2.7.2:${testdir}/../../../../experimental/stubs/rhino-1.7.13:${testdir}/../../../../stubs/bsh-2.0b5:${testdir}/../../../../experimental/stubs/jshell:${testdir}/../../../../experimental/stubs/apache-freemarker-2.3.31:${testdir}/../../../../experimental/stubs/jinjava-2.6.0:${testdir}/../../../../experimental/stubs/pebble-3.1.5:${testdir}/../../../../experimental/stubs/thymeleaf-3.0.14:${testdir}/../../../../experimental/stubs/apache-velocity-2.3
\ No newline at end of file
diff --git a/java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/cache/StringTemplateLoader.java b/java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/cache/StringTemplateLoader.java
new file mode 100644
index 000000000000..1dd644063c10
--- /dev/null
+++ b/java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/cache/StringTemplateLoader.java
@@ -0,0 +1,7 @@
+package freemarker.cache;
+
+public class StringTemplateLoader {
+ public StringTemplateLoader() {}
+ public void putTemplate(java.lang.String name, java.lang.String templateContent){}
+ public void putTemplate(java.lang.String name, java.lang.String templateContent, long lastModified){}
+}
\ No newline at end of file
diff --git a/java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/Configuration.java b/java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/Configuration.java
new file mode 100644
index 000000000000..3c4b9190e949
--- /dev/null
+++ b/java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/Configuration.java
@@ -0,0 +1,9 @@
+package freemarker.template;
+
+import freemarker.template.Template;
+
+public class Configuration implements ParserConfiguration {
+
+ public Configuration() {}
+ public Template getTemplate(java.lang.String name){return null;}
+}
diff --git a/java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/ObjectWrapper.java b/java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/ObjectWrapper.java
new file mode 100644
index 000000000000..53eece8a9f42
--- /dev/null
+++ b/java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/ObjectWrapper.java
@@ -0,0 +1,3 @@
+package freemarker.template;
+
+public interface ObjectWrapper {}
diff --git a/java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/ParserConfiguration.java b/java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/ParserConfiguration.java
new file mode 100644
index 000000000000..83e646f39c6a
--- /dev/null
+++ b/java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/ParserConfiguration.java
@@ -0,0 +1,3 @@
+package freemarker.template;
+
+public interface ParserConfiguration {}
diff --git a/java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/Template.java b/java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/Template.java
new file mode 100644
index 000000000000..ff72e8747c48
--- /dev/null
+++ b/java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/Template.java
@@ -0,0 +1,55 @@
+package freemarker.template;
+
+import java.io.Reader;
+import java.lang.String;
+
+public class Template {
+
+ public Template(String name, Reader reader) {
+ }
+
+ public Template(String name, Reader reader, Configuration cfg) {
+ }
+
+ public Template(String name, Reader reader, Configuration cfg, String encoding) {
+ }
+
+ public Template(String name, String sourceCode, Configuration cfg) {
+ }
+
+ public Template(String name, String sourceName, Reader reader, Configuration cfg) {
+ }
+
+ public Template(
+ String name,
+ String sourceName,
+ Reader reader,
+ Configuration cfg,
+ ParserConfiguration customParserConfiguration,
+ String encoding) {
+ }
+
+ public Template(
+ String name,
+ String sourceName,
+ Reader reader,
+ Configuration cfg,
+ String encoding) {
+ }
+
+ public void process(java.lang.Object dataModel, java.io.Writer out) {
+ }
+
+ public void process(
+ java.lang.Object dataModel,
+ java.io.Writer out,
+ ObjectWrapper wrapper) {
+ }
+
+ public void process(
+ java.lang.Object dataModel,
+ java.io.Writer out,
+ ObjectWrapper wrapper,
+ TemplateNodeModel rootNode) {
+ }
+}
diff --git a/java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateNodeModel.java b/java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateNodeModel.java
new file mode 100644
index 000000000000..4b4c14ad11db
--- /dev/null
+++ b/java/ql/test/experimental/stubs/apache-freemarker-2.3.31/freemarker/template/TemplateNodeModel.java
@@ -0,0 +1,3 @@
+package freemarker.template;
+
+public interface TemplateNodeModel {}
diff --git a/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/Template.java b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/Template.java
new file mode 100644
index 000000000000..933006f59444
--- /dev/null
+++ b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/Template.java
@@ -0,0 +1,13 @@
+package org.apache.velocity;
+
+import org.apache.velocity.context.Context;
+import java.io.Writer;
+import java.util.List;
+
+public class Template {
+ public void merge(Context context, Writer writer) {
+ }
+
+ public void merge(Context context, Writer writer, List macroLibraries) {
+ }
+}
diff --git a/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/VelocityContext.java b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/VelocityContext.java
new file mode 100644
index 000000000000..3f28c3edf5e7
--- /dev/null
+++ b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/VelocityContext.java
@@ -0,0 +1,10 @@
+package org.apache.velocity;
+
+import org.apache.velocity.context.AbstractContext;
+import org.apache.velocity.context.Context;
+import java.io.Writer;
+
+public class VelocityContext extends AbstractContext implements Context {
+ public VelocityContext() {
+ }
+}
diff --git a/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/VelocityEngine.java b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/VelocityEngine.java
new file mode 100644
index 000000000000..b9f758fc2292
--- /dev/null
+++ b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/VelocityEngine.java
@@ -0,0 +1,20 @@
+package org.apache.velocity;
+
+import org.apache.velocity.context;
+import java.io.Writer;
+import java.lang.String;
+import java.io.Reader;
+
+public class VelocityEngine {
+ public static boolean evaluate(Context context, Writer out, String logTag, String instring) {
+ return true;
+ }
+
+ public static boolean evaluate(Context context, Writer writer, String logTag, Reader reader) {
+ return true;
+ }
+
+ public static boolean mergeTemplate(String templateName, String encoding, Context context, Writer writer) {
+ return true;
+ }
+}
diff --git a/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/app/Velocity.java b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/app/Velocity.java
new file mode 100644
index 000000000000..d1d38019dbe5
--- /dev/null
+++ b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/app/Velocity.java
@@ -0,0 +1,15 @@
+package org.apache.velocity.app;
+
+import org.apache.velocity.context.Context;
+import java.io.Reader;
+import java.io.Writer;
+
+public class Velocity {
+ public static boolean evaluate(Context context, Writer out, String logTag, String instring) {
+ return true;
+ }
+
+ public static boolean evaluate(Context context, Writer writer, String logTag, Reader reader) {
+ return true;
+ }
+}
diff --git a/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/app/VelocityEngine.java b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/app/VelocityEngine.java
new file mode 100644
index 000000000000..f68b1ca19d55
--- /dev/null
+++ b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/app/VelocityEngine.java
@@ -0,0 +1,20 @@
+package org.apache.velocity.app;
+
+import org.apache.velocity.context.Context;
+import java.io.Writer;
+import java.lang.String;
+import java.io.Reader;
+
+public class VelocityEngine {
+ public static boolean evaluate(Context context, Writer out, String logTag, String instring) {
+ return true;
+ }
+
+ public static boolean evaluate(Context context, Writer writer, String logTag, Reader reader) {
+ return true;
+ }
+
+ public static boolean mergeTemplate(String templateName, String encoding, Context context, Writer writer) {
+ return true;
+ }
+}
diff --git a/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/context/AbstractContext.java b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/context/AbstractContext.java
new file mode 100644
index 000000000000..bdb94850e256
--- /dev/null
+++ b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/context/AbstractContext.java
@@ -0,0 +1,14 @@
+package org.apache.velocity.context;
+
+import org.apache.velocity.context.Context;
+import java.io.Writer;
+
+public class AbstractContext implements Context {
+ public Object put(String key, Object value) {
+ return null;
+ }
+
+ public Object internalPut(String key, Object value) {
+ return null;
+ }
+}
diff --git a/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/context/Context.java b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/context/Context.java
new file mode 100644
index 000000000000..c32f4308d398
--- /dev/null
+++ b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/context/Context.java
@@ -0,0 +1,7 @@
+package org.apache.velocity.context;
+
+public interface Context {
+ public Object put(String key, Object value);
+
+ public Object internalPut(String key, Object value);
+}
diff --git a/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/RuntimeServices.java b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/RuntimeServices.java
new file mode 100644
index 000000000000..bdf61a72a520
--- /dev/null
+++ b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/RuntimeServices.java
@@ -0,0 +1,25 @@
+package org.apache.velocity.runtime;
+
+import org.apache.velocity.runtime.parser.node.*;
+
+import org.apache.velocity.context.Context;
+import java.io.Reader;
+import java.io.Writer;
+import org.apache.velocity.Template;
+
+public class RuntimeServices {
+ public RuntimeServices() {
+ }
+
+ public static SimpleNode parse(Reader reader, Template template) {
+ return null;
+ }
+
+ public static boolean evaluate(Context context, Writer out, String logTag, String instring) {
+ return true;
+ }
+
+ public static boolean evaluate(Context context, Writer writer, String logTag, Reader reader) {
+ return true;
+ }
+}
diff --git a/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/RuntimeSingleton.java b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/RuntimeSingleton.java
new file mode 100644
index 000000000000..4b89c59e2ca0
--- /dev/null
+++ b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/RuntimeSingleton.java
@@ -0,0 +1,8 @@
+package org.apache.velocity.runtime;
+
+import org.apache.velocity.runtime.parser.node.*;
+
+public class RuntimeSingleton {
+ public static SimpleNode parse(Reader reader, Template template) {
+ }
+}
diff --git a/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/parser/node/SimpleNode.java b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/parser/node/SimpleNode.java
new file mode 100644
index 000000000000..5e8a3695ba51
--- /dev/null
+++ b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/parser/node/SimpleNode.java
@@ -0,0 +1,5 @@
+package org.apache.velocity.runtime.parser.node;
+
+public class SimpleNode {
+
+}
diff --git a/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/resource/util/StringResourceRepository.java b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/resource/util/StringResourceRepository.java
new file mode 100644
index 000000000000..8043d4b7136f
--- /dev/null
+++ b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/resource/util/StringResourceRepository.java
@@ -0,0 +1,7 @@
+package org.apache.velocity.runtime.resource.util;
+
+public interface StringResourceRepository {
+ public void putStringResource(String name, String body);
+
+ public void putStringResource(String name, String body, String encoding);
+}
diff --git a/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/resource/util/StringResourceRepositoryImpl.java b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/resource/util/StringResourceRepositoryImpl.java
new file mode 100644
index 000000000000..01845deed974
--- /dev/null
+++ b/java/ql/test/experimental/stubs/apache-velocity-2.3/org/apache/velocity/runtime/resource/util/StringResourceRepositoryImpl.java
@@ -0,0 +1,9 @@
+package org.apache.velocity.runtime.resource.util;
+
+public class StringResourceRepositoryImpl implements StringResourceRepository {
+ public void putStringResource(String name, String body) {
+ }
+
+ public void putStringResource(String name, String body, String encoding) {
+ }
+}
diff --git a/java/ql/test/experimental/stubs/jinjava-2.6.0/com/hubspot/jinjava/Jinjava.java b/java/ql/test/experimental/stubs/jinjava-2.6.0/com/hubspot/jinjava/Jinjava.java
new file mode 100644
index 000000000000..8f00ee19b796
--- /dev/null
+++ b/java/ql/test/experimental/stubs/jinjava-2.6.0/com/hubspot/jinjava/Jinjava.java
@@ -0,0 +1,24 @@
+package com.hubspot.jinjava;
+
+import com.hubspot.jinjava.JinjavaConfig;
+import com.hubspot.jinjava.interpret.RenderResult;
+
+import java.lang.String;
+import java.util.Map;
+
+public class Jinjava {
+ public Jinjava() {
+ }
+
+ public String render(String template, Map bindings) {
+ return "test";
+ };
+
+ public RenderResult renderForResult(String template, Map bindings) {
+ return new RenderResult("result");
+ }
+
+ public RenderResult renderForResult(String template, Map bindings, JinjavaConfig renderConfig) {
+ return new RenderResult("result");
+ }
+}
diff --git a/java/ql/test/experimental/stubs/jinjava-2.6.0/com/hubspot/jinjava/JinjavaConfig.java b/java/ql/test/experimental/stubs/jinjava-2.6.0/com/hubspot/jinjava/JinjavaConfig.java
new file mode 100644
index 000000000000..6b6fc076cc3c
--- /dev/null
+++ b/java/ql/test/experimental/stubs/jinjava-2.6.0/com/hubspot/jinjava/JinjavaConfig.java
@@ -0,0 +1,5 @@
+package com.hubspot.jinjava;
+
+public class JinjavaConfig {
+
+}
diff --git a/java/ql/test/experimental/stubs/jinjava-2.6.0/com/hubspot/jinjava/interpret/RenderResult.java b/java/ql/test/experimental/stubs/jinjava-2.6.0/com/hubspot/jinjava/interpret/RenderResult.java
new file mode 100644
index 000000000000..c9a9b2265d7d
--- /dev/null
+++ b/java/ql/test/experimental/stubs/jinjava-2.6.0/com/hubspot/jinjava/interpret/RenderResult.java
@@ -0,0 +1,6 @@
+package com.hubspot.jinjava.interpret;
+
+public class RenderResult {
+ public RenderResult(String result) {
+ }
+}
diff --git a/java/ql/test/experimental/stubs/pebble-3.1.5/com/mitchellbosecke/pebble/PebbleEngine.java b/java/ql/test/experimental/stubs/pebble-3.1.5/com/mitchellbosecke/pebble/PebbleEngine.java
new file mode 100644
index 000000000000..60506ce81d4e
--- /dev/null
+++ b/java/ql/test/experimental/stubs/pebble-3.1.5/com/mitchellbosecke/pebble/PebbleEngine.java
@@ -0,0 +1,27 @@
+package com.mitchellbosecke.pebble;
+
+import com.mitchellbosecke.pebble.template.*;
+
+public class PebbleEngine {
+ public static class Builder {
+ public Builder() {
+ };
+
+ public PebbleEngine build() {
+ return new PebbleEngine();
+ }
+ };
+
+ PebbleEngine() {
+ }
+
+ public PebbleTemplate getLiteralTemplate(String templateName) {
+ return new PebbleTemplate() {
+ };
+ }
+
+ public PebbleTemplate getTemplate(String templateName) {
+ return new PebbleTemplate() {
+ };
+ }
+}
diff --git a/java/ql/test/experimental/stubs/pebble-3.1.5/com/mitchellbosecke/pebble/template/PebbleTemplate.java b/java/ql/test/experimental/stubs/pebble-3.1.5/com/mitchellbosecke/pebble/template/PebbleTemplate.java
new file mode 100644
index 000000000000..3f7ff70aec98
--- /dev/null
+++ b/java/ql/test/experimental/stubs/pebble-3.1.5/com/mitchellbosecke/pebble/template/PebbleTemplate.java
@@ -0,0 +1,3 @@
+package com.mitchellbosecke.pebble.template;
+
+public interface PebbleTemplate {}
\ No newline at end of file
diff --git a/java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/ITemplateEngine.java b/java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/ITemplateEngine.java
new file mode 100644
index 000000000000..0ffad058ee19
--- /dev/null
+++ b/java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/ITemplateEngine.java
@@ -0,0 +1,28 @@
+package org.thymeleaf;
+
+import java.io.Writer;
+import java.lang.String;
+import java.util.Set;
+import org.thymeleaf.context.IContext;
+import org.thymeleaf.*;
+
+public interface ITemplateEngine {
+
+ public String process(String template, Set templateSelectors, IContext context);
+
+ public void process(String template, Set templateSelectors, IContext context, Writer writer);
+
+ public String process(String template, IContext context);
+
+ public void process(String template, IContext context, Writer writer);
+
+ public String process(TemplateSpec templateSpec, IContext context);
+
+ public void process(TemplateSpec templateSpec, IContext context, Writer writer);
+
+ public IThrottledTemplateProcessor processThrottled(String template, Set templateSelectors, IContext context);
+
+ public IThrottledTemplateProcessor processThrottled(String template, IContext context);
+
+ public IThrottledTemplateProcessor processThrottled(TemplateSpec templateSpec, IContext context);
+}
diff --git a/java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/IThrottledTemplateProcessor.java b/java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/IThrottledTemplateProcessor.java
new file mode 100644
index 000000000000..d1bcd3e7c401
--- /dev/null
+++ b/java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/IThrottledTemplateProcessor.java
@@ -0,0 +1,5 @@
+package org.thymeleaf;
+
+public interface IThrottledTemplateProcessor {
+
+}
diff --git a/java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/TemplateEngine.java b/java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/TemplateEngine.java
new file mode 100644
index 000000000000..3c51d321ddf4
--- /dev/null
+++ b/java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/TemplateEngine.java
@@ -0,0 +1,51 @@
+package org.thymeleaf;
+
+import java.io.Writer;
+import java.lang.String;
+import java.util.Set;
+import org.thymeleaf.context.IContext;
+import org.thymeleaf.TemplateSpec;
+import org.thymeleaf.ITemplateEngine;
+import org.thymeleaf.IThrottledTemplateProcessor;
+
+public class TemplateEngine implements ITemplateEngine {
+
+ public String process(String template, Set templateSelectors, IContext context) {
+ return "";
+ }
+
+ public void process(String template, Set templateSelectors, IContext context, Writer writer) {
+ }
+
+ public String process(String template, IContext context) {
+ return "";
+ }
+
+ public void process(String template, IContext context, Writer writer) {
+ }
+
+ public String process(TemplateSpec templateSpec, IContext context) {
+ return "";
+ }
+
+ public void process(TemplateSpec templateSpec, IContext context, Writer writer) {
+ }
+
+ public IThrottledTemplateProcessor processThrottled(String template, Set templateSelectors,
+ IContext context) {
+ return new IThrottledTemplateProcessor() {
+ };
+ }
+
+ public IThrottledTemplateProcessor processThrottled(String template, IContext context) {
+ return new IThrottledTemplateProcessor() {
+ };
+
+ }
+
+ public IThrottledTemplateProcessor processThrottled(TemplateSpec templateSpec, IContext context) {
+ return new IThrottledTemplateProcessor() {
+ };
+
+ }
+}
diff --git a/java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/TemplateSpec.java b/java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/TemplateSpec.java
new file mode 100644
index 000000000000..59687892527a
--- /dev/null
+++ b/java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/TemplateSpec.java
@@ -0,0 +1,5 @@
+package org.thymeleaf;
+
+public class TemplateSpec {
+
+}
diff --git a/java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/context/Context.java b/java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/context/Context.java
new file mode 100644
index 000000000000..afba6712ad7a
--- /dev/null
+++ b/java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/context/Context.java
@@ -0,0 +1,7 @@
+package org.thymeleaf.context;
+
+import org.thymeleaf.context.IContext;
+
+public class Context implements IContext {
+
+}
diff --git a/java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/context/IContext.java b/java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/context/IContext.java
new file mode 100644
index 000000000000..131de89067d4
--- /dev/null
+++ b/java/ql/test/experimental/stubs/thymeleaf-3.0.14/org/thymeleaf/context/IContext.java
@@ -0,0 +1,5 @@
+package org.thymeleaf.context;
+
+public interface IContext {
+
+}
From c81d85f32185e91adabcbe3729bc01d077c360e4 Mon Sep 17 00:00:00 2001
From: Porcupiney Hairs
Date: Tue, 22 Feb 2022 23:07:34 +0530
Subject: [PATCH 2/6] Include suggestions from review
---
.../experimental/Security/CWE/CWE-094/TemplateInjection.qhelp | 4 ++--
.../query-tests/security/CWE-094/JinJavaSSTI.java | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.qhelp b/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.qhelp
index 86d821b85205..882e9cecab1b 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.qhelp
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.qhelp
@@ -16,14 +16,14 @@
code
is used as a Velocity template string. This can lead to remote code execution.
-
+
In the next example the problem is avoided by using a fixed template string
s
. Since, the template is not attacker controlled in this case, we prevent untrusted code execution.
-
+
Portswigger : [Server Side Template Injection](https://portswigger.net/web-security/server-side-template-injection)
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/JinJavaSSTI.java b/java/ql/test/experimental/query-tests/security/CWE-094/JinJavaSSTI.java
index 5f0d932678d7..0a2f5a4fe04b 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-094/JinJavaSSTI.java
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/JinJavaSSTI.java
@@ -21,7 +21,7 @@ public void bad1(HttpServletRequest request) {
String template = request.getParameter("template");
Jinjava jinjava = new Jinjava();
Map context = new HashMap<>();
- // String render(String template, Map bindings)
+ // String render(String template, Map bindings)
String renderedTemplate = jinjava.render(template, context);
}
From 476997a599e737c091f07da3ade1efd4e6d226af Mon Sep 17 00:00:00 2001
From: Chris Smowton
Date: Wed, 23 Feb 2022 11:02:17 +0000
Subject: [PATCH 3/6] Replace more non-breaking spaces
---
.../query-tests/security/CWE-094/JinJavaSSTI.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/JinJavaSSTI.java b/java/ql/test/experimental/query-tests/security/CWE-094/JinJavaSSTI.java
index 0a2f5a4fe04b..a5791ae1d570 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-094/JinJavaSSTI.java
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/JinJavaSSTI.java
@@ -21,7 +21,7 @@ public void bad1(HttpServletRequest request) {
String template = request.getParameter("template");
Jinjava jinjava = new Jinjava();
Map context = new HashMap<>();
- // String render(String template, Map bindings)
+ // String render(String template, Map bindings)
String renderedTemplate = jinjava.render(template, context);
}
@@ -30,7 +30,7 @@ public void bad2(HttpServletRequest request) {
String template = request.getParameter("template");
Jinjava jinjava = new Jinjava();
Map bindings = new HashMap<>();
- // RenderResult renderForResult(String template, Map bindings)
+ // RenderResult renderForResult (String template, Map bindings)
RenderResult renderResult = jinjava.renderForResult(template, bindings);
}
@@ -41,7 +41,7 @@ public void bad3(HttpServletRequest request) {
Map bindings = new HashMap<>();
JinjavaConfig renderConfig = new JinjavaConfig();
- // RenderResult renderForResult(String template, Map bindings,
+ // RenderResult renderForResult (String template, Map bindings,
// JinjavaConfig renderConfig)
RenderResult renderResult = jinjava.renderForResult(template, bindings, renderConfig);
}
From 50d99456252125e862676fc10ce754f09f32816d Mon Sep 17 00:00:00 2001
From: Chris Smowton
Date: Wed, 23 Feb 2022 11:41:23 +0000
Subject: [PATCH 4/6] Autoformat
---
.../semmle/code/java/frameworks/Thymeleaf.qll | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/java/ql/src/experimental/semmle/code/java/frameworks/Thymeleaf.qll b/java/ql/src/experimental/semmle/code/java/frameworks/Thymeleaf.qll
index 18235257be1d..e93f2739be1a 100644
--- a/java/ql/src/experimental/semmle/code/java/frameworks/Thymeleaf.qll
+++ b/java/ql/src/experimental/semmle/code/java/frameworks/Thymeleaf.qll
@@ -2,10 +2,10 @@
import java
-/**
- * A class implementing the `ITemplateEngine` interface of the Thymeleaf
- * Templating Engine such as the `TemplateEngine` class.
- * */
+/**
+ * A class implementing the `ITemplateEngine` interface of the Thymeleaf
+ * Templating Engine such as the `TemplateEngine` class.
+ */
class TypeThymeleafTemplateEngine extends Class {
TypeThymeleafTemplateEngine() {
this.hasQualifiedName("org.thymeleaf", "TemplateEngine")
From a8fe10f3535e079a215db4afecb54ec07452ce9d Mon Sep 17 00:00:00 2001
From: Chris Smowton
Date: Wed, 23 Feb 2022 13:47:24 +0000
Subject: [PATCH 5/6] Java template injection query: import pathgraph
---
.../src/experimental/Security/CWE/CWE-094/TemplateInjection.ql | 1 +
1 file changed, 1 insertion(+)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.ql
index d4dc0c3952ef..18e47d2c6b35 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/TemplateInjection.ql
@@ -11,6 +11,7 @@
import java
import TemplateInjection
+import DataFlow::PathGraph
from TemplateInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
From 7b425a80bc4b143fd0f3d0501b4b6da99b514a94 Mon Sep 17 00:00:00 2001
From: Chris Smowton
Date: Wed, 23 Feb 2022 16:02:54 +0000
Subject: [PATCH 6/6] Note path query expectations
---
.../CWE-094/TemplateInjection.expected | 112 ++++++++++++++++++
1 file changed, 112 insertions(+)
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/TemplateInjection.expected b/java/ql/test/experimental/query-tests/security/CWE-094/TemplateInjection.expected
index dc884612625e..9b739f8d1daa 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-094/TemplateInjection.expected
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/TemplateInjection.expected
@@ -1,3 +1,115 @@
+edges
+| FreemarkerSSTI.java:23:17:23:44 | getParameter(...) : String | FreemarkerSSTI.java:24:36:24:39 | code : String |
+| FreemarkerSSTI.java:24:19:24:40 | new StringReader(...) : StringReader | FreemarkerSSTI.java:27:35:27:40 | reader |
+| FreemarkerSSTI.java:24:36:24:39 | code : String | FreemarkerSSTI.java:24:19:24:40 | new StringReader(...) : StringReader |
+| FreemarkerSSTI.java:33:17:33:44 | getParameter(...) : String | FreemarkerSSTI.java:34:36:34:39 | code : String |
+| FreemarkerSSTI.java:34:19:34:40 | new StringReader(...) : StringReader | FreemarkerSSTI.java:38:35:38:40 | reader |
+| FreemarkerSSTI.java:34:36:34:39 | code : String | FreemarkerSSTI.java:34:19:34:40 | new StringReader(...) : StringReader |
+| FreemarkerSSTI.java:44:17:44:44 | getParameter(...) : String | FreemarkerSSTI.java:45:36:45:39 | code : String |
+| FreemarkerSSTI.java:45:19:45:40 | new StringReader(...) : StringReader | FreemarkerSSTI.java:50:35:50:40 | reader |
+| FreemarkerSSTI.java:45:36:45:39 | code : String | FreemarkerSSTI.java:45:19:45:40 | new StringReader(...) : StringReader |
+| FreemarkerSSTI.java:56:23:56:56 | getParameter(...) : String | FreemarkerSSTI.java:61:35:61:44 | sourceCode |
+| FreemarkerSSTI.java:67:17:67:44 | getParameter(...) : String | FreemarkerSSTI.java:69:36:69:39 | code : String |
+| FreemarkerSSTI.java:69:19:69:40 | new StringReader(...) : StringReader | FreemarkerSSTI.java:73:47:73:52 | reader |
+| FreemarkerSSTI.java:69:36:69:39 | code : String | FreemarkerSSTI.java:69:19:69:40 | new StringReader(...) : StringReader |
+| FreemarkerSSTI.java:79:17:79:44 | getParameter(...) : String | FreemarkerSSTI.java:82:36:82:39 | code : String |
+| FreemarkerSSTI.java:82:19:82:40 | new StringReader(...) : StringReader | FreemarkerSSTI.java:87:47:87:52 | reader |
+| FreemarkerSSTI.java:82:36:82:39 | code : String | FreemarkerSSTI.java:82:19:82:40 | new StringReader(...) : StringReader |
+| FreemarkerSSTI.java:93:17:93:44 | getParameter(...) : String | FreemarkerSSTI.java:96:36:96:39 | code : String |
+| FreemarkerSSTI.java:96:19:96:40 | new StringReader(...) : StringReader | FreemarkerSSTI.java:100:47:100:52 | reader |
+| FreemarkerSSTI.java:96:36:96:39 | code : String | FreemarkerSSTI.java:96:19:96:40 | new StringReader(...) : StringReader |
+| FreemarkerSSTI.java:105:17:105:44 | getParameter(...) : String | FreemarkerSSTI.java:109:42:109:45 | code |
+| FreemarkerSSTI.java:114:17:114:44 | getParameter(...) : String | FreemarkerSSTI.java:119:42:119:45 | code |
+| FreemarkerSSTI.java:125:17:125:44 | getParameter(...) : String | FreemarkerSSTI.java:126:26:126:29 | code : String |
+| FreemarkerSSTI.java:126:9:126:12 | root [post update] [] : String | FreemarkerSSTI.java:130:22:130:25 | root |
+| FreemarkerSSTI.java:126:26:126:29 | code : String | FreemarkerSSTI.java:126:9:126:12 | root [post update] [] : String |
+| JinJavaSSTI.java:21:21:21:52 | getParameter(...) : String | JinJavaSSTI.java:25:44:25:51 | template |
+| JinJavaSSTI.java:30:21:30:52 | getParameter(...) : String | JinJavaSSTI.java:34:55:34:62 | template |
+| JinJavaSSTI.java:39:21:39:52 | getParameter(...) : String | JinJavaSSTI.java:46:55:46:62 | template |
+| PebbleSSTI.java:18:17:18:44 | getParameter(...) : String | PebbleSSTI.java:21:56:21:59 | code |
+| PebbleSSTI.java:25:17:25:44 | getParameter(...) : String | PebbleSSTI.java:28:63:28:66 | code |
+| ThymeleafSSTI.java:22:17:22:44 | getParameter(...) : String | ThymeleafSSTI.java:27:27:27:30 | code |
+| VelocitySSTI.java:31:17:31:44 | getParameter(...) : String | VelocitySSTI.java:38:45:38:48 | code |
+| VelocitySSTI.java:44:17:44:44 | getParameter(...) : String | VelocitySSTI.java:50:42:50:45 | code : String |
+| VelocitySSTI.java:50:25:50:46 | new StringReader(...) : StringReader | VelocitySSTI.java:53:45:53:50 | reader |
+| VelocitySSTI.java:50:42:50:45 | code : String | VelocitySSTI.java:50:25:50:46 | new StringReader(...) : StringReader |
+| VelocitySSTI.java:59:17:59:44 | getParameter(...) : String | VelocitySSTI.java:62:42:62:45 | code : String |
+| VelocitySSTI.java:62:25:62:46 | new StringReader(...) : StringReader | VelocitySSTI.java:63:25:63:30 | reader |
+| VelocitySSTI.java:62:42:62:45 | code : String | VelocitySSTI.java:62:25:62:46 | new StringReader(...) : StringReader |
+| VelocitySSTI.java:69:17:69:44 | getParameter(...) : String | VelocitySSTI.java:77:21:77:27 | context |
+| VelocitySSTI.java:83:17:83:44 | getParameter(...) : String | VelocitySSTI.java:89:60:89:66 | context |
+| VelocitySSTI.java:95:17:95:44 | getParameter(...) : String | VelocitySSTI.java:102:11:102:17 | context |
+| VelocitySSTI.java:108:17:108:44 | getParameter(...) : String | VelocitySSTI.java:115:11:115:17 | context |
+| VelocitySSTI.java:120:17:120:44 | getParameter(...) : String | VelocitySSTI.java:123:37:123:40 | code |
+nodes
+| FreemarkerSSTI.java:23:17:23:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| FreemarkerSSTI.java:24:19:24:40 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader |
+| FreemarkerSSTI.java:24:36:24:39 | code : String | semmle.label | code : String |
+| FreemarkerSSTI.java:27:35:27:40 | reader | semmle.label | reader |
+| FreemarkerSSTI.java:33:17:33:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| FreemarkerSSTI.java:34:19:34:40 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader |
+| FreemarkerSSTI.java:34:36:34:39 | code : String | semmle.label | code : String |
+| FreemarkerSSTI.java:38:35:38:40 | reader | semmle.label | reader |
+| FreemarkerSSTI.java:44:17:44:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| FreemarkerSSTI.java:45:19:45:40 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader |
+| FreemarkerSSTI.java:45:36:45:39 | code : String | semmle.label | code : String |
+| FreemarkerSSTI.java:50:35:50:40 | reader | semmle.label | reader |
+| FreemarkerSSTI.java:56:23:56:56 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| FreemarkerSSTI.java:61:35:61:44 | sourceCode | semmle.label | sourceCode |
+| FreemarkerSSTI.java:67:17:67:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| FreemarkerSSTI.java:69:19:69:40 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader |
+| FreemarkerSSTI.java:69:36:69:39 | code : String | semmle.label | code : String |
+| FreemarkerSSTI.java:73:47:73:52 | reader | semmle.label | reader |
+| FreemarkerSSTI.java:79:17:79:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| FreemarkerSSTI.java:82:19:82:40 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader |
+| FreemarkerSSTI.java:82:36:82:39 | code : String | semmle.label | code : String |
+| FreemarkerSSTI.java:87:47:87:52 | reader | semmle.label | reader |
+| FreemarkerSSTI.java:93:17:93:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| FreemarkerSSTI.java:96:19:96:40 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader |
+| FreemarkerSSTI.java:96:36:96:39 | code : String | semmle.label | code : String |
+| FreemarkerSSTI.java:100:47:100:52 | reader | semmle.label | reader |
+| FreemarkerSSTI.java:105:17:105:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| FreemarkerSSTI.java:109:42:109:45 | code | semmle.label | code |
+| FreemarkerSSTI.java:114:17:114:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| FreemarkerSSTI.java:119:42:119:45 | code | semmle.label | code |
+| FreemarkerSSTI.java:125:17:125:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| FreemarkerSSTI.java:126:9:126:12 | root [post update] [] : String | semmle.label | root [post update] [] : String |
+| FreemarkerSSTI.java:126:26:126:29 | code : String | semmle.label | code : String |
+| FreemarkerSSTI.java:130:22:130:25 | root | semmle.label | root |
+| JinJavaSSTI.java:21:21:21:52 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| JinJavaSSTI.java:25:44:25:51 | template | semmle.label | template |
+| JinJavaSSTI.java:30:21:30:52 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| JinJavaSSTI.java:34:55:34:62 | template | semmle.label | template |
+| JinJavaSSTI.java:39:21:39:52 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| JinJavaSSTI.java:46:55:46:62 | template | semmle.label | template |
+| PebbleSSTI.java:18:17:18:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| PebbleSSTI.java:21:56:21:59 | code | semmle.label | code |
+| PebbleSSTI.java:25:17:25:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| PebbleSSTI.java:28:63:28:66 | code | semmle.label | code |
+| ThymeleafSSTI.java:22:17:22:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| ThymeleafSSTI.java:27:27:27:30 | code | semmle.label | code |
+| VelocitySSTI.java:31:17:31:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| VelocitySSTI.java:38:45:38:48 | code | semmle.label | code |
+| VelocitySSTI.java:44:17:44:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| VelocitySSTI.java:50:25:50:46 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader |
+| VelocitySSTI.java:50:42:50:45 | code : String | semmle.label | code : String |
+| VelocitySSTI.java:53:45:53:50 | reader | semmle.label | reader |
+| VelocitySSTI.java:59:17:59:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| VelocitySSTI.java:62:25:62:46 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader |
+| VelocitySSTI.java:62:42:62:45 | code : String | semmle.label | code : String |
+| VelocitySSTI.java:63:25:63:30 | reader | semmle.label | reader |
+| VelocitySSTI.java:69:17:69:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| VelocitySSTI.java:77:21:77:27 | context | semmle.label | context |
+| VelocitySSTI.java:83:17:83:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| VelocitySSTI.java:89:60:89:66 | context | semmle.label | context |
+| VelocitySSTI.java:95:17:95:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| VelocitySSTI.java:102:11:102:17 | context | semmle.label | context |
+| VelocitySSTI.java:108:17:108:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| VelocitySSTI.java:115:11:115:17 | context | semmle.label | context |
+| VelocitySSTI.java:120:17:120:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| VelocitySSTI.java:123:37:123:40 | code | semmle.label | code |
+subpaths
+#select
| FreemarkerSSTI.java:27:35:27:40 | reader | FreemarkerSSTI.java:23:17:23:44 | getParameter(...) : String | FreemarkerSSTI.java:27:35:27:40 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:23:17:23:44 | getParameter(...) | a template value loaded from a remote source. |
| FreemarkerSSTI.java:38:35:38:40 | reader | FreemarkerSSTI.java:33:17:33:44 | getParameter(...) : String | FreemarkerSSTI.java:38:35:38:40 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:33:17:33:44 | getParameter(...) | a template value loaded from a remote source. |
| FreemarkerSSTI.java:50:35:50:40 | reader | FreemarkerSSTI.java:44:17:44:44 | getParameter(...) : String | FreemarkerSSTI.java:50:35:50:40 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:44:17:44:44 | getParameter(...) | a template value loaded from a remote source. |