Merge branch 'main' into redsun82/python-match-fps

This commit is contained in:
Paolo Tranquilli
2024-11-07 09:46:32 +01:00
committed by GitHub
10547 changed files with 616588 additions and 200080 deletions

View File

@@ -1,2 +1 @@
semmle-extractor-options: -R . -p . --filter exclude:**/src_archive/**
semmle-extractor-options: -R . -p . --filter exclude:**/*.testproj/**

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -1 +1 @@
| 38 |
| 11 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -1 +1 @@
| 51 |
| 11 |

View File

@@ -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. |

View File

@@ -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>

View 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
)
}
}

View File

@@ -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;
}

View File

@@ -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) + "\""

View File

@@ -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>>>>

View File

@@ -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) {

View 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>

View File

@@ -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

View File

@@ -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() |

View File

@@ -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 | |

View File

@@ -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"}

View File

@@ -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>

View File

@@ -0,0 +1,3 @@
missingAnnotationOnSink
testFailures
failures

View File

@@ -0,0 +1,4 @@
import python
import TestUtilities.dataflow.DataflowQueryTest
import experimental.semmle.python.security.RemoteCommandExecution
import FromTaintTrackingConfig<RemoteCommandExecutionConfig>

View File

@@ -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"}

View File

@@ -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}

View File

@@ -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 |

View File

@@ -0,0 +1 @@
experimental/Security/CWE-074/remoteCommandExecution/RemoteCommandExecution.ql

View File

@@ -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"}

View File

@@ -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"}

View File

@@ -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"}

View File

@@ -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"}

View File

@@ -1 +0,0 @@
experimental/Security/CWE-074/paramiko/paramiko.ql

View File

@@ -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 |

View File

@@ -0,0 +1 @@
experimental/Security/CWE-094/Js2Py.ql

View File

@@ -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()")

View File

@@ -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")

View File

@@ -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. |

View File

@@ -0,0 +1 @@
experimental/Security/CWE-346/CorsBypass.ql

View File

@@ -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() |

View File

@@ -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 |

View File

@@ -1 +0,0 @@
experimental/Security/CWE-614/CookieInjection.ql

View File

@@ -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. |

View File

@@ -1 +0,0 @@
experimental/Security/CWE-614/InsecureCookie.ql

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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/**

View File

@@ -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/**

View File

@@ -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 |

View File

@@ -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

View File

@@ -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/**

View File

@@ -1 +1 @@
semmle-extractor-options: -R . -p non-such --filter exclude:**/src_archive/**
semmle-extractor-options: -R . -p non-such --filter exclude:**/*.testproj/**

View File

@@ -1 +1 @@
semmle-extractor-options: -R . --filter=include:**/*.thrift --filter exclude:**/src_archive/**
semmle-extractor-options: -R . --filter=include:**/*.thrift --filter exclude:**/*.testproj/**

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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)

View File

@@ -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

View File

@@ -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 |

View File

@@ -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

View File

@@ -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

View File

@@ -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 |

View File

@@ -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

View File

@@ -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", ""]

View File

@@ -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", ""]

View File

@@ -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

View File

@@ -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)

View File

@@ -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 |

View File

@@ -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)

View File

@@ -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>

View File

@@ -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"])

View File

@@ -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()

View File

@@ -0,0 +1,4 @@
argumentToEnsureNotTaintedNotMarkedAsSpurious
untaintedArgumentToEnsureTaintedNotMarkedAsMissing
testFailures
failures

View File

@@ -0,0 +1,2 @@
import experimental.meta.InlineTaintTest
import MakeInlineTaintTest<TestTaintTrackingConfig>

View File

@@ -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

View File

@@ -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

View File

@@ -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] |

View File

@@ -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

View File

@@ -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

View File

@@ -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 | |

View File

@@ -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__':

View File

@@ -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

View File

@@ -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