Skip to content

Commit 349cadf

Browse files
authored
pySCG: adding 843 as part of #531 (#886)
* pySCG: adding 843 as part of #531 --------- Signed-off-by: edanhub <[email protected]> Signed-off-by: Hubert Daniszewski <[email protected]> Signed-off-by: Helge Wehder <[email protected]> Co-authored-by: andrew-costello
1 parent 8c2fc6b commit 349cadf

File tree

5 files changed

+115
-5
lines changed

5 files changed

+115
-5
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# CWE-843: Access of Resource Using Incompatible Type ('Type Confusion')
2+
3+
When operating on unsigned values coming from external sources, such as `C` or `C++` applications, they should be unpacked using variable types that can represent their entire value range.
4+
This rule is related to [CWE-197: Control rounding when converting to less precise numbers](https://github.com/ossf/wg-best-practices-os-developers/blob/main/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-197/01/README.md).
5+
6+
The scenario in `example01.py` demonstrates what can go wrong when Python needs to interact with `C` or `C++` data types using the `struct` module [[Python docs](https://docs.python.org/3/library/struct.html)]. This can be either over the network, via file, or an interaction with the operating system. A file or stream is simulated with `io.BytesIO`.
7+
8+
[*example01.py:*](example01.py)
9+
10+
```py
11+
# SPDX-FileCopyrightText: OpenSSF project contributors
12+
# SPDX-License-Identifier: MIT
13+
""" Code Example """
14+
15+
# https://docs.python.org/3/library/struct.html#format-characters
16+
# https://docs.python.org/3/library/ctypes.html
17+
18+
import io
19+
from struct import pack, unpack
20+
21+
22+
def read_from_stream(stream):
23+
value = unpack('>H', stream.getvalue())[0]
24+
return value
25+
26+
27+
#####################
28+
# attempting to exploit above code example
29+
#####################
30+
file_sim = io.BytesIO(pack("<H", 1))
31+
print(read_from_stream(file_sim))
32+
33+
```
34+
35+
The `read_from_stream` method expects a `big-endian unsigned short` but is given a `little-endian unsigned short` instead. The original packaged `1` is read as a `256`. In some use cases, it might be enough to mask the data as shown in [[SEI CERT 2015](https://wiki.sei.cmu.edu/confluence/display/java/NUM03-J.+Use+integer+types+that+can+fully+represent+the+possible+range+of++unsigned+data)] but generally it's a question of data structure and integrity that is much harder to control in raw `ctype` data than in a language-independent data format such as `Json` or `Yaml`.
36+
37+
## Non-Compliant Code Example
38+
39+
The `noncompliant01.py` demonstrates that type hints for design documentation do not prevent type confusion at runtime.
40+
41+
*[noncompliant01.py](noncompliant01.py):*
42+
43+
```python
44+
# SPDX-FileCopyrightText: OpenSSF project contributors
45+
# SPDX-License-Identifier: MIT
46+
""" Non-compliant Code Example """
47+
48+
49+
def shopping_bag(price: int, qty: int) -> int:
50+
return price * qty
51+
52+
53+
####################
54+
# attempting to exploit above code example
55+
#####################
56+
print(shopping_bag(100, "3"))
57+
58+
```
59+
60+
The `noncompliant01.py` prints "`3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333`" (number `3` 100 times) as opposed to multiplying the two numbers.
61+
62+
Pylance detects the incompatible types in the attack section during design time, however, this warning would not be of any use at runtime when an unexpected type can still be sent:
63+
![image01.png](image01.png "image01.png")
64+
65+
## Compliant Solution
66+
67+
The `compliant01.py` code ensures that both `price` and `qty` are interpreted as numeric types by explicitly casting them as `int`.
68+
69+
*[compliant01.py](compliant01.py):*
70+
71+
```python
72+
# SPDX-FileCopyrightText: OpenSSF project contributors
73+
# SPDX-License-Identifier: MIT
74+
""" Compliant Code Example """
75+
76+
77+
def shopping_bag(price: int, qty: int) -> int:
78+
return int(price) * int(qty)
79+
80+
81+
####################
82+
# attempting to exploit above code example
83+
#####################
84+
print(shopping_bag(100, "3"))
85+
86+
```
87+
88+
Depending on the use case, it can instead be safer to throw an exception when an incorrect data type is provided.
89+
90+
## Automated Detection
91+
92+
|Tool|Version|Checker|Description|
93+
|:---|:---|:---|:---|
94+
|Bandit|1.7.4 on Python 3.10.4|Not Available||
95+
|Flake8|8-4.0.1 on Python 3.10.4|Not Available||
96+
97+
## Related Guidelines
98+
99+
|||
100+
|:---|:---|
101+
|[MITRE CWE](http://cwe.mitre.org/)|Pillar: [CWE-664: Improper Control of a Resource Through its Lifetime (4.13) (mitre.org)](https://cwe.mitre.org/data/definitions/664.html)|
102+
|[MITRE CWE](http://cwe.mitre.org/)|Base: [CWE-843: Access of Resource Using Incompatible Type ('Type Confusion')](https://cwe.mitre.org/data/definitions/843.html)|
103+
|[SEI CERT Coding Standard for Java](https://wiki.sei.cmu.edu/confluence/display/java/SEI+CERT+Oracle+Coding+Standard+for+Java)|[NUM03-J. Use integer types that can fully represent the possible range of unsigned data - SEI CERT Oracle Coding Standard for Java - Confluence (cmu.edu)](https://wiki.sei.cmu.edu/confluence/display/java/NUM03-J.+Use+integer+types+that+can+fully+represent+the+possible+range+of++unsigned+data)|
104+
105+
## Bibliography
106+
107+
|||
108+
|:---|:---|
109+
|[[Python docs](https://docs.python.org/3/library/struct.html)]|Python Software Foundation. (2025). struct — Interpret bytes as packed binary data [online]. Available from: [https://docs.python.org/3/library/struct.html](https://docs.python.org/3/library/struct.html) [accessed 12 May 2025]|
110+
|[[SEI CERT 2015](https://wiki.sei.cmu.edu/confluence/display/java/NUM03-J.+Use+integer+types+that+can+fully+represent+the+possible+range+of++unsigned+data)]|Software Engineering Institute CERT Coordination Center. (2025). NUM03-J. Use integer types that can fully represent the possible range of unsigned data [online]. Available from: [https://wiki.sei.cmu.edu/confluence/display/java/NUM03-J.+Use+integer+types+that+can+fully+represent+the+possible+range+of++unsigned+data](https://wiki.sei.cmu.edu/confluence/display/java/NUM03-J.+Use+integer+types+that+can+fully+represent+the+possible+range+of++unsigned+data) [accessed 12 May 2025]|

docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-843/compliant01.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
""" Compliant Code Example """
44

55

6-
def shopping_bag(price: int, qty: str) -> int:
6+
def shopping_bag(price: int, qty: int) -> int:
77
return int(price) * int(qty)
88

99

1010
####################
11-
# attempting to exploit #above code example
11+
# attempting to exploit above code example
1212
#####################
1313
print(shopping_bag(100, "3"))
15.7 KB
Loading

docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-843/noncompliant01.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
""" Non-compliant Code Example """
44

55

6-
def shopping_bag(price: int, qty: str) -> int:
6+
def shopping_bag(price: int, qty: int) -> int:
77
return price * qty
88

99

1010
####################
11-
# attempting to exploit #above code example
11+
# attempting to exploit above code example
1212
#####################
1313
print(shopping_bag(100, "3"))

docs/Secure-Coding-Guide-for-Python/readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ It is __not production code__ and requires code-style or python best practices t
6262
|[CWE-681: Incorrect Conversion between Numeric Types](CWE-664/CWE-681/README.md)||
6363
|[CWE-681: Avoid an uncontrolled loss of precision when passing floating-point literals to a Decimal constructor.](CWE-664/CWE-681/01/README.md)||
6464
|[CWE-833: Deadlock](CWE-664/CWE-833/README.md)||
65-
|[CWE-843: Access of Resource Using Incompatible Type ('Type Confusion')](CWE-664/CWE-843/.)|[CVE-2021-29513](https://www.cvedetails.com/cve/CVE-2021-29513),<br/>CVSSv3.1: __7.8__,<br/>EPSS: __00.05__ (05.11.2024)|
65+
|[CWE-843: Access of Resource Using Incompatible Type ('Type Confusion')](CWE-664/CWE-843/README.md)|[CVE-2021-29513](https://www.cvedetails.com/cve/CVE-2021-29513),<br/>CVSSv3.1: __7.8__,<br/>EPSS: __00.02__ (13.05.2025)|
6666

6767
|[CWE-682: Incorrect Calculation](https://cwe.mitre.org/data/definitions/682.html)|Prominent CVE|
6868
|:---------------------------------------------------------------------------------------------------------------|:----|

0 commit comments

Comments
 (0)