Promote template injection sinks for each framework covered

`Cheetah` was excluded as it was last updated 15 years ago and its documentation links are dead.
This commit is contained in:
Joe Farebrother
2024-11-06 16:13:36 +00:00
parent 60d8a85a9c
commit b2c13fe351
11 changed files with 229 additions and 3 deletions

View File

@@ -11,13 +11,17 @@ private import semmle.python.frameworks.Aiohttp
private import semmle.python.frameworks.Aiomysql
private import semmle.python.frameworks.Aiopg
private import semmle.python.frameworks.Aiosqlite
private import semmle.python.frameworks.Airspeed
private import semmle.python.frameworks.Anyio
private import semmle.python.frameworks.Asyncpg
private import semmle.python.frameworks.Baize
private import semmle.python.frameworks.Bottle
private import semmle.python.frameworks.BSon
private import semmle.python.frameworks.Bottle
private import semmle.python.frameworks.CassandraDriver
private import semmle.python.frameworks.Chameleon
private import semmle.python.frameworks.Cherrypy
private import semmle.python.frameworks.Chevron
private import semmle.python.frameworks.ClickhouseDriver
private import semmle.python.frameworks.Cryptodome
private import semmle.python.frameworks.Cryptography
@@ -30,10 +34,12 @@ private import semmle.python.frameworks.FastApi
private import semmle.python.frameworks.Flask
private import semmle.python.frameworks.FlaskAdmin
private import semmle.python.frameworks.FlaskSqlAlchemy
private import semmle.python.frameworks.Genshi
private import semmle.python.frameworks.Gradio
private import semmle.python.frameworks.Httpx
private import semmle.python.frameworks.Idna
private import semmle.python.frameworks.Invoke
private import semmle.python.frameworks.Jinja2
private import semmle.python.frameworks.Jmespath
private import semmle.python.frameworks.Joblib
private import semmle.python.frameworks.JsonPickle
@@ -42,6 +48,7 @@ private import semmle.python.frameworks.Ldap3
private import semmle.python.frameworks.Libtaxii
private import semmle.python.frameworks.Libxml2
private import semmle.python.frameworks.Lxml
private import semmle.python.frameworks.Mako
private import semmle.python.frameworks.MarkupSafe
private import semmle.python.frameworks.Multidict
private import semmle.python.frameworks.Mysql
@@ -78,6 +85,7 @@ private import semmle.python.frameworks.Streamlit
private import semmle.python.frameworks.Toml
private import semmle.python.frameworks.Torch
private import semmle.python.frameworks.Tornado
private import semmle.python.frameworks.TRender
private import semmle.python.frameworks.Twisted
private import semmle.python.frameworks.Ujson
private import semmle.python.frameworks.Urllib3

View File

@@ -0,0 +1,26 @@
/**
* Provides classes modeling security-relevant aspects of the `airspeed` library.
* See https://github.com/purcell/airspeed.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.ApiGraphs
private import semmle.python.Concepts
/**
* INTERNAL: Do not use.
*
* Provides classes modeling security-relevant aspects of the `airspeed` library.
* See https://github.com/purcell/airspeed.
*/
module Airspeed {
/** A call to `airspeed.Template`. */
private class AirspeedTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
AirspeedTemplateConstruction() {
this = API::moduleImport("airspeed").getMember("Template").getACall()
}
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
}
}

View File

@@ -39,7 +39,7 @@ module Bottle {
ViewCallable() { this = any(BottleRouteSetup rs).getARequestHandler() }
}
/** Get methods that reprsent a route in Bottle */
/** Get methods that represent a route in Bottle */
string routeMethods() { result = ["route", "get", "post", "put", "delete", "patch"] }
private class BottleRouteSetup extends Http::Server::RouteSetup::Range, DataFlow::CallCfgNode {
@@ -171,5 +171,17 @@ module Bottle {
override predicate valueAllowsNewline() { none() }
}
}
/** Provides models for functions that construct templates. */
module Templates {
/** A call to `bottle.template`or `bottle.SimpleTemplate`. */
private class BottleTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
BottleTemplateConstruction() {
this = API::moduleImport("bottle").getMember(["template", "SimpleTemplate"]).getACall()
}
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
}
}
}
}

View File

@@ -0,0 +1,26 @@
/**
* Provides classes modeling security-relevant aspects of the `chameleon` PyPI package.
* See https://chameleon.readthedocs.io/en/latest/.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.ApiGraphs
private import semmle.python.Concepts
/**
* INTERNAL: Do not use.
*
* Provides classes modeling security-relevant aspects of the `chameleon` PyPI package.
* See https://chameleon.readthedocs.io/en/latest/.
*/
module Chameleon {
/** A call to `chameleon.PageTemplate`. */
private class ChameleonTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
ChameleonTemplateConstruction() {
this = API::moduleImport("chameleon").getMember("PageTemplate").getACall()
}
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
}
}

View File

@@ -0,0 +1,26 @@
/**
* Provides classes modeling security-relevant aspects of the `chevron` PyPI package.
* See https://pypi.org/project/chevron.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.ApiGraphs
private import semmle.python.Concepts
/**
* INTERNAL: Do not use.
*
* Provides classes modeling security-relevant aspects of the `chevron` PyPI package.
* See https://pypi.org/project/chevron.
*/
module Chevron {
/** A call to `chevron.render`. */
private class ChevronRenderConstruction extends TemplateConstruction::Range, API::CallNode {
ChevronRenderConstruction() {
this = API::moduleImport("chevron").getMember("render").getACall()
}
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
}
}

View File

@@ -2996,4 +2996,19 @@ module PrivateDjango {
any()
}
}
// ---------------------------------------------------------------------------
// Templates
// ---------------------------------------------------------------------------
/** A call to `django.template.Template` */
private 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 `from_string` on instances of `django.template.Engine`.
}

View File

@@ -721,4 +721,13 @@ module Flask {
preservesValue = false
}
}
/** A call to `flask.render_template_string` as a template construction sink. */
private 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) }
}
}

View File

@@ -0,0 +1,45 @@
/**
* Provides classes modeling security-relevant aspects of the `Genshi` PyPI package.
* See https://genshi.edgewall.org/.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.ApiGraphs
private import semmle.python.Concepts
/**
* INTERNAL: Do not use.
*
* Provides classes modeling security-relevant aspects of the `Genshi` PyPI package.
* See https://genshi.edgewall.org/.
*/
module Genshi {
/** A call to `genshi.template.text.NewTextTemplate` or `genshi.template.text.OldTextTemplate`. */
private class GenshiTextTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
GenshiTextTemplateConstruction() {
this =
API::moduleImport("genshi")
.getMember("template")
.getMember("text")
.getMember(["NewTextTemplate", "OldTextTemplate"])
.getACall()
}
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
}
/** A call to `genshi.template.MarkupTemplate` */
private class GenshiMarkupTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
GenshiMarkupTemplateConstruction() {
this =
API::moduleImport("genshi")
.getMember("template")
.getMember("markup")
.getMember("MarkupTemplate")
.getACall()
}
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
}
}

View File

@@ -9,9 +9,15 @@ private import semmle.python.ApiGraphs
private import semmle.python.Concepts
private import semmle.python.frameworks.data.ModelsAsData
/**
* INTERNAL: Do not use
*
* Provides classes modeling security-relevant aspects of the `jinja2` PyPI package.
* See https://jinja.palletsprojects.com.
*/
module Jinja2 {
/** A call to `jinja2.Template`. */
class Jinja2TemplateConstruction extends TemplateConstruction::Range, API::CallNode {
private class Jinja2TemplateConstruction extends TemplateConstruction::Range, API::CallNode {
Jinja2TemplateConstruction() {
this = API::moduleImport("jinja2").getMember("Template").getACall()
}
@@ -39,7 +45,8 @@ module Jinja2 {
DataFlow::Node instance() { instance(DataFlow::TypeTracker::end()).flowsTo(result) }
/** A call to `jinja2.Environment.from_string`. */
class Jinja2FromStringConstruction extends TemplateConstruction::Range, DataFlow::MethodCallNode
private class Jinja2FromStringConstruction extends TemplateConstruction::Range,
DataFlow::MethodCallNode
{
Jinja2FromStringConstruction() { this.calls(EnvironmentClass::instance(), "from_string") }

View File

@@ -0,0 +1,26 @@
/**
* Provides classes modeling security-relevant aspects of the `Mako` PyPI package.
* See https://www.makotemplates.org/.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.ApiGraphs
private import semmle.python.Concepts
/**
* INTERNAL: Do not use.
*
* Provides classes modeling security-relevant aspects of the `Mako` PyPI package.
* See https://www.makotemplates.org/.
*/
module Mako {
/** A call to `mako.template.Template`. */
private 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) }
}
}

View File

@@ -0,0 +1,26 @@
/**
* Provides classes modeling security-relevant aspects of the `trender` PyPI package.
* See https://github.com/cesbit/trender.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.ApiGraphs
private import semmle.python.Concepts
/**
* INTERNAL: Do not use.
*
* Provides classes modeling security-relevant aspects of the `trender` PyPI package.
* See https://github.com/cesbit/trender.
*/
module TRender {
/** A call to `trender.TRender`. */
private class TRenderTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
TRenderTemplateConstruction() {
this = API::moduleImport("trender").getMember("TRender").getACall()
}
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
}
}