Skip to content

Commit b2c13fe

Browse files
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.
1 parent 60d8a85 commit b2c13fe

File tree

11 files changed

+229
-3
lines changed

11 files changed

+229
-3
lines changed

python/ql/lib/semmle/python/Frameworks.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,17 @@ private import semmle.python.frameworks.Aiohttp
1111
private import semmle.python.frameworks.Aiomysql
1212
private import semmle.python.frameworks.Aiopg
1313
private import semmle.python.frameworks.Aiosqlite
14+
private import semmle.python.frameworks.Airspeed
1415
private import semmle.python.frameworks.Anyio
1516
private import semmle.python.frameworks.Asyncpg
1617
private import semmle.python.frameworks.Baize
18+
private import semmle.python.frameworks.Bottle
1719
private import semmle.python.frameworks.BSon
1820
private import semmle.python.frameworks.Bottle
1921
private import semmle.python.frameworks.CassandraDriver
22+
private import semmle.python.frameworks.Chameleon
2023
private import semmle.python.frameworks.Cherrypy
24+
private import semmle.python.frameworks.Chevron
2125
private import semmle.python.frameworks.ClickhouseDriver
2226
private import semmle.python.frameworks.Cryptodome
2327
private import semmle.python.frameworks.Cryptography
@@ -30,10 +34,12 @@ private import semmle.python.frameworks.FastApi
3034
private import semmle.python.frameworks.Flask
3135
private import semmle.python.frameworks.FlaskAdmin
3236
private import semmle.python.frameworks.FlaskSqlAlchemy
37+
private import semmle.python.frameworks.Genshi
3338
private import semmle.python.frameworks.Gradio
3439
private import semmle.python.frameworks.Httpx
3540
private import semmle.python.frameworks.Idna
3641
private import semmle.python.frameworks.Invoke
42+
private import semmle.python.frameworks.Jinja2
3743
private import semmle.python.frameworks.Jmespath
3844
private import semmle.python.frameworks.Joblib
3945
private import semmle.python.frameworks.JsonPickle
@@ -42,6 +48,7 @@ private import semmle.python.frameworks.Ldap3
4248
private import semmle.python.frameworks.Libtaxii
4349
private import semmle.python.frameworks.Libxml2
4450
private import semmle.python.frameworks.Lxml
51+
private import semmle.python.frameworks.Mako
4552
private import semmle.python.frameworks.MarkupSafe
4653
private import semmle.python.frameworks.Multidict
4754
private import semmle.python.frameworks.Mysql
@@ -78,6 +85,7 @@ private import semmle.python.frameworks.Streamlit
7885
private import semmle.python.frameworks.Toml
7986
private import semmle.python.frameworks.Torch
8087
private import semmle.python.frameworks.Tornado
88+
private import semmle.python.frameworks.TRender
8189
private import semmle.python.frameworks.Twisted
8290
private import semmle.python.frameworks.Ujson
8391
private import semmle.python.frameworks.Urllib3
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* Provides classes modeling security-relevant aspects of the `airspeed` library.
3+
* See https://github.com/purcell/airspeed.
4+
*/
5+
6+
private import python
7+
private import semmle.python.dataflow.new.DataFlow
8+
private import semmle.python.ApiGraphs
9+
private import semmle.python.Concepts
10+
11+
/**
12+
* INTERNAL: Do not use.
13+
*
14+
* Provides classes modeling security-relevant aspects of the `airspeed` library.
15+
* See https://github.com/purcell/airspeed.
16+
*/
17+
module Airspeed {
18+
/** A call to `airspeed.Template`. */
19+
private class AirspeedTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
20+
AirspeedTemplateConstruction() {
21+
this = API::moduleImport("airspeed").getMember("Template").getACall()
22+
}
23+
24+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
25+
}
26+
}

python/ql/lib/semmle/python/frameworks/Bottle.qll

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ module Bottle {
3939
ViewCallable() { this = any(BottleRouteSetup rs).getARequestHandler() }
4040
}
4141

42-
/** Get methods that reprsent a route in Bottle */
42+
/** Get methods that represent a route in Bottle */
4343
string routeMethods() { result = ["route", "get", "post", "put", "delete", "patch"] }
4444

4545
private class BottleRouteSetup extends Http::Server::RouteSetup::Range, DataFlow::CallCfgNode {
@@ -171,5 +171,17 @@ module Bottle {
171171
override predicate valueAllowsNewline() { none() }
172172
}
173173
}
174+
175+
/** Provides models for functions that construct templates. */
176+
module Templates {
177+
/** A call to `bottle.template`or `bottle.SimpleTemplate`. */
178+
private class BottleTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
179+
BottleTemplateConstruction() {
180+
this = API::moduleImport("bottle").getMember(["template", "SimpleTemplate"]).getACall()
181+
}
182+
183+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
184+
}
185+
}
174186
}
175187
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* Provides classes modeling security-relevant aspects of the `chameleon` PyPI package.
3+
* See https://chameleon.readthedocs.io/en/latest/.
4+
*/
5+
6+
private import python
7+
private import semmle.python.dataflow.new.DataFlow
8+
private import semmle.python.ApiGraphs
9+
private import semmle.python.Concepts
10+
11+
/**
12+
* INTERNAL: Do not use.
13+
*
14+
* Provides classes modeling security-relevant aspects of the `chameleon` PyPI package.
15+
* See https://chameleon.readthedocs.io/en/latest/.
16+
*/
17+
module Chameleon {
18+
/** A call to `chameleon.PageTemplate`. */
19+
private class ChameleonTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
20+
ChameleonTemplateConstruction() {
21+
this = API::moduleImport("chameleon").getMember("PageTemplate").getACall()
22+
}
23+
24+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
25+
}
26+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* Provides classes modeling security-relevant aspects of the `chevron` PyPI package.
3+
* See https://pypi.org/project/chevron.
4+
*/
5+
6+
private import python
7+
private import semmle.python.dataflow.new.DataFlow
8+
private import semmle.python.ApiGraphs
9+
private import semmle.python.Concepts
10+
11+
/**
12+
* INTERNAL: Do not use.
13+
*
14+
* Provides classes modeling security-relevant aspects of the `chevron` PyPI package.
15+
* See https://pypi.org/project/chevron.
16+
*/
17+
module Chevron {
18+
/** A call to `chevron.render`. */
19+
private class ChevronRenderConstruction extends TemplateConstruction::Range, API::CallNode {
20+
ChevronRenderConstruction() {
21+
this = API::moduleImport("chevron").getMember("render").getACall()
22+
}
23+
24+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
25+
}
26+
}

python/ql/lib/semmle/python/frameworks/Django.qll

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2996,4 +2996,19 @@ module PrivateDjango {
29962996
any()
29972997
}
29982998
}
2999+
3000+
// ---------------------------------------------------------------------------
3001+
// Templates
3002+
// ---------------------------------------------------------------------------
3003+
3004+
/** A call to `django.template.Template` */
3005+
private class DjangoTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
3006+
DjangoTemplateConstruction() {
3007+
this = API::moduleImport("django").getMember("template").getMember("Template").getACall()
3008+
}
3009+
3010+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
3011+
}
3012+
3013+
// TODO: Support `from_string` on instances of `django.template.Engine`.
29993014
}

python/ql/lib/semmle/python/frameworks/Flask.qll

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,4 +721,13 @@ module Flask {
721721
preservesValue = false
722722
}
723723
}
724+
725+
/** A call to `flask.render_template_string` as a template construction sink. */
726+
private class FlaskTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
727+
FlaskTemplateConstruction() {
728+
this = API::moduleImport("flask").getMember("render_template_string").getACall()
729+
}
730+
731+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
732+
}
724733
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* Provides classes modeling security-relevant aspects of the `Genshi` PyPI package.
3+
* See https://genshi.edgewall.org/.
4+
*/
5+
6+
private import python
7+
private import semmle.python.dataflow.new.DataFlow
8+
private import semmle.python.ApiGraphs
9+
private import semmle.python.Concepts
10+
11+
/**
12+
* INTERNAL: Do not use.
13+
*
14+
* Provides classes modeling security-relevant aspects of the `Genshi` PyPI package.
15+
* See https://genshi.edgewall.org/.
16+
*/
17+
module Genshi {
18+
/** A call to `genshi.template.text.NewTextTemplate` or `genshi.template.text.OldTextTemplate`. */
19+
private class GenshiTextTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
20+
GenshiTextTemplateConstruction() {
21+
this =
22+
API::moduleImport("genshi")
23+
.getMember("template")
24+
.getMember("text")
25+
.getMember(["NewTextTemplate", "OldTextTemplate"])
26+
.getACall()
27+
}
28+
29+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
30+
}
31+
32+
/** A call to `genshi.template.MarkupTemplate` */
33+
private class GenshiMarkupTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
34+
GenshiMarkupTemplateConstruction() {
35+
this =
36+
API::moduleImport("genshi")
37+
.getMember("template")
38+
.getMember("markup")
39+
.getMember("MarkupTemplate")
40+
.getACall()
41+
}
42+
43+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
44+
}
45+
}

python/ql/lib/semmle/python/frameworks/Jinja2.qll

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,15 @@ private import semmle.python.ApiGraphs
99
private import semmle.python.Concepts
1010
private import semmle.python.frameworks.data.ModelsAsData
1111

12+
/**
13+
* INTERNAL: Do not use
14+
*
15+
* Provides classes modeling security-relevant aspects of the `jinja2` PyPI package.
16+
* See https://jinja.palletsprojects.com.
17+
*/
1218
module Jinja2 {
1319
/** A call to `jinja2.Template`. */
14-
class Jinja2TemplateConstruction extends TemplateConstruction::Range, API::CallNode {
20+
private class Jinja2TemplateConstruction extends TemplateConstruction::Range, API::CallNode {
1521
Jinja2TemplateConstruction() {
1622
this = API::moduleImport("jinja2").getMember("Template").getACall()
1723
}
@@ -39,7 +45,8 @@ module Jinja2 {
3945
DataFlow::Node instance() { instance(DataFlow::TypeTracker::end()).flowsTo(result) }
4046

4147
/** A call to `jinja2.Environment.from_string`. */
42-
class Jinja2FromStringConstruction extends TemplateConstruction::Range, DataFlow::MethodCallNode
48+
private class Jinja2FromStringConstruction extends TemplateConstruction::Range,
49+
DataFlow::MethodCallNode
4350
{
4451
Jinja2FromStringConstruction() { this.calls(EnvironmentClass::instance(), "from_string") }
4552

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* Provides classes modeling security-relevant aspects of the `Mako` PyPI package.
3+
* See https://www.makotemplates.org/.
4+
*/
5+
6+
private import python
7+
private import semmle.python.dataflow.new.DataFlow
8+
private import semmle.python.ApiGraphs
9+
private import semmle.python.Concepts
10+
11+
/**
12+
* INTERNAL: Do not use.
13+
*
14+
* Provides classes modeling security-relevant aspects of the `Mako` PyPI package.
15+
* See https://www.makotemplates.org/.
16+
*/
17+
module Mako {
18+
/** A call to `mako.template.Template`. */
19+
private class MakoTemplateConstruction extends TemplateConstruction::Range, API::CallNode {
20+
MakoTemplateConstruction() {
21+
this = API::moduleImport("mako").getMember("template").getMember("Template").getACall()
22+
}
23+
24+
override DataFlow::Node getSourceArg() { result = this.getArg(0) }
25+
}
26+
}

0 commit comments

Comments
 (0)