Merge branch 'main' into python/promote-log-injection

This commit is contained in:
Rasmus Wriedt Larsen
2022-02-21 09:59:31 +01:00
1177 changed files with 250609 additions and 41897 deletions

View File

@@ -1,3 +1,15 @@
## 0.0.9
### Bug Fixes
* The [View AST functionality](https://codeql.github.com/docs/codeql-for-visual-studio-code/exploring-the-structure-of-your-source-code/) no longer prints detailed information about regular expressions, greatly improving performance.
## 0.0.8
### Major Analysis Improvements
* User names and other account information is no longer considered to be sensitive data for the queries `py/clear-text-logging-sensitive-data` and `py/clear-text-storage-sensitive-data`, since this lead to many false positives.
## 0.0.7
## 0.0.6

View File

@@ -18,7 +18,9 @@
import python
import semmle.python.security.dataflow.PathInjection
import DataFlow::PathGraph
from CustomPathNode source, CustomPathNode sink
where pathInjection(source, sink)
select sink, source, sink, "This path depends on $@.", source, "a user-provided value"
from PathInjection::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "This path depends on $@.", source.getNode(),
"a user-provided value"

View File

@@ -4,22 +4,22 @@
<qhelp>
<overview>
<p>If an LDAP query or DN is built using string concatenation or string formatting, and the
components of the concatenation include user input without any proper sanitization, a user
components of the concatenation include user input without any proper sanitization, a user
is likely to be able to run malicious LDAP queries.</p>
</overview>
<recommendation>
<p>If user input must be included in an LDAP query or DN, it should be escaped to
avoid a malicious user providing special characters that change the meaning
of the query. In Python2, user input should be escaped with <code>ldap.dn.escape_dn_chars</code>
or <code>ldap.filter.escape_filter_chars</code>, while in Python3, user input should be escaped with
of the query. In Python2, user input should be escaped with <code>ldap.dn.escape_dn_chars</code>
or <code>ldap.filter.escape_filter_chars</code>, while in Python3, user input should be escaped with
<code>ldap3.utils.dn.escape_rdn</code> or <code>ldap3.utils.conv.escape_filter_chars</code>
depending on the component tainted by the user. A good practice is to escape filter characters
depending on the component tainted by the user. A good practice is to escape filter characters
that could change the meaning of the query (https://tools.ietf.org/search/rfc4515#section-3).</p>
</recommendation>
<example>
<p>In the following examples, the code accepts both <code>username</code> and <code>dc</code> from the user,
<p>In the following examples, the code accepts both <code>username</code> and <code>dc</code> from the user,
which it then uses to build a LDAP query and DN.</p>
<p>The first and the second example uses the unsanitized user input directly
@@ -30,7 +30,7 @@ components, and search for a completely different set of values.</p>
<sample src="examples/example_bad1.py" />
<sample src="examples/example_bad2.py" />
<p>In the third and four example, the input provided by the user is sanitized before it is included in the search filter or DN.
<p>In the third and fourth example, the input provided by the user is sanitized before it is included in the search filter or DN.
This ensures the meaning of the query cannot be changed by a malicious user.</p>
<sample src="examples/example_good1.py" />

View File

@@ -0,0 +1,28 @@
/**
* @name LDAP query built from user-controlled sources
* @description Building an LDAP query from user-controlled sources is vulnerable to insertion of
* malicious LDAP code by the user.
* @kind path-problem
* @problem.severity error
* @security-severity 9.8
* @precision high
* @id py/ldap-injection
* @tags security
* external/cwe/cwe-090
*/
// Determine precision above
import python
import semmle.python.security.dataflow.LdapInjection
import DataFlow::PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, string parameterName
where
any(LdapInjection::DnConfiguration dnConfig).hasFlowPath(source, sink) and
parameterName = "DN"
or
any(LdapInjection::FilterConfiguration filterConfig).hasFlowPath(source, sink) and
parameterName = "filter"
select sink.getNode(), source, sink,
"$@ LDAP query parameter (" + parameterName + ") comes from $@.", sink.getNode(), "This",
source.getNode(), "a user-provided value"

View File

@@ -0,0 +1,4 @@
---
category: newQuery
---
* The query "LDAP query built from user-controlled sources" (`py/ldap-injection`) has been promoted from experimental to the main query pack. Its results will now appear by default. This query was originally [submitted as an experimental query by @jorgectf](https://github.com/github/codeql/pull/5443).

View File

@@ -1,4 +1,5 @@
---
category: majorAnalysis
---
## 0.0.8
### Major Analysis Improvements
* User names and other account information is no longer considered to be sensitive data for the queries `py/clear-text-logging-sensitive-data` and `py/clear-text-storage-sensitive-data`, since this lead to many false positives.

View File

@@ -0,0 +1,5 @@
## 0.0.9
### Bug Fixes
* The [View AST functionality](https://codeql.github.com/docs/codeql-for-visual-studio-code/exploring-the-structure-of-your-source-code/) no longer prints detailed information about regular expressions, greatly improving performance.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.0.7
lastReleaseVersion: 0.0.9

View File

@@ -21,11 +21,11 @@ import semmle.python.security.strings.Untrusted
class TemplateInjectionConfiguration extends TaintTracking::Configuration {
TemplateInjectionConfiguration() { this = "Template injection configuration" }
override predicate isSource(TaintTracking::Source source) {
deprecated override predicate isSource(TaintTracking::Source source) {
source instanceof HttpRequestTaintSource
}
override predicate isSink(TaintTracking::Sink sink) { sink instanceof SSTISink }
deprecated override predicate isSink(TaintTracking::Sink sink) { sink instanceof SSTISink }
}
from TemplateInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink

View File

@@ -1,20 +0,0 @@
/**
* @name LDAP query built from user-controlled sources
* @description Building an LDAP query from user-controlled sources is vulnerable to insertion of
* malicious LDAP code by the user.
* @kind path-problem
* @problem.severity error
* @id py/ldap-injection
* @tags security
* external/cwe/cwe-090
*/
// Determine precision above
import python
import experimental.semmle.python.security.injection.LDAP
import DataFlow::PathGraph
from LDAPInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "$@ LDAP query parameter comes from $@.", sink.getNode(),
"This", source.getNode(), "a user-provided value"

View File

@@ -20,11 +20,11 @@ import experimental.semmle.python.security.injection.XSLT
class XSLTInjectionConfiguration extends TaintTracking::Configuration {
XSLTInjectionConfiguration() { this = "XSLT injection configuration" }
override predicate isSource(TaintTracking::Source source) {
deprecated override predicate isSource(TaintTracking::Source source) {
source instanceof HttpRequestTaintSource
}
override predicate isSink(TaintTracking::Sink sink) {
deprecated override predicate isSink(TaintTracking::Sink sink) {
sink instanceof XSLTInjection::XSLTInjectionSink
}
}

View File

@@ -0,0 +1,48 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Using a cryptographically weak pseudo-random number generator to generate a security-sensitive value,
such as a password, makes it easier for an attacker to predict the value.
</p>
<p>
Pseudo-random number generators generate a sequence of numbers that only approximates the properties
of random numbers. The sequence is not truly random because it is completely determined by a
relatively small set of initial values, the seed. If the random number generator is
cryptographically weak, then this sequence may be easily predictable through outside observations.
</p>
</overview>
<recommendation>
<p>
Use a cryptographically secure pseudo-random number generator if the output is to be used in a
security sensitive context. As a rule of thumb, a value should be considered "security sensitive"
if predicting it would allow the attacker to perform an action that they would otherwise be unable
to perform. For example, if an attacker could predict the random password generated for a new user,
they would be able to log in as that new user.
</p>
<p>
For Python, <code>secrets</code> provides a cryptographically secure pseudo-random
number generator. <code>random</code> is not cryptographically secure, and should be avoided in
security contexts.
</p>
</recommendation>
<example>
<p>
The example below uses the <code>random</code> package instead of <code>secrets</code> to generate a password:
</p>
<sample src="examples/InsecureRandomness.py" />
<p>
Instead, use <code>secrets</code>:
</p>
<sample src="examples/InsecureRandomnessGood.py" />
</example>
<references>
<li>Wikipedia. <a href="http://en.wikipedia.org/wiki/Pseudorandom_number_generator">Pseudo-random number generator</a>.</li>
<li>OWASP: <a href="https://owasp.org/www-community/vulnerabilities/Insecure_Randomness">Insecure Randomness</a>.</li>
<li>OWASP: <a href="https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#secure-random-number-generation">Secure Random Number Generation</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,23 @@
/**
* @name Insecure randomness
* @description Using a cryptographically weak pseudo-random number generator to generate a
* security-sensitive value may allow an attacker to predict what value will
* be generated.
* @kind path-problem
* @problem.severity warning
* @security-severity 7.8
* @precision high
* @id py/insecure-randomness
* @tags security
* external/cwe/cwe-338
*/
import python
import experimental.semmle.python.security.InsecureRandomness::InsecureRandomness
import semmle.python.dataflow.new.DataFlow
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Cryptographically insecure $@ in a security context.",
source.getNode(), "random value"

View File

@@ -0,0 +1,6 @@
import random
def generatePassword():
# BAD: the random is not cryptographically secure
return random.random()

View File

@@ -0,0 +1,7 @@
import secrets
def generatePassword():
# GOOD: the random is cryptographically secure
secret_generator = secrets.SystemRandom()
return secret_generator.random()

View File

@@ -11,8 +11,9 @@
import python
import experimental.semmle.python.security.injection.NoSQLInjection
import DataFlow::PathGraph
from CustomPathNode source, CustomPathNode sink
where noSQLInjectionFlow(source, sink)
from NoSQLInjection::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink, source, sink, "$@ NoSQL query contains an unsanitized $@", sink, "This", source,
"user-provided value"

View File

@@ -0,0 +1,37 @@
/**
* Provides a taint tracking configuration for reasoning about random
* values that are not cryptographically secure.
*
* Note, for performance reasons: only import this file if
* `InsecureRandomness::Configuration` is needed, otherwise
* `InsecureRandomnessCustomizations` should be imported instead.
*/
private import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
/**
* A taint tracking configuration for random values that are not cryptographically secure.
*/
module InsecureRandomness {
import InsecureRandomnessCustomizations::InsecureRandomness
/**
* A taint-tracking configuration for reasoning about random values that are
* not cryptographically secure.
*/
class Configuration extends TaintTracking::Configuration {
Configuration() { this = "InsecureRandomness" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof SanitizerGuard
}
}
}

View File

@@ -0,0 +1,79 @@
/**
* Provides default sources, sinks and sanitizers for reasoning about random values that are
* not cryptographically secure, as well as extension points for adding your own.
*/
private import python
private import semmle.python.ApiGraphs
private import semmle.python.Concepts
private import semmle.python.dataflow.new.BarrierGuards
private import semmle.python.dataflow.new.internal.DataFlowPrivate
/**
* Provides default sources, sinks and sanitizers for reasoning about random values that are
* not cryptographically secure, as well as extension points for adding your own.
*/
module InsecureRandomness {
/**
* A data flow source for random values that are not cryptographically secure.
*/
abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for random values that are not cryptographically secure.
*/
abstract class Sink extends DataFlow::Node { }
/**
* A sanitizer for random values that are not cryptographically secure.
*/
abstract class Sanitizer extends DataFlow::Node { }
/**
* A sanitizer guard for random values that are not cryptographically secure.
*/
abstract class SanitizerGuard extends DataFlow::BarrierGuard { }
/**
* A random source that is not sufficient for security use. So far this is only made up
* of the math package's rand function, more insufficient random sources can be added here.
*/
class InsecureRandomSource extends Source {
InsecureRandomSource() {
this =
API::moduleImport("random")
.getMember([
"betavariate", "choice", "choices", "expovariate", "gammavariate", "gauss",
"getrandbits", "getstate", "lognormvariate", "normalvariate", "paretovariate",
"randbytes", "randint", "random", "randrange", "sample", "seed", "setstate",
"shuffle", "triangular", "uniform", "vonmisesvariate", "weibullvariate"
])
.getACall()
}
}
/**
* A use in a function that heuristically deals with unsafe random numbers or random strings.
*/
class RandomFnSink extends Sink {
RandomFnSink() {
exists(DataFlowCallable randomFn |
randomFn
.getName()
.regexpMatch("(?i).*(gen(erate)?|make|mk|create).*(nonce|salt|pepper|Password).*")
|
this.getEnclosingCallable() = randomFn
)
}
}
/**
* A cryptographic key, considered as a sink for random values that are not cryptographically
* secure.
*/
class CryptoKeySink extends Sink {
CryptoKeySink() {
exists(Cryptography::CryptographicOperation operation | this = operation.getAnInput())
}
}
}

View File

@@ -1,24 +0,0 @@
/**
* Provides a taint-tracking configuration for detecting LDAP injection vulnerabilities
*/
import python
import experimental.semmle.python.Concepts
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.RemoteFlowSources
/**
* A taint-tracking configuration for detecting LDAP injections.
*/
class LDAPInjectionFlowConfig extends TaintTracking::Configuration {
LDAPInjectionFlowConfig() { this = "LDAPInjectionFlowConfig" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink = any(LDAPQuery ldapQuery).getQuery() }
override predicate isSanitizer(DataFlow::Node sanitizer) {
sanitizer = any(LDAPEscape ldapEsc).getAnInput()
}
}

View File

@@ -1,57 +1,54 @@
import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.DataFlow2
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.TaintTracking2
import semmle.python.dataflow.new.RemoteFlowSources
import semmle.python.security.dataflow.ChainedConfigs12
import experimental.semmle.python.Concepts
import semmle.python.Concepts
/**
* A taint-tracking configuration for detecting string-to-dict conversions.
*/
class RFSToDictConfig extends TaintTracking::Configuration {
RFSToDictConfig() { this = "RFSToDictConfig" }
module NoSQLInjection {
class Configuration extends TaintTracking::Configuration {
Configuration() { this = "NoSQLInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
source instanceof RemoteFlowSource and
state instanceof RemoteInput
}
override predicate isSink(DataFlow::Node sink) {
exists(Decoding decoding | decoding.getFormat() = "JSON" and sink = decoding.getOutput())
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
sink = any(NoSQLQuery noSQLQuery).getQuery() and
state instanceof ConvertedToDict
}
override predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) {
// Block `RemoteInput` paths here, since they change state to `ConvertedToDict`
exists(Decoding decoding | decoding.getFormat() = "JSON" and node = decoding.getOutput()) and
state instanceof RemoteInput
}
override predicate isAdditionalFlowStep(
DataFlow::Node nodeFrom, DataFlow::FlowState stateFrom, DataFlow::Node nodeTo,
DataFlow::FlowState stateTo
) {
exists(Decoding decoding | decoding.getFormat() = "JSON" |
nodeFrom = decoding.getAnInput() and
nodeTo = decoding.getOutput()
) and
stateFrom instanceof RemoteInput and
stateTo instanceof ConvertedToDict
}
override predicate isSanitizer(DataFlow::Node sanitizer) {
sanitizer = any(NoSQLSanitizer noSQLSanitizer).getAnInput()
}
}
override predicate isSanitizer(DataFlow::Node sanitizer) {
sanitizer = any(NoSQLSanitizer noSQLSanitizer).getAnInput()
/** A flow state signifying remote input. */
class RemoteInput extends DataFlow::FlowState {
RemoteInput() { this = "RemoteInput" }
}
/** A flow state signifying remote input converted to a dictionary. */
class ConvertedToDict extends DataFlow::FlowState {
ConvertedToDict() { this = "ConvertedToDict" }
}
}
/**
* A taint-tracking configuration for detecting NoSQL injections (previously converted to a dict).
*/
class FromDataDictToSink extends TaintTracking2::Configuration {
FromDataDictToSink() { this = "FromDataDictToSink" }
override predicate isSource(DataFlow::Node source) {
exists(Decoding decoding | decoding.getFormat() = "JSON" and source = decoding.getOutput())
}
override predicate isSink(DataFlow::Node sink) { sink = any(NoSQLQuery noSQLQuery).getQuery() }
override predicate isSanitizer(DataFlow::Node sanitizer) {
sanitizer = any(NoSQLSanitizer noSQLSanitizer).getAnInput()
}
}
/**
* A predicate checking string-to-dict conversion and its arrival to a NoSQL injection sink.
*/
predicate noSQLInjectionFlow(CustomPathNode source, CustomPathNode sink) {
exists(
RFSToDictConfig config, DataFlow::PathNode mid1, DataFlow2::PathNode mid2,
FromDataDictToSink config2
|
config.hasFlowPath(source.asNode1(), mid1) and
config2.hasFlowPath(mid2, sink.asNode2()) and
mid1.getNode().asCfgNode() = mid2.getNode().asCfgNode()
)
}

View File

@@ -21,7 +21,7 @@ module XSLTInjection {
/**
* A kind of "taint", representing an untrusted XML string
*/
private class ExternalXmlStringKind extends ExternalStringKind {
deprecated private class ExternalXmlStringKind extends ExternalStringKind {
ExternalXmlStringKind() { this = "etree.XML string" }
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {

View File

@@ -5,7 +5,7 @@ import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
/** returns the ClassValue representing `airspeed.Template` */
ClassValue theAirspeedTemplateClass() { result = Value::named("airspeed.Template") }
deprecated ClassValue theAirspeedTemplateClass() { result = Value::named("airspeed.Template") }
/**
* Sink representing the `airspeed.Template` class instantiation argument.
@@ -13,7 +13,7 @@ ClassValue theAirspeedTemplateClass() { result = Value::named("airspeed.Template
* import airspeed
* temp = airspeed.Template(`"sink"`)
*/
class AirspeedTemplateSink extends SSTISink {
deprecated class AirspeedTemplateSink extends SSTISink {
override string toString() { result = "argument to airspeed.Template()" }
AirspeedTemplateSink() {

View File

@@ -5,7 +5,9 @@ import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
/** returns the ClassValue representing `bottle.SimpleTemplate` */
ClassValue theBottleSimpleTemplateClass() { result = Value::named("bottle.SimpleTemplate") }
deprecated ClassValue theBottleSimpleTemplateClass() {
result = Value::named("bottle.SimpleTemplate")
}
/**
* Sink representing the `bottle.SimpleTemplate` class instantiation argument.
@@ -13,7 +15,7 @@ ClassValue theBottleSimpleTemplateClass() { result = Value::named("bottle.Simple
* from bottle import SimpleTemplate
* template = SimpleTemplate(`sink`)
*/
class BottleSimpleTemplateSink extends SSTISink {
deprecated class BottleSimpleTemplateSink extends SSTISink {
override string toString() { result = "argument to bottle.SimpleTemplate()" }
BottleSimpleTemplateSink() {
@@ -32,7 +34,7 @@ class BottleSimpleTemplateSink extends SSTISink {
* from bottle import template
* tmp = template(`sink`)
*/
class BottleTemplateSink extends SSTISink {
deprecated class BottleTemplateSink extends SSTISink {
override string toString() { result = "argument to bottle.template()" }
BottleTemplateSink() {

View File

@@ -5,7 +5,9 @@ import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
/** returns the ClassValue representing `chameleon.PageTemplate` */
ClassValue theChameleonPageTemplateClass() { result = Value::named("chameleon.PageTemplate") }
deprecated ClassValue theChameleonPageTemplateClass() {
result = Value::named("chameleon.PageTemplate")
}
/**
* Sink representing the `chameleon.PageTemplate` class instantiation argument.
@@ -13,7 +15,7 @@ ClassValue theChameleonPageTemplateClass() { result = Value::named("chameleon.Pa
* from chameleon import PageTemplate
* template = PageTemplate(`sink`)
*/
class ChameleonTemplateSink extends SSTISink {
deprecated class ChameleonTemplateSink extends SSTISink {
override string toString() { result = "argument to Chameleon.PageTemplate()" }
ChameleonTemplateSink() {

View File

@@ -5,7 +5,9 @@ import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
/** returns the ClassValue representing `Cheetah.Template.Template` */
ClassValue theCheetahTemplateClass() { result = Value::named("Cheetah.Template.Template") }
deprecated ClassValue theCheetahTemplateClass() {
result = Value::named("Cheetah.Template.Template")
}
/**
* Sink representing the instantiation argument of any class which derives from
@@ -22,7 +24,7 @@ ClassValue theCheetahTemplateClass() { result = Value::named("Cheetah.Template.T
* from Cheetah.Template import Template
* t3 = Template("sink")
*/
class CheetahTemplateInstantiationSink extends SSTISink {
deprecated class CheetahTemplateInstantiationSink extends SSTISink {
override string toString() { result = "argument to Cheetah.Template.Template()" }
CheetahTemplateInstantiationSink() {

View File

@@ -5,7 +5,7 @@ import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
/** returns the Value representing `chevron.render` function */
Value theChevronRenderFunc() { result = Value::named("chevron.render") }
deprecated Value theChevronRenderFunc() { result = Value::named("chevron.render") }
/**
* Sink representing the `chevron.render` function call argument.
@@ -13,7 +13,7 @@ Value theChevronRenderFunc() { result = Value::named("chevron.render") }
* import chevron
* tmp = chevron.render(`sink`,{ 'key' : 'value' })
*/
class ChevronRenderSink extends SSTISink {
deprecated class ChevronRenderSink extends SSTISink {
override string toString() { result = "argument to chevron.render()" }
ChevronRenderSink() {

View File

@@ -4,7 +4,7 @@ import python
import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
ClassValue theDjangoTemplateClass() { result = Value::named("django.template.Template") }
deprecated ClassValue theDjangoTemplateClass() { result = Value::named("django.template.Template") }
/**
* Sink representng `django.template.Template` class instantiation argument.
@@ -12,7 +12,7 @@ ClassValue theDjangoTemplateClass() { result = Value::named("django.template.Tem
* from django.template import Template
* template = Template(`sink`)
*/
class DjangoTemplateTemplateSink extends SSTISink {
deprecated class DjangoTemplateTemplateSink extends SSTISink {
override string toString() { result = "argument to Django.template()" }
DjangoTemplateTemplateSink() {

View File

@@ -4,7 +4,9 @@ import python
import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
Value theFlaskRenderTemplateClass() { result = Value::named("flask.render_template_string") }
deprecated Value theFlaskRenderTemplateClass() {
result = Value::named("flask.render_template_string")
}
/**
* Sink representng `flask.render_template_string` function call argument.
@@ -12,7 +14,7 @@ Value theFlaskRenderTemplateClass() { result = Value::named("flask.render_templa
* from flask import render_template_string
* render_template_string(`sink`)
*/
class FlaskTemplateSink extends SSTISink {
deprecated class FlaskTemplateSink extends SSTISink {
override string toString() { result = "argument to flask.render_template_string()" }
FlaskTemplateSink() {

View File

@@ -5,10 +5,12 @@ import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
/** returns the ClassValue representing `Genshi.template.TextTemplate` */
ClassValue theGenshiTextTemplateClass() { result = Value::named("genshi.template.TextTemplate") }
deprecated ClassValue theGenshiTextTemplateClass() {
result = Value::named("genshi.template.TextTemplate")
}
/** returns the ClassValue representing `Genshi.template.MarkupTemplate` */
ClassValue theGenshiMarkupTemplateClass() {
deprecated ClassValue theGenshiMarkupTemplateClass() {
result = Value::named("genshi.template.MarkupTemplate")
}
@@ -18,7 +20,7 @@ ClassValue theGenshiMarkupTemplateClass() {
* from genshi.template import TextTemplate
* tmpl = TextTemplate('sink')
*/
class GenshiTextTemplateSink extends SSTISink {
deprecated class GenshiTextTemplateSink extends SSTISink {
override string toString() { result = "argument to genshi.template.TextTemplate()" }
GenshiTextTemplateSink() {
@@ -37,7 +39,7 @@ class GenshiTextTemplateSink extends SSTISink {
* from genshi.template import MarkupTemplate
* tmpl = MarkupTemplate('sink')
*/
class GenshiMarkupTemplateSink extends SSTISink {
deprecated class GenshiMarkupTemplateSink extends SSTISink {
override string toString() { result = "argument to genshi.template.MarkupTemplate()" }
GenshiMarkupTemplateSink() {

View File

@@ -5,10 +5,10 @@ import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
/** returns the ClassValue representing `jinja2.Template` */
ClassValue theJinja2TemplateClass() { result = Value::named("jinja2.Template") }
deprecated ClassValue theJinja2TemplateClass() { result = Value::named("jinja2.Template") }
/** returns the ClassValue representing `jinja2.Template` */
Value theJinja2FromStringValue() { result = Value::named("jinja2.from_string") }
deprecated Value theJinja2FromStringValue() { result = Value::named("jinja2.from_string") }
/**
* Sink representing the `jinja2.Template` class instantiation argument.
@@ -16,7 +16,7 @@ Value theJinja2FromStringValue() { result = Value::named("jinja2.from_string") }
* from jinja2 import Template
* template = Template(`sink`)
*/
class Jinja2TemplateSink extends SSTISink {
deprecated class Jinja2TemplateSink extends SSTISink {
override string toString() { result = "argument to jinja2.Template()" }
Jinja2TemplateSink() {
@@ -35,7 +35,7 @@ class Jinja2TemplateSink extends SSTISink {
* from jinja2 import from_string
* template = from_string(`sink`)
*/
class Jinja2FromStringSink extends SSTISink {
deprecated class Jinja2FromStringSink extends SSTISink {
override string toString() { result = "argument to jinja2.from_string()" }
Jinja2FromStringSink() {

View File

@@ -5,7 +5,7 @@ import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
/** returns the ClassValue representing `mako.template.Template` */
ClassValue theMakoTemplateClass() { result = Value::named("mako.template.Template") }
deprecated ClassValue theMakoTemplateClass() { result = Value::named("mako.template.Template") }
/**
* Sink representing the `mako.template.Template` class instantiation argument.
@@ -13,7 +13,7 @@ ClassValue theMakoTemplateClass() { result = Value::named("mako.template.Templat
* from mako.template import Template
* mytemplate = Template("hello world!")
*/
class MakoTemplateSink extends SSTISink {
deprecated class MakoTemplateSink extends SSTISink {
override string toString() { result = "argument to mako.template.Template()" }
MakoTemplateSink() {

View File

@@ -4,4 +4,4 @@ import semmle.python.dataflow.TaintTracking
* A generic taint sink that is vulnerable to template inclusions.
* The `temp` in `jinja2.Template(temp)` and similar.
*/
abstract class SSTISink extends TaintSink { }
abstract deprecated class SSTISink extends TaintSink { }

View File

@@ -5,7 +5,7 @@ import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
/** returns the ClassValue representing `trender.TRender` */
ClassValue theTRenderTemplateClass() { result = Value::named("trender.TRender") }
deprecated ClassValue theTRenderTemplateClass() { result = Value::named("trender.TRender") }
/**
* Sink representing the `trender.TRender` class instantiation argument.
@@ -13,7 +13,7 @@ ClassValue theTRenderTemplateClass() { result = Value::named("trender.TRender")
* from trender import TRender
* template = TRender(`sink`)
*/
class TRenderTemplateSink extends SSTISink {
deprecated class TRenderTemplateSink extends SSTISink {
override string toString() { result = "argument to trender.TRender()" }
TRenderTemplateSink() {

View File

@@ -1,5 +1,5 @@
name: codeql/python-queries
version: 0.0.8-dev
version: 0.0.10-dev
groups:
- python
- queries