Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
f2fee60
spelling: access
jsoref Oct 13, 2022
ac1c522
spelling: attribute
jsoref Oct 12, 2022
e3b85b1
spelling: compatibility
jsoref Oct 12, 2022
6e905ce
spelling: connection
jsoref Oct 12, 2022
d648886
spelling: context
jsoref Oct 12, 2022
3f74fa9
spelling: corresponding
jsoref Oct 12, 2022
dc38300
spelling: credentials
jsoref Oct 12, 2022
cce8a97
spelling: cross
jsoref Oct 12, 2022
9eaeafd
spelling: decide
jsoref Oct 13, 2022
7b070ba
spelling: decorated
jsoref Oct 13, 2022
165514c
spelling: dispatcher
jsoref Oct 12, 2022
7fd7d9c
spelling: distinguish
jsoref Oct 12, 2022
90b8781
spelling: edge
jsoref Oct 12, 2022
565543a
spelling: elliptic
jsoref Oct 12, 2022
b2f5bfa
spelling: emptiness
jsoref Oct 12, 2022
de63bbc
spelling: everything
jsoref Oct 12, 2022
c527264
spelling: execute
jsoref Oct 12, 2022
df9c8c7
spelling: flow
jsoref Oct 12, 2022
9004a83
spelling: for
jsoref Oct 12, 2022
9d53938
spelling: further
jsoref Oct 12, 2022
df05c77
spelling: important
jsoref Oct 12, 2022
5f1f551
spelling: indirection
jsoref Oct 13, 2022
d18f5c7
spelling: interacting
jsoref Oct 13, 2022
3a38da0
spelling: jumpsteps
jsoref Oct 13, 2022
06ec1e2
spelling: looking
jsoref Oct 12, 2022
6ac3151
spelling: method
jsoref Oct 12, 2022
02f3ce1
spelling: mutually
jsoref Oct 12, 2022
3337f4c
spelling: override
jsoref Oct 12, 2022
90aa65a
spelling: package
jsoref Oct 12, 2022
2f8c515
spelling: parameter
jsoref Oct 12, 2022
7883263
spelling: printing
jsoref Oct 12, 2022
662c96e
spelling: processing
jsoref Oct 12, 2022
7b019da
spelling: quadratic
jsoref Oct 12, 2022
c02b6b3
spelling: qualified
jsoref Oct 12, 2022
7ad24f3
spelling: recommendation
jsoref Oct 12, 2022
441d535
spelling: recursion
jsoref Oct 12, 2022
24f847a
spelling: representing
jsoref Oct 12, 2022
00cc333
spelling: request
jsoref Oct 12, 2022
76aa048
spelling: resolve
jsoref Oct 12, 2022
36bd186
spelling: response
jsoref Oct 13, 2022
d1929ab
spelling: restrictions
jsoref Oct 12, 2022
eed0971
spelling: retrieval
jsoref Oct 12, 2022
ad7dc81
spelling: sanitize
jsoref Oct 12, 2022
bc339e4
spelling: see https
jsoref Oct 12, 2022
05e20a3
spelling: shortcuts
jsoref Oct 12, 2022
33bc313
spelling: something
jsoref Oct 12, 2022
887b49a
spelling: superfluous
jsoref Oct 12, 2022
7ee24e5
spelling: synthesized
jsoref Oct 12, 2022
8669de5
spelling: the
jsoref Oct 12, 2022
f19a5c4
spelling: uninitialized
jsoref Oct 12, 2022
5765a71
spelling: whether
jsoref Oct 12, 2022
9fef7d4
spelling: which
jsoref Oct 12, 2022
08f688d
spelling: without
jsoref Oct 13, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions python/PoCs/XmlParsing/PoC.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
# other setup

# we set up local Flask application so we can tests whether loading external resources
# works (such as SSRF from DTD-retrival works)
# works (such as SSRF from DTD-retrieval works)
app = Flask(__name__)

@app.route("/alive")
Expand Down Expand Up @@ -187,7 +187,7 @@ def test_billion_laughs_allowed_by_default():

@staticmethod
@expects_timeout
def test_quardratic_blowup_allowed_by_default():
def test_quadratic_blowup_allowed_by_default():
parser = xml.sax.make_parser()
parser.parse(StringIO(quadratic_blowup))

Expand Down Expand Up @@ -263,7 +263,7 @@ def test_billion_laughs_allowed_by_default():

@staticmethod
@expects_timeout
def test_quardratic_blowup_allowed_by_default():
def test_quadratic_blowup_allowed_by_default():
parser = xml.etree.ElementTree.XMLParser()
_root = xml.etree.ElementTree.fromstring(quadratic_blowup, parser=parser)

Expand Down Expand Up @@ -324,7 +324,7 @@ def test_billion_laughs_disabled_by_default():
assert "Detected an entity reference loop" in str(e)

@staticmethod
def test_quardratic_blowup_disabled_by_default():
def test_quadratic_blowup_disabled_by_default():
parser = lxml.etree.XMLParser()
try:
_root = lxml.etree.fromstring(quadratic_blowup, parser=parser)
Expand Down Expand Up @@ -465,7 +465,7 @@ def test_billion_laughs_disabled_by_default():
assert d == {"lolz": None}, d

@staticmethod
def test_quardratic_blowup_disabled_by_default():
def test_quadratic_blowup_disabled_by_default():
d = xmltodict.parse(quadratic_blowup)
assert d == {"foo": None}, d

Expand All @@ -476,7 +476,7 @@ def test_billion_laughs_manually_enabled():

@staticmethod
@expects_timeout
def test_quardratic_blowup_manually_enabled():
def test_quadratic_blowup_manually_enabled():
xmltodict.parse(quadratic_blowup, disable_entities=False)

@staticmethod
Expand Down Expand Up @@ -524,7 +524,7 @@ def test_billion_laughs():

@staticmethod
@expects_timeout
def test_quardratic_blowup():
def test_quadratic_blowup():
xml.dom.minidom.parseString(quadratic_blowup)

@staticmethod
Expand Down Expand Up @@ -585,7 +585,7 @@ def test_billion_laughs():

@staticmethod
@expects_timeout
def test_quardratic_blowup():
def test_quadratic_blowup():
doc = xml.dom.pulldom.parseString(quadratic_blowup)
for event, node in doc:
pass
Expand Down Expand Up @@ -670,7 +670,7 @@ def test_billion_laughs():

@staticmethod
@expects_timeout
def test_quardratic_blowup():
def test_quadratic_blowup():
parser = xml.parsers.expat.ParserCreate()
parser.Parse(quadratic_blowup, True)

Expand Down Expand Up @@ -699,7 +699,7 @@ def char_data_handler(data):

assert char_data_recv == []

# there might be ways to make it vuln, but I did not investigate futher.
# there might be ways to make it vuln, but I did not investigate further.

@staticmethod
def test_dtd():
Expand All @@ -711,4 +711,4 @@ def test_dtd():
parser.Parse(dtd_retrieval, True)
assert hit_dtd == False

# there might be ways to make it vuln, but I did not investigate futher.
# there might be ways to make it vuln, but I did not investigate further.
2 changes: 1 addition & 1 deletion python/ql/examples/snippets/override_method.ql
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* @id py/examples/override-method
* @name Override of method
* @description Finds methods that overide MyClass.methodName
* @description Finds methods that override MyClass.methodName
* @tags method
* override
*/
Expand Down
2 changes: 1 addition & 1 deletion python/ql/lib/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

### Minor Analysis Improvements

* Added the ability to refer to subscript operations in the API graph. It is now possible to write `response().getMember("cookies").getASubscript()` to find code like `resp.cookies["key"]` (assuming `response` returns an API node for reponse objects).
* Added the ability to refer to subscript operations in the API graph. It is now possible to write `response().getMember("cookies").getASubscript()` to find code like `resp.cookies["key"]` (assuming `response` returns an API node for response objects).
* Added modeling of creating Flask responses with `flask.jsonify`.

## 0.6.0
Expand Down
2 changes: 1 addition & 1 deletion python/ql/lib/change-notes/released/0.6.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

### Minor Analysis Improvements

* Added the ability to refer to subscript operations in the API graph. It is now possible to write `response().getMember("cookies").getASubscript()` to find code like `resp.cookies["key"]` (assuming `response` returns an API node for reponse objects).
* Added the ability to refer to subscript operations in the API graph. It is now possible to write `response().getMember("cookies").getASubscript()` to find code like `resp.cookies["key"]` (assuming `response` returns an API node for response objects).
* Added modeling of creating Flask responses with `flask.jsonify`.
8 changes: 4 additions & 4 deletions python/ql/lib/design.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# The Python libraries

The Python libraries are a collection of libraries for analysing Python code.
Everythng can be imported by importing `python.qll`.
Everything can be imported by importing `python.qll`.

## The analysis layers

Expand All @@ -15,10 +15,10 @@ The analysis is built up in layers. the stack looks like this:

## Avoiding non-monotonic recursion

Given the many interactivg layers, it is imprtant to decie which predicates are allowed to be mutually recursive in order to avoid non-monotonic recursion when negation is used to express the predicates.
As an example, we have defined local source as those whcih do not receive local flow. This means that the local flow relation is not allowed to be recursive with anything depending on local sources.
Given the many interacting layers, it is important to decide which predicates are allowed to be mutually recursive in order to avoid non-monotonic recursion when negation is used to express the predicates.
As an example, we have defined local source as those which do not receive local flow. This means that the local flow relation is not allowed to be recursive with anything depending on local sources.

Some particular reatrictions to keep in mind:
Some particular restrictions to keep in mind:

- Typetracking needs to use a local flow step not including summaries
- Typetracking needs to use a call graph not including summaries
4 changes: 2 additions & 2 deletions python/ql/lib/semmle/python/ApiGraphs.qll
Original file line number Diff line number Diff line change
Expand Up @@ -211,15 +211,15 @@ module API {
* Gets a node representing the `i`th parameter of the function represented by this node.
*
* This predicate may have multiple results when there are multiple invocations of this API component.
* Consider using `getAnInvocation()` if there is a need to distingiush between individual calls.
* Consider using `getAnInvocation()` if there is a need to distinguish between individual calls.
*/
Node getParameter(int i) { result = this.getASuccessor(Label::parameter(i)) }

/**
* Gets the node representing the keyword parameter `name` of the function represented by this node.
*
* This predicate may have multiple results when there are multiple invocations of this API component.
* Consider using `getAnInvocation()` if there is a need to distingiush between individual calls.
* Consider using `getAnInvocation()` if there is a need to distinguish between individual calls.
*/
Node getKeywordParameter(string name) {
result = this.getASuccessor(Label::keywordParameter(name))
Expand Down
2 changes: 1 addition & 1 deletion python/ql/lib/semmle/python/Constants.qll
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ int major_version() {
explicit_major_version(result)
or
not explicit_major_version(_) and
/* If there is more than one version, prefer 2 for backwards compatibilty */
/* If there is more than one version, prefer 2 for backwards compatibility */
(if py_flags_versioned("version.major", "2", "2") then result = 2 else result = 3)
}

Expand Down
2 changes: 1 addition & 1 deletion python/ql/lib/semmle/python/Flow.qll
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,7 @@ class NameConstantNode extends NameNode {

}

/** A control flow node correspoinding to a starred expression, `*a`. */
/** A control flow node corresponding to a starred expression, `*a`. */
class StarredNode extends ControlFlowNode {
StarredNode() { toAst(this) instanceof Starred }

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Provides an extension point for for modeling user-controlled data.
* Provides an extension point for modeling user-controlled data.
* Such data is often used as data-flow sources in security queries.
*/

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Provides an extension point for for modeling sensitive data, such as secrets, certificates, or passwords.
* Provides an extension point for modeling sensitive data, such as secrets, certificates, or passwords.
* Sensitive data can be interesting to use as data-flow sources in security queries.
*/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,12 @@ module ArgumentPassing {
result = TCfgNode(call.getArgByName(unbind_string(argName)))
)
or
// a synthezised argument passed to the starred parameter (at position -1)
// a synthesized argument passed to the starred parameter (at position -1)
callable.getScope().hasVarArg() and
paramN = -1 and
result = TPosOverflowNode(call, callable)
or
// a synthezised argument passed to the doubly starred parameter (at position -2)
// a synthesized argument passed to the doubly starred parameter (at position -2)
callable.getScope().hasKwArg() and
paramN = -2 and
result = TKwOverflowNode(call, callable)
Expand Down Expand Up @@ -769,7 +769,7 @@ DataFlowCallable viableCallable(ExtractedDataFlowCall call) {
// A call to a library callable with a flow summary
// In this situation we can not resolve the callable from the call,
// as that would make data flow depend on type tracking.
// Instead we reolve the call from the summary.
// Instead we resolve the call from the summary.
exists(LibraryCallable callable |
result = TLibraryCallable(callable) and
call.getNode() = callable.getACall().getNode()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ predicate jumpStep(Node nodeFrom, Node nodeTo) {
* Set of jumpSteps that are shared with type-tracker implementation.
*
* For ORM modeling we want to add jumpsteps to global dataflow, but since these are
* based on type-trackers, it's important that these new ORM jumsteps are not used in
* based on type-trackers, it's important that these new ORM jumpsteps are not used in
* the type-trackers as well, as that would make evaluation of type-tracking recursive
* with the new jumpsteps.
*
Expand All @@ -485,7 +485,7 @@ predicate jumpStepSharedWithTypeTracker(Node nodeFrom, Node nodeTo) {
* Set of jumpSteps that are NOT shared with type-tracker implementation.
*
* For ORM modeling we want to add jumpsteps to global dataflow, but since these are
* based on type-trackers, it's important that these new ORM jumsteps are not used in
* based on type-trackers, it's important that these new ORM jumpsteps are not used in
* the type-trackers as well, as that would make evaluation of type-tracking recursive
* with the new jumpsteps.
*
Expand Down Expand Up @@ -668,7 +668,7 @@ predicate attributeStoreStep(Node nodeFrom, AttributeContent c, PostUpdateNode n
}

/**
* Holds if `nodeFrom` flows into the synthezised positional overflow argument (`nodeTo`)
* Holds if `nodeFrom` flows into the synthesized positional overflow argument (`nodeTo`)
* at the position indicated by `c`.
*/
predicate posOverflowStoreStep(CfgNode nodeFrom, TupleElementContent c, Node nodeTo) {
Expand All @@ -680,7 +680,7 @@ predicate posOverflowStoreStep(CfgNode nodeFrom, TupleElementContent c, Node nod
}

/**
* Holds if `nodeFrom` flows into the synthezised keyword overflow argument (`nodeTo`)
* Holds if `nodeFrom` flows into the synthesized keyword overflow argument (`nodeTo`)
* at the key indicated by `c`.
*/
predicate kwOverflowStoreStep(CfgNode nodeFrom, DictionaryElementContent c, Node nodeTo) {
Expand Down Expand Up @@ -814,7 +814,7 @@ predicate attributeReadStep(Node nodeFrom, AttributeContent c, AttrRead nodeTo)

/**
* Holds if `nodeFrom` is a dictionary argument being unpacked and `nodeTo` is the
* synthezised unpacked argument with the name indicated by `c`.
* synthesized unpacked argument with the name indicated by `c`.
*/
predicate kwUnpackReadStep(CfgNode nodeFrom, DictionaryElementContent c, Node nodeTo) {
exists(CallNode call, CallableValue callable, string name |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@
*
* Having both extracted and non-extracted callables means that we now have three types of calls:
* - Extracted calls to extracted callables, either `NormalCall` or `SpecialCall`. These are handled by standard data flow.
* - Extracted calls to non-extracted callables, `LibraryCall`. These are handled by loking up the relevant summary when the
* global data flwo graph is connected up via `getViableCallable`.
* - Extracted calls to non-extracted callables, `LibraryCall`. These are handled by looking up the relevant summary when the
* global data flow graph is connected up via `getViableCallable`.
* - Non-extracted calls, `SummaryCall`. These are synthesised by the flow summary framework.
*
* The first two can be referred to as `ExtractedDataFlowCall`. In fact, `LibraryCall` is a subclass of `NormalCall`, where
* `getCallable` is set to `none()`. The member predicate `ExtractedDataFlowCall::getCallable` is _not_ the mechanism for
* call resolution in global data flow. That mechanism is `getViableCallable`.
* Resolving a call to a non-extracted callable goes via `LibraryCallable::getACall`, which may involve type tracking.
* To avoid that type tracking becomes mutualy recursive with data flow, type tracking must use a call graph not including summaries.
* To avoid that type tracking becomes mutually recursive with data flow, type tracking must use a call graph not including summaries.
* Type tracking sees the callgraph given by `ExtractedDataFlowCall::getACallable`.
*
* We do not support summaries of special methods via the special methods framework,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@
* Note that an empty access path means that the value we are tracking flows directly to the element.
*
*
* The `TIterableSequence(sequence)` is at this point superflous but becomes useful when handling recursive
* The `TIterableSequence(sequence)` is at this point superfluous but becomes useful when handling recursive
* structures in the LHS, where `sequence` is some internal sequence node. We can have a uniform treatment
* by always having these two synthetic nodes. So we transfer to (or, in the recursive case, read into)
* `TIterableSequence(sequence)`, from which we take a read step to `TIterableElement(sequence)` and then a
* store step to `sequence`.
*
* This allows the unknown content from the RHS to be read into `TIterableElement(sequence)` and tuple content
* to then be stored into `sequence`. If the content is already tuple content, this inderection creates crosstalk
* to then be stored into `sequence`. If the content is already tuple content, this indirection creates crosstalk
* between indices. Therefore, tuple content is never read into `TIterableElement(sequence)`; it is instead
* transferred directly from `TIterableSequence(sequence)` to `sequence` via a flow step. Such a flow step will
* also transfer other content, but only tuple content is further read from `sequence` into its elements.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ private module Cached {
/**
* Holds if `source` is a `LocalSourceNode` that can reach `sink` via local flow steps.
*
* The slightly backwards parametering ordering is to force correct indexing.
* The slightly backwards parameter ordering is to force correct indexing.
*/
cached
predicate hasLocalSource(Node sink, LocalSourceNode source) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ class TaintTrackingImplementation extends string {
}

/**
* Hold if taint flows to `src` to `(node, context, path, kind)` in a single step, labelled with `egdeLabel` with this configuration.
* Hold if taint flows to `src` to `(node, context, path, kind)` in a single step, labelled with `edgeLabel` with this configuration.
* `edgeLabel` is purely informative.
*/
predicate flowStep(
Expand Down
2 changes: 1 addition & 1 deletion python/ql/lib/semmle/python/frameworks/Aioch.qll
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ module Aioch {
}

/**
* A call to any of the the execute methods on a `aioch.Client`, which are just async
* A call to any of the execute methods on a `aioch.Client`, which are just async
* versions of the methods in the `clickhouse-driver` PyPI package.
*
* See
Expand Down
4 changes: 2 additions & 2 deletions python/ql/lib/semmle/python/frameworks/Aiohttp.qll
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ module AiohttpWebModel {
}

/** Gets a reference to an `aiohttp.web.UrlDispatcher` instance. */
API::Node urlDispathcerInstance() {
API::Node urlDispatcherInstance() {
result = API::moduleImport("aiohttp").getMember("web").getMember("UrlDispatcher").getReturn()
or
result = applicationInstance().getMember("router")
Expand Down Expand Up @@ -170,7 +170,7 @@ module AiohttpWebModel {
funcName = "route" and
routeArgsStart = 1
|
this = urlDispathcerInstance().getMember("add_" + funcName).getACall()
this = urlDispatcherInstance().getMember("add_" + funcName).getACall()
or
this = API::moduleImport("aiohttp").getMember("web").getMember(funcName).getACall()
)
Expand Down
6 changes: 3 additions & 3 deletions python/ql/lib/semmle/python/frameworks/Aiopg.qll
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ private module Aiopg {
* See https://aiopg.readthedocs.io/en/stable/sa.html#aiopg.sa.SAConnection.execute
*/
class AwaitedSAConnectionExecuteCall extends SqlExecution::Range {
SAConnectionExecuteCall excute;
SAConnectionExecuteCall execute;

AwaitedSAConnectionExecuteCall() { this = excute.getReturn().getAwaited().asSource() }
AwaitedSAConnectionExecuteCall() { this = execute.getReturn().getAwaited().asSource() }

override DataFlow::Node getSql() { result = excute.getSql() }
override DataFlow::Node getSql() { result = execute.getSql() }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ module ClickhouseDriver {
string getExecuteMethodName() { result in ["execute_with_progress", "execute", "execute_iter"] }

/**
* A call to any of the the execute methods on a `clickhouse_driver.Client` method
* A call to any of the execute methods on a `clickhouse_driver.Client` method
*
* See
* - https://clickhouse-driver.readthedocs.io/en/latest/api.html#clickhouse_driver.Client.execute
Expand Down
2 changes: 1 addition & 1 deletion python/ql/lib/semmle/python/frameworks/Cryptography.qll
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ private import semmle.python.ApiGraphs
*/
private module CryptographyModel {
/**
* Provides helper predicates for the eliptic curve cryptography parts in
* Provides helper predicates for the elliptic curve cryptography parts in
* `cryptography.hazmat.primitives.asymmetric.ec`.
*/
module Ecc {
Expand Down
2 changes: 1 addition & 1 deletion python/ql/lib/semmle/python/frameworks/Pydantic.qll
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ module Pydantic {
* NOTE: We currently overapproximate, and treat all attributes as containing
* another pydantic model. For the code below, we _could_ limit this to `main_foo`
* and members of `other_foos`. IF THIS IS CHANGED, YOU MUST CHANGE THE ADDITIONAL
* TAINT STEPS BELOW, SUCH THAT SIMPLE ACCESS OF SOMETHIGN LIKE `str` IS STILL
* TAINT STEPS BELOW, SUCH THAT SIMPLE ACCESS OF SOMETHING LIKE `str` IS STILL
* TAINTED.
*
*
Expand Down
2 changes: 1 addition & 1 deletion python/ql/lib/semmle/python/frameworks/Requests.qll
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ private module Requests {
ClassInstantiation() { this = classRef().getACall() }
}

/** Return value from making a reuqest. */
/** Return value from making a request. */
private class RequestReturnValue extends InstanceSource, DataFlow::Node {
RequestReturnValue() { this = any(OutgoingRequestCall c) }
}
Expand Down
Loading