Skip to content

Commit 8afdf26

Browse files
committed
Python: Add modeling of idna PyPI package
1 parent 7ed20a8 commit 8afdf26

File tree

9 files changed

+63
-0
lines changed

9 files changed

+63
-0
lines changed

docs/codeql/support/reusables/frameworks.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ Python built-in support
158158
dill, Serialization
159159
fabric, Utility library
160160
invoke, Utility library
161+
idna, Utility library
161162
mysql-connector-python, Database
162163
MySQLdb, Database
163164
psycopg2, Database
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* Added modeling of the PyPI package `idna`, for encoding/decoding Internationalised Domain Names in Applications.

python/ql/src/semmle/python/Frameworks.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ private import semmle.python.frameworks.Dill
1010
private import semmle.python.frameworks.Django
1111
private import semmle.python.frameworks.Fabric
1212
private import semmle.python.frameworks.Flask
13+
private import semmle.python.frameworks.Idna
1314
private import semmle.python.frameworks.Invoke
1415
private import semmle.python.frameworks.MysqlConnectorPython
1516
private import semmle.python.frameworks.MySQLdb
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* Provides classes modeling security-relevant aspects of the `idna` PyPI package.
3+
* See https://pypi.org/project/idna/.
4+
*/
5+
6+
private import python
7+
private import semmle.python.dataflow.new.DataFlow
8+
private import semmle.python.dataflow.new.TaintTracking
9+
private import semmle.python.Concepts
10+
private import semmle.python.ApiGraphs
11+
12+
/**
13+
* Provides models for the `idna` PyPI package.
14+
* See https://pypi.org/project/idna/.
15+
*/
16+
private module IdnaModel {
17+
/** A call to `idna.encode`. */
18+
private class IdnaEncodeCall extends Encoding::Range, DataFlow::CallCfgNode {
19+
IdnaEncodeCall() { this = API::moduleImport("idna").getMember("encode").getACall() }
20+
21+
override DataFlow::Node getAnInput() { result = [this.getArg(0), this.getArgByName("s")] }
22+
23+
override DataFlow::Node getOutput() { result = this }
24+
25+
override string getFormat() { result = "IDNA" }
26+
}
27+
28+
/** A call to `idna.decode`. */
29+
private class IdnaDecodeCall extends Decoding::Range, DataFlow::CallCfgNode {
30+
IdnaDecodeCall() { this = API::moduleImport("idna").getMember("decode").getACall() }
31+
32+
override DataFlow::Node getAnInput() { result = [this.getArg(0), this.getArgByName("s")] }
33+
34+
override DataFlow::Node getOutput() { result = this }
35+
36+
override string getFormat() { result = "IDNA" }
37+
38+
override predicate mayExecuteInput() { none() }
39+
}
40+
}

python/ql/test/library-tests/frameworks/idna/ConceptsTest.expected

Whitespace-only changes.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import python
2+
import experimental.meta.ConceptsTest
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
argumentToEnsureNotTaintedNotMarkedAsSpurious
2+
untaintedArgumentToEnsureTaintedNotMarkedAsMissing
3+
failures
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import experimental.meta.InlineTaintTest
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import idna
2+
3+
def test_idna():
4+
ts = TAINTED_STRING
5+
tb = TAINTED_BYTES
6+
7+
ensure_tainted(
8+
idna.encode(ts), # $ tainted encodeInput=ts encodeOutput=Attribute() encodeFormat=IDNA
9+
idna.encode(s=ts), # $ tainted encodeInput=ts encodeOutput=Attribute() encodeFormat=IDNA
10+
11+
idna.decode(tb), # $ tainted decodeInput=tb decodeOutput=Attribute() decodeFormat=IDNA
12+
idna.decode(s=tb), # $ tainted decodeInput=tb decodeOutput=Attribute() decodeFormat=IDNA
13+
)

0 commit comments

Comments
 (0)