From 91edde72c4855491edc1593ffdd02c675ee0ffb4 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 17 Aug 2023 11:51:00 +0200 Subject: [PATCH] Python: Port `py/template-injection` to new data-flow I kept all the modeling in _one_ file, since that makes it easy to work with such an external contribution... and I would certainly propose this file setup for the future :+1: --- .../CWE-074/TemplateConstructionConcept.qll | 159 ++++++++++++++++++ .../Security/CWE-074/TemplateInjection.ql | 27 +-- .../TemplateInjectionCustomizations.qll | 51 ++++++ .../CWE-074/TemplateInjectionQuery.qll | 18 ++ .../semmle/python/templates/Airspeed.qll | 27 --- .../semmle/python/templates/Bottle.qll | 48 ------ .../semmle/python/templates/Chameleon.qll | 29 ---- .../semmle/python/templates/Cheetah.qll | 39 ----- .../semmle/python/templates/Chevron.qll | 36 ---- .../python/templates/DjangoTemplate.qll | 35 ---- .../semmle/python/templates/FlaskTemplate.qll | 28 --- .../semmle/python/templates/Genshi.qll | 53 ------ .../semmle/python/templates/Jinja.qll | 49 ------ .../semmle/python/templates/Mako.qll | 27 --- .../semmle/python/templates/SSTISink.qll | 7 - .../semmle/python/templates/Ssti.qll | 13 -- .../semmle/python/templates/TRender.qll | 27 --- .../CWE-074/TemplateInjection.expected | 144 +++++++++------- .../query-tests/Security/CWE-074/options | 1 - 19 files changed, 320 insertions(+), 498 deletions(-) create mode 100644 python/ql/src/experimental/Security/CWE-074/TemplateConstructionConcept.qll create mode 100644 python/ql/src/experimental/Security/CWE-074/TemplateInjectionCustomizations.qll create mode 100644 python/ql/src/experimental/Security/CWE-074/TemplateInjectionQuery.qll delete mode 100644 python/ql/src/experimental/semmle/python/templates/Airspeed.qll delete mode 100644 python/ql/src/experimental/semmle/python/templates/Bottle.qll delete mode 100644 python/ql/src/experimental/semmle/python/templates/Chameleon.qll delete mode 100644 python/ql/src/experimental/semmle/python/templates/Cheetah.qll delete mode 100644 python/ql/src/experimental/semmle/python/templates/Chevron.qll delete mode 100644 python/ql/src/experimental/semmle/python/templates/DjangoTemplate.qll delete mode 100644 python/ql/src/experimental/semmle/python/templates/FlaskTemplate.qll delete mode 100644 python/ql/src/experimental/semmle/python/templates/Genshi.qll delete mode 100644 python/ql/src/experimental/semmle/python/templates/Jinja.qll delete mode 100644 python/ql/src/experimental/semmle/python/templates/Mako.qll delete mode 100644 python/ql/src/experimental/semmle/python/templates/SSTISink.qll delete mode 100644 python/ql/src/experimental/semmle/python/templates/Ssti.qll delete mode 100644 python/ql/src/experimental/semmle/python/templates/TRender.qll delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-074/options diff --git a/python/ql/src/experimental/Security/CWE-074/TemplateConstructionConcept.qll b/python/ql/src/experimental/Security/CWE-074/TemplateConstructionConcept.qll new file mode 100644 index 00000000000..a20babf15eb --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-074/TemplateConstructionConcept.qll @@ -0,0 +1,159 @@ +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.ApiGraphs + +/** + * A data-flow node that constructs a template. + * + * Extend this class to refine existing API models. If you want to model new APIs, + * extend `TemplateConstruction::Range` instead. + */ +class TemplateConstruction extends DataFlow::Node instanceof TemplateConstruction::Range { + /** Gets the argument that specifies the template source. */ + DataFlow::Node getSourceArg() { result = super.getSourceArg() } +} + +/** Provides a class for modeling new system-command execution APIs. */ +module TemplateConstruction { + /** + * A data-flow node that constructs a template. + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `TemplateConstruction` instead. + */ + abstract class Range extends DataFlow::Node { + /** Gets the argument that specifies the template source. */ + abstract DataFlow::Node getSourceArg(); + } +} + +// ----------------------------------------------------------------------------- +/** A call to `airspeed.Template`. */ +class AirspeedTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + AirspeedTemplateConstruction() { + this = API::moduleImport("airspeed").getMember("Template").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `bottle.SimpleTemplate`. */ +class BottleSimpleTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + BottleSimpleTemplateConstruction() { + this = API::moduleImport("bottle").getMember("SimpleTemplate").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `bottle.template`. */ +class BottleTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + BottleTemplateConstruction() { + this = API::moduleImport("bottle").getMember("template").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `chameleon.PageTemplate`. */ +class ChameleonTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + ChameleonTemplateConstruction() { + this = API::moduleImport("chameleon").getMember("PageTemplate").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `Cheetah.Template.Template`. */ +class CheetahTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + CheetahTemplateConstruction() { + this = + API::moduleImport("Cheetah") + .getMember("Template") + .getMember("Template") + .getASubclass*() + .getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `chevron.render`. */ +class ChevronRenderConstruction extends TemplateConstruction::Range, API::CallNode { + ChevronRenderConstruction() { this = API::moduleImport("chevron").getMember("render").getACall() } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `django.template.Template` */ +class DjangoTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + DjangoTemplateConstruction() { + this = API::moduleImport("django").getMember("template").getMember("Template").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +// TODO: support django.template.engines["django"]].from_string +/** A call to `flask.render_template_string`. */ +class FlaskTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + FlaskTemplateConstruction() { + this = API::moduleImport("flask").getMember("render_template_string").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `genshi.template.TextTemplate`. */ +class GenshiTextTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + GenshiTextTemplateConstruction() { + this = API::moduleImport("genshi").getMember("template").getMember("TextTemplate").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `genshi.template.MarkupTemplate` */ +class GenshiMarkupTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + GenshiMarkupTemplateConstruction() { + this = API::moduleImport("genshi").getMember("template").getMember("MarkupTemplate").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `jinja2.Template`. */ +class Jinja2TemplateConstruction extends TemplateConstruction::Range, API::CallNode { + Jinja2TemplateConstruction() { + this = API::moduleImport("jinja2").getMember("Template").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `jinja2.from_string`. */ +class Jinja2FromStringConstruction extends TemplateConstruction::Range, API::CallNode { + Jinja2FromStringConstruction() { + this = API::moduleImport("jinja2").getMember("from_string").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `mako.template.Template`. */ +class MakoTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + MakoTemplateConstruction() { + this = API::moduleImport("mako").getMember("template").getMember("Template").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} + +/** A call to `trender.TRender`. */ +class TRenderTemplateConstruction extends TemplateConstruction::Range, API::CallNode { + TRenderTemplateConstruction() { + this = API::moduleImport("trender").getMember("TRender").getACall() + } + + override DataFlow::Node getSourceArg() { result = this.getArg(0) } +} diff --git a/python/ql/src/experimental/Security/CWE-074/TemplateInjection.ql b/python/ql/src/experimental/Security/CWE-074/TemplateInjection.ql index cbc3536ad7d..a10ad09a6ac 100644 --- a/python/ql/src/experimental/Security/CWE-074/TemplateInjection.ql +++ b/python/ql/src/experimental/Security/CWE-074/TemplateInjection.ql @@ -11,25 +11,10 @@ */ import python -import semmle.python.security.Paths -/* Sources */ -import semmle.python.web.HttpRequest -/* Sinks */ -import experimental.semmle.python.templates.Ssti -/* Flow */ -import semmle.python.security.strings.Untrusted +import TemplateInjectionQuery +import TemplateInjectionFlow::PathGraph -class TemplateInjectionConfiguration extends TaintTracking::Configuration { - TemplateInjectionConfiguration() { this = "Template injection configuration" } - - deprecated override predicate isSource(TaintTracking::Source source) { - source instanceof HttpRequestTaintSource - } - - deprecated override predicate isSink(TaintTracking::Sink sink) { sink instanceof SSTISink } -} - -from TemplateInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink -where config.hasFlowPath(src, sink) -select sink.getSink(), src, sink, "This Template depends on $@.", src.getSource(), - "a user-provided value" +from TemplateInjectionFlow::PathNode source, TemplateInjectionFlow::PathNode sink +where TemplateInjectionFlow::flowPath(source, sink) +select sink.getNode(), source, sink, "This Template depends on $@.", source.getNode(), + "user-provided value" diff --git a/python/ql/src/experimental/Security/CWE-074/TemplateInjectionCustomizations.qll b/python/ql/src/experimental/Security/CWE-074/TemplateInjectionCustomizations.qll new file mode 100644 index 00000000000..84d1a407c5f --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-074/TemplateInjectionCustomizations.qll @@ -0,0 +1,51 @@ +/** + * Provides default sources, sinks and sanitizers for detecting + * "template injection" + * vulnerabilities, as well as extension points for adding your own. + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.Concepts +private import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.dataflow.new.BarrierGuards +private import TemplateConstructionConcept + +/** + * Provides default sources, sinks and sanitizers for detecting + * "template injection" + * vulnerabilities, as well as extension points for adding your own. + */ +module SqlInjection { + /** + * A data flow source for "template injection" vulnerabilities. + */ + abstract class Source extends DataFlow::Node { } + + /** + * A data flow sink for "template injection" vulnerabilities. + */ + abstract class Sink extends DataFlow::Node { } + + /** + * A sanitizer for "template injection" vulnerabilities. + */ + abstract class Sanitizer extends DataFlow::Node { } + + /** + * A source of remote user input, considered as a flow source. + */ + class RemoteFlowSourceAsSource extends Source, RemoteFlowSource { } + + /** + * A SQL statement of a SQL construction, considered as a flow sink. + */ + class TemplateConstructionAsSink extends Sink { + TemplateConstructionAsSink() { this = any(TemplateConstruction c).getSourceArg() } + } + + /** + * A comparison with a constant string, considered as a sanitizer-guard. + */ + class StringConstCompareAsSanitizerGuard extends Sanitizer, StringConstCompareBarrier { } +} diff --git a/python/ql/src/experimental/Security/CWE-074/TemplateInjectionQuery.qll b/python/ql/src/experimental/Security/CWE-074/TemplateInjectionQuery.qll new file mode 100644 index 00000000000..855dac0d80c --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-074/TemplateInjectionQuery.qll @@ -0,0 +1,18 @@ +/** + * Provides a taint-tracking configuration for detecting "template injection" vulnerabilities. + */ + +private import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import TemplateInjectionCustomizations::SqlInjection + +module TemplateInjectionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node instanceof Source } + + predicate isSink(DataFlow::Node node) { node instanceof Sink } + + predicate isBarrierIn(DataFlow::Node node) { node instanceof Sanitizer } +} + +module TemplateInjectionFlow = TaintTracking::Global; diff --git a/python/ql/src/experimental/semmle/python/templates/Airspeed.qll b/python/ql/src/experimental/semmle/python/templates/Airspeed.qll deleted file mode 100644 index dc266ac0f82..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/Airspeed.qll +++ /dev/null @@ -1,27 +0,0 @@ -/** Provides classes which model the `airspeed` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -/** returns the ClassValue representing `airspeed.Template` */ -deprecated ClassValue theAirspeedTemplateClass() { result = Value::named("airspeed.Template") } - -/** - * A sink representing the `airspeed.Template` class instantiation argument. - * - * import airspeed - * temp = airspeed.Template(`"sink"`) - */ -deprecated class AirspeedTemplateSink extends SSTISink { - override string toString() { result = "argument to airspeed.Template()" } - - AirspeedTemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theAirspeedTemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/experimental/semmle/python/templates/Bottle.qll b/python/ql/src/experimental/semmle/python/templates/Bottle.qll deleted file mode 100644 index 1f5bd2bba85..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/Bottle.qll +++ /dev/null @@ -1,48 +0,0 @@ -/** Provides classes which model the `bottle` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -/** returns the ClassValue representing `bottle.SimpleTemplate` */ -deprecated ClassValue theBottleSimpleTemplateClass() { - result = Value::named("bottle.SimpleTemplate") -} - -/** - * A sink representing the `bottle.SimpleTemplate` class instantiation argument. - * - * from bottle import SimpleTemplate - * template = SimpleTemplate(`sink`) - */ -deprecated class BottleSimpleTemplateSink extends SSTISink { - override string toString() { result = "argument to bottle.SimpleTemplate()" } - - BottleSimpleTemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theBottleSimpleTemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} - -/** - * A sink representing the `bottle.template` function call argument. - * - * from bottle import template - * tmp = template(`sink`) - */ -deprecated class BottleTemplateSink extends SSTISink { - override string toString() { result = "argument to bottle.template()" } - - BottleTemplateSink() { - exists(CallNode call | - call.getFunction() = theBottleModule().attr("template").getAReference() and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/experimental/semmle/python/templates/Chameleon.qll b/python/ql/src/experimental/semmle/python/templates/Chameleon.qll deleted file mode 100644 index f094dda97b5..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/Chameleon.qll +++ /dev/null @@ -1,29 +0,0 @@ -/** Provides classes which model the `Chameleon` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -/** returns the ClassValue representing `chameleon.PageTemplate` */ -deprecated ClassValue theChameleonPageTemplateClass() { - result = Value::named("chameleon.PageTemplate") -} - -/** - * A sink representing the `chameleon.PageTemplate` class instantiation argument. - * - * from chameleon import PageTemplate - * template = PageTemplate(`sink`) - */ -deprecated class ChameleonTemplateSink extends SSTISink { - override string toString() { result = "argument to Chameleon.PageTemplate()" } - - ChameleonTemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theChameleonPageTemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/experimental/semmle/python/templates/Cheetah.qll b/python/ql/src/experimental/semmle/python/templates/Cheetah.qll deleted file mode 100644 index 9812fdb7c88..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/Cheetah.qll +++ /dev/null @@ -1,39 +0,0 @@ -/** Provides classes which model the `Cheetah3` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -/** returns the ClassValue representing `Cheetah.Template.Template` */ -deprecated ClassValue theCheetahTemplateClass() { - result = Value::named("Cheetah.Template.Template") -} - -/** - * A sink representing the instantiation argument of any class which derives from - * the `Cheetah.Template.Template` class . - * - * from Cheetah.Template import Template - * class Template3(Template): - * title = 'Hello World Example!' - * contents = 'Hello World!' - * t3 = Template3("sink") - * - * This will also detect cases of the following type : - * - * from Cheetah.Template import Template - * t3 = Template("sink") - */ -deprecated class CheetahTemplateInstantiationSink extends SSTISink { - override string toString() { result = "argument to Cheetah.Template.Template()" } - - CheetahTemplateInstantiationSink() { - exists(CallNode call, ClassValue cv | - cv.getASuperType() = theCheetahTemplateClass() and - call.getFunction().pointsTo(cv) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/experimental/semmle/python/templates/Chevron.qll b/python/ql/src/experimental/semmle/python/templates/Chevron.qll deleted file mode 100644 index cc93016891c..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/Chevron.qll +++ /dev/null @@ -1,36 +0,0 @@ -/** Provides classes which model the `chevron` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -/** returns the Value representing `chevron.render` function */ -deprecated Value theChevronRenderFunc() { result = Value::named("chevron.render") } - -/** - * A sink representing the `chevron.render` function call argument. - * - * import chevron - * tmp = chevron.render(`sink`,{ 'key' : 'value' }) - */ -deprecated class ChevronRenderSink extends SSTISink { - override string toString() { result = "argument to chevron.render()" } - - ChevronRenderSink() { - exists(CallNode call | - call.getFunction() = theChevronRenderFunc().getAReference() and - call.getArg(0) = this - ) - // TODO: this should also detect : - // import chevron - // args = { - // 'template': 'sink', - // 'data': { - // 'mustache': 'World' - // } - // } - // chevron.render(**args) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/experimental/semmle/python/templates/DjangoTemplate.qll b/python/ql/src/experimental/semmle/python/templates/DjangoTemplate.qll deleted file mode 100644 index 1089ab872ec..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/DjangoTemplate.qll +++ /dev/null @@ -1,35 +0,0 @@ -/** Provides classes which model the `DjangoTemplate` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -deprecated ClassValue theDjangoTemplateClass() { result = Value::named("django.template.Template") } - -/** - * A sink representing `django.template.Template` class instantiation argument. - * - * from django.template import Template - * template = Template(`sink`) - */ -deprecated class DjangoTemplateTemplateSink extends SSTISink { - override string toString() { result = "argument to Django.template()" } - - DjangoTemplateTemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theDjangoTemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} -// TODO (intentionally commented out QLDoc, since qlformat will delete those lines otherwise) -// /** -// * Sinks representing the django.template.Template class instantiation. -// * -// * from django.template import engines -// * -// * django_engine = engines["django"] -// * template = django_engine.from_string(`sink`) -// */ diff --git a/python/ql/src/experimental/semmle/python/templates/FlaskTemplate.qll b/python/ql/src/experimental/semmle/python/templates/FlaskTemplate.qll deleted file mode 100644 index c0f3c90235d..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/FlaskTemplate.qll +++ /dev/null @@ -1,28 +0,0 @@ -/** Provides classes which model templates in the`flask` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -deprecated Value theFlaskRenderTemplateClass() { - result = Value::named("flask.render_template_string") -} - -/** - * A sink representing `flask.render_template_string` function call argument. - * - * from flask import render_template_string - * render_template_string(`sink`) - */ -deprecated class FlaskTemplateSink extends SSTISink { - override string toString() { result = "argument to flask.render_template_string()" } - - FlaskTemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theFlaskRenderTemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/experimental/semmle/python/templates/Genshi.qll b/python/ql/src/experimental/semmle/python/templates/Genshi.qll deleted file mode 100644 index c808d7c60f8..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/Genshi.qll +++ /dev/null @@ -1,53 +0,0 @@ -/** Provides classes which model the `Genshi` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -/** returns the ClassValue representing `Genshi.template.TextTemplate` */ -deprecated ClassValue theGenshiTextTemplateClass() { - result = Value::named("genshi.template.TextTemplate") -} - -/** returns the ClassValue representing `Genshi.template.MarkupTemplate` */ -deprecated ClassValue theGenshiMarkupTemplateClass() { - result = Value::named("genshi.template.MarkupTemplate") -} - -/** - * A sink representing the `genshi.template.TextTemplate` class instantiation argument. - * - * from genshi.template import TextTemplate - * tmpl = TextTemplate('sink') - */ -deprecated class GenshiTextTemplateSink extends SSTISink { - override string toString() { result = "argument to genshi.template.TextTemplate()" } - - GenshiTextTemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theGenshiTextTemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} - -/** - * A sink representing the `genshi.template.MarkupTemplate` class instantiation argument. - * - * from genshi.template import MarkupTemplate - * tmpl = MarkupTemplate('sink') - */ -deprecated class GenshiMarkupTemplateSink extends SSTISink { - override string toString() { result = "argument to genshi.template.MarkupTemplate()" } - - GenshiMarkupTemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theGenshiMarkupTemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/experimental/semmle/python/templates/Jinja.qll b/python/ql/src/experimental/semmle/python/templates/Jinja.qll deleted file mode 100644 index 44bc103cf04..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/Jinja.qll +++ /dev/null @@ -1,49 +0,0 @@ -/** Provides classes which model the `Jinja2` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -/** returns the ClassValue representing `jinja2.Template` */ -deprecated ClassValue theJinja2TemplateClass() { result = Value::named("jinja2.Template") } - -/** returns the ClassValue representing `jinja2.Template` */ -deprecated Value theJinja2FromStringValue() { result = Value::named("jinja2.from_string") } - -/** - * A sink representing the `jinja2.Template` class instantiation argument. - * - * from jinja2 import Template - * template = Template(`sink`) - */ -deprecated class Jinja2TemplateSink extends SSTISink { - override string toString() { result = "argument to jinja2.Template()" } - - Jinja2TemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theJinja2TemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} - -/** - * A sink representing the `jinja2.from_string` function call argument. - * - * from jinja2 import from_string - * template = from_string(`sink`) - */ -deprecated class Jinja2FromStringSink extends SSTISink { - override string toString() { result = "argument to jinja2.from_string()" } - - Jinja2FromStringSink() { - exists(CallNode call | - call.getFunction().pointsTo(theJinja2FromStringValue()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/experimental/semmle/python/templates/Mako.qll b/python/ql/src/experimental/semmle/python/templates/Mako.qll deleted file mode 100644 index b8634b3001a..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/Mako.qll +++ /dev/null @@ -1,27 +0,0 @@ -/** Provides classes which model the `Mako` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -/** returns the ClassValue representing `mako.template.Template` */ -deprecated ClassValue theMakoTemplateClass() { result = Value::named("mako.template.Template") } - -/** - * A sink representing the `mako.template.Template` class instantiation argument. - * - * from mako.template import Template - * mytemplate = Template("hello world!") - */ -deprecated class MakoTemplateSink extends SSTISink { - override string toString() { result = "argument to mako.template.Template()" } - - MakoTemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theMakoTemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/src/experimental/semmle/python/templates/SSTISink.qll b/python/ql/src/experimental/semmle/python/templates/SSTISink.qll deleted file mode 100644 index 1a68fe17b68..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/SSTISink.qll +++ /dev/null @@ -1,7 +0,0 @@ -import semmle.python.dataflow.TaintTracking - -/** - * A generic taint sink that is vulnerable to template inclusions. - * The `temp` in `jinja2.Template(temp)` and similar. - */ -abstract deprecated class SSTISink extends TaintSink { } diff --git a/python/ql/src/experimental/semmle/python/templates/Ssti.qll b/python/ql/src/experimental/semmle/python/templates/Ssti.qll deleted file mode 100644 index eb4f8d0ec2f..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/Ssti.qll +++ /dev/null @@ -1,13 +0,0 @@ -/** Imports all files which model potential SSTI sinks */ - -import experimental.semmle.python.templates.Airspeed -import experimental.semmle.python.templates.Bottle -import experimental.semmle.python.templates.Chameleon -import experimental.semmle.python.templates.Cheetah -import experimental.semmle.python.templates.Chevron -import experimental.semmle.python.templates.DjangoTemplate -import experimental.semmle.python.templates.FlaskTemplate -import experimental.semmle.python.templates.Genshi -import experimental.semmle.python.templates.Jinja -import experimental.semmle.python.templates.Mako -import experimental.semmle.python.templates.TRender diff --git a/python/ql/src/experimental/semmle/python/templates/TRender.qll b/python/ql/src/experimental/semmle/python/templates/TRender.qll deleted file mode 100644 index 8d5431ad9e0..00000000000 --- a/python/ql/src/experimental/semmle/python/templates/TRender.qll +++ /dev/null @@ -1,27 +0,0 @@ -/** Provides classes which model the `TRender` package. */ - -import python -import semmle.python.web.HttpRequest -import experimental.semmle.python.templates.SSTISink - -/** returns the ClassValue representing `trender.TRender` */ -deprecated ClassValue theTRenderTemplateClass() { result = Value::named("trender.TRender") } - -/** - * A sink representing the `trender.TRender` class instantiation argument. - * - * from trender import TRender - * template = TRender(`sink`) - */ -deprecated class TRenderTemplateSink extends SSTISink { - override string toString() { result = "argument to trender.TRender()" } - - TRenderTemplateSink() { - exists(CallNode call | - call.getFunction().pointsTo(theTRenderTemplateClass()) and - call.getArg(0) = this - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } -} diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/TemplateInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-074/TemplateInjection.expected index 058a53bdf91..188aec4c024 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-074/TemplateInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-074/TemplateInjection.expected @@ -1,60 +1,88 @@ edges -| AirspeedSsti.py:10:16:10:27 | dict of externally controlled string | AirspeedSsti.py:10:16:10:43 | externally controlled string | -| AirspeedSsti.py:10:16:10:27 | dict of externally controlled string | AirspeedSsti.py:10:16:10:43 | externally controlled string | -| AirspeedSsti.py:10:16:10:43 | externally controlled string | AirspeedSsti.py:11:30:11:37 | externally controlled string | -| AirspeedSsti.py:10:16:10:43 | externally controlled string | AirspeedSsti.py:11:30:11:37 | externally controlled string | -| ChevronSsti.py:10:16:10:27 | dict of externally controlled string | ChevronSsti.py:10:16:10:43 | externally controlled string | -| ChevronSsti.py:10:16:10:27 | dict of externally controlled string | ChevronSsti.py:10:16:10:43 | externally controlled string | -| ChevronSsti.py:10:16:10:43 | externally controlled string | ChevronSsti.py:11:27:11:34 | externally controlled string | -| ChevronSsti.py:10:16:10:43 | externally controlled string | ChevronSsti.py:11:27:11:34 | externally controlled string | -| DjangoTemplates.py:6:8:6:14 | django.request.HttpRequest | DjangoTemplates.py:8:16:8:22 | django.request.HttpRequest | -| DjangoTemplates.py:6:8:6:14 | django.request.HttpRequest | DjangoTemplates.py:8:16:8:22 | django.request.HttpRequest | -| DjangoTemplates.py:8:16:8:22 | django.request.HttpRequest | DjangoTemplates.py:8:16:8:26 | django.http.request.QueryDict | -| DjangoTemplates.py:8:16:8:22 | django.request.HttpRequest | DjangoTemplates.py:8:16:8:26 | django.http.request.QueryDict | -| DjangoTemplates.py:8:16:8:26 | django.http.request.QueryDict | DjangoTemplates.py:8:16:8:38 | externally controlled string | -| DjangoTemplates.py:8:16:8:26 | django.http.request.QueryDict | DjangoTemplates.py:8:16:8:38 | externally controlled string | -| DjangoTemplates.py:8:16:8:38 | externally controlled string | DjangoTemplates.py:9:18:9:25 | externally controlled string | -| DjangoTemplates.py:8:16:8:38 | externally controlled string | DjangoTemplates.py:9:18:9:25 | externally controlled string | -| FlaskTemplate.py:17:41:17:52 | dict of externally controlled string | FlaskTemplate.py:17:41:17:68 | externally controlled string | -| FlaskTemplate.py:17:41:17:52 | dict of externally controlled string | FlaskTemplate.py:17:41:17:68 | externally controlled string | -| JinjaSsti.py:7:7:7:13 | django.request.HttpRequest | JinjaSsti.py:9:16:9:22 | django.request.HttpRequest | -| JinjaSsti.py:7:7:7:13 | django.request.HttpRequest | JinjaSsti.py:9:16:9:22 | django.request.HttpRequest | -| JinjaSsti.py:9:16:9:22 | django.request.HttpRequest | JinjaSsti.py:9:16:9:26 | django.http.request.QueryDict | -| JinjaSsti.py:9:16:9:22 | django.request.HttpRequest | JinjaSsti.py:9:16:9:26 | django.http.request.QueryDict | -| JinjaSsti.py:9:16:9:26 | django.http.request.QueryDict | JinjaSsti.py:9:16:9:38 | externally controlled string | -| JinjaSsti.py:9:16:9:26 | django.http.request.QueryDict | JinjaSsti.py:9:16:9:38 | externally controlled string | -| JinjaSsti.py:9:16:9:38 | externally controlled string | JinjaSsti.py:10:25:10:32 | externally controlled string | -| JinjaSsti.py:9:16:9:38 | externally controlled string | JinjaSsti.py:10:25:10:32 | externally controlled string | -| JinjaSsti.py:16:7:16:13 | django.request.HttpRequest | JinjaSsti.py:19:16:19:22 | django.request.HttpRequest | -| JinjaSsti.py:16:7:16:13 | django.request.HttpRequest | JinjaSsti.py:19:16:19:22 | django.request.HttpRequest | -| JinjaSsti.py:19:16:19:22 | django.request.HttpRequest | JinjaSsti.py:19:16:19:26 | django.http.request.QueryDict | -| JinjaSsti.py:19:16:19:22 | django.request.HttpRequest | JinjaSsti.py:19:16:19:26 | django.http.request.QueryDict | -| JinjaSsti.py:19:16:19:26 | django.http.request.QueryDict | JinjaSsti.py:19:16:19:38 | externally controlled string | -| JinjaSsti.py:19:16:19:26 | django.http.request.QueryDict | JinjaSsti.py:19:16:19:38 | externally controlled string | -| JinjaSsti.py:19:16:19:38 | externally controlled string | JinjaSsti.py:20:28:20:35 | externally controlled string | -| JinjaSsti.py:19:16:19:38 | externally controlled string | JinjaSsti.py:20:28:20:35 | externally controlled string | -| MakoSsti.py:6:10:6:16 | django.request.HttpRequest | MakoSsti.py:8:16:8:22 | django.request.HttpRequest | -| MakoSsti.py:6:10:6:16 | django.request.HttpRequest | MakoSsti.py:8:16:8:22 | django.request.HttpRequest | -| MakoSsti.py:8:16:8:22 | django.request.HttpRequest | MakoSsti.py:8:16:8:26 | django.http.request.QueryDict | -| MakoSsti.py:8:16:8:22 | django.request.HttpRequest | MakoSsti.py:8:16:8:26 | django.http.request.QueryDict | -| MakoSsti.py:8:16:8:26 | django.http.request.QueryDict | MakoSsti.py:8:16:8:38 | externally controlled string | -| MakoSsti.py:8:16:8:26 | django.http.request.QueryDict | MakoSsti.py:8:16:8:38 | externally controlled string | -| MakoSsti.py:8:16:8:38 | externally controlled string | MakoSsti.py:9:27:9:34 | externally controlled string | -| MakoSsti.py:8:16:8:38 | externally controlled string | MakoSsti.py:9:27:9:34 | externally controlled string | -| TRender.py:5:13:5:19 | django.request.HttpRequest | TRender.py:6:16:6:22 | django.request.HttpRequest | -| TRender.py:5:13:5:19 | django.request.HttpRequest | TRender.py:6:16:6:22 | django.request.HttpRequest | -| TRender.py:6:16:6:22 | django.request.HttpRequest | TRender.py:6:16:6:26 | django.http.request.QueryDict | -| TRender.py:6:16:6:22 | django.request.HttpRequest | TRender.py:6:16:6:26 | django.http.request.QueryDict | -| TRender.py:6:16:6:26 | django.http.request.QueryDict | TRender.py:6:16:6:38 | externally controlled string | -| TRender.py:6:16:6:26 | django.http.request.QueryDict | TRender.py:6:16:6:38 | externally controlled string | -| TRender.py:6:16:6:38 | externally controlled string | TRender.py:7:24:7:31 | externally controlled string | -| TRender.py:6:16:6:38 | externally controlled string | TRender.py:7:24:7:31 | externally controlled string | +| AirspeedSsti.py:2:26:2:32 | ControlFlowNode for ImportMember | AirspeedSsti.py:2:26:2:32 | GSSA Variable request | +| AirspeedSsti.py:2:26:2:32 | GSSA Variable request | AirspeedSsti.py:10:16:10:22 | ControlFlowNode for request | +| AirspeedSsti.py:10:16:10:22 | ControlFlowNode for request | AirspeedSsti.py:10:16:10:27 | ControlFlowNode for Attribute | +| AirspeedSsti.py:10:16:10:27 | ControlFlowNode for Attribute | AirspeedSsti.py:10:16:10:43 | ControlFlowNode for Attribute() | +| AirspeedSsti.py:10:16:10:43 | ControlFlowNode for Attribute() | AirspeedSsti.py:11:30:11:37 | ControlFlowNode for template | +| ChevronSsti.py:1:26:1:32 | ControlFlowNode for ImportMember | ChevronSsti.py:1:26:1:32 | GSSA Variable request | +| ChevronSsti.py:1:26:1:32 | GSSA Variable request | ChevronSsti.py:10:16:10:22 | ControlFlowNode for request | +| ChevronSsti.py:10:16:10:22 | ControlFlowNode for request | ChevronSsti.py:10:16:10:27 | ControlFlowNode for Attribute | +| ChevronSsti.py:10:16:10:27 | ControlFlowNode for Attribute | ChevronSsti.py:10:16:10:43 | ControlFlowNode for Attribute() | +| ChevronSsti.py:10:16:10:43 | ControlFlowNode for Attribute() | ChevronSsti.py:11:27:11:34 | ControlFlowNode for template | +| DjangoTemplates.py:6:8:6:14 | ControlFlowNode for request | DjangoTemplates.py:8:16:8:26 | ControlFlowNode for Attribute | +| DjangoTemplates.py:8:16:8:26 | ControlFlowNode for Attribute | DjangoTemplates.py:8:16:8:38 | ControlFlowNode for Subscript | +| DjangoTemplates.py:8:16:8:38 | ControlFlowNode for Subscript | DjangoTemplates.py:9:18:9:25 | ControlFlowNode for template | +| FlaskTemplate.py:1:26:1:32 | ControlFlowNode for ImportMember | FlaskTemplate.py:1:26:1:32 | GSSA Variable request | +| FlaskTemplate.py:1:26:1:32 | GSSA Variable request | FlaskTemplate.py:10:8:10:14 | ControlFlowNode for request | +| FlaskTemplate.py:1:26:1:32 | GSSA Variable request | FlaskTemplate.py:11:39:11:45 | ControlFlowNode for request | +| FlaskTemplate.py:1:26:1:32 | GSSA Variable request | FlaskTemplate.py:17:41:17:47 | ControlFlowNode for request | +| FlaskTemplate.py:10:8:10:14 | ControlFlowNode for request | FlaskTemplate.py:11:39:11:50 | ControlFlowNode for Attribute | +| FlaskTemplate.py:11:39:11:45 | ControlFlowNode for request | FlaskTemplate.py:11:39:11:50 | ControlFlowNode for Attribute | +| FlaskTemplate.py:11:39:11:50 | ControlFlowNode for Attribute | FlaskTemplate.py:11:39:11:66 | ControlFlowNode for Attribute() | +| FlaskTemplate.py:17:41:17:47 | ControlFlowNode for request | FlaskTemplate.py:17:41:17:52 | ControlFlowNode for Attribute | +| FlaskTemplate.py:17:41:17:52 | ControlFlowNode for Attribute | FlaskTemplate.py:17:41:17:68 | ControlFlowNode for Attribute() | +| JinjaSsti.py:7:7:7:13 | ControlFlowNode for request | JinjaSsti.py:9:16:9:26 | ControlFlowNode for Attribute | +| JinjaSsti.py:9:16:9:26 | ControlFlowNode for Attribute | JinjaSsti.py:9:16:9:38 | ControlFlowNode for Subscript | +| JinjaSsti.py:9:16:9:38 | ControlFlowNode for Subscript | JinjaSsti.py:10:25:10:32 | ControlFlowNode for template | +| JinjaSsti.py:16:7:16:13 | ControlFlowNode for request | JinjaSsti.py:19:16:19:26 | ControlFlowNode for Attribute | +| JinjaSsti.py:19:16:19:26 | ControlFlowNode for Attribute | JinjaSsti.py:19:16:19:38 | ControlFlowNode for Subscript | +| JinjaSsti.py:19:16:19:38 | ControlFlowNode for Subscript | JinjaSsti.py:20:28:20:35 | ControlFlowNode for template | +| MakoSsti.py:6:10:6:16 | ControlFlowNode for request | MakoSsti.py:8:16:8:26 | ControlFlowNode for Attribute | +| MakoSsti.py:8:16:8:26 | ControlFlowNode for Attribute | MakoSsti.py:8:16:8:38 | ControlFlowNode for Subscript | +| MakoSsti.py:8:16:8:38 | ControlFlowNode for Subscript | MakoSsti.py:9:27:9:34 | ControlFlowNode for template | +| TRender.py:5:13:5:19 | ControlFlowNode for request | TRender.py:6:16:6:26 | ControlFlowNode for Attribute | +| TRender.py:6:16:6:26 | ControlFlowNode for Attribute | TRender.py:6:16:6:38 | ControlFlowNode for Subscript | +| TRender.py:6:16:6:38 | ControlFlowNode for Subscript | TRender.py:7:24:7:31 | ControlFlowNode for template | +nodes +| AirspeedSsti.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| AirspeedSsti.py:2:26:2:32 | GSSA Variable request | semmle.label | GSSA Variable request | +| AirspeedSsti.py:10:16:10:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| AirspeedSsti.py:10:16:10:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| AirspeedSsti.py:10:16:10:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| AirspeedSsti.py:11:30:11:37 | ControlFlowNode for template | semmle.label | ControlFlowNode for template | +| ChevronSsti.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| ChevronSsti.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | +| ChevronSsti.py:10:16:10:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| ChevronSsti.py:10:16:10:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| ChevronSsti.py:10:16:10:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| ChevronSsti.py:11:27:11:34 | ControlFlowNode for template | semmle.label | ControlFlowNode for template | +| DjangoTemplates.py:6:8:6:14 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| DjangoTemplates.py:8:16:8:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| DjangoTemplates.py:8:16:8:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| DjangoTemplates.py:9:18:9:25 | ControlFlowNode for template | semmle.label | ControlFlowNode for template | +| FlaskTemplate.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| FlaskTemplate.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | +| FlaskTemplate.py:10:8:10:14 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| FlaskTemplate.py:11:39:11:45 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| FlaskTemplate.py:11:39:11:50 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| FlaskTemplate.py:11:39:11:66 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| FlaskTemplate.py:17:41:17:47 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| FlaskTemplate.py:17:41:17:52 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| FlaskTemplate.py:17:41:17:68 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| JinjaSsti.py:7:7:7:13 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| JinjaSsti.py:9:16:9:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| JinjaSsti.py:9:16:9:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| JinjaSsti.py:10:25:10:32 | ControlFlowNode for template | semmle.label | ControlFlowNode for template | +| JinjaSsti.py:16:7:16:13 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| JinjaSsti.py:19:16:19:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| JinjaSsti.py:19:16:19:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| JinjaSsti.py:20:28:20:35 | ControlFlowNode for template | semmle.label | ControlFlowNode for template | +| MakoSsti.py:6:10:6:16 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| MakoSsti.py:8:16:8:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| MakoSsti.py:8:16:8:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| MakoSsti.py:9:27:9:34 | ControlFlowNode for template | semmle.label | ControlFlowNode for template | +| TRender.py:5:13:5:19 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| TRender.py:6:16:6:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| TRender.py:6:16:6:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| TRender.py:7:24:7:31 | ControlFlowNode for template | semmle.label | ControlFlowNode for template | +subpaths #select -| AirspeedSsti.py:11:30:11:37 | template | AirspeedSsti.py:10:16:10:27 | dict of externally controlled string | AirspeedSsti.py:11:30:11:37 | externally controlled string | This Template depends on $@. | AirspeedSsti.py:10:16:10:27 | Attribute | a user-provided value | -| ChevronSsti.py:11:27:11:34 | template | ChevronSsti.py:10:16:10:27 | dict of externally controlled string | ChevronSsti.py:11:27:11:34 | externally controlled string | This Template depends on $@. | ChevronSsti.py:10:16:10:27 | Attribute | a user-provided value | -| DjangoTemplates.py:9:18:9:25 | template | DjangoTemplates.py:6:8:6:14 | django.request.HttpRequest | DjangoTemplates.py:9:18:9:25 | externally controlled string | This Template depends on $@. | DjangoTemplates.py:6:8:6:14 | request | a user-provided value | -| FlaskTemplate.py:17:41:17:68 | Attribute() | FlaskTemplate.py:17:41:17:52 | dict of externally controlled string | FlaskTemplate.py:17:41:17:68 | externally controlled string | This Template depends on $@. | FlaskTemplate.py:17:41:17:52 | Attribute | a user-provided value | -| JinjaSsti.py:10:25:10:32 | template | JinjaSsti.py:7:7:7:13 | django.request.HttpRequest | JinjaSsti.py:10:25:10:32 | externally controlled string | This Template depends on $@. | JinjaSsti.py:7:7:7:13 | request | a user-provided value | -| JinjaSsti.py:20:28:20:35 | template | JinjaSsti.py:16:7:16:13 | django.request.HttpRequest | JinjaSsti.py:20:28:20:35 | externally controlled string | This Template depends on $@. | JinjaSsti.py:16:7:16:13 | request | a user-provided value | -| MakoSsti.py:9:27:9:34 | template | MakoSsti.py:6:10:6:16 | django.request.HttpRequest | MakoSsti.py:9:27:9:34 | externally controlled string | This Template depends on $@. | MakoSsti.py:6:10:6:16 | request | a user-provided value | -| TRender.py:7:24:7:31 | template | TRender.py:5:13:5:19 | django.request.HttpRequest | TRender.py:7:24:7:31 | externally controlled string | This Template depends on $@. | TRender.py:5:13:5:19 | request | a user-provided value | +| AirspeedSsti.py:11:30:11:37 | ControlFlowNode for template | AirspeedSsti.py:2:26:2:32 | ControlFlowNode for ImportMember | AirspeedSsti.py:11:30:11:37 | ControlFlowNode for template | This Template depends on $@. | AirspeedSsti.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | +| ChevronSsti.py:11:27:11:34 | ControlFlowNode for template | ChevronSsti.py:1:26:1:32 | ControlFlowNode for ImportMember | ChevronSsti.py:11:27:11:34 | ControlFlowNode for template | This Template depends on $@. | ChevronSsti.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| DjangoTemplates.py:9:18:9:25 | ControlFlowNode for template | DjangoTemplates.py:6:8:6:14 | ControlFlowNode for request | DjangoTemplates.py:9:18:9:25 | ControlFlowNode for template | This Template depends on $@. | DjangoTemplates.py:6:8:6:14 | ControlFlowNode for request | user-provided value | +| FlaskTemplate.py:11:39:11:66 | ControlFlowNode for Attribute() | FlaskTemplate.py:1:26:1:32 | ControlFlowNode for ImportMember | FlaskTemplate.py:11:39:11:66 | ControlFlowNode for Attribute() | This Template depends on $@. | FlaskTemplate.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| FlaskTemplate.py:17:41:17:68 | ControlFlowNode for Attribute() | FlaskTemplate.py:1:26:1:32 | ControlFlowNode for ImportMember | FlaskTemplate.py:17:41:17:68 | ControlFlowNode for Attribute() | This Template depends on $@. | FlaskTemplate.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| JinjaSsti.py:10:25:10:32 | ControlFlowNode for template | JinjaSsti.py:7:7:7:13 | ControlFlowNode for request | JinjaSsti.py:10:25:10:32 | ControlFlowNode for template | This Template depends on $@. | JinjaSsti.py:7:7:7:13 | ControlFlowNode for request | user-provided value | +| JinjaSsti.py:20:28:20:35 | ControlFlowNode for template | JinjaSsti.py:16:7:16:13 | ControlFlowNode for request | JinjaSsti.py:20:28:20:35 | ControlFlowNode for template | This Template depends on $@. | JinjaSsti.py:16:7:16:13 | ControlFlowNode for request | user-provided value | +| MakoSsti.py:9:27:9:34 | ControlFlowNode for template | MakoSsti.py:6:10:6:16 | ControlFlowNode for request | MakoSsti.py:9:27:9:34 | ControlFlowNode for template | This Template depends on $@. | MakoSsti.py:6:10:6:16 | ControlFlowNode for request | user-provided value | +| TRender.py:7:24:7:31 | ControlFlowNode for template | TRender.py:5:13:5:19 | ControlFlowNode for request | TRender.py:7:24:7:31 | ControlFlowNode for template | This Template depends on $@. | TRender.py:5:13:5:19 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074/options b/python/ql/test/experimental/query-tests/Security/CWE-074/options deleted file mode 100644 index 2f457593f2e..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-074/options +++ /dev/null @@ -1 +0,0 @@ -semmle-extractor-options: --max-import-depth=3 -p ../../../../query-tests/Security/lib/