Merge branch 'main' of https://github.com/github/codeql into python-dataflow/flow-summaries-from-scratch

synced files have changed
This commit is contained in:
yoff
2022-08-25 09:24:05 +00:00
2460 changed files with 213219 additions and 79450 deletions

View File

@@ -1,3 +1,5 @@
## 0.4.1
## 0.4.0
### Breaking Changes

0
python/ql/src/Exceptions/EmptyExcept.ql Executable file → Normal file
View File

0
python/ql/src/Exceptions/UnguardedNextInGenerator.ql Executable file → Normal file
View File

0
python/ql/src/Resources/FileNotAlwaysClosed.ql Executable file → Normal file
View File

View File

@@ -35,7 +35,7 @@ private import semmle.python.objects.ObjectInternal
// functionality into `BuiltinFunctionValue` and `BuiltinMethodValue`, but will
// probably require some more work: for this query, it's totally ok to use
// `builtins.open` for the code `open(f)`, but well, it requires a bit of thinking to
// figure out if that is desireable in general. I simply skipped a corner here!
// figure out if that is desirable in general. I simply skipped a corner here!
// 4. TaintTrackingPrivate: Nothing else gives us access to `defaultAdditionalTaintStep` :(
/**
* A callable that is considered a "safe" external API from a security perspective.
@@ -131,7 +131,9 @@ class UntrustedExternalApiDataNode extends ExternalApiDataNode {
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */
deprecated class UntrustedExternalAPIDataNode = UntrustedExternalApiDataNode;
/** An external API which is used with untrusted data. */
private newtype TExternalApi =
/** An untrusted API method `m` where untrusted data is passed at `index`. */
TExternalApiParameter(DataFlowPrivate::DataFlowCallable callable, int index) {
exists(UntrustedExternalApiDataNode n |
callable = n.getCallable() and

View File

@@ -0,0 +1,65 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
It's easy to write a regular expression range that matches a wider range of characters than you intended.
For example, <code>/[a-zA-z]/</code> matches all lowercase and all uppercase letters,
as you would expect, but it also matches the characters: <code>[ \ ] ^ _ `</code>.
</p>
<p>
Another common problem is failing to escape the dash character in a regular
expression. An unescaped dash is interpreted
as part of a range. For example, in the character class <code>[a-zA-Z0-9%=.,-_]</code>
the last character range matches the 55 characters between
<code>,</code> and <code>_</code> (both included), which overlaps with the
range <code>[0-9]</code> and is clearly not intended by the writer.
</p>
</overview>
<recommendation>
<p>
Avoid any confusion about which characters are included in the range by
writing unambiguous regular expressions.
Always check that character ranges match only the expected characters.
</p>
</recommendation>
<example>
<p>
The following example code is intended to check whether a string is a valid 6 digit hex color.
</p>
<sample language="python">
import re
def is_valid_hex_color(color):
return re.match(r'^#[0-9a-fA-f]{6}$', color) is not None
</sample>
<p>
However, the <code>A-f</code> range is overly large and matches every uppercase character.
It would parse a "color" like <code>#XXYYZZ</code> as valid.
</p>
<p>
The fix is to use an uppercase <code>A-F</code> range instead.
</p>
<sample language="python">
import re
def is_valid_hex_color(color):
return re.match(r'^#[0-9a-fA-F]{6}$', color) is not None
</sample>
</example>
<references>
<li>GitHub Advisory Database: <a href="https://github.com/advisories/GHSA-g4rg-993r-mgx7">CVE-2021-42740: Improper Neutralization of Special Elements used in a Command in Shell-quote</a></li>
<li>wh0.github.io: <a href="https://wh0.github.io/2021/10/28/shell-quote-rce-exploiting.html">Exploiting CVE-2021-42740</a></li>
<li>Yosuke Ota: <a href="https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-obscure-range.html">no-obscure-range</a></li>
<li>Paul Boyd: <a href="https://pboyd.io/posts/comma-dash-dot/">The regex [,-.]</a></li>
</references>
</qhelp>

View File

@@ -0,0 +1,19 @@
/**
* @name Overly permissive regular expression range
* @description Overly permissive regular expression ranges match a wider range of characters than intended.
* This may allow an attacker to bypass a filter or sanitizer.
* @kind problem
* @problem.severity warning
* @security-severity 5.0
* @precision high
* @id py/overly-large-range
* @tags correctness
* security
* external/cwe/cwe-020
*/
import semmle.python.security.OverlyLargeRangeQuery
from RegExpCharacterRange range, string reason
where problem(range, reason)
select range, "Suspicious character range that " + reason + "."

0
python/ql/src/Security/CWE-078/CommandInjection.ql Executable file → Normal file
View File

View File

@@ -19,14 +19,14 @@ private API::Node unsafe_paramiko_policy(string name) {
result = API::moduleImport("paramiko").getMember("client").getMember(name)
}
private API::Node paramikoSSHClientInstance() {
private API::Node paramikoSshClientInstance() {
result = API::moduleImport("paramiko").getMember("client").getMember("SSHClient").getReturn()
}
from DataFlow::CallCfgNode call, DataFlow::Node arg, string name
where
// see http://docs.paramiko.org/en/stable/api/client.html#paramiko.client.SSHClient.set_missing_host_key_policy
call = paramikoSSHClientInstance().getMember("set_missing_host_key_policy").getACall() and
call = paramikoSshClientInstance().getMember("set_missing_host_key_policy").getACall() and
arg in [call.getArg(0), call.getArgByName("policy")] and
(
arg = unsafe_paramiko_policy(name).getAValueReachableFromSource() or

View File

@@ -29,7 +29,7 @@ The example shows two unsafe calls to <a href="https://semmle.com">semmle.com</a
<references>
<li>
Python requests documentation: <a href="http://docs.python-requests.org/en/master/user/advanced/#ssl-cert-verification">SSL Cert Verification</a>.
Python requests documentation: <a href="https://requests.readthedocs.io/en/latest/user/advanced/#ssl-cert-verification">SSL Cert Verification</a>.
</li>
</references>
</qhelp>

View File

@@ -7,13 +7,13 @@ private import python
private import semmle.python.ApiGraphs
import TlsLibraryModel
class PyOpenSSLContextCreation extends ContextCreation, DataFlow::CallCfgNode {
PyOpenSSLContextCreation() {
class PyOpenSslContextCreation extends ContextCreation, DataFlow::CallCfgNode {
PyOpenSslContextCreation() {
this = API::moduleImport("OpenSSL").getMember("SSL").getMember("Context").getACall()
}
override string getProtocol() {
exists(DataFlow::Node protocolArg, PyOpenSSL pyo |
exists(DataFlow::Node protocolArg, PyOpenSsl pyo |
protocolArg in [this.getArg(0), this.getArgByName("method")]
|
protocolArg in [
@@ -51,12 +51,12 @@ class SetOptionsCall extends ProtocolRestriction, DataFlow::CallCfgNode {
}
}
class UnspecificPyOpenSSLContextCreation extends PyOpenSSLContextCreation, UnspecificContextCreation {
UnspecificPyOpenSSLContextCreation() { library instanceof PyOpenSSL }
class UnspecificPyOpenSslContextCreation extends PyOpenSslContextCreation, UnspecificContextCreation {
UnspecificPyOpenSslContextCreation() { library instanceof PyOpenSsl }
}
class PyOpenSSL extends TlsLibrary {
PyOpenSSL() { this = "pyOpenSSL" }
class PyOpenSsl extends TlsLibrary {
PyOpenSsl() { this = "pyOpenSSL" }
override string specific_version_name(ProtocolVersion version) { result = version + "_METHOD" }
@@ -70,7 +70,7 @@ class PyOpenSSL extends TlsLibrary {
override ContextCreation default_context_creation() { none() }
override ContextCreation specific_context_creation() {
result instanceof PyOpenSSLContextCreation
result instanceof PyOpenSslContextCreation
}
override DataFlow::Node insecure_connection_creation(ProtocolVersion version) { none() }
@@ -80,6 +80,6 @@ class PyOpenSSL extends TlsLibrary {
override ProtocolRestriction protocol_restriction() { result instanceof SetOptionsCall }
override ProtocolUnrestriction protocol_unrestriction() {
result instanceof UnspecificPyOpenSSLContextCreation
result instanceof UnspecificPyOpenSslContextCreation
}
}

View File

@@ -7,8 +7,8 @@ private import python
private import semmle.python.ApiGraphs
import TlsLibraryModel
class SSLContextCreation extends ContextCreation, DataFlow::CallCfgNode {
SSLContextCreation() { this = API::moduleImport("ssl").getMember("SSLContext").getACall() }
class SslContextCreation extends ContextCreation, DataFlow::CallCfgNode {
SslContextCreation() { this = API::moduleImport("ssl").getMember("SSLContext").getACall() }
override string getProtocol() {
exists(DataFlow::Node protocolArg, Ssl ssl |
@@ -27,8 +27,8 @@ class SSLContextCreation extends ContextCreation, DataFlow::CallCfgNode {
}
}
class SSLDefaultContextCreation extends ContextCreation {
SSLDefaultContextCreation() {
class SslDefaultContextCreation extends ContextCreation {
SslDefaultContextCreation() {
this = API::moduleImport("ssl").getMember("create_default_context").getACall()
}
@@ -161,8 +161,8 @@ class ContextSetVersion extends ProtocolRestriction, ProtocolUnrestriction, Data
}
}
class UnspecificSSLContextCreation extends SSLContextCreation, UnspecificContextCreation {
UnspecificSSLContextCreation() { library instanceof Ssl }
class UnspecificSslContextCreation extends SslContextCreation, UnspecificContextCreation {
UnspecificSslContextCreation() { library instanceof Ssl }
override ProtocolVersion getUnrestriction() {
result = UnspecificContextCreation.super.getUnrestriction() and
@@ -172,7 +172,7 @@ class UnspecificSSLContextCreation extends SSLContextCreation, UnspecificContext
}
}
class UnspecificSSLDefaultContextCreation extends SSLDefaultContextCreation, ProtocolUnrestriction {
class UnspecificSslDefaultContextCreation extends SslDefaultContextCreation, ProtocolUnrestriction {
override DataFlow::Node getContext() { result = this }
// see https://docs.python.org/3/library/ssl.html#ssl.create_default_context
@@ -195,10 +195,10 @@ class Ssl extends TlsLibrary {
override API::Node version_constants() { result = API::moduleImport("ssl") }
override ContextCreation default_context_creation() {
result instanceof SSLDefaultContextCreation
result instanceof SslDefaultContextCreation
}
override ContextCreation specific_context_creation() { result instanceof SSLContextCreation }
override ContextCreation specific_context_creation() { result instanceof SslContextCreation }
override DataFlow::CallCfgNode insecure_connection_creation(ProtocolVersion version) {
result = API::moduleImport("ssl").getMember("wrap_socket").getACall() and
@@ -220,8 +220,8 @@ class Ssl extends TlsLibrary {
or
result instanceof ContextSetVersion
or
result instanceof UnspecificSSLContextCreation
result instanceof UnspecificSslContextCreation
or
result instanceof UnspecificSSLDefaultContextCreation
result instanceof UnspecificSslDefaultContextCreation
}
}

View File

@@ -13,7 +13,7 @@
*/
import python
import semmle.python.security.performance.SuperlinearBackTracking
import semmle.python.security.regexp.SuperlinearBackTracking
import semmle.python.security.dataflow.PolynomialReDoSQuery
import DataFlow::PathGraph

View File

@@ -14,7 +14,7 @@
*/
import python
import semmle.python.security.performance.ExponentialBackTracking
import semmle.python.security.regexp.ExponentialBackTracking
from RegExpTerm t, string pump, State s, string prefixMsg
where

View File

@@ -0,0 +1,5 @@
---
category: newQuery
---
* Added a new query, `py/suspicious-regexp-range`, to detect character ranges in regular expressions that seem to match
too many characters.

View File

@@ -0,0 +1 @@
## 0.4.1

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.4.0
lastReleaseVersion: 0.4.1

View File

@@ -17,8 +17,8 @@ import semmle.python.web.HttpRequest
/* Sinks */
import experimental.semmle.python.security.injection.XSLT
class XSLTInjectionConfiguration extends TaintTracking::Configuration {
XSLTInjectionConfiguration() { this = "XSLT injection configuration" }
class XsltInjectionConfiguration extends TaintTracking::Configuration {
XsltInjectionConfiguration() { this = "XSLT injection configuration" }
deprecated override predicate isSource(TaintTracking::Source source) {
source instanceof HttpRequestTaintSource
@@ -29,7 +29,7 @@ class XSLTInjectionConfiguration extends TaintTracking::Configuration {
}
}
from XSLTInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink
from XsltInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink
where config.hasFlowPath(src, sink)
select sink.getSink(), src, sink, "This XSLT query depends on $@.", src.getSource(),
"a user-provided value"

View File

@@ -2,7 +2,6 @@ private import python
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.dataflow.new.DataFlow
/**
* A data flow source of the client ip obtained according to the remote endpoint identifier specified

View File

@@ -182,7 +182,10 @@ module LdapBind {
/**
* Holds if the binding process use SSL.
*/
abstract predicate useSSL();
abstract predicate useSsl();
/** DEPRECATED: Alias for useSsl */
deprecated predicate useSSL() { useSsl() }
}
}
@@ -213,7 +216,10 @@ class LdapBind extends DataFlow::Node {
/**
* Holds if the binding process use SSL.
*/
predicate useSSL() { range.useSSL() }
predicate useSsl() { range.useSsl() }
/** DEPRECATED: Alias for useSsl */
deprecated predicate useSSL() { useSsl() }
}
/** DEPRECATED: Alias for LdapBind */

View File

@@ -12,13 +12,13 @@ private import semmle.python.ApiGraphs
/**
* Provides models for Python's ldap-related libraries.
*/
private module LDAP {
private module Ldap {
/**
* Provides models for the `python-ldap` PyPI package (imported as `ldap`).
*
* See https://www.python-ldap.org/en/python-ldap-3.3.0/index.html
*/
private module LDAP2 {
private module Ldap2 {
/** Gets a reference to the `ldap` module. */
API::Node ldap() { result = API::moduleImport("ldap") }
@@ -38,8 +38,8 @@ private module LDAP {
*
* See https://www.python-ldap.org/en/python-ldap-3.3.0/reference/ldap.html#functions
*/
private class LDAP2QueryMethods extends string {
LDAP2QueryMethods() {
private class Ldap2QueryMethods extends string {
Ldap2QueryMethods() {
this in ["search", "search_s", "search_st", "search_ext", "search_ext_s"]
}
}
@@ -52,7 +52,7 @@ private module LDAP {
/** Gets a reference to a `ldap` query. */
private DataFlow::Node ldapQuery() {
result = ldapOperation() and
result.(DataFlow::AttrRead).getAttributeName() instanceof LDAP2QueryMethods
result.(DataFlow::AttrRead).getAttributeName() instanceof Ldap2QueryMethods
}
/**
@@ -60,8 +60,8 @@ private module LDAP {
*
* See `LDAP2QueryMethods`
*/
private class LDAP2Query extends DataFlow::CallCfgNode, LdapQuery::Range {
LDAP2Query() { this.getFunction() = ldapQuery() }
private class Ldap2Query extends DataFlow::CallCfgNode, LdapQuery::Range {
Ldap2Query() { this.getFunction() = ldapQuery() }
override DataFlow::Node getQuery() {
result in [this.getArg(0), this.getArg(2), this.getArgByName("filterstr")]
@@ -73,8 +73,8 @@ private module LDAP {
*
* See https://www.python-ldap.org/en/python-ldap-3.3.0/reference/ldap.html#functions
*/
private class LDAP2BindMethods extends string {
LDAP2BindMethods() {
private class Ldap2BindMethods extends string {
Ldap2BindMethods() {
this in [
"bind", "bind_s", "simple_bind", "simple_bind_s", "sasl_interactive_bind_s",
"sasl_non_interactive_bind_s", "sasl_external_bind_s", "sasl_gssapi_bind_s"
@@ -85,12 +85,12 @@ private module LDAP {
/** Gets a reference to a `ldap` bind. */
private DataFlow::Node ldapBind() {
result = ldapOperation() and
result.(DataFlow::AttrRead).getAttributeName() instanceof LDAP2BindMethods
result.(DataFlow::AttrRead).getAttributeName() instanceof Ldap2BindMethods
}
/**List of SSL-demanding options */
private class LDAPSSLOptions extends DataFlow::Node {
LDAPSSLOptions() {
private class LdapSslOptions extends DataFlow::Node {
LdapSslOptions() {
this = ldap().getMember("OPT_X_TLS_" + ["DEMAND", "HARD"]).getAValueReachableFromSource()
}
}
@@ -100,8 +100,8 @@ private module LDAP {
*
* See `LDAP2BindMethods`
*/
private class LDAP2Bind extends DataFlow::CallCfgNode, LdapBind::Range {
LDAP2Bind() { this.getFunction() = ldapBind() }
private class Ldap2Bind extends DataFlow::CallCfgNode, LdapBind::Range {
Ldap2Bind() { this.getFunction() = ldapBind() }
override DataFlow::Node getPassword() {
result in [this.getArg(1), this.getArgByName("cred")]
@@ -115,11 +115,11 @@ private module LDAP {
)
}
override predicate useSSL() {
override predicate useSsl() {
// use initialize to correlate `this` and so avoid FP in several instances
exists(DataFlow::CallCfgNode initialize |
// ldap.set_option(ldap.OPT_X_TLS_%s)
ldap().getMember("set_option").getACall().getArg(_) instanceof LDAPSSLOptions
ldap().getMember("set_option").getACall().getArg(_) instanceof LdapSslOptions
or
this.getFunction().(DataFlow::AttrRead).getObject().getALocalSource() = initialize and
initialize = ldapInitialize().getACall() and
@@ -136,7 +136,7 @@ private module LDAP {
setOption.getFunction().(DataFlow::AttrRead).getObject().getALocalSource() =
initialize and
setOption.getFunction().(DataFlow::AttrRead).getAttributeName() = "set_option" and
setOption.getArg(0) instanceof LDAPSSLOptions and
setOption.getArg(0) instanceof LdapSslOptions and
not DataFlow::exprNode(any(False falseExpr))
.(DataFlow::LocalSourceNode)
.flowsTo(setOption.getArg(1))
@@ -144,6 +144,9 @@ private module LDAP {
)
)
}
/** DEPRECATED: Alias for useSsl */
deprecated override predicate useSSL() { this.useSsl() }
}
/**
@@ -151,8 +154,8 @@ private module LDAP {
*
* See https://github.com/python-ldap/python-ldap/blob/7ce471e238cdd9a4dd8d17baccd1c9e05e6f894a/Lib/ldap/dn.py#L17
*/
private class LDAP2EscapeDNCall extends DataFlow::CallCfgNode, LdapEscape::Range {
LDAP2EscapeDNCall() { this = ldap().getMember("dn").getMember("escape_dn_chars").getACall() }
private class Ldap2EscapeDNCall extends DataFlow::CallCfgNode, LdapEscape::Range {
Ldap2EscapeDNCall() { this = ldap().getMember("dn").getMember("escape_dn_chars").getACall() }
override DataFlow::Node getAnInput() { result = this.getArg(0) }
}
@@ -162,8 +165,8 @@ private module LDAP {
*
* See https://www.python-ldap.org/en/python-ldap-3.3.0/reference/ldap-filter.html#ldap.filter.escape_filter_chars
*/
private class LDAP2EscapeFilterCall extends DataFlow::CallCfgNode, LdapEscape::Range {
LDAP2EscapeFilterCall() {
private class Ldap2EscapeFilterCall extends DataFlow::CallCfgNode, LdapEscape::Range {
Ldap2EscapeFilterCall() {
this = ldap().getMember("filter").getMember("escape_filter_chars").getACall()
}
@@ -176,7 +179,7 @@ private module LDAP {
*
* See https://pypi.org/project/ldap3/
*/
private module LDAP3 {
private module Ldap3 {
/** Gets a reference to the `ldap3` module. */
API::Node ldap3() { result = API::moduleImport("ldap3") }
@@ -192,8 +195,8 @@ private module LDAP {
/**
* A class to find `ldap3` methods executing a query.
*/
private class LDAP3Query extends DataFlow::CallCfgNode, LdapQuery::Range {
LDAP3Query() {
private class Ldap3Query extends DataFlow::CallCfgNode, LdapQuery::Range {
Ldap3Query() {
this.getFunction().(DataFlow::AttrRead).getObject().getALocalSource() =
ldap3Connection().getACall() and
this.getFunction().(DataFlow::AttrRead).getAttributeName() = "search"
@@ -205,8 +208,8 @@ private module LDAP {
/**
* A class to find `ldap3` methods binding a connection.
*/
class LDAP3Bind extends DataFlow::CallCfgNode, LdapBind::Range {
LDAP3Bind() { this = ldap3Connection().getACall() }
class Ldap3Bind extends DataFlow::CallCfgNode, LdapBind::Range {
Ldap3Bind() { this = ldap3Connection().getACall() }
override DataFlow::Node getPassword() {
result in [this.getArg(2), this.getArgByName("password")]
@@ -220,7 +223,7 @@ private module LDAP {
)
}
override predicate useSSL() {
override predicate useSsl() {
exists(DataFlow::CallCfgNode serverCall |
serverCall = ldap3Server().getACall() and
this.getArg(0).getALocalSource() = serverCall and
@@ -236,6 +239,9 @@ private module LDAP {
startTLS.getObject().getALocalSource() = this
)
}
/** DEPRECATED: Alias for useSsl */
deprecated override predicate useSSL() { this.useSsl() }
}
/**
@@ -243,8 +249,8 @@ private module LDAP {
*
* See https://github.com/cannatag/ldap3/blob/4d33166f0869b929f59c6e6825a1b9505eb99967/ldap3/utils/dn.py#L390
*/
private class LDAP3EscapeDNCall extends DataFlow::CallCfgNode, LdapEscape::Range {
LDAP3EscapeDNCall() { this = ldap3Utils().getMember("dn").getMember("escape_rdn").getACall() }
private class Ldap3EscapeDNCall extends DataFlow::CallCfgNode, LdapEscape::Range {
Ldap3EscapeDNCall() { this = ldap3Utils().getMember("dn").getMember("escape_rdn").getACall() }
override DataFlow::Node getAnInput() { result = this.getArg(0) }
}
@@ -254,8 +260,8 @@ private module LDAP {
*
* See https://github.com/cannatag/ldap3/blob/4d33166f0869b929f59c6e6825a1b9505eb99967/ldap3/utils/conv.py#L91
*/
private class LDAP3EscapeFilterCall extends DataFlow::CallCfgNode, LdapEscape::Range {
LDAP3EscapeFilterCall() {
private class Ldap3EscapeFilterCall extends DataFlow::CallCfgNode, LdapEscape::Range {
Ldap3EscapeFilterCall() {
this = ldap3Utils().getMember("conv").getMember("escape_filter_chars").getACall()
}

View File

@@ -122,7 +122,7 @@ class LdapInsecureAuthConfig extends TaintTracking::Configuration {
}
override predicate isSink(DataFlow::Node sink) {
exists(LdapBind ldapBind | not ldapBind.useSSL() and sink = ldapBind.getHost())
exists(LdapBind ldapBind | not ldapBind.useSsl() and sink = ldapBind.getHost())
}
}

View File

@@ -11,12 +11,15 @@ import semmle.python.dataflow.TaintTracking
import semmle.python.web.HttpRequest
/** Models XSLT Injection related classes and functions */
module XSLTInjection {
module XsltInjection {
/** Returns a class value which refers to `lxml.etree` */
Value etree() { result = Value::named("lxml.etree") }
/** A generic taint sink that is vulnerable to XSLT injection. */
abstract class XSLTInjectionSink extends TaintSink { }
abstract class XsltInjectionSink extends TaintSink { }
/** DEPRECATED: Alias for XsltInjectionSink */
deprecated class XSLTInjectionSink = XsltInjectionSink;
/**
* A kind of "taint", representing an untrusted XML string
@@ -73,10 +76,10 @@ module XSLTInjection {
* root = etree.XML("<xmlContent>")
* find_text = etree.XSLT("`sink`")
*/
private class EtreeXSLTArgument extends XSLTInjectionSink {
private class EtreeXsltArgument extends XsltInjectionSink {
override string toString() { result = "lxml.etree.XSLT" }
EtreeXSLTArgument() {
EtreeXsltArgument() {
exists(CallNode call | call.getFunction().(AttrNode).getObject("XSLT").pointsTo(etree()) |
call.getArg(0) = this
)
@@ -94,10 +97,10 @@ module XSLTInjection {
* tree = etree.parse(f)
* result_tree = tree.xslt(`sink`)
*/
private class ParseXSLTArgument extends XSLTInjectionSink {
private class ParseXsltArgument extends XsltInjectionSink {
override string toString() { result = "lxml.etree.parse.xslt" }
ParseXSLTArgument() {
ParseXsltArgument() {
exists(
CallNode parseCall, CallNode xsltCall, ControlFlowNode obj, Variable var, AssignStmt assign
|
@@ -113,3 +116,6 @@ module XSLTInjection {
override predicate sinks(TaintKind kind) { kind instanceof ExternalXmlKind }
}
}
/** DEPRECATED: Alias for XsltInjection */
deprecated module XSLTInjection = XsltInjection;

View File

@@ -1,5 +1,5 @@
name: codeql/python-queries
version: 0.4.1-dev
version: 0.4.2-dev
groups:
- python
- queries