mirror of
https://github.com/github/codeql.git
synced 2026-04-25 16:55:19 +02:00
Merge branch 'main' into redsun82/python-match-fps
This commit is contained in:
@@ -1,2 +1 @@
|
||||
semmle-extractor-options: -R . -p . --filter exclude:**/src_archive/**
|
||||
|
||||
semmle-extractor-options: -R . -p . --filter exclude:**/*.testproj/**
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
| mapping | builtin-class collections.defaultdict |
|
||||
| mapping | builtin-class dict |
|
||||
| mapping | class MyDictSubclass |
|
||||
| mapping | class MyMappingABC |
|
||||
| mapping | class OrderedDict |
|
||||
| neither sequence nor mapping | builtin-class set |
|
||||
| neither sequence nor mapping | class MyMappingABC |
|
||||
| neither sequence nor mapping | class MySequenceABC |
|
||||
| sequence | builtin-class list |
|
||||
| sequence | builtin-class str |
|
||||
| sequence | builtin-class tuple |
|
||||
| sequence | builtin-class unicode |
|
||||
| sequence | class MySequenceABC |
|
||||
| sequence | class MySequenceImpl |
|
||||
|
||||
@@ -44,14 +44,10 @@
|
||||
| test.py | 15 | ControlFlowNode for moduleX | Module package.moduleX | Entry node for Module package.moduleX |
|
||||
| test.py | 16 | ControlFlowNode for Attribute | class Y | ControlFlowNode for ClassExpr |
|
||||
| test.py | 16 | ControlFlowNode for moduleX | Module package.moduleX | Entry node for Module package.moduleX |
|
||||
| test.py | 19 | ControlFlowNode for ImportExpr | Module tty | ControlFlowNode for ImportExpr |
|
||||
| test.py | 19 | ControlFlowNode for tty | Module tty | ControlFlowNode for ImportExpr |
|
||||
| test.py | 22 | ControlFlowNode for Attribute | Builtin-function exc_info | ControlFlowNode for from sys import * |
|
||||
| test.py | 22 | ControlFlowNode for x | Module package.x | Entry node for Module package.x |
|
||||
| test.py | 24 | ControlFlowNode for IntegerLiteral | int 0 | ControlFlowNode for IntegerLiteral |
|
||||
| test.py | 24 | ControlFlowNode for argv | int 0 | ControlFlowNode for IntegerLiteral |
|
||||
| test.py | 27 | ControlFlowNode for ImportExpr | Module sys | ControlFlowNode for ImportExpr |
|
||||
| test.py | 31 | ControlFlowNode for argv | list object | ControlFlowNode for from sys import * |
|
||||
| test.py | 33 | ControlFlowNode for ImportExpr | Module socket | ControlFlowNode for ImportExpr |
|
||||
| test.py | 34 | ControlFlowNode for timeout | builtin-class socket.timeout | ControlFlowNode for from _socket import * |
|
||||
| x.py | 2 | ControlFlowNode for ImportExpr | Module sys | ControlFlowNode for ImportExpr |
|
||||
|
||||
@@ -44,14 +44,10 @@
|
||||
| test.py | 15 | ControlFlowNode for moduleX | Module package.moduleX | builtin-class module | Entry node for Module package.moduleX |
|
||||
| test.py | 16 | ControlFlowNode for Attribute | class Y | builtin-class type | ControlFlowNode for ClassExpr |
|
||||
| test.py | 16 | ControlFlowNode for moduleX | Module package.moduleX | builtin-class module | Entry node for Module package.moduleX |
|
||||
| test.py | 19 | ControlFlowNode for ImportExpr | Module tty | builtin-class module | ControlFlowNode for ImportExpr |
|
||||
| test.py | 19 | ControlFlowNode for tty | Module tty | builtin-class module | ControlFlowNode for ImportExpr |
|
||||
| test.py | 22 | ControlFlowNode for Attribute | Builtin-function exc_info | builtin-class builtin_function_or_method | ControlFlowNode for from sys import * |
|
||||
| test.py | 22 | ControlFlowNode for x | Module package.x | builtin-class module | Entry node for Module package.x |
|
||||
| test.py | 24 | ControlFlowNode for IntegerLiteral | int 0 | builtin-class int | ControlFlowNode for IntegerLiteral |
|
||||
| test.py | 24 | ControlFlowNode for argv | int 0 | builtin-class int | ControlFlowNode for IntegerLiteral |
|
||||
| test.py | 27 | ControlFlowNode for ImportExpr | Module sys | builtin-class module | ControlFlowNode for ImportExpr |
|
||||
| test.py | 31 | ControlFlowNode for argv | list object | builtin-class list | ControlFlowNode for from sys import * |
|
||||
| test.py | 33 | ControlFlowNode for ImportExpr | Module socket | builtin-class module | ControlFlowNode for ImportExpr |
|
||||
| test.py | 34 | ControlFlowNode for timeout | builtin-class socket.timeout | builtin-class type | ControlFlowNode for from _socket import * |
|
||||
| x.py | 2 | ControlFlowNode for ImportExpr | Module sys | builtin-class module | ControlFlowNode for ImportExpr |
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
| six | Package six |
|
||||
| six.moves | Package six.moves |
|
||||
| six.moves.http_client | Module httplib |
|
||||
| six.moves.http_client.HTTPConnection | class HTTPConnection |
|
||||
| six.moves.http_client | Missing module httplib |
|
||||
| six.moves.http_client.HTTPConnection | Missing module attribute httplib.HTTPConnection |
|
||||
| six.moves.range | builtin-class xrange |
|
||||
| six.moves.urllib | Package six.moves.urllib |
|
||||
| six.moves.urllib.parse | Module six.moves.urllib_parse |
|
||||
|
||||
@@ -1 +1 @@
|
||||
| 38 |
|
||||
| 11 |
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
| mapping | builtin-class collections.OrderedDict |
|
||||
| mapping | builtin-class collections.defaultdict |
|
||||
| mapping | builtin-class dict |
|
||||
| mapping | class MyDictSubclass |
|
||||
| mapping | class MyMappingABC |
|
||||
| mapping | class OrderedDict |
|
||||
| neither sequence nor mapping | builtin-class set |
|
||||
| sequence | builtin-class bytes |
|
||||
| sequence | builtin-class list |
|
||||
|
||||
@@ -44,14 +44,10 @@
|
||||
| test.py | 15 | ControlFlowNode for moduleX | Module package.moduleX | Entry node for Module package.moduleX |
|
||||
| test.py | 16 | ControlFlowNode for Attribute | class Y | ControlFlowNode for ClassExpr |
|
||||
| test.py | 16 | ControlFlowNode for moduleX | Module package.moduleX | Entry node for Module package.moduleX |
|
||||
| test.py | 19 | ControlFlowNode for ImportExpr | Module tty | ControlFlowNode for ImportExpr |
|
||||
| test.py | 19 | ControlFlowNode for tty | Module tty | ControlFlowNode for ImportExpr |
|
||||
| test.py | 22 | ControlFlowNode for Attribute | Builtin-function exc_info | ControlFlowNode for from sys import * |
|
||||
| test.py | 22 | ControlFlowNode for x | Module package.x | Entry node for Module package.x |
|
||||
| test.py | 24 | ControlFlowNode for IntegerLiteral | int 0 | ControlFlowNode for IntegerLiteral |
|
||||
| test.py | 24 | ControlFlowNode for argv | int 0 | ControlFlowNode for IntegerLiteral |
|
||||
| test.py | 27 | ControlFlowNode for ImportExpr | Module sys | ControlFlowNode for ImportExpr |
|
||||
| test.py | 31 | ControlFlowNode for argv | list object | ControlFlowNode for from sys import * |
|
||||
| test.py | 33 | ControlFlowNode for ImportExpr | Module socket | ControlFlowNode for ImportExpr |
|
||||
| test.py | 34 | ControlFlowNode for timeout | builtin-class TimeoutError | ControlFlowNode for from _socket import * |
|
||||
| x.py | 2 | ControlFlowNode for ImportExpr | Module sys | ControlFlowNode for ImportExpr |
|
||||
|
||||
@@ -44,14 +44,10 @@
|
||||
| test.py | 15 | ControlFlowNode for moduleX | Module package.moduleX | builtin-class module | Entry node for Module package.moduleX |
|
||||
| test.py | 16 | ControlFlowNode for Attribute | class Y | builtin-class type | ControlFlowNode for ClassExpr |
|
||||
| test.py | 16 | ControlFlowNode for moduleX | Module package.moduleX | builtin-class module | Entry node for Module package.moduleX |
|
||||
| test.py | 19 | ControlFlowNode for ImportExpr | Module tty | builtin-class module | ControlFlowNode for ImportExpr |
|
||||
| test.py | 19 | ControlFlowNode for tty | Module tty | builtin-class module | ControlFlowNode for ImportExpr |
|
||||
| test.py | 22 | ControlFlowNode for Attribute | Builtin-function exc_info | builtin-class builtin_function_or_method | ControlFlowNode for from sys import * |
|
||||
| test.py | 22 | ControlFlowNode for x | Module package.x | builtin-class module | Entry node for Module package.x |
|
||||
| test.py | 24 | ControlFlowNode for IntegerLiteral | int 0 | builtin-class int | ControlFlowNode for IntegerLiteral |
|
||||
| test.py | 24 | ControlFlowNode for argv | int 0 | builtin-class int | ControlFlowNode for IntegerLiteral |
|
||||
| test.py | 27 | ControlFlowNode for ImportExpr | Module sys | builtin-class module | ControlFlowNode for ImportExpr |
|
||||
| test.py | 31 | ControlFlowNode for argv | list object | builtin-class list | ControlFlowNode for from sys import * |
|
||||
| test.py | 33 | ControlFlowNode for ImportExpr | Module socket | builtin-class module | ControlFlowNode for ImportExpr |
|
||||
| test.py | 34 | ControlFlowNode for timeout | builtin-class TimeoutError | builtin-class type | ControlFlowNode for from _socket import * |
|
||||
| x.py | 2 | ControlFlowNode for ImportExpr | Module sys | builtin-class module | ControlFlowNode for ImportExpr |
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
| mwe_failure.py:7:1:7:23 | class MyTest | <MISSING BASE TYPE> |
|
||||
| mwe_failure_2.py:7:1:7:23 | class MyTest | <MISSING BASE TYPE> |
|
||||
| mwe_failure.py:7:1:7:23 | class MyTest | class TestCase |
|
||||
| mwe_failure_2.py:7:1:7:23 | class MyTest | class TestCase |
|
||||
| mwe_success.py:7:1:7:23 | class MyTest | class TestCase |
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
| Module package.assistant | e | Wrong() |
|
||||
| Module package.assistant | f | int 1 |
|
||||
| Module package.helper | __name__ | str u'package.helper' |
|
||||
| Module package.helper | absolute_import | _Feature() |
|
||||
| Module package.helper | assistant | Module package.assistant |
|
||||
| Module package.helper | d | int 4 |
|
||||
| Module package.helper | e | int 5 |
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
| six | Package six |
|
||||
| six.moves | Package six.moves |
|
||||
| six.moves.http_client | Module http.client |
|
||||
| six.moves.http_client.HTTPConnection | class HTTPConnection |
|
||||
| six.moves.http_client | Missing module http.client |
|
||||
| six.moves.http_client.HTTPConnection | Missing module attribute http.client.HTTPConnection |
|
||||
| six.moves.range | builtin-class range |
|
||||
| six.moves.urllib | Package six.moves.urllib |
|
||||
| six.moves.urllib.parse | Module six.moves.urllib_parse |
|
||||
|
||||
@@ -1 +1 @@
|
||||
| 51 |
|
||||
| 11 |
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
| UndefinedExport.py:3:18:3:20 | StringLiteral | The name 'y' is exported by __all__ but is not defined. |
|
||||
| UndefinedExport.py:3:23:3:25 | StringLiteral | The name 'z' is exported by __all__ but is not defined. |
|
||||
| UndefinedExport.py:3:28:3:35 | StringLiteral | The name 'module' is exported by __all__ but is not defined. |
|
||||
| enum_convert.py:8:13:8:19 | StringLiteral | The name 'Maybe' is exported by __all__ but is not defined. |
|
||||
| enum_convert.py:8:22:8:32 | StringLiteral | The name 'Maybe_not' is exported by __all__ but is not defined. |
|
||||
| package/__init__.py:1:23:1:34 | StringLiteral | The name 'not_exists' is exported by __all__ but is not defined. |
|
||||
|
||||
@@ -5,15 +5,5 @@
|
||||
|
||||
private import python as PY
|
||||
private import codeql.util.test.InlineExpectationsTest
|
||||
|
||||
private module Impl implements InlineExpectationsTestSig {
|
||||
/**
|
||||
* A class representing line comments in Python. As this is the only form of comment Python
|
||||
* permits, we simply reuse the `Comment` class.
|
||||
*/
|
||||
class ExpectationComment = PY::Comment;
|
||||
|
||||
class Location = PY::Location;
|
||||
}
|
||||
|
||||
private import internal.InlineExpectationsTestImpl
|
||||
import Make<Impl>
|
||||
|
||||
21
python/ql/test/TestUtilities/InlineExpectationsTestQuery.ql
Normal file
21
python/ql/test/TestUtilities/InlineExpectationsTestQuery.ql
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @kind test-postprocess
|
||||
*/
|
||||
|
||||
private import python
|
||||
private import codeql.util.test.InlineExpectationsTest as T
|
||||
private import internal.InlineExpectationsTestImpl
|
||||
import T::TestPostProcessing
|
||||
import T::TestPostProcessing::Make<Impl, Input>
|
||||
|
||||
private module Input implements T::TestPostProcessing::InputSig<Impl> {
|
||||
string getRelativeUrl(Location location) {
|
||||
exists(File f, int startline, int startcolumn, int endline, int endcolumn |
|
||||
location.hasLocationInfo(_, startline, startcolumn, endline, endcolumn) and
|
||||
f = location.getFile()
|
||||
|
|
||||
result =
|
||||
f.getRelativePath() + ":" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
private import python as PY
|
||||
private import codeql.util.test.InlineExpectationsTest
|
||||
|
||||
module Impl implements InlineExpectationsTestSig {
|
||||
/**
|
||||
* A class representing line comments in Python. As this is the only form of comment Python
|
||||
* permits, we simply reuse the `Comment` class.
|
||||
*/
|
||||
class ExpectationComment = PY::Comment;
|
||||
|
||||
class Location = PY::Location;
|
||||
}
|
||||
@@ -31,10 +31,7 @@ predicate typeTrackerCallEdge(CallNode call, Function callable) {
|
||||
predicate typeTrackerClassCall(CallNode call, Function callable) {
|
||||
exists(call.getLocation().getFile().getRelativePath()) and
|
||||
exists(callable.getLocation().getFile().getRelativePath()) and
|
||||
exists(TT::NormalCall cc |
|
||||
cc = TT::TNormalCall(call, _, any(TT::TCallType t | t instanceof TT::CallTypeClass)) and
|
||||
TT::TFunction(callable) = TT::viableCallable(cc)
|
||||
)
|
||||
TT::resolveCall(call, callable, any(TT::TCallType t | t instanceof TT::CallTypeClass))
|
||||
}
|
||||
|
||||
module CallGraphTest implements TestSig {
|
||||
@@ -65,7 +62,7 @@ string getCallEdgeValue(CallNode call, Function target) {
|
||||
else
|
||||
exists(string fixedRelativePath |
|
||||
fixedRelativePath =
|
||||
target.getLocation().getFile().getRelativePath().regexpCapture(".*/CallGraph[^/]*/(.*)", 1)
|
||||
target.getLocation().getFile().getAbsolutePath().regexpCapture(".*/CallGraph[^/]*/(.*)", 1)
|
||||
|
|
||||
// the value needs to be enclosed in quotes to allow special characters
|
||||
result = "\"" + fixedRelativePath + ":" + betterQualName(target) + "\""
|
||||
|
||||
@@ -3,6 +3,7 @@ import semmle.python.dataflow.new.DataFlow
|
||||
import semmle.python.Concepts
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
private import semmle.python.dataflow.new.internal.PrintNode
|
||||
private import codeql.threatmodels.ThreatModels
|
||||
|
||||
module SystemCommandExecutionTest implements TestSig {
|
||||
string getARelevantTag() { result = "getCommand" }
|
||||
@@ -323,8 +324,8 @@ module HttpResponseHeaderWriteTest implements TestSig {
|
||||
string getARelevantTag() {
|
||||
result =
|
||||
[
|
||||
"headerWriteNameUnsanitized", "headerWriteNameSanitized", "headerWriteValueUnsanitized",
|
||||
"headerWriteValueSanitized", "headerWriteBulk"
|
||||
"headerWriteNameUnsanitized", "headerWriteName", "headerWriteValueUnsanitized",
|
||||
"headerWriteValue", "headerWriteBulk", "headerWriteBulkUnsanitized"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -339,7 +340,7 @@ module HttpResponseHeaderWriteTest implements TestSig {
|
||||
(
|
||||
if write.nameAllowsNewline()
|
||||
then tag = "headerWriteNameUnsanitized"
|
||||
else tag = "headerWriteNameSanitized"
|
||||
else tag = "headerWriteName"
|
||||
) and
|
||||
value = prettyNodeForInlineTest(node)
|
||||
or
|
||||
@@ -347,7 +348,7 @@ module HttpResponseHeaderWriteTest implements TestSig {
|
||||
(
|
||||
if write.valueAllowsNewline()
|
||||
then tag = "headerWriteValueUnsanitized"
|
||||
else tag = "headerWriteValueSanitized"
|
||||
else tag = "headerWriteValue"
|
||||
) and
|
||||
value = prettyNodeForInlineTest(node)
|
||||
)
|
||||
@@ -360,19 +361,20 @@ module HttpResponseHeaderWriteTest implements TestSig {
|
||||
tag = "headerWriteBulk" and
|
||||
value = prettyNodeForInlineTest(node)
|
||||
or
|
||||
tag = "headerWriteBulkUnsanitized" and
|
||||
(
|
||||
if write.nameAllowsNewline()
|
||||
then tag = "headerWriteNameUnsanitized"
|
||||
else tag = "headerWriteNameSanitized"
|
||||
) and
|
||||
value = ""
|
||||
or
|
||||
(
|
||||
if write.valueAllowsNewline()
|
||||
then tag = "headerWriteValueUnsanitized"
|
||||
else tag = "headerWriteValueSanitized"
|
||||
) and
|
||||
value = ""
|
||||
write.nameAllowsNewline() and
|
||||
not write.valueAllowsNewline() and
|
||||
value = "name"
|
||||
or
|
||||
not write.nameAllowsNewline() and
|
||||
write.valueAllowsNewline() and
|
||||
value = "value"
|
||||
or
|
||||
write.nameAllowsNewline() and
|
||||
write.valueAllowsNewline() and
|
||||
value = "name,value"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -404,7 +406,10 @@ module HttpServerHttpRedirectResponseTest implements TestSig {
|
||||
|
||||
module HttpServerCookieWriteTest implements TestSig {
|
||||
string getARelevantTag() {
|
||||
result in ["CookieWrite", "CookieRawHeader", "CookieName", "CookieValue"]
|
||||
result in [
|
||||
"CookieWrite", "CookieRawHeader", "CookieName", "CookieValue", "CookieSecure",
|
||||
"CookieHttpOnly", "CookieSameSite"
|
||||
]
|
||||
}
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
@@ -427,6 +432,20 @@ module HttpServerCookieWriteTest implements TestSig {
|
||||
element = cookieWrite.toString() and
|
||||
value = prettyNodeForInlineTest(cookieWrite.getValueArg()) and
|
||||
tag = "CookieValue"
|
||||
or
|
||||
element = cookieWrite.toString() and
|
||||
value = any(boolean b | cookieWrite.hasSecureFlag(b)).toString() and
|
||||
tag = "CookieSecure"
|
||||
or
|
||||
element = cookieWrite.toString() and
|
||||
value = any(boolean b | cookieWrite.hasHttpOnlyFlag(b)).toString() and
|
||||
tag = "CookieHttpOnly"
|
||||
or
|
||||
element = cookieWrite.toString() and
|
||||
value =
|
||||
any(Http::Server::CookieWrite::SameSiteValue v | cookieWrite.hasSameSiteAttribute(v))
|
||||
.toString() and
|
||||
tag = "CookieSameSite"
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -614,14 +633,44 @@ module XmlParsingTest implements TestSig {
|
||||
}
|
||||
}
|
||||
|
||||
module ThreatModelSourceTest implements TestSig {
|
||||
string getARelevantTag() {
|
||||
exists(string kind | knownThreatModel(kind) | result = "threatModelSource" + "[" + kind + "]")
|
||||
}
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(location.getFile().getRelativePath()) and
|
||||
exists(ThreatModelSource src | not src.getThreatModel() = "remote" |
|
||||
location = src.getLocation() and
|
||||
element = src.toString() and
|
||||
value = prettyNodeForInlineTest(src) and
|
||||
tag = "threatModelSource[" + src.getThreatModel() + "]"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module CorsMiddlewareTest implements TestSig {
|
||||
string getARelevantTag() { result = "CorsMiddleware" }
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(location.getFile().getRelativePath()) and
|
||||
exists(Http::Server::CorsMiddleware cm |
|
||||
location = cm.getLocation() and
|
||||
element = cm.toString() and
|
||||
value = cm.getMiddlewareName().toString() and
|
||||
tag = "CorsMiddleware"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import MakeTest<MergeTests5<MergeTests5<SystemCommandExecutionTest, DecodingTest, EncodingTest, LoggingTest,
|
||||
CodeExecutionTest>,
|
||||
MergeTests5<SqlConstructionTest, SqlExecutionTest, XPathConstructionTest, XPathExecutionTest,
|
||||
EscapingTest>,
|
||||
MergeTests5<HttpServerRouteSetupTest, HttpServerRequestHandlerTest, HttpServerHttpResponseTest,
|
||||
HttpServerHttpRedirectResponseTest,
|
||||
MergeTests<HttpServerCookieWriteTest, HttpResponseHeaderWriteTest>>,
|
||||
MergeTests3<HttpServerCookieWriteTest, HttpResponseHeaderWriteTest, CorsMiddlewareTest>>,
|
||||
MergeTests5<FileSystemAccessTest, FileSystemWriteAccessTest, PathNormalizationTest,
|
||||
SafeAccessCheckTest, PublicKeyGenerationTest>,
|
||||
MergeTests5<CryptographicOperationTest, HttpClientRequestTest, CsrfProtectionSettingTest,
|
||||
CsrfLocalProtectionSettingTest, XmlParsingTest>>>
|
||||
CsrfLocalProtectionSettingTest, MergeTests<XmlParsingTest, ThreatModelSourceTest>>>>
|
||||
|
||||
@@ -15,6 +15,7 @@ import semmle.python.dataflow.new.TaintTracking
|
||||
import semmle.python.dataflow.new.RemoteFlowSources
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
private import semmle.python.dataflow.new.internal.PrintNode
|
||||
private import semmle.python.Concepts
|
||||
|
||||
DataFlow::Node shouldBeTainted() {
|
||||
exists(DataFlow::CallCfgNode call |
|
||||
@@ -45,7 +46,7 @@ module Conf {
|
||||
source.(DataFlow::CfgNode).getNode() = call.getAnArg()
|
||||
)
|
||||
or
|
||||
source instanceof RemoteFlowSource
|
||||
source instanceof ThreatModelSource
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
|
||||
20
python/ql/test/experimental/meta/RemoteFlowSourceTest.qll
Normal file
20
python/ql/test/experimental/meta/RemoteFlowSourceTest.qll
Normal file
@@ -0,0 +1,20 @@
|
||||
import python
|
||||
import semmle.python.dataflow.new.RemoteFlowSources
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
private import semmle.python.dataflow.new.internal.PrintNode
|
||||
|
||||
module SourceTest implements TestSig {
|
||||
string getARelevantTag() { result = "source" }
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(location.getFile().getRelativePath()) and
|
||||
exists(RemoteFlowSource rfs |
|
||||
location = rfs.getLocation() and
|
||||
element = rfs.toString() and
|
||||
value = prettyNode(rfs) and
|
||||
tag = "source"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import MakeTest<SourceTest>
|
||||
@@ -4,5 +4,5 @@ untaintedArgumentToEnsureTaintedNotMarkedAsMissing
|
||||
| taint_test.py:32:9:32:25 | taint_test.py:32 | ERROR, you should add `# $ MISSING: tainted` annotation | should_be_tainted |
|
||||
| taint_test.py:37:24:37:40 | taint_test.py:37 | ERROR, you should add `# $ MISSING: tainted` annotation | should_be_tainted |
|
||||
testFailures
|
||||
| taint_test.py:41:20:41:21 | ts | Fixed missing result:tainted= |
|
||||
| taint_test.py:41:20:41:21 | ts | Fixed missing result: tainted |
|
||||
failures
|
||||
|
||||
@@ -11,7 +11,7 @@ edges
|
||||
| TarSlipImprov.py:38:1:38:3 | ControlFlowNode for tar | TarSlipImprov.py:39:65:39:67 | ControlFlowNode for tar | provenance | |
|
||||
| TarSlipImprov.py:38:7:38:39 | ControlFlowNode for Attribute() | TarSlipImprov.py:38:1:38:3 | ControlFlowNode for tar | provenance | |
|
||||
| TarSlipImprov.py:39:65:39:67 | ControlFlowNode for tar | TarSlipImprov.py:26:21:26:27 | ControlFlowNode for tarfile | provenance | |
|
||||
| TarSlipImprov.py:39:65:39:67 | ControlFlowNode for tar | TarSlipImprov.py:39:49:39:68 | ControlFlowNode for members_filter1() | provenance | |
|
||||
| TarSlipImprov.py:39:65:39:67 | ControlFlowNode for tar | TarSlipImprov.py:39:49:39:68 | ControlFlowNode for members_filter1() | provenance | list.append |
|
||||
| TarSlipImprov.py:43:6:43:38 | ControlFlowNode for Attribute() | TarSlipImprov.py:43:43:43:45 | ControlFlowNode for tar | provenance | |
|
||||
| TarSlipImprov.py:43:43:43:45 | ControlFlowNode for tar | TarSlipImprov.py:44:9:44:13 | ControlFlowNode for entry | provenance | |
|
||||
| TarSlipImprov.py:44:9:44:13 | ControlFlowNode for entry | TarSlipImprov.py:47:21:47:25 | ControlFlowNode for entry | provenance | |
|
||||
@@ -34,7 +34,9 @@ edges
|
||||
| TarSlipImprov.py:142:9:142:13 | ControlFlowNode for entry | TarSlipImprov.py:143:36:143:40 | ControlFlowNode for entry | provenance | |
|
||||
| TarSlipImprov.py:151:14:151:50 | ControlFlowNode for closing() | TarSlipImprov.py:151:55:151:56 | ControlFlowNode for tf | provenance | |
|
||||
| TarSlipImprov.py:151:22:151:49 | ControlFlowNode for Attribute() | TarSlipImprov.py:151:14:151:50 | ControlFlowNode for closing() | provenance | Config |
|
||||
| TarSlipImprov.py:151:55:151:56 | ControlFlowNode for tf | TarSlipImprov.py:152:13:152:20 | ControlFlowNode for Yield | provenance | |
|
||||
| TarSlipImprov.py:151:55:151:56 | ControlFlowNode for tf | TarSlipImprov.py:152:19:152:20 | ControlFlowNode for tf | provenance | |
|
||||
| TarSlipImprov.py:152:13:152:20 | ControlFlowNode for Yield | TarSlipImprov.py:157:18:157:40 | ControlFlowNode for py2_tarxz() | provenance | |
|
||||
| TarSlipImprov.py:152:19:152:20 | ControlFlowNode for tf | TarSlipImprov.py:157:18:157:40 | ControlFlowNode for py2_tarxz() | provenance | |
|
||||
| TarSlipImprov.py:157:9:157:14 | ControlFlowNode for tar_cm | TarSlipImprov.py:162:20:162:23 | ControlFlowNode for tarc | provenance | |
|
||||
| TarSlipImprov.py:157:18:157:40 | ControlFlowNode for py2_tarxz() | TarSlipImprov.py:157:9:157:14 | ControlFlowNode for tar_cm | provenance | |
|
||||
@@ -131,6 +133,7 @@ nodes
|
||||
| TarSlipImprov.py:151:14:151:50 | ControlFlowNode for closing() | semmle.label | ControlFlowNode for closing() |
|
||||
| TarSlipImprov.py:151:22:151:49 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| TarSlipImprov.py:151:55:151:56 | ControlFlowNode for tf | semmle.label | ControlFlowNode for tf |
|
||||
| TarSlipImprov.py:152:13:152:20 | ControlFlowNode for Yield | semmle.label | ControlFlowNode for Yield |
|
||||
| TarSlipImprov.py:152:19:152:20 | ControlFlowNode for tf | semmle.label | ControlFlowNode for tf |
|
||||
| TarSlipImprov.py:157:9:157:14 | ControlFlowNode for tar_cm | semmle.label | ControlFlowNode for tar_cm |
|
||||
| TarSlipImprov.py:157:18:157:40 | ControlFlowNode for py2_tarxz() | semmle.label | ControlFlowNode for py2_tarxz() |
|
||||
|
||||
@@ -75,6 +75,7 @@ edges
|
||||
| UnsafeUnpack.py:161:19:161:21 | ControlFlowNode for tar | UnsafeUnpack.py:163:33:163:35 | ControlFlowNode for tar | provenance | |
|
||||
| UnsafeUnpack.py:161:25:161:46 | ControlFlowNode for Attribute() | UnsafeUnpack.py:161:19:161:21 | ControlFlowNode for tar | provenance | |
|
||||
| UnsafeUnpack.py:161:38:161:45 | ControlFlowNode for savepath | UnsafeUnpack.py:161:25:161:46 | ControlFlowNode for Attribute() | provenance | Config |
|
||||
| UnsafeUnpack.py:161:38:161:45 | ControlFlowNode for savepath | UnsafeUnpack.py:161:25:161:46 | ControlFlowNode for Attribute() | provenance | MaD:69 |
|
||||
| UnsafeUnpack.py:163:23:163:28 | ControlFlowNode for member | UnsafeUnpack.py:166:37:166:42 | ControlFlowNode for member | provenance | |
|
||||
| UnsafeUnpack.py:163:33:163:35 | ControlFlowNode for tar | UnsafeUnpack.py:163:23:163:28 | ControlFlowNode for member | provenance | |
|
||||
| UnsafeUnpack.py:166:23:166:28 | [post] ControlFlowNode for result | UnsafeUnpack.py:167:67:167:72 | ControlFlowNode for result | provenance | |
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from fastapi import FastAPI
|
||||
import asyncssh
|
||||
|
||||
|
||||
app = FastAPI()
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.connect(("host", "port"))
|
||||
session = Session()
|
||||
session.handshake(sock)
|
||||
session.userauth_password("user", "password")
|
||||
|
||||
@app.get("/bad1")
|
||||
async def bad1(cmd: str):
|
||||
async with asyncssh.connect('localhost') as conn:
|
||||
result = await conn.run(cmd, check=True) # $ result=BAD getRemoteCommand=cmd
|
||||
print(result.stdout, end='')
|
||||
return {"success": "Dangerous"}
|
||||
@@ -0,0 +1,2 @@
|
||||
testFailures
|
||||
failures
|
||||
@@ -0,0 +1,23 @@
|
||||
import python
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
import semmle.python.dataflow.new.internal.DataFlowDispatch as DataFlowDispatch
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
private import semmle.python.dataflow.new.internal.PrintNode
|
||||
import experimental.semmle.python.Concepts
|
||||
|
||||
module SystemCommandExecutionTest implements TestSig {
|
||||
string getARelevantTag() { result = "getRemoteCommand" }
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(location.getFile().getRelativePath()) and
|
||||
exists(RemoteCommandExecution sci, DataFlow::Node command |
|
||||
command = sci.getCommand() and
|
||||
location = command.getLocation() and
|
||||
element = command.toString() and
|
||||
value = prettyNodeForInlineTest(command) and
|
||||
tag = "getRemoteCommand"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import MakeTest<SystemCommandExecutionTest>
|
||||
@@ -0,0 +1,3 @@
|
||||
missingAnnotationOnSink
|
||||
testFailures
|
||||
failures
|
||||
@@ -0,0 +1,4 @@
|
||||
import python
|
||||
import TestUtilities.dataflow.DataflowQueryTest
|
||||
import experimental.semmle.python.security.RemoteCommandExecution
|
||||
import FromTaintTrackingConfig<RemoteCommandExecutionConfig>
|
||||
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from fastapi import FastAPI
|
||||
from netmiko import ConnectHandler
|
||||
|
||||
|
||||
app = FastAPI()
|
||||
cisco_881 = {
|
||||
'device_type': 'cisco_ios',
|
||||
'host': '10.10.10.10',
|
||||
'username': 'test',
|
||||
'password': 'password',
|
||||
'port': 8022, # optional, defaults to 22
|
||||
'secret': 'secret', # optional, defaults to ''
|
||||
}
|
||||
|
||||
@app.get("/bad1")
|
||||
async def bad1(cmd: str):
|
||||
net_connect = ConnectHandler(**cisco_881)
|
||||
net_connect.send_command(command_string=cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
net_connect.send_command_expect(command_string=cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
net_connect.send_command_timing(command_string=cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
net_connect.send_multiline(commands=[[cmd, "expect"]]) # $ result=BAD getRemoteCommand=List
|
||||
net_connect.send_multiline_timing(commands=cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
return {"success": "Dangerous"}
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from fastapi import FastAPI
|
||||
from pexpect import pxssh
|
||||
|
||||
ssh = pxssh.pxssh()
|
||||
hostname = "localhost"
|
||||
username = "username"
|
||||
password = "password"
|
||||
ssh.login(hostname, username, password)
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@app.get("/bad1")
|
||||
async def bad1(cmd: str):
|
||||
ssh.send(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
ssh.prompt()
|
||||
ssh.sendline(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
ssh.prompt()
|
||||
ssh.logout()
|
||||
return {"success": stdout}
|
||||
@@ -0,0 +1,88 @@
|
||||
edges
|
||||
| AsyncSsh.py:15:16:15:18 | ControlFlowNode for cmd | AsyncSsh.py:17:33:17:35 | ControlFlowNode for cmd | provenance | |
|
||||
| Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | Netmiko.py:20:45:20:47 | ControlFlowNode for cmd | provenance | |
|
||||
| Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | Netmiko.py:21:52:21:54 | ControlFlowNode for cmd | provenance | |
|
||||
| Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | Netmiko.py:22:52:22:54 | ControlFlowNode for cmd | provenance | |
|
||||
| Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | Netmiko.py:23:41:23:57 | ControlFlowNode for List | provenance | |
|
||||
| Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | Netmiko.py:24:48:24:50 | ControlFlowNode for cmd | provenance | |
|
||||
| Pexpect.py:15:16:15:18 | ControlFlowNode for cmd | Pexpect.py:16:14:16:16 | ControlFlowNode for cmd | provenance | |
|
||||
| Pexpect.py:15:16:15:18 | ControlFlowNode for cmd | Pexpect.py:18:18:18:20 | ControlFlowNode for cmd | provenance | |
|
||||
| Scrapli.py:13:16:13:18 | ControlFlowNode for cmd | Scrapli.py:24:42:24:44 | ControlFlowNode for cmd | provenance | |
|
||||
| Scrapli.py:13:16:13:18 | ControlFlowNode for cmd | Scrapli.py:27:42:27:44 | ControlFlowNode for cmd | provenance | |
|
||||
| Scrapli.py:13:16:13:18 | ControlFlowNode for cmd | Scrapli.py:30:42:30:44 | ControlFlowNode for cmd | provenance | |
|
||||
| Scrapli.py:13:16:13:18 | ControlFlowNode for cmd | Scrapli.py:33:42:33:44 | ControlFlowNode for cmd | provenance | |
|
||||
| Scrapli.py:13:16:13:18 | ControlFlowNode for cmd | Scrapli.py:36:42:36:44 | ControlFlowNode for cmd | provenance | |
|
||||
| Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | Scrapli.py:51:36:51:38 | ControlFlowNode for cmd | provenance | |
|
||||
| Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | Scrapli.py:54:36:54:38 | ControlFlowNode for cmd | provenance | |
|
||||
| Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | Scrapli.py:57:36:57:38 | ControlFlowNode for cmd | provenance | |
|
||||
| Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | Scrapli.py:60:36:60:38 | ControlFlowNode for cmd | provenance | |
|
||||
| Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | Scrapli.py:63:36:63:38 | ControlFlowNode for cmd | provenance | |
|
||||
| Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | Scrapli.py:74:36:74:38 | ControlFlowNode for cmd | provenance | |
|
||||
| Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | Scrapli.py:84:36:84:38 | ControlFlowNode for cmd | provenance | |
|
||||
| Twisted.py:13:16:13:18 | ControlFlowNode for cmd | Twisted.py:16:5:16:7 | ControlFlowNode for cmd | provenance | |
|
||||
| Twisted.py:13:16:13:18 | ControlFlowNode for cmd | Twisted.py:24:9:24:11 | ControlFlowNode for cmd | provenance | |
|
||||
| paramiko.py:15:16:15:18 | ControlFlowNode for cmd | paramiko.py:16:62:16:64 | ControlFlowNode for cmd | provenance | |
|
||||
| paramiko.py:20:16:20:18 | ControlFlowNode for cmd | paramiko.py:21:70:21:72 | ControlFlowNode for cmd | provenance | |
|
||||
| ssh2.py:15:16:15:18 | ControlFlowNode for cmd | ssh2.py:17:21:17:23 | ControlFlowNode for cmd | provenance | |
|
||||
nodes
|
||||
| AsyncSsh.py:15:16:15:18 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| AsyncSsh.py:17:33:17:35 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Netmiko.py:20:45:20:47 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Netmiko.py:21:52:21:54 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Netmiko.py:22:52:22:54 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Netmiko.py:23:41:23:57 | ControlFlowNode for List | semmle.label | ControlFlowNode for List |
|
||||
| Netmiko.py:24:48:24:50 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Pexpect.py:15:16:15:18 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Pexpect.py:16:14:16:16 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Pexpect.py:18:18:18:20 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Scrapli.py:13:16:13:18 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Scrapli.py:24:42:24:44 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Scrapli.py:27:42:27:44 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Scrapli.py:30:42:30:44 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Scrapli.py:33:42:33:44 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Scrapli.py:36:42:36:44 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Scrapli.py:51:36:51:38 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Scrapli.py:54:36:54:38 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Scrapli.py:57:36:57:38 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Scrapli.py:60:36:60:38 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Scrapli.py:63:36:63:38 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Scrapli.py:74:36:74:38 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Scrapli.py:84:36:84:38 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Twisted.py:13:16:13:18 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Twisted.py:16:5:16:7 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| Twisted.py:24:9:24:11 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| paramiko.py:15:16:15:18 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| paramiko.py:16:62:16:64 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| paramiko.py:20:16:20:18 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| paramiko.py:21:70:21:72 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| ssh2.py:15:16:15:18 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
| ssh2.py:17:21:17:23 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
|
||||
subpaths
|
||||
#select
|
||||
| AsyncSsh.py:17:33:17:35 | ControlFlowNode for cmd | AsyncSsh.py:15:16:15:18 | ControlFlowNode for cmd | AsyncSsh.py:17:33:17:35 | ControlFlowNode for cmd | This code execution depends on a $@. | AsyncSsh.py:15:16:15:18 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Netmiko.py:20:45:20:47 | ControlFlowNode for cmd | Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | Netmiko.py:20:45:20:47 | ControlFlowNode for cmd | This code execution depends on a $@. | Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Netmiko.py:21:52:21:54 | ControlFlowNode for cmd | Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | Netmiko.py:21:52:21:54 | ControlFlowNode for cmd | This code execution depends on a $@. | Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Netmiko.py:22:52:22:54 | ControlFlowNode for cmd | Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | Netmiko.py:22:52:22:54 | ControlFlowNode for cmd | This code execution depends on a $@. | Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Netmiko.py:23:41:23:57 | ControlFlowNode for List | Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | Netmiko.py:23:41:23:57 | ControlFlowNode for List | This code execution depends on a $@. | Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Netmiko.py:24:48:24:50 | ControlFlowNode for cmd | Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | Netmiko.py:24:48:24:50 | ControlFlowNode for cmd | This code execution depends on a $@. | Netmiko.py:18:16:18:18 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Pexpect.py:16:14:16:16 | ControlFlowNode for cmd | Pexpect.py:15:16:15:18 | ControlFlowNode for cmd | Pexpect.py:16:14:16:16 | ControlFlowNode for cmd | This code execution depends on a $@. | Pexpect.py:15:16:15:18 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Pexpect.py:18:18:18:20 | ControlFlowNode for cmd | Pexpect.py:15:16:15:18 | ControlFlowNode for cmd | Pexpect.py:18:18:18:20 | ControlFlowNode for cmd | This code execution depends on a $@. | Pexpect.py:15:16:15:18 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Scrapli.py:24:42:24:44 | ControlFlowNode for cmd | Scrapli.py:13:16:13:18 | ControlFlowNode for cmd | Scrapli.py:24:42:24:44 | ControlFlowNode for cmd | This code execution depends on a $@. | Scrapli.py:13:16:13:18 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Scrapli.py:27:42:27:44 | ControlFlowNode for cmd | Scrapli.py:13:16:13:18 | ControlFlowNode for cmd | Scrapli.py:27:42:27:44 | ControlFlowNode for cmd | This code execution depends on a $@. | Scrapli.py:13:16:13:18 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Scrapli.py:30:42:30:44 | ControlFlowNode for cmd | Scrapli.py:13:16:13:18 | ControlFlowNode for cmd | Scrapli.py:30:42:30:44 | ControlFlowNode for cmd | This code execution depends on a $@. | Scrapli.py:13:16:13:18 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Scrapli.py:33:42:33:44 | ControlFlowNode for cmd | Scrapli.py:13:16:13:18 | ControlFlowNode for cmd | Scrapli.py:33:42:33:44 | ControlFlowNode for cmd | This code execution depends on a $@. | Scrapli.py:13:16:13:18 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Scrapli.py:36:42:36:44 | ControlFlowNode for cmd | Scrapli.py:13:16:13:18 | ControlFlowNode for cmd | Scrapli.py:36:42:36:44 | ControlFlowNode for cmd | This code execution depends on a $@. | Scrapli.py:13:16:13:18 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Scrapli.py:51:36:51:38 | ControlFlowNode for cmd | Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | Scrapli.py:51:36:51:38 | ControlFlowNode for cmd | This code execution depends on a $@. | Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Scrapli.py:54:36:54:38 | ControlFlowNode for cmd | Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | Scrapli.py:54:36:54:38 | ControlFlowNode for cmd | This code execution depends on a $@. | Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Scrapli.py:57:36:57:38 | ControlFlowNode for cmd | Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | Scrapli.py:57:36:57:38 | ControlFlowNode for cmd | This code execution depends on a $@. | Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Scrapli.py:60:36:60:38 | ControlFlowNode for cmd | Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | Scrapli.py:60:36:60:38 | ControlFlowNode for cmd | This code execution depends on a $@. | Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Scrapli.py:63:36:63:38 | ControlFlowNode for cmd | Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | Scrapli.py:63:36:63:38 | ControlFlowNode for cmd | This code execution depends on a $@. | Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Scrapli.py:74:36:74:38 | ControlFlowNode for cmd | Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | Scrapli.py:74:36:74:38 | ControlFlowNode for cmd | This code execution depends on a $@. | Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Scrapli.py:84:36:84:38 | ControlFlowNode for cmd | Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | Scrapli.py:84:36:84:38 | ControlFlowNode for cmd | This code execution depends on a $@. | Scrapli.py:40:10:40:12 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Twisted.py:16:5:16:7 | ControlFlowNode for cmd | Twisted.py:13:16:13:18 | ControlFlowNode for cmd | Twisted.py:16:5:16:7 | ControlFlowNode for cmd | This code execution depends on a $@. | Twisted.py:13:16:13:18 | ControlFlowNode for cmd | a user-provided value |
|
||||
| Twisted.py:24:9:24:11 | ControlFlowNode for cmd | Twisted.py:13:16:13:18 | ControlFlowNode for cmd | Twisted.py:24:9:24:11 | ControlFlowNode for cmd | This code execution depends on a $@. | Twisted.py:13:16:13:18 | ControlFlowNode for cmd | a user-provided value |
|
||||
| paramiko.py:16:62:16:64 | ControlFlowNode for cmd | paramiko.py:15:16:15:18 | ControlFlowNode for cmd | paramiko.py:16:62:16:64 | ControlFlowNode for cmd | This code execution depends on a $@. | paramiko.py:15:16:15:18 | ControlFlowNode for cmd | a user-provided value |
|
||||
| paramiko.py:21:70:21:72 | ControlFlowNode for cmd | paramiko.py:20:16:20:18 | ControlFlowNode for cmd | paramiko.py:21:70:21:72 | ControlFlowNode for cmd | This code execution depends on a $@. | paramiko.py:20:16:20:18 | ControlFlowNode for cmd | a user-provided value |
|
||||
| ssh2.py:17:21:17:23 | ControlFlowNode for cmd | ssh2.py:15:16:15:18 | ControlFlowNode for cmd | ssh2.py:17:21:17:23 | ControlFlowNode for cmd | This code execution depends on a $@. | ssh2.py:15:16:15:18 | ControlFlowNode for cmd | a user-provided value |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE-074/remoteCommandExecution/RemoteCommandExecution.ql
|
||||
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from fastapi import FastAPI
|
||||
from scrapli import Scrapli
|
||||
from scrapli.driver.core import AsyncNXOSDriver, AsyncJunosDriver, AsyncEOSDriver, AsyncIOSXEDriver, AsyncIOSXRDriver
|
||||
from scrapli.driver.core import NXOSDriver, JunosDriver, EOSDriver, IOSXEDriver, IOSXRDriver
|
||||
from scrapli.driver import GenericDriver
|
||||
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@app.get("/bad1")
|
||||
async def bad1(cmd: str):
|
||||
dev_connect = {
|
||||
"host": host,
|
||||
"auth_username": user,
|
||||
"auth_password": password,
|
||||
"port": port,
|
||||
"auth_strict_key": False,
|
||||
"transport": "asyncssh",
|
||||
}
|
||||
driver = AsyncIOSXEDriver
|
||||
async with driver(**dev_connect) as conn:
|
||||
output = await conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
driver = AsyncIOSXRDriver
|
||||
async with driver(**dev_connect) as conn:
|
||||
output = await conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
driver = AsyncNXOSDriver
|
||||
async with driver(**dev_connect) as conn:
|
||||
output = await conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
driver = AsyncEOSDriver
|
||||
async with driver(**dev_connect) as conn:
|
||||
output = await conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
driver = AsyncJunosDriver
|
||||
async with driver(**dev_connect) as conn:
|
||||
output = await conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
return {"success": "Dangerous"}
|
||||
|
||||
@app.get("/bad1")
|
||||
def bad2(cmd: str):
|
||||
dev_connect = {
|
||||
"host": host,
|
||||
"auth_username": user,
|
||||
"auth_password": password,
|
||||
"port": port,
|
||||
"auth_strict_key": False,
|
||||
"transport": "ssh2",
|
||||
}
|
||||
driver = NXOSDriver
|
||||
with driver(**dev_connect) as conn:
|
||||
output = conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
driver = IOSXRDriver
|
||||
with driver(**dev_connect) as conn:
|
||||
output = conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
driver = IOSXEDriver
|
||||
with driver(**dev_connect) as conn:
|
||||
output = conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
driver = EOSDriver
|
||||
with driver(**dev_connect) as conn:
|
||||
output = conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
driver = JunosDriver
|
||||
with driver(**dev_connect) as conn:
|
||||
output = conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
|
||||
dev_connect = {
|
||||
"host": "65.65.65.65",
|
||||
"auth_username": "root",
|
||||
"auth_private_key": "keyPath",
|
||||
"auth_strict_key": False,
|
||||
"transport": "ssh2",
|
||||
"platform": "cisco_iosxe",
|
||||
}
|
||||
with Scrapli(**dev_connect) as conn:
|
||||
result = conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
|
||||
dev_connect = {
|
||||
"host": "65.65.65.65",
|
||||
"auth_username": "root",
|
||||
"auth_password": "password",
|
||||
"auth_strict_key": False,
|
||||
"transport": "ssh2",
|
||||
}
|
||||
with GenericDriver(**dev_connect) as conn:
|
||||
result = conn.send_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
return {"success": "Dangerous"}
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from fastapi import FastAPI
|
||||
from twisted.conch.endpoints import SSHCommandClientEndpoint
|
||||
from twisted.internet.protocol import Factory
|
||||
from twisted.internet import reactor
|
||||
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/bad1")
|
||||
async def bad1(cmd: bytes):
|
||||
endpoint = SSHCommandClientEndpoint.newConnection(
|
||||
reactor,
|
||||
cmd, # $ result=BAD getRemoteCommand=cmd
|
||||
b"username",
|
||||
b"ssh.example.com",
|
||||
22,
|
||||
password=b"password")
|
||||
|
||||
SSHCommandClientEndpoint.existingConnection(
|
||||
endpoint,
|
||||
cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
|
||||
factory = Factory()
|
||||
d = endpoint.connect(factory)
|
||||
d.addCallback(lambda protocol: protocol.finished)
|
||||
|
||||
return {"success": "Dangerous"}
|
||||
@@ -12,16 +12,11 @@ app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/bad1")
|
||||
async def read_item(cmd: str):
|
||||
stdin, stdout, stderr = paramiko_ssh_client.exec_command(cmd)
|
||||
return {"success": stdout}
|
||||
async def bad1(cmd: str):
|
||||
stdin, stdout, stderr = paramiko_ssh_client.exec_command(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
return {"success": "Dangerous"}
|
||||
|
||||
@app.get("/bad2")
|
||||
async def read_item(cmd: str):
|
||||
stdin, stdout, stderr = paramiko_ssh_client.exec_command(command=cmd)
|
||||
return {"success": "OK"}
|
||||
|
||||
@app.get("/bad3")
|
||||
async def read_item(cmd: str):
|
||||
stdin, stdout, stderr = paramiko_ssh_client.connect('hostname', username='user',password='yourpassword',sock=paramiko.ProxyCommand(cmd))
|
||||
return {"success": "OK"}
|
||||
async def bad2(cmd: str):
|
||||
stdin, stdout, stderr = paramiko_ssh_client.exec_command(command=cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
return {"success": "Dangerous"}
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from fastapi import FastAPI
|
||||
from socket import socket
|
||||
from ssh2.session import Session
|
||||
|
||||
app = FastAPI()
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.connect(("host", "port"))
|
||||
session = Session()
|
||||
session.handshake(sock)
|
||||
session.userauth_password("user", "password")
|
||||
|
||||
@app.get("/bad1")
|
||||
async def bad1(cmd: str):
|
||||
channel = session.open_session()
|
||||
channel.execute(cmd) # $ result=BAD getRemoteCommand=cmd
|
||||
channel.wait_eof()
|
||||
channel.close()
|
||||
channel.wait_closed()
|
||||
return {"success": "Dangerous"}
|
||||
@@ -1 +0,0 @@
|
||||
experimental/Security/CWE-074/paramiko/paramiko.ql
|
||||
@@ -0,0 +1,10 @@
|
||||
edges
|
||||
| Js2PyTest.py:9:5:9:6 | ControlFlowNode for jk | Js2PyTest.py:10:18:10:28 | ControlFlowNode for Fstring | provenance | |
|
||||
| Js2PyTest.py:9:10:9:22 | ControlFlowNode for Attribute | Js2PyTest.py:9:5:9:6 | ControlFlowNode for jk | provenance | AdditionalTaintStep |
|
||||
nodes
|
||||
| Js2PyTest.py:9:5:9:6 | ControlFlowNode for jk | semmle.label | ControlFlowNode for jk |
|
||||
| Js2PyTest.py:9:10:9:22 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
|
||||
| Js2PyTest.py:10:18:10:28 | ControlFlowNode for Fstring | semmle.label | ControlFlowNode for Fstring |
|
||||
subpaths
|
||||
#select
|
||||
| Js2PyTest.py:10:18:10:28 | ControlFlowNode for Fstring | Js2PyTest.py:9:10:9:22 | ControlFlowNode for Attribute | Js2PyTest.py:10:18:10:28 | ControlFlowNode for Fstring | This input to Js2Py depends on a $@. | Js2PyTest.py:9:10:9:22 | ControlFlowNode for Attribute | user-provided value |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE-094/Js2Py.ql
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
import flask
|
||||
from js2py import eval_js, disable_pyimport
|
||||
|
||||
bp = flask.Blueprint("app", __name__, url_prefix="/")
|
||||
|
||||
@bp.route("/bad")
|
||||
def bad():
|
||||
jk = flask.request.form["jk"]
|
||||
jk = eval_js(f"{jk} f()")
|
||||
@@ -0,0 +1,17 @@
|
||||
import cherrypy
|
||||
|
||||
def bad():
|
||||
request = cherrypy.request
|
||||
validCors = "domain.com"
|
||||
if request.method in ['POST', 'PUT', 'PATCH', 'DELETE']:
|
||||
origin = request.headers.get('Origin', None)
|
||||
if origin.startswith(validCors):
|
||||
print("Origin Valid")
|
||||
|
||||
def good():
|
||||
request = cherrypy.request
|
||||
validOrigin = "domain.com"
|
||||
if request.method in ['POST', 'PUT', 'PATCH', 'DELETE']:
|
||||
origin = request.headers.get('Origin', None)
|
||||
if origin == validOrigin:
|
||||
print("Origin Valid")
|
||||
@@ -0,0 +1,13 @@
|
||||
edges
|
||||
| Cors.py:7:9:7:14 | ControlFlowNode for origin | Cors.py:8:12:8:17 | ControlFlowNode for origin | provenance | |
|
||||
| Cors.py:7:18:7:32 | ControlFlowNode for Attribute | Cors.py:7:18:7:52 | ControlFlowNode for Attribute() | provenance | Config |
|
||||
| Cors.py:7:18:7:32 | ControlFlowNode for Attribute | Cors.py:7:18:7:52 | ControlFlowNode for Attribute() | provenance | dict.get |
|
||||
| Cors.py:7:18:7:52 | ControlFlowNode for Attribute() | Cors.py:7:9:7:14 | ControlFlowNode for origin | provenance | |
|
||||
nodes
|
||||
| Cors.py:7:9:7:14 | ControlFlowNode for origin | semmle.label | ControlFlowNode for origin |
|
||||
| Cors.py:7:18:7:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
|
||||
| Cors.py:7:18:7:52 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| Cors.py:8:12:8:17 | ControlFlowNode for origin | semmle.label | ControlFlowNode for origin |
|
||||
subpaths
|
||||
#select
|
||||
| Cors.py:8:12:8:17 | ControlFlowNode for origin | Cors.py:7:18:7:32 | ControlFlowNode for Attribute | Cors.py:8:12:8:17 | ControlFlowNode for origin | Potentially incorrect string comparison which could lead to a CORS bypass. |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE-346/CorsBypass.ql
|
||||
@@ -1,13 +1,23 @@
|
||||
edges
|
||||
| test.py:10:16:10:24 | ControlFlowNode for file_path | test.py:11:21:11:29 | ControlFlowNode for file_path | provenance | |
|
||||
| test.py:11:5:11:35 | ControlFlowNode for Attribute() | test.py:11:5:11:52 | ControlFlowNode for Attribute() | provenance | Config |
|
||||
| test.py:11:21:11:29 | ControlFlowNode for file_path | test.py:11:5:11:35 | ControlFlowNode for Attribute() | provenance | MaD:85 |
|
||||
| test.py:11:21:11:29 | ControlFlowNode for file_path | test.py:11:5:11:52 | ControlFlowNode for Attribute() | provenance | Config |
|
||||
| test.py:11:21:11:29 | ControlFlowNode for file_path | test.py:12:21:12:29 | ControlFlowNode for file_path | provenance | |
|
||||
| test.py:12:5:12:35 | ControlFlowNode for Attribute() | test.py:12:5:12:48 | ControlFlowNode for Attribute() | provenance | Config |
|
||||
| test.py:12:21:12:29 | ControlFlowNode for file_path | test.py:12:5:12:35 | ControlFlowNode for Attribute() | provenance | MaD:85 |
|
||||
| test.py:12:21:12:29 | ControlFlowNode for file_path | test.py:12:5:12:48 | ControlFlowNode for Attribute() | provenance | Config |
|
||||
| test.py:12:21:12:29 | ControlFlowNode for file_path | test.py:14:26:14:34 | ControlFlowNode for file_path | provenance | |
|
||||
| test.py:14:10:14:35 | ControlFlowNode for Attribute() | test.py:15:14:15:29 | ControlFlowNode for Attribute() | provenance | Config |
|
||||
| test.py:14:26:14:34 | ControlFlowNode for file_path | test.py:14:10:14:35 | ControlFlowNode for Attribute() | provenance | MaD:85 |
|
||||
| test.py:14:26:14:34 | ControlFlowNode for file_path | test.py:15:14:15:29 | ControlFlowNode for Attribute() | provenance | Config |
|
||||
| test.py:14:26:14:34 | ControlFlowNode for file_path | test.py:18:26:18:34 | ControlFlowNode for file_path | provenance | |
|
||||
| test.py:18:10:18:35 | ControlFlowNode for Attribute() | test.py:19:14:19:39 | ControlFlowNode for Attribute() | provenance | Config |
|
||||
| test.py:18:26:18:34 | ControlFlowNode for file_path | test.py:18:10:18:35 | ControlFlowNode for Attribute() | provenance | MaD:85 |
|
||||
| test.py:18:26:18:34 | ControlFlowNode for file_path | test.py:19:14:19:39 | ControlFlowNode for Attribute() | provenance | Config |
|
||||
| test.py:18:26:18:34 | ControlFlowNode for file_path | test.py:22:21:22:29 | ControlFlowNode for file_path | provenance | |
|
||||
| test.py:22:5:22:30 | ControlFlowNode for Attribute() | test.py:22:5:22:60 | ControlFlowNode for Attribute() | provenance | Config |
|
||||
| test.py:22:21:22:29 | ControlFlowNode for file_path | test.py:22:5:22:30 | ControlFlowNode for Attribute() | provenance | MaD:85 |
|
||||
| test.py:22:21:22:29 | ControlFlowNode for file_path | test.py:22:5:22:60 | ControlFlowNode for Attribute() | provenance | Config |
|
||||
| test.py:22:21:22:29 | ControlFlowNode for file_path | test.py:24:18:24:26 | ControlFlowNode for file_path | provenance | |
|
||||
| test.py:24:18:24:26 | ControlFlowNode for file_path | test.py:24:5:24:52 | ControlFlowNode for Attribute() | provenance | Config |
|
||||
@@ -37,14 +47,19 @@ edges
|
||||
| test.py:28:26:28:34 | ControlFlowNode for file_path | test.py:64:36:64:44 | ControlFlowNode for file_path | provenance | |
|
||||
nodes
|
||||
| test.py:10:16:10:24 | ControlFlowNode for file_path | semmle.label | ControlFlowNode for file_path |
|
||||
| test.py:11:5:11:35 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| test.py:11:5:11:52 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| test.py:11:21:11:29 | ControlFlowNode for file_path | semmle.label | ControlFlowNode for file_path |
|
||||
| test.py:12:5:12:35 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| test.py:12:5:12:48 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| test.py:12:21:12:29 | ControlFlowNode for file_path | semmle.label | ControlFlowNode for file_path |
|
||||
| test.py:14:10:14:35 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| test.py:14:26:14:34 | ControlFlowNode for file_path | semmle.label | ControlFlowNode for file_path |
|
||||
| test.py:15:14:15:29 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| test.py:18:10:18:35 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| test.py:18:26:18:34 | ControlFlowNode for file_path | semmle.label | ControlFlowNode for file_path |
|
||||
| test.py:19:14:19:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| test.py:22:5:22:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| test.py:22:5:22:60 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| test.py:22:21:22:29 | ControlFlowNode for file_path | semmle.label | ControlFlowNode for file_path |
|
||||
| test.py:24:5:24:52 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
edges
|
||||
| flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:1:26:1:32 | ControlFlowNode for request | provenance | |
|
||||
| flask_bad.py:1:26:1:32 | ControlFlowNode for request | flask_bad.py:24:21:24:27 | ControlFlowNode for request | provenance | |
|
||||
| flask_bad.py:1:26:1:32 | ControlFlowNode for request | flask_bad.py:24:49:24:55 | ControlFlowNode for request | provenance | |
|
||||
| flask_bad.py:1:26:1:32 | ControlFlowNode for request | flask_bad.py:32:37:32:43 | ControlFlowNode for request | provenance | |
|
||||
| flask_bad.py:1:26:1:32 | ControlFlowNode for request | flask_bad.py:32:60:32:66 | ControlFlowNode for request | provenance | |
|
||||
| flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | provenance | AdditionalTaintStep |
|
||||
| flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | provenance | AdditionalTaintStep |
|
||||
| flask_bad.py:24:49:24:55 | ControlFlowNode for request | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | provenance | AdditionalTaintStep |
|
||||
| flask_bad.py:32:37:32:43 | ControlFlowNode for request | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | provenance | AdditionalTaintStep |
|
||||
| flask_bad.py:32:60:32:66 | ControlFlowNode for request | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | provenance | AdditionalTaintStep |
|
||||
nodes
|
||||
| django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
|
||||
| flask_bad.py:1:26:1:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
|
||||
| flask_bad.py:24:21:24:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
|
||||
| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| flask_bad.py:24:49:24:55 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
|
||||
| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
|
||||
| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | semmle.label | ControlFlowNode for Fstring |
|
||||
| flask_bad.py:32:37:32:43 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
|
||||
| flask_bad.py:32:60:32:66 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
|
||||
subpaths
|
||||
#select
|
||||
| django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | Cookie is constructed from a $@,and its httponly flag is not properly set. | django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | user-supplied input |
|
||||
| django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | Cookie is constructed from a $@,and its samesite flag is not properly set. | django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | user-supplied input |
|
||||
| django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | Cookie is constructed from a $@,and its secure flag is not properly set. | django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | user-supplied input |
|
||||
| django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | Cookie is constructed from a $@,and its httponly flag is not properly set. | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | user-supplied input |
|
||||
| django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | Cookie is constructed from a $@,and its samesite flag is not properly set. | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | user-supplied input |
|
||||
| django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | Cookie is constructed from a $@,and its secure flag is not properly set. | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | user-supplied input |
|
||||
| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
|
||||
| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
|
||||
| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
|
||||
| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
|
||||
| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
|
||||
| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
|
||||
| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
|
||||
| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
|
||||
| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
|
||||
@@ -1 +0,0 @@
|
||||
experimental/Security/CWE-614/CookieInjection.ql
|
||||
@@ -1,24 +0,0 @@
|
||||
| django_bad.py:6:5:7:52 | ControlFlowNode for Attribute() | Cookie is added without the 'httponly' flag properly set. |
|
||||
| django_bad.py:6:5:7:52 | ControlFlowNode for Attribute() | Cookie is added without the 'samesite' flag properly set. |
|
||||
| django_bad.py:6:5:7:52 | ControlFlowNode for Attribute() | Cookie is added without the 'secure' flag properly set. |
|
||||
| django_bad.py:19:5:21:66 | ControlFlowNode for Attribute() | Cookie is added without the 'httponly' flag properly set. |
|
||||
| django_bad.py:19:5:21:66 | ControlFlowNode for Attribute() | Cookie is added without the 'samesite' flag properly set. |
|
||||
| django_bad.py:19:5:21:66 | ControlFlowNode for Attribute() | Cookie is added without the 'secure' flag properly set. |
|
||||
| django_good.py:19:5:19:44 | ControlFlowNode for Attribute() | Cookie is added without the 'httponly' flag properly set. |
|
||||
| django_good.py:19:5:19:44 | ControlFlowNode for Attribute() | Cookie is added without the 'samesite' flag properly set. |
|
||||
| django_good.py:19:5:19:44 | ControlFlowNode for Attribute() | Cookie is added without the 'secure' flag properly set. |
|
||||
| flask_bad.py:9:5:10:52 | ControlFlowNode for Attribute() | Cookie is added without the 'httponly' flag properly set. |
|
||||
| flask_bad.py:9:5:10:52 | ControlFlowNode for Attribute() | Cookie is added without the 'samesite' flag properly set. |
|
||||
| flask_bad.py:9:5:10:52 | ControlFlowNode for Attribute() | Cookie is added without the 'secure' flag properly set. |
|
||||
| flask_bad.py:17:5:17:30 | ControlFlowNode for Subscript | Cookie is added without the 'httponly' flag properly set. |
|
||||
| flask_bad.py:17:5:17:30 | ControlFlowNode for Subscript | Cookie is added without the 'samesite' flag properly set. |
|
||||
| flask_bad.py:17:5:17:30 | ControlFlowNode for Subscript | Cookie is added without the 'secure' flag properly set. |
|
||||
| flask_bad.py:24:5:25:52 | ControlFlowNode for Attribute() | Cookie is added without the 'httponly' flag properly set. |
|
||||
| flask_bad.py:24:5:25:52 | ControlFlowNode for Attribute() | Cookie is added without the 'samesite' flag properly set. |
|
||||
| flask_bad.py:24:5:25:52 | ControlFlowNode for Attribute() | Cookie is added without the 'secure' flag properly set. |
|
||||
| flask_bad.py:32:5:32:30 | ControlFlowNode for Subscript | Cookie is added without the 'httponly' flag properly set. |
|
||||
| flask_bad.py:32:5:32:30 | ControlFlowNode for Subscript | Cookie is added without the 'samesite' flag properly set. |
|
||||
| flask_bad.py:32:5:32:30 | ControlFlowNode for Subscript | Cookie is added without the 'secure' flag properly set. |
|
||||
| flask_good.py:23:5:23:57 | ControlFlowNode for Attribute() | Cookie is added without the 'httponly' flag properly set. |
|
||||
| flask_good.py:23:5:23:57 | ControlFlowNode for Attribute() | Cookie is added without the 'samesite' flag properly set. |
|
||||
| flask_good.py:23:5:23:57 | ControlFlowNode for Attribute() | Cookie is added without the 'secure' flag properly set. |
|
||||
@@ -1 +0,0 @@
|
||||
experimental/Security/CWE-614/InsecureCookie.ql
|
||||
@@ -1,28 +0,0 @@
|
||||
import django.http
|
||||
|
||||
|
||||
def django_response(request):
|
||||
resp = django.http.HttpResponse()
|
||||
resp.set_cookie("name", "value", secure=False,
|
||||
httponly=False, samesite='None')
|
||||
return resp
|
||||
|
||||
# This test no longer produces an output due to django header setting methods not being modeled in the main query pack
|
||||
def django_response():
|
||||
response = django.http.HttpResponse()
|
||||
response['Set-Cookie'] = "name=value; SameSite=None;"
|
||||
return response
|
||||
|
||||
|
||||
def django_response(request):
|
||||
resp = django.http.HttpResponse()
|
||||
resp.set_cookie(django.http.request.GET.get("name"),
|
||||
django.http.request.GET.get("value"),
|
||||
secure=False, httponly=False, samesite='None')
|
||||
return resp
|
||||
|
||||
# This test no longer produces an output due to django header setting methods not being modeled in the main query pack
|
||||
def django_response():
|
||||
response = django.http.HttpResponse()
|
||||
response['Set-Cookie'] = f"{django.http.request.GET.get('name')}={django.http.request.GET.get('value')}; SameSite=None;"
|
||||
return response
|
||||
@@ -1,20 +0,0 @@
|
||||
import django.http
|
||||
|
||||
|
||||
def django_response(request):
|
||||
resp = django.http.HttpResponse()
|
||||
resp['Set-Cookie'] = "name=value; Secure; HttpOnly; SameSite=Lax;"
|
||||
return resp
|
||||
|
||||
|
||||
def django_response(request):
|
||||
resp = django.http.HttpResponse()
|
||||
resp.set_cookie("name", "value", secure=True,
|
||||
httponly=True, samesite='Lax')
|
||||
return resp
|
||||
|
||||
|
||||
def indeterminate(secure):
|
||||
resp = django.http.HttpResponse()
|
||||
resp.set_cookie("name", "value", secure)
|
||||
return resp
|
||||
@@ -1,37 +0,0 @@
|
||||
from flask import Flask, request, make_response, Response
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
@app.route("/1")
|
||||
def false():
|
||||
resp = make_response()
|
||||
resp.set_cookie("name", value="value", secure=False,
|
||||
httponly=False, samesite='None')
|
||||
return resp
|
||||
|
||||
|
||||
@app.route("/2")
|
||||
def flask_Response():
|
||||
resp = Response()
|
||||
resp.headers['Set-Cookie'] = "name=value; SameSite=None;"
|
||||
return resp
|
||||
|
||||
|
||||
@app.route("/3")
|
||||
def false():
|
||||
resp = make_response()
|
||||
resp.set_cookie(request.args["name"], value=request.args["value"], secure=False,
|
||||
httponly=False, samesite='None')
|
||||
return resp
|
||||
|
||||
|
||||
@app.route("/4")
|
||||
def flask_Response():
|
||||
resp = Response()
|
||||
resp.headers['Set-Cookie'] = f"{request.args['name']}={request.args['value']}; SameSite=None;"
|
||||
return resp
|
||||
|
||||
|
||||
# if __name__ == "__main__":
|
||||
# app.run(debug=True)
|
||||
@@ -1,28 +0,0 @@
|
||||
from flask import Flask, request, make_response, Response
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
@app.route("/1")
|
||||
def true():
|
||||
resp = make_response()
|
||||
resp.set_cookie("name", value="value", secure=True,
|
||||
httponly=True, samesite='Lax')
|
||||
return resp
|
||||
|
||||
|
||||
@app.route("/2")
|
||||
def flask_Response():
|
||||
resp = Response()
|
||||
resp.headers['Set-Cookie'] = "name=value; Secure; HttpOnly; SameSite=Lax;"
|
||||
return resp
|
||||
|
||||
|
||||
def indeterminate(secure):
|
||||
resp = make_response()
|
||||
resp.set_cookie("name", value="value", secure=secure)
|
||||
return resp
|
||||
|
||||
|
||||
# if __name__ == "__main__":
|
||||
# app.run(debug=True)
|
||||
@@ -1 +1 @@
|
||||
semmle-extractor-options: --path path1 -p path2 -R . --filter exclude:**/src_archive/**
|
||||
semmle-extractor-options: --path path1 -p path2 -R . --filter exclude:**/*.testproj/**
|
||||
|
||||
@@ -1 +1 @@
|
||||
semmle-extractor-options: -v --filter include:**/*.py --filter exclude:**/*test.py -R . --filter exclude:**/foo/exclude_this.py --filter include:**/include*.py --filter exclude:**/src_archive/**
|
||||
semmle-extractor-options: -v --filter include:**/*.py --filter exclude:**/*test.py -R . --filter exclude:**/foo/exclude_this.py --filter include:**/include*.py --filter exclude:**/*.testproj/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
| options.all | False |
|
||||
| options.colorize | True |
|
||||
| options.context_cost | 11 |
|
||||
| options.extract_stdlib | True |
|
||||
| options.extract_stdlib | False |
|
||||
| options.guess | False |
|
||||
| options.help | False |
|
||||
| options.ignore_missing_modules | False |
|
||||
|
||||
@@ -1 +1 @@
|
||||
semmle-extractor-options: -R . --path no-such-path --filter exclude:**/src_archive/** --respect-init=False --max-context-cost=11 --dont-split-graph
|
||||
semmle-extractor-options: -R . --path no-such-path --filter exclude:**/*.testproj/** --respect-init=False --max-context-cost=11 --dont-split-graph
|
||||
|
||||
@@ -1 +1 @@
|
||||
semmle-extractor-options: -R . --path no-such-path --filter exclude:**/src_archive/**
|
||||
semmle-extractor-options: -R . --path no-such-path --filter exclude:**/*.testproj/**
|
||||
|
||||
@@ -1 +1 @@
|
||||
semmle-extractor-options: -R . -p non-such --filter exclude:**/src_archive/**
|
||||
semmle-extractor-options: -R . -p non-such --filter exclude:**/*.testproj/**
|
||||
|
||||
@@ -1 +1 @@
|
||||
semmle-extractor-options: -R . --filter=include:**/*.thrift --filter exclude:**/src_archive/**
|
||||
semmle-extractor-options: -R . --filter=include:**/*.thrift --filter exclude:**/*.testproj/**
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
| 1 | ControlFlowNode for functools | Module functools | test.py:1 |
|
||||
| 3 | ControlFlowNode for annotate | Function annotate | test.py:3 |
|
||||
| 4 | ControlFlowNode for inner | Function inner | test.py:4 |
|
||||
| 5 | ControlFlowNode for func | Function func1 | test.py:23 |
|
||||
@@ -11,7 +10,6 @@
|
||||
| 13 | ControlFlowNode for wrapper | Function wrapper | test.py:10 |
|
||||
| 15 | ControlFlowNode for wraps2 | Function wraps2 | test.py:15 |
|
||||
| 16 | ControlFlowNode for func | Function func3 | test.py:31 |
|
||||
| 16 | ControlFlowNode for functools | Module functools | test.py:1 |
|
||||
| 17 | ControlFlowNode for args | args | test.py:17 |
|
||||
| 17 | ControlFlowNode for wrapper | Attribute()() | test.py:16 |
|
||||
| 18 | ControlFlowNode for args | args | test.py:17 |
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
| test.py:11:21:11:24 | ControlFlowNode for args | runtime | instance of tuple |
|
||||
| test.py:13:12:13:18 | ControlFlowNode for wrapper | runtime | Function wraps1.wrapper |
|
||||
| test.py:13:12:13:18 | ControlFlowNode for wrapper | test.py:26 from import | Function wraps1.wrapper |
|
||||
| test.py:16:6:16:14 | ControlFlowNode for functools | runtime | Module functools |
|
||||
| test.py:16:6:16:14 | ControlFlowNode for functools | test.py:30 from import | Module functools |
|
||||
| test.py:16:6:16:14 | ControlFlowNode for functools | runtime | Missing module functools |
|
||||
| test.py:16:6:16:14 | ControlFlowNode for functools | test.py:30 from import | Missing module functools |
|
||||
| test.py:16:22:16:25 | ControlFlowNode for func | runtime | Unknown value |
|
||||
| test.py:16:22:16:25 | ControlFlowNode for func | test.py:30 from import | Function func3 |
|
||||
| test.py:18:21:18:24 | ControlFlowNode for args | runtime | instance of tuple |
|
||||
|
||||
@@ -87,10 +87,6 @@
|
||||
| Module pointsto_test | 69 | ControlFlowNode for X | class X |
|
||||
| Module pointsto_test | 70 | ControlFlowNode for Attribute | deco() |
|
||||
| Module pointsto_test | 70 | ControlFlowNode for X | class X |
|
||||
| Module pointsto_test | 72 | ControlFlowNode for ImportExpr | Module abc |
|
||||
| Module pointsto_test | 72 | ControlFlowNode for ImportMember | Function abstractmethod |
|
||||
| Module pointsto_test | 72 | ControlFlowNode for abstractmethod | Function abstractmethod |
|
||||
| Module pointsto_test | 73 | ControlFlowNode for abstractmethod | Function abstractmethod |
|
||||
| Module pointsto_test | 75 | ControlFlowNode for C | class C |
|
||||
| Module pointsto_test | 75 | ControlFlowNode for C() | C() |
|
||||
| Module pointsto_test | 75 | ControlFlowNode for type | builtin-class type |
|
||||
|
||||
@@ -95,10 +95,6 @@
|
||||
| 69 | ControlFlowNode for X | class X |
|
||||
| 70 | ControlFlowNode for Attribute | deco() |
|
||||
| 70 | ControlFlowNode for X | class X |
|
||||
| 72 | ControlFlowNode for ImportExpr | Module abc |
|
||||
| 72 | ControlFlowNode for ImportMember | Function abstractmethod |
|
||||
| 72 | ControlFlowNode for abstractmethod | Function abstractmethod |
|
||||
| 73 | ControlFlowNode for abstractmethod | Function abstractmethod |
|
||||
| 75 | ControlFlowNode for C | class C |
|
||||
| 75 | ControlFlowNode for C() | C() |
|
||||
| 75 | ControlFlowNode for type | builtin-class type |
|
||||
|
||||
@@ -95,10 +95,6 @@
|
||||
| 69 | ControlFlowNode for Attribute | Attribute | builtin-class method |
|
||||
| 69 | ControlFlowNode for X | class X | builtin-class type |
|
||||
| 70 | ControlFlowNode for X | class X | builtin-class type |
|
||||
| 72 | ControlFlowNode for ImportExpr | Module abc | builtin-class module |
|
||||
| 72 | ControlFlowNode for ImportMember | Function abstractmethod | builtin-class function |
|
||||
| 72 | ControlFlowNode for abstractmethod | Function abstractmethod | builtin-class function |
|
||||
| 73 | ControlFlowNode for abstractmethod | Function abstractmethod | builtin-class function |
|
||||
| 75 | ControlFlowNode for C | class C | builtin-class type |
|
||||
| 75 | ControlFlowNode for C() | C() | class C |
|
||||
| 75 | ControlFlowNode for type | builtin-class type | builtin-class type |
|
||||
|
||||
@@ -70,7 +70,3 @@
|
||||
| type_test.py | 55 | ControlFlowNode for arg | class E | 29 |
|
||||
| type_test.py | 67 | ControlFlowNode for x | float 1.0 | 62 |
|
||||
| type_test.py | 67 | ControlFlowNode for x | int 0 | 62 |
|
||||
| type_test.py | 77 | ControlFlowNode for IntegerLiteral | int 0 | 77 |
|
||||
| type_test.py | 83 | ControlFlowNode for IntegerLiteral | int 0 | 83 |
|
||||
| type_test.py | 89 | ControlFlowNode for IntegerLiteral | int 0 | 89 |
|
||||
| type_test.py | 95 | ControlFlowNode for IntegerLiteral | int 0 | 95 |
|
||||
|
||||
@@ -70,7 +70,3 @@
|
||||
| type_test.py | 55 | ControlFlowNode for arg | class E | builtin-class type | 29 |
|
||||
| type_test.py | 67 | ControlFlowNode for x | float 1.0 | builtin-class float | 62 |
|
||||
| type_test.py | 67 | ControlFlowNode for x | int 0 | builtin-class int | 62 |
|
||||
| type_test.py | 77 | ControlFlowNode for IntegerLiteral | int 0 | builtin-class int | 77 |
|
||||
| type_test.py | 83 | ControlFlowNode for IntegerLiteral | int 0 | builtin-class int | 83 |
|
||||
| type_test.py | 89 | ControlFlowNode for IntegerLiteral | int 0 | builtin-class int | 89 |
|
||||
| type_test.py | 95 | ControlFlowNode for IntegerLiteral | int 0 | builtin-class int | 95 |
|
||||
|
||||
@@ -85,15 +85,12 @@
|
||||
| h_classes.py:23 | Class Base | __init__ | Function __init__ |
|
||||
| h_classes.py:48 | Class D | m | Function f |
|
||||
| h_classes.py:48 | Class D | n | Function n |
|
||||
| i_imports.py:0 | Module code.i_imports | BytesIO | builtin-class _io.BytesIO |
|
||||
| i_imports.py:0 | Module code.i_imports | StringIO | builtin-class _io.StringIO |
|
||||
| i_imports.py:0 | Module code.i_imports | _io | Module _io |
|
||||
| i_imports.py:0 | Module code.i_imports | a | int 1 |
|
||||
| i_imports.py:0 | Module code.i_imports | argv | list object |
|
||||
| i_imports.py:0 | Module code.i_imports | b | int 2 |
|
||||
| i_imports.py:0 | Module code.i_imports | c | int 3 |
|
||||
| i_imports.py:0 | Module code.i_imports | code | Module code |
|
||||
| i_imports.py:0 | Module code.i_imports | io | Module io |
|
||||
| i_imports.py:0 | Module code.i_imports | module1 | Module code.test_package.module1 |
|
||||
| i_imports.py:0 | Module code.i_imports | module2 | Module code.test_package.module2 |
|
||||
| i_imports.py:0 | Module code.i_imports | p | int 1 |
|
||||
|
||||
@@ -475,14 +475,6 @@
|
||||
| i_imports.py:31 | ControlFlowNode for Attribute | builtin-class _io.BytesIO | builtin-class type | 31 | import |
|
||||
| i_imports.py:31 | ControlFlowNode for BytesIO | builtin-class _io.BytesIO | builtin-class type | 31 | import |
|
||||
| i_imports.py:31 | ControlFlowNode for _io | Module _io | builtin-class module | 29 | import |
|
||||
| i_imports.py:33 | ControlFlowNode for ImportExpr | Module io | builtin-class module | 33 | import |
|
||||
| i_imports.py:33 | ControlFlowNode for io | Module io | builtin-class module | 33 | import |
|
||||
| i_imports.py:34 | ControlFlowNode for Attribute | builtin-class _io.StringIO | builtin-class type | 55 | import |
|
||||
| i_imports.py:34 | ControlFlowNode for StringIO | builtin-class _io.StringIO | builtin-class type | 55 | import |
|
||||
| i_imports.py:34 | ControlFlowNode for io | Module io | builtin-class module | 33 | import |
|
||||
| i_imports.py:35 | ControlFlowNode for Attribute | builtin-class _io.BytesIO | builtin-class type | 55 | import |
|
||||
| i_imports.py:35 | ControlFlowNode for BytesIO | builtin-class _io.BytesIO | builtin-class type | 55 | import |
|
||||
| i_imports.py:35 | ControlFlowNode for io | Module io | builtin-class module | 33 | import |
|
||||
| i_imports.py:37 | ControlFlowNode for ImportExpr | Module code | builtin-class module | 37 | import |
|
||||
| i_imports.py:37 | ControlFlowNode for code | Module code | builtin-class module | 37 | import |
|
||||
| i_imports.py:38 | ControlFlowNode for Attribute | Function f2 | builtin-class function | 24 | import |
|
||||
|
||||
@@ -572,14 +572,6 @@
|
||||
| i_imports.py:31 | ControlFlowNode for Attribute | builtin-class _io.BytesIO | builtin-class type | 31 |
|
||||
| i_imports.py:31 | ControlFlowNode for BytesIO | builtin-class _io.BytesIO | builtin-class type | 31 |
|
||||
| i_imports.py:31 | ControlFlowNode for _io | Module _io | builtin-class module | 29 |
|
||||
| i_imports.py:33 | ControlFlowNode for ImportExpr | Module io | builtin-class module | 33 |
|
||||
| i_imports.py:33 | ControlFlowNode for io | Module io | builtin-class module | 33 |
|
||||
| i_imports.py:34 | ControlFlowNode for Attribute | builtin-class _io.StringIO | builtin-class type | 55 |
|
||||
| i_imports.py:34 | ControlFlowNode for StringIO | builtin-class _io.StringIO | builtin-class type | 55 |
|
||||
| i_imports.py:34 | ControlFlowNode for io | Module io | builtin-class module | 33 |
|
||||
| i_imports.py:35 | ControlFlowNode for Attribute | builtin-class _io.BytesIO | builtin-class type | 55 |
|
||||
| i_imports.py:35 | ControlFlowNode for BytesIO | builtin-class _io.BytesIO | builtin-class type | 55 |
|
||||
| i_imports.py:35 | ControlFlowNode for io | Module io | builtin-class module | 33 |
|
||||
| i_imports.py:37 | ControlFlowNode for ImportExpr | Module code | builtin-class module | 37 |
|
||||
| i_imports.py:37 | ControlFlowNode for code | Module code | builtin-class module | 37 |
|
||||
| i_imports.py:38 | ControlFlowNode for Attribute | Function f2 | builtin-class function | 24 |
|
||||
|
||||
@@ -373,11 +373,9 @@
|
||||
| i_imports.py:30 | ControlFlowNode for _io | import | Module _io | builtin-class module |
|
||||
| i_imports.py:31 | ControlFlowNode for Attribute | import | builtin-class _io.BytesIO | builtin-class type |
|
||||
| i_imports.py:31 | ControlFlowNode for _io | import | Module _io | builtin-class module |
|
||||
| i_imports.py:33 | ControlFlowNode for ImportExpr | import | Module io | builtin-class module |
|
||||
| i_imports.py:34 | ControlFlowNode for Attribute | import | builtin-class _io.StringIO | builtin-class type |
|
||||
| i_imports.py:34 | ControlFlowNode for io | import | Module io | builtin-class module |
|
||||
| i_imports.py:35 | ControlFlowNode for Attribute | import | builtin-class _io.BytesIO | builtin-class type |
|
||||
| i_imports.py:35 | ControlFlowNode for io | import | Module io | builtin-class module |
|
||||
| i_imports.py:33 | ControlFlowNode for ImportExpr | import | Missing module io | builtin-class module |
|
||||
| i_imports.py:34 | ControlFlowNode for io | import | Missing module io | builtin-class module |
|
||||
| i_imports.py:35 | ControlFlowNode for io | import | Missing module io | builtin-class module |
|
||||
| i_imports.py:37 | ControlFlowNode for ImportExpr | import | Package code | builtin-class module |
|
||||
| i_imports.py:38 | ControlFlowNode for Attribute | import | Function f2 | builtin-class function |
|
||||
| i_imports.py:38 | ControlFlowNode for Attribute | import | Module code.n_nesting | builtin-class module |
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
| Local module | code-invalid-package-name/cmd.py:0:0:0:0 | Module cmd | referenced in external file called | pdb.py |
|
||||
| Local module | code-invalid-package-name/cmd.py:0:0:0:0 | Module cmd | referenced in local file called | test_ok.py |
|
||||
| Local module | code-invalid-package-name/unique_name.py:0:0:0:0 | Module unique_name | referenced in local file called | unique_name_use.py |
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
| Module 'cmd' (local, not in stdlib, not missing) referenced in local file | code-invalid-package-name/test_ok.py:1 |
|
||||
| Module 'pdb' (external, in stdlib, not missing) referenced in local file | code-invalid-package-name/test_fail.py:3 |
|
||||
| Module 'pdb' (external, not in stdlib, missing) referenced in local file | code-invalid-package-name/test_fail.py:3 |
|
||||
| Module 'unique_name' (local, not in stdlib, not missing) referenced in local file | code-invalid-package-name/unique_name_use.py:1 |
|
||||
|
||||
@@ -21,8 +21,11 @@ module DataFlowCallTest implements TestSig {
|
||||
value = prettyExpr(call.getNode().getNode()) and
|
||||
tag = "call"
|
||||
or
|
||||
value = call.(DataFlowDispatch::NormalCall).getCallType().toString() and
|
||||
tag = "callType"
|
||||
exists(DataFlowDispatch::CallType callType |
|
||||
DataFlowDispatch::resolveCall(call.getNode(), _, callType) and
|
||||
value = callType.toString() and
|
||||
tag = "callType"
|
||||
)
|
||||
or
|
||||
exists(DataFlowDispatch::ArgumentPosition pos, DataFlow::Node arg |
|
||||
arg = call.getArgument(pos)
|
||||
|
||||
@@ -1,2 +1,6 @@
|
||||
testFailures
|
||||
| classes.py:54:44:54:107 | Comment #$ arg1="with_length_hint" func=With_length_hint.__length_hint__ | Missing result: arg1="with_length_hint" |
|
||||
| classes.py:54:44:54:107 | Comment #$ arg1="with_length_hint" func=With_length_hint.__length_hint__ | Missing result: func=With_length_hint.__length_hint__ |
|
||||
| classes.py:71:32:71:77 | Comment #$ arg1="with_index" func=With_index.__index__ | Missing result: arg1="with_index" |
|
||||
| classes.py:71:32:71:77 | Comment #$ arg1="with_index" func=With_index.__index__ | Missing result: func=With_index.__index__ |
|
||||
failures
|
||||
|
||||
@@ -8,9 +8,4 @@
|
||||
| test.py:208:1:208:53 | Entry definition for SsaSourceVariable SINK | test.py:210:5:210:8 | ControlFlowNode for SINK |
|
||||
| test.py:208:1:208:53 | Entry definition for SsaSourceVariable SOURCE | test.py:209:25:209:30 | ControlFlowNode for SOURCE |
|
||||
| test.py:209:5:209:5 | ControlFlowNode for x | test.py:210:10:210:10 | ControlFlowNode for x |
|
||||
| test.py:209:9:209:68 | ControlFlowNode for .0 | test.py:209:9:209:68 | ControlFlowNode for .0 |
|
||||
| test.py:209:9:209:68 | ControlFlowNode for ListComp | test.py:209:5:209:5 | ControlFlowNode for x |
|
||||
| test.py:209:16:209:16 | ControlFlowNode for v | test.py:209:45:209:45 | ControlFlowNode for v |
|
||||
| test.py:209:40:209:40 | ControlFlowNode for u | test.py:209:56:209:56 | ControlFlowNode for u |
|
||||
| test.py:209:51:209:51 | ControlFlowNode for z | test.py:209:67:209:67 | ControlFlowNode for z |
|
||||
| test.py:209:62:209:62 | ControlFlowNode for y | test.py:209:10:209:10 | ControlFlowNode for y |
|
||||
|
||||
@@ -137,7 +137,7 @@ def test_list_comprehension_with_tuple_result():
|
||||
s = SOURCE
|
||||
ns = NONSOURCE
|
||||
l3 = [(s, ns) for _ in [1]]
|
||||
SINK(l3[0][0]) # $ MISSING: flow="SOURCE, l:-3 -> l3[0][0]"
|
||||
SINK(l3[0][0]) # $ flow="SOURCE, l:-3 -> l3[0][0]"
|
||||
SINK_F(l3[0][1])
|
||||
|
||||
|
||||
@@ -245,7 +245,7 @@ def gen(x):
|
||||
|
||||
def test_yield():
|
||||
g = gen(SOURCE)
|
||||
SINK(next(g)) #$ MISSING:flow="SOURCE, l:-1 -> next()"
|
||||
SINK(next(g)) #$ flow="SOURCE, l:-1 -> next(..)"
|
||||
|
||||
|
||||
def gen_from(x):
|
||||
@@ -260,7 +260,7 @@ def test_yield_from():
|
||||
# a statement rather than an expression, but related to generators
|
||||
def test_for():
|
||||
for x in gen(SOURCE):
|
||||
SINK(x) #$ MISSING:flow="SOURCE, l:-1 -> x"
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
|
||||
|
||||
# 6.2.9.1. Generator-iterator methods
|
||||
|
||||
@@ -132,8 +132,8 @@ def test_dict_from_keyword():
|
||||
@expects(2)
|
||||
def test_dict_from_list():
|
||||
d = dict([("k", SOURCE), ("k1", NONSOURCE)])
|
||||
SINK(d["k"]) #$ MISSING: flow="SOURCE, l:-1 -> d[k]"
|
||||
SINK_F(d["k1"])
|
||||
SINK(d["k"]) #$ flow="SOURCE, l:-1 -> d['k']"
|
||||
SINK_F(d["k1"]) #$ SPURIOUS: flow="SOURCE, l:-2 -> d['k1']" // due to imprecise list content
|
||||
|
||||
@expects(2)
|
||||
def test_dict_from_dict():
|
||||
@@ -142,6 +142,14 @@ def test_dict_from_dict():
|
||||
SINK(d2["k"]) #$ flow="SOURCE, l:-2 -> d2['k']"
|
||||
SINK_F(d2["k1"])
|
||||
|
||||
@expects(4)
|
||||
def test_dict_from_multiple_args():
|
||||
d = dict([("k", SOURCE), ("k1", NONSOURCE)], k2 = SOURCE, k3 = NONSOURCE)
|
||||
SINK(d["k"]) #$ flow="SOURCE, l:-1 -> d['k']"
|
||||
SINK_F(d["k1"]) #$ SPURIOUS: flow="SOURCE, l:-2 -> d['k1']" // due to imprecise list content
|
||||
SINK(d["k2"]) #$ flow="SOURCE, l:-3 -> d['k2']"
|
||||
SINK_F(d["k3"]) #$ SPURIOUS: flow="SOURCE, l:-4 -> d['k3']" // due to imprecise list content
|
||||
|
||||
## Container methods
|
||||
|
||||
### List
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
| generator.py:0:0:0:0 | Module generator | generator.py:1:1:1:23 | ControlFlowNode for FunctionExpr |
|
||||
| generator.py:0:0:0:0 | Module generator | generator.py:1:5:1:18 | ControlFlowNode for generator_func |
|
||||
| generator.py:1:1:1:23 | Function generator_func | generator.py:1:20:1:21 | ControlFlowNode for xs |
|
||||
| generator.py:1:1:1:23 | Function generator_func | generator.py:2:12:2:26 | ControlFlowNode for .0 |
|
||||
| generator.py:1:1:1:23 | Function generator_func | generator.py:2:12:2:26 | ControlFlowNode for .0 |
|
||||
| generator.py:1:1:1:23 | Function generator_func | generator.py:2:12:2:26 | ControlFlowNode for ListComp |
|
||||
| generator.py:1:1:1:23 | Function generator_func | generator.py:2:13:2:13 | ControlFlowNode for Yield |
|
||||
| generator.py:1:1:1:23 | Function generator_func | generator.py:2:13:2:13 | ControlFlowNode for x |
|
||||
| generator.py:1:1:1:23 | Function generator_func | generator.py:2:19:2:19 | ControlFlowNode for x |
|
||||
| generator.py:1:1:1:23 | Function generator_func | generator.py:2:24:2:25 | ControlFlowNode for xs |
|
||||
| generator.py:2:12:2:26 | Function listcomp | generator.py:2:12:2:26 | ControlFlowNode for .0 |
|
||||
| generator.py:2:12:2:26 | Function listcomp | generator.py:2:12:2:26 | ControlFlowNode for .0 |
|
||||
| generator.py:2:12:2:26 | Function listcomp | generator.py:2:13:2:13 | ControlFlowNode for Yield |
|
||||
| generator.py:2:12:2:26 | Function listcomp | generator.py:2:13:2:13 | ControlFlowNode for x |
|
||||
| generator.py:2:12:2:26 | Function listcomp | generator.py:2:19:2:19 | ControlFlowNode for x |
|
||||
|
||||
@@ -1,2 +1,6 @@
|
||||
testFailures
|
||||
| test.py:4:17:4:60 | ControlFlowNode for Attribute() | Unexpected result: unresolved_call=os.path.dirname(..) |
|
||||
| test.py:4:33:4:59 | ControlFlowNode for Attribute() | Unexpected result: unresolved_call=os.path.dirname(..) |
|
||||
| test_dict.py:4:17:4:60 | ControlFlowNode for Attribute() | Unexpected result: unresolved_call=os.path.dirname(..) |
|
||||
| test_dict.py:4:33:4:59 | ControlFlowNode for Attribute() | Unexpected result: unresolved_call=os.path.dirname(..) |
|
||||
failures
|
||||
|
||||
@@ -25,3 +25,15 @@ extensions:
|
||||
- ["foo.MS_Class", "Member[instance_method]", "Argument[0]", "ReturnValue.TupleElement[1]", "value"]
|
||||
- ["foo.MS_Class", "Member[explicit_self]", "Argument[self:]", "ReturnValue", "value"]
|
||||
- ["json", "Member[MS_loads]", "Argument[0]", "ReturnValue", "taint"]
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/python-all
|
||||
extensible: typeModel
|
||||
data:
|
||||
- ["foo.MS_Class", "foo", "Member[get_instance].ReturnValue"]
|
||||
- ["foo.MS_Class!", "foo", "Member[get_class].ReturnValue"]
|
||||
# Ideally this would be a consequence of the above line
|
||||
- ["foo.MS_Class", "foo", "Member[get_class].ReturnValue.Instance"]
|
||||
- ["foo.MS_Class", "foo.MS_Factory!", "Member[get_instance].ReturnValue"]
|
||||
- ["foo.MS_Class", "foo.MS_Factory", "Member[make].ReturnValue"]
|
||||
- ["foo.MS_Class", "foo.Impl.MS_Class_Impl", ""]
|
||||
|
||||
@@ -25,3 +25,15 @@ extensions:
|
||||
- ["foo.MS_Class", "Member[instance_method]", "Argument[0]", "ReturnValue.TupleElement[1]", "value"]
|
||||
- ["foo.MS_Class", "Member[explicit_self]", "Argument[self:]", "ReturnValue", "value"]
|
||||
- ["json", "Member[MS_loads]", "Argument[0]", "ReturnValue", "taint"]
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/python-all
|
||||
extensible: typeModel
|
||||
data:
|
||||
- ["foo.MS_Class", "foo", "Member[get_instance].ReturnValue"]
|
||||
- ["foo.MS_Class!", "foo", "Member[get_class].ReturnValue"]
|
||||
# Ideally this would be a consequence of the above line
|
||||
- ["foo.MS_Class", "foo", "Member[get_class].ReturnValue.Instance"]
|
||||
- ["foo.MS_Class", "foo.MS_Factory!", "Member[get_instance].ReturnValue"]
|
||||
- ["foo.MS_Class", "foo.MS_Factory", "Member[make].ReturnValue"]
|
||||
- ["foo.MS_Class", "foo.Impl.MS_Class_Impl", ""]
|
||||
|
||||
@@ -30,7 +30,7 @@ def SINK_F(x):
|
||||
ensure_tainted = ensure_not_tainted = print
|
||||
TAINTED_STRING = "TAINTED_STRING"
|
||||
|
||||
from foo import MS_identity, MS_apply_lambda, MS_reversed, MS_list_map, MS_append_to_list, MS_spread, MS_spread_all
|
||||
from foo import MS_identity, MS_apply_lambda, MS_reversed, MS_list_map, MS_append_to_list, MS_spread, MS_spread_all, Impl
|
||||
|
||||
# Simple summary
|
||||
via_identity = MS_identity(SOURCE)
|
||||
@@ -122,7 +122,7 @@ a, b = MS_spread_all(SOURCE)
|
||||
SINK(a) # $ flow="SOURCE, l:-1 -> a"
|
||||
SINK(b) # $ flow="SOURCE, l:-2 -> b"
|
||||
|
||||
from foo import MS_Class, MS_Class_transitive
|
||||
from foo import MS_Class, MS_Class_transitive, get_instance, get_class, MS_Factory
|
||||
|
||||
# Class summaries
|
||||
class_via_positional = MS_Class(SOURCE)
|
||||
@@ -175,6 +175,24 @@ SINK_F(MS_Class.explicit_self(SOURCE))
|
||||
# Instead, `Argument[self:]` refers to a keyword argument named `self` (which you are allowed to do in Python)
|
||||
SINK(c.explicit_self(self = SOURCE)) # $ flow="SOURCE -> c.explicit_self(..)"
|
||||
|
||||
|
||||
instance = get_instance()
|
||||
SINK(instance.instance_method(SOURCE)[1]) # $ flow="SOURCE -> instance.instance_method(..)[1]"
|
||||
|
||||
returned_class = get_class()
|
||||
SINK(returned_class(SOURCE).config) # $ flow="SOURCE -> returned_class(..).config"
|
||||
|
||||
SINK(returned_class().instance_method(SOURCE)[1]) # $flow="SOURCE -> returned_class().instance_method(..)[1]"
|
||||
|
||||
fatory_instance = MS_Factory.get_instance()
|
||||
SINK(fatory_instance.instance_method(SOURCE)[1]) # $ flow="SOURCE -> fatory_instance.instance_method(..)[1]"
|
||||
|
||||
factory = MS_Factory()
|
||||
SINK(factory.make().instance_method(SOURCE)[1]) # $ flow="SOURCE -> factory.make().instance_method(..)[1]"
|
||||
|
||||
also_instance = Impl.MS_Class_Impl()
|
||||
SINK(also_instance.instance_method(SOURCE)[1]) # $ flow="SOURCE -> also_instance.instance_method(..)[1]"
|
||||
|
||||
# Modeled flow-summary is not value preserving
|
||||
from json import MS_loads as json_loads
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
ERROR: Could not resolve type DataFlow::Add (Test.ql:7,6-19)
|
||||
ERROR: could not resolve type DataFlow::Add (Test.ql:7,6-19)
|
||||
|
||||
@@ -23,3 +23,4 @@
|
||||
| test.py:195:9:195:14 | ControlFlowNode for SOURCE | test.py:199:14:199:14 | ControlFlowNode for t |
|
||||
| test.py:202:10:202:15 | ControlFlowNode for SOURCE | test.py:204:14:204:14 | ControlFlowNode for i |
|
||||
| test.py:202:10:202:15 | ControlFlowNode for SOURCE | test.py:205:10:205:10 | ControlFlowNode for i |
|
||||
| test.py:208:12:208:17 | ControlFlowNode for SOURCE | test.py:214:14:214:14 | ControlFlowNode for x |
|
||||
|
||||
@@ -211,4 +211,4 @@ def flow_in_generator():
|
||||
|
||||
def flow_from_generator():
|
||||
for x in flow_in_generator():
|
||||
SINK(x) # Flow not found
|
||||
SINK(x)
|
||||
|
||||
@@ -6,7 +6,7 @@ module CustomSanitizerOverridesConfig implements DataFlow::ConfigSig {
|
||||
|
||||
predicate isSink = TestTaintTrackingConfig::isSink/1;
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof StringConstCompareBarrier }
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof ConstCompareBarrier }
|
||||
}
|
||||
|
||||
import MakeInlineTaintTest<CustomSanitizerOverridesConfig>
|
||||
|
||||
@@ -85,6 +85,32 @@ def test_in_local_variable():
|
||||
else:
|
||||
ensure_tainted(ts) # $ tainted
|
||||
|
||||
def test_is_none():
|
||||
ts = TAINTED_STRING
|
||||
if ts is None:
|
||||
ensure_not_tainted(ts)
|
||||
else:
|
||||
ensure_tainted(ts) # $ tainted
|
||||
|
||||
def test_is_not_none():
|
||||
ts = TAINTED_STRING
|
||||
if ts is not None:
|
||||
ensure_tainted(ts) # $ tainted
|
||||
else:
|
||||
ensure_not_tainted(ts)
|
||||
|
||||
def test_in_list_with_constants():
|
||||
ts = TAINTED_STRING
|
||||
if ts in ["safe", None, 3, False]:
|
||||
ensure_not_tainted(ts)
|
||||
else:
|
||||
ensure_tainted(ts) # $ tainted
|
||||
|
||||
if ts in ["safe", not_constant(), None]:
|
||||
ensure_tainted(ts) # $ tainted
|
||||
|
||||
def not_constant():
|
||||
return "x"
|
||||
|
||||
SAFE = ["safe", "also_safe"]
|
||||
|
||||
@@ -184,6 +210,9 @@ test_in_tuple()
|
||||
test_in_set()
|
||||
test_in_local_variable()
|
||||
test_in_global_variable()
|
||||
test_is_none()
|
||||
test_is_not_none()
|
||||
test_in_list_with_constants()
|
||||
make_modification("unsafe")
|
||||
test_in_modified_global_variable()
|
||||
test_in_unsafe1(["unsafe", "foo"])
|
||||
@@ -61,7 +61,7 @@ def test_access(x, y, z):
|
||||
iter(tainted_list), # $ tainted
|
||||
next(iter(tainted_list)), # $ MISSING: tainted
|
||||
[i for i in tainted_list], # $ tainted
|
||||
[tainted_list for _i in [1,2,3]], # $ MISSING: tainted
|
||||
[tainted_list for _i in [1,2,3]], # $ tainted
|
||||
)
|
||||
|
||||
a, b, c = tainted_list[0:3]
|
||||
@@ -85,7 +85,7 @@ def test_access_explicit(x, y, z):
|
||||
iter(tainted_list), # $ tainted
|
||||
next(iter(tainted_list)), # $ tainted
|
||||
[i for i in tainted_list], # $ tainted
|
||||
[tainted_list for i in [1,2,3]], # $ MISSING: tainted
|
||||
[tainted_list for i in [1,2,3]], # $ tainted
|
||||
[TAINTED_STRING for i in [1,2,3]], # $ tainted
|
||||
[tainted_list], # $ tainted
|
||||
)
|
||||
@@ -166,6 +166,34 @@ def test_copy_2():
|
||||
copy.deepcopy(TAINTED_LIST), # $ tainted
|
||||
)
|
||||
|
||||
def test_replace():
|
||||
from copy import replace
|
||||
|
||||
class C:
|
||||
def __init__(self, always_tainted, tainted_to_safe, safe_to_tainted, always_safe):
|
||||
self.always_tainted = always_tainted
|
||||
self.tainted_to_safe = tainted_to_safe
|
||||
self.safe_to_tainted = safe_to_tainted
|
||||
self.always_safe = always_safe
|
||||
|
||||
c = C(always_tainted=TAINTED_STRING,
|
||||
tainted_to_safe=TAINTED_STRING,
|
||||
safe_to_tainted=NOT_TAINTED,
|
||||
always_safe=NOT_TAINTED)
|
||||
|
||||
d = replace(c, tainted_to_safe=NOT_TAINTED, safe_to_tainted=TAINTED_STRING)
|
||||
|
||||
ensure_tainted(d.always_tainted) # $ tainted
|
||||
ensure_tainted(d.safe_to_tainted) # $ tainted
|
||||
ensure_not_tainted(d.always_safe)
|
||||
|
||||
# Currently, we have no way of stopping the value in the tainted_to_safe field (which gets
|
||||
# overwritten) from flowing through the replace call, which means we get a spurious result.
|
||||
|
||||
ensure_not_tainted(d.tainted_to_safe) # $ SPURIOUS: tainted
|
||||
|
||||
|
||||
|
||||
|
||||
def list_index_assign():
|
||||
tainted_string = TAINTED_STRING
|
||||
@@ -274,6 +302,7 @@ test_named_tuple()
|
||||
test_defaultdict("key", "key")
|
||||
test_copy_1()
|
||||
test_copy_2()
|
||||
test_replace()
|
||||
|
||||
list_index_assign()
|
||||
list_index_aug_assign()
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
argumentToEnsureNotTaintedNotMarkedAsSpurious
|
||||
untaintedArgumentToEnsureTaintedNotMarkedAsMissing
|
||||
testFailures
|
||||
failures
|
||||
@@ -0,0 +1,2 @@
|
||||
import experimental.meta.InlineTaintTest
|
||||
import MakeInlineTaintTest<TestTaintTrackingConfig>
|
||||
@@ -0,0 +1,11 @@
|
||||
def impossible_flow(cond: bool):
|
||||
TAINTED_STRING = "ts"
|
||||
x = (TAINTED_STRING, 42) if cond else "SAFE"
|
||||
|
||||
if isinstance(x, str):
|
||||
# tainted-flow to here is impossible, replicated from path-flow seen in a real
|
||||
# repo.
|
||||
ensure_not_tainted(x) # $ SPURIOUS: tainted
|
||||
else:
|
||||
ensure_tainted(x) # $ tainted
|
||||
ensure_tainted(x[0]) # $ tainted
|
||||
@@ -96,10 +96,12 @@ async def streaming_response(request): # $ requestHandler
|
||||
async def setting_cookie(request): # $ requestHandler
|
||||
resp = web.Response(text="foo") # $ HttpResponse mimetype=text/plain responseBody="foo"
|
||||
resp.cookies["key"] = "value" # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
resp.headers["Set-Cookie"] = "key2=value2" # $ MISSING: CookieWrite CookieRawHeader="key2=value2"
|
||||
resp.set_cookie("key3", "value3") # $ CookieWrite CookieName="key3" CookieValue="value3"
|
||||
resp.set_cookie(name="key3", value="value3") # $ CookieWrite CookieName="key3" CookieValue="value3"
|
||||
resp.headers["Set-Cookie"] = "key2=value2" # $ headerWriteName="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.set_cookie("key3", "value3") # $ CookieWrite CookieName="key3" CookieValue="value3" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.set_cookie(name="key3", value="value3") # $ CookieWrite CookieName="key3" CookieValue="value3" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.del_cookie("key4") # $ CookieWrite CookieName="key4"
|
||||
resp.set_cookie(name="key5", value="value5", secure=True, httponly=True, samesite="Strict") # $ CookieWrite CookieName="key5" CookieValue="value5" CookieSecure=true CookieHttpOnly=true CookieSameSite=Strict
|
||||
resp.headers["Set-Cookie"] = "key6=value6; Secure; HttpOnly; SameSite=Strict" # $ headerWriteName="Set-Cookie" headerWriteValue="key6=value6; Secure; HttpOnly; SameSite=Strict" CookieWrite CookieRawHeader="key6=value6; Secure; HttpOnly; SameSite=Strict" CookieSecure=true CookieHttpOnly=true CookieSameSite=Strict
|
||||
return resp
|
||||
|
||||
|
||||
|
||||
@@ -106,6 +106,8 @@ isSource
|
||||
| test.py:117:31:117:41 | ControlFlowNode for getSource() | test-source |
|
||||
| test.py:118:35:118:45 | ControlFlowNode for getSource() | test-source |
|
||||
| test.py:119:20:119:30 | ControlFlowNode for getSource() | test-source |
|
||||
| test.py:124:1:124:33 | ControlFlowNode for Attribute() | test-source |
|
||||
| test.py:126:11:126:43 | ControlFlowNode for Attribute() | test-source |
|
||||
syntaxErrors
|
||||
| Member[foo |
|
||||
| Member[foo] .Member[bar] |
|
||||
|
||||
@@ -23,6 +23,12 @@ extensions:
|
||||
- ["testlib", "Member[ArgPos].Member[MyClass].Subclass.Member[otherSelfTest].Parameter[0]", "test-source"]
|
||||
- ["testlib", "Member[ArgPos].Member[MyClass].Subclass.Member[anyParam].Parameter[any]", "test-source"]
|
||||
- ["testlib", "Member[ArgPos].Member[MyClass].Subclass.Member[anyNamed].Parameter[any-named]", "test-source"]
|
||||
# test steps through content
|
||||
- ["testlib", "Member[source_dict].DictionaryElement[key].Member[func].ReturnValue", "test-source"]
|
||||
- ["testlib", "Member[source_dict_any].DictionaryElementAny.Member[func].ReturnValue", "test-source"]
|
||||
# TODO: Add support for list/tuples
|
||||
# - ["testlib", "Member[source_list].ListElement.Member[func].ReturnValue", "test-source"]
|
||||
# - ["testlib", "Member[source_tuple].TupleElement[0].Member[func].ReturnValue", "test-source"]
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/python-all
|
||||
|
||||
@@ -117,3 +117,17 @@ testlib.foo.bar.baz.fuzzyCall(getSource()) # NOT OK
|
||||
testlib.foo().bar().fuzzyCall(getSource()) # NOT OK
|
||||
testlib.foo(lambda x: x.fuzzyCall(getSource())) # NOT OK
|
||||
otherlib.fuzzyCall(getSource()) # OK
|
||||
|
||||
# defining sources through content steps
|
||||
|
||||
# dictionaries
|
||||
testlib.source_dict["key"].func() # source
|
||||
testlib.source_dict["safe"].func() # not a source
|
||||
lambda k: testlib.source_dict_any[k].func() # source
|
||||
|
||||
# TODO: implement support for lists
|
||||
lambda i: testlib.source_list[i].func()
|
||||
|
||||
# TODO: implement support for tuples
|
||||
testlib.source_tuple[0].func() # a source
|
||||
testlib.source_tuple[1].func() # not a source
|
||||
|
||||
@@ -16,7 +16,6 @@ edges
|
||||
| testapp/orm_security_tests.py:42:13:42:18 | ControlFlowNode for person [Attribute name] | testapp/orm_security_tests.py:43:49:43:54 | ControlFlowNode for person [Attribute name] | provenance | |
|
||||
| testapp/orm_security_tests.py:42:23:42:42 | ControlFlowNode for Attribute() [List element, Attribute age] | testapp/orm_security_tests.py:42:13:42:18 | ControlFlowNode for person [Attribute age] | provenance | |
|
||||
| testapp/orm_security_tests.py:42:23:42:42 | ControlFlowNode for Attribute() [List element, Attribute name] | testapp/orm_security_tests.py:42:13:42:18 | ControlFlowNode for person [Attribute name] | provenance | |
|
||||
| testapp/orm_security_tests.py:43:13:43:21 | ControlFlowNode for resp_text | testapp/orm_security_tests.py:43:13:43:21 | ControlFlowNode for resp_text | provenance | |
|
||||
| testapp/orm_security_tests.py:43:13:43:21 | ControlFlowNode for resp_text | testapp/orm_security_tests.py:44:29:44:37 | ControlFlowNode for resp_text | provenance | |
|
||||
| testapp/orm_security_tests.py:43:49:43:54 | ControlFlowNode for person [Attribute name] | testapp/orm_security_tests.py:43:49:43:59 | ControlFlowNode for Attribute | provenance | |
|
||||
| testapp/orm_security_tests.py:43:49:43:59 | ControlFlowNode for Attribute | testapp/orm_security_tests.py:43:13:43:21 | ControlFlowNode for resp_text | provenance | |
|
||||
|
||||
@@ -6,7 +6,7 @@ import sys
|
||||
|
||||
def main():
|
||||
"""Run administrative tasks."""
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testproj.settings')
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testproj.settings') # $ threatModelSource[environment]=os.environ
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError as exc:
|
||||
@@ -15,7 +15,7 @@ def main():
|
||||
"available on your PYTHONPATH environment variable? Did you "
|
||||
"forget to activate a virtual environment?"
|
||||
) from exc
|
||||
execute_from_command_line(sys.argv)
|
||||
execute_from_command_line(sys.argv) # $ threatModelSource[commandargs]=sys.argv
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -62,7 +62,7 @@ def redirect_through_normal_response(request):
|
||||
|
||||
resp = HttpResponse() # $ HttpResponse mimetype=text/html
|
||||
resp.status_code = 302
|
||||
resp['Location'] = next # $ MISSING: redirectLocation=next
|
||||
resp['Location'] = next # $ headerWriteName='Location' headerWriteValue=next MISSING: redirectLocation=next
|
||||
resp.content = private # $ MISSING: responseBody=private
|
||||
return resp
|
||||
|
||||
@@ -72,7 +72,7 @@ def redirect_through_normal_response_new_headers_attr(request):
|
||||
|
||||
resp = HttpResponse() # $ HttpResponse mimetype=text/html
|
||||
resp.status_code = 302
|
||||
resp.headers['Location'] = next # $ MISSING: redirectLocation=next
|
||||
resp.headers['Location'] = next # $ headerWriteName='Location' headerWriteValue=next MISSING: redirectLocation=next
|
||||
resp.content = private # $ MISSING: responseBody=private
|
||||
return resp
|
||||
|
||||
@@ -128,10 +128,14 @@ def safe__custom_json_response(request):
|
||||
|
||||
def setting_cookie(request):
|
||||
resp = HttpResponse() # $ HttpResponse mimetype=text/html
|
||||
resp.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
resp.set_cookie(key="key", value="value") # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
resp.headers["Set-Cookie"] = "key2=value2" # $ MISSING: CookieWrite CookieRawHeader="key2=value2"
|
||||
resp.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.set_cookie(key="key", value="value") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.headers["Set-Cookie"] = "key2=value2" # $ headerWriteName="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.cookies["key3"] = "value3" # $ CookieWrite CookieName="key3" CookieValue="value3"
|
||||
resp.delete_cookie("key4") # $ CookieWrite CookieName="key4"
|
||||
resp.delete_cookie(key="key4") # $ CookieWrite CookieName="key4"
|
||||
resp["Set-Cookie"] = "key5=value5" # $ headerWriteName="Set-Cookie" headerWriteValue="key5=value5" CookieWrite CookieRawHeader="key5=value5" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.set_cookie(key="key6", value="value6", secure=True, httponly=False, samesite="None") # $ CookieWrite CookieName="key6" CookieValue="value6" CookieSecure=true CookieHttpOnly=false CookieSameSite=None
|
||||
kwargs = {'secure': True}
|
||||
resp.set_cookie(key="key7", value="value7", **kwargs) # $ CookieWrite CookieName="key7" CookieValue="value7"
|
||||
return resp
|
||||
|
||||
@@ -11,6 +11,6 @@ import os
|
||||
|
||||
from django.core.asgi import get_asgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testproj.settings')
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testproj.settings') # $ threatModelSource[environment]=os.environ
|
||||
|
||||
application = get_asgi_application()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user