forked from ossf/wg-best-practices-os-developers
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding documentation to CWE-617 as part of ossf#531
Signed-off-by: edanhub <[email protected]>
- Loading branch information
Showing
5 changed files
with
268 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
153 changes: 153 additions & 0 deletions
153
docs/Secure-Coding-Guide-for-Python/CWE-691/CWE-617/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
# CWE-617: Reachable Assertion | ||
|
||
Assertions are a useful developer tool, but they cannot be relied upon to be present in a production environment. Incorrect function arguments should be handled by an appropriate exception. | ||
|
||
Python removes assertions when a script is run with the `-O` and `-OO` options [[Python 3.9 Documentation](https://docs.python.org/3.9/using/cmdline.html?highlight=pythonoptimize#cmdoption-o)]. | ||
|
||
## Non-Compliant Code Example | ||
|
||
The code is checking for invalid arguments by using assertions. In this example, any positive integer between 1-709 inclusive is valid, and any other argument is invalid. | ||
|
||
If the script is run normally, the assertions will catch the invalid arguments. If the script is run in optimized mode, assertions are removed from the bytecode and the function will not work as intended. To simplify the exploit code, the specific exception raised by the argument is caught. | ||
|
||
[*noncompliant01.py:*](noncompliant01.py) | ||
|
||
```py | ||
""" Non-compliant Code Example """ | ||
import math | ||
|
||
|
||
def my_exp(x): | ||
assert x in range( | ||
1, 710 | ||
), f"Argument {x} is not valid" # range(1, 709) produces 1-708 | ||
return math.exp(x) | ||
|
||
|
||
##################### | ||
# exploiting above code example | ||
##################### | ||
|
||
try: | ||
print(my_exp(1)) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
try: | ||
print(my_exp(709)) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
try: | ||
print(my_exp(710)) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
try: | ||
print(my_exp(0)) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
try: | ||
print(my_exp("b")) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
# output | ||
|
||
# $ python3.9 noncompliant01.py | ||
# 2.718281828459045 | ||
# 8.218407461554972e+307 | ||
# Argument 710 is not valid | ||
# Argument 0 is not valid | ||
# Argument b is not valid | ||
# $ python3.9 -O noncompliant01.py | ||
# 2.718281828459045 | ||
# 8.218407461554972e+307 | ||
# math range error | ||
# 1.0 | ||
# must be real number, not str | ||
|
||
``` | ||
|
||
## Compliant Solution | ||
|
||
The `my_exp()` function raises a `ValueError` exception if an invalid argument is supplied. This works if the script is run in an optimized mode or not. | ||
|
||
[*compliant01.py:*](compliant01.py) | ||
|
||
```py | ||
""" Compliant Code Example """ | ||
import math | ||
|
||
|
||
def my_exp(x): | ||
if x not in range(1, 710): # range(1, 709) produces 1-708 | ||
raise ValueError(f"Argument {x} is not valid") | ||
return math.exp(x) | ||
|
||
|
||
##################### | ||
# exploiting above code example | ||
##################### | ||
|
||
try: | ||
print(my_exp(1)) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
try: | ||
print(my_exp(709)) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
try: | ||
print(my_exp(710)) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
try: | ||
print(my_exp(0)) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
try: | ||
print(my_exp("b")) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
# output | ||
|
||
# $ python3.9 compliant01.py | ||
# 2.718281828459045 | ||
# 8.218407461554972e+307 | ||
# Argument 710 is not valid | ||
# Argument 0 is not valid | ||
# Argument b is not valid | ||
# $ python3.9 -O compliant01.py | ||
# 2.718281828459045 | ||
# 8.218407461554972e+307 | ||
# Argument 710 is not valid | ||
# Argument 0 is not valid | ||
# Argument b is not valid | ||
|
||
``` | ||
|
||
## Automated Detection | ||
|
||
|Tool|Version|Checker|Description| | ||
|:---|:---|:---|:---| | ||
|Bandit|1.6.2|B101:assert_used|Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.| | ||
|
||
## Related Guidelines | ||
|
||
||| | ||
|:---|:---| | ||
|[MITRE CWE](http://cwe.mitre.org/)|Pillar<br>[CWE-691: Insufficient Control Flow Management (4.13) (mitre.org)](https://cwe.mitre.org/data/definitions/691.html)| | ||
|[MITRE CWE](http://cwe.mitre.org/)|Base:<br>[CWE-617, Reachable Assertion](https://cwe.mitre.org/data/definitions/617.html)| | ||
|
||
## Bibliography | ||
|
||
||| | ||
|:---|:---| | ||
|[[Python 3.9 Documentation](https://docs.python.org/3.9/using/cmdline.html?highlight=pythonoptimize#cmdoption-o)]|Python Software Foundation. (2024). Command line and environment - cmdoption -o [online].<br>Available from: [https://docs.python.org/3.9/using/cmdline.html?highlight=pythonoptimize#cmdoption-o](https://docs.python.org/3.9/using/cmdline.html?highlight=pythonoptimize#cmdoption-o)<br>[accessed 10 October 2024].| |
55 changes: 55 additions & 0 deletions
55
docs/Secure-Coding-Guide-for-Python/CWE-691/CWE-617/compliant01.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# SPDX-FileCopyrightText: OpenSSF project contributors | ||
# SPDX-License-Identifier: MIT | ||
import math | ||
|
||
|
||
def my_exp(x): | ||
if x not in range(1, 710): # range(1, 709) produces 1-708 | ||
raise ValueError(f"Argument {x} is not valid") | ||
return math.exp(x) | ||
|
||
|
||
##################### | ||
# exploiting above code example | ||
##################### | ||
|
||
try: | ||
print(my_exp(1)) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
try: | ||
print(my_exp(709)) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
try: | ||
print(my_exp(710)) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
try: | ||
print(my_exp(0)) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
try: | ||
print(my_exp("b")) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
# output | ||
|
||
# $ python3.9 compliant01.py | ||
# 2.718281828459045 | ||
# 8.218407461554972e+307 | ||
# Argument 710 is not valid | ||
# Argument 0 is not valid | ||
# Argument b is not valid | ||
# $ python3.9 -O compliant01.py | ||
# 2.718281828459045 | ||
# 8.218407461554972e+307 | ||
# Argument 710 is not valid | ||
# Argument 0 is not valid | ||
# Argument b is not valid | ||
|
55 changes: 55 additions & 0 deletions
55
docs/Secure-Coding-Guide-for-Python/CWE-691/CWE-617/noncompliant01.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# SPDX-FileCopyrightText: OpenSSF project contributors | ||
# SPDX-License-Identifier: MIT | ||
import math | ||
|
||
|
||
def my_exp(x): | ||
assert x in range( | ||
1, 710 | ||
), f"Argument {x} is not valid" # range(1, 709) produces 1-708 | ||
return math.exp(x) | ||
|
||
|
||
##################### | ||
# exploiting above code example | ||
##################### | ||
|
||
try: | ||
print(my_exp(1)) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
try: | ||
print(my_exp(709)) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
try: | ||
print(my_exp(710)) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
try: | ||
print(my_exp(0)) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
try: | ||
print(my_exp("b")) | ||
except (AssertionError, OverflowError, TypeError, ValueError) as e: | ||
print(e) | ||
|
||
# output | ||
|
||
# $ python3.9 noncompliant01.py | ||
# 2.718281828459045 | ||
# 8.218407461554972e+307 | ||
# Argument 710 is not valid | ||
# Argument 0 is not valid | ||
# Argument b is not valid | ||
# $ python3.9 -O noncompliant01.py | ||
# 2.718281828459045 | ||
# 8.218407461554972e+307 | ||
# math range error | ||
# 1.0 | ||
# must be real number, not str |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters