Skip to content
This repository has been archived by the owner on Oct 11, 2024. It is now read-only.

Adding CWE-400 README.md and updated main README.md #9

Merged
merged 3 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
107 changes: 107 additions & 0 deletions CWE-664/CWE-400/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# CWE-400: Uncontrolled Resource Consumption

Canceling the task in a thread pool only prevents it from being executed if it has not started yet. For the task to be interruptible, it must handle the `threading.Event` flag.

## Non-Compliant Code Example

Tasks can be submitted to the ThreadPoolExecutor by calling `submit()`. Submitted tasks can be canceled by calling `cancel()` on the Future object returned by `submit()`. Calling this method will return True and stop the task from being executed if it has not started yet. However, if its execution has already started, calling `cancel()` will instead return False and will not stop the task [[Python 3.10.4 docs on threading.Event]](https://docs.python.org/3/library/threading.html#event-objects).

[*noncompliant01.py:*](noncompliant01.py)

```py
""" Non-compliant Code Example """
import time
from concurrent.futures import ThreadPoolExecutor


def take_time(x):
print(f"Started Task: {x}")
# Simulate work
for i in range(10):
time.sleep(1)
print(f"Completed Task: {x}")


def run_thread(_executor, var):
future = _executor.submit(take_time, var)
return future


def interrupt(future):
print(future.cancel())
print(f"Interrupted: {future}")


#####################
# Exploiting above code example
#####################


with ThreadPoolExecutor() as executor:
task = run_thread(executor, "A")
interrupt(task)

```

## Compliant Solution

Tasks submitted to the ThreadPoolExecutor can be interrupted by setting a thread-safe flag, such as `threading.Event` [[Python 3.10.4 docs on threading.Event]](https://docs.python.org/3/library/threading.html#event-objects). An Event object should be passed as an argument to the submitted task. From within the task function, we need to manually check the flag status by calling `event.is_set()` and handling the interruption. In order to set the Event flag, we can call `event.set()` on the event object.

[*compliant01.py:*](compliant01.py)

```py
""" Compliant Code Example """
import time
from concurrent.futures import ThreadPoolExecutor
from threading import Event


def take_time(x, _event):
print(f"Started Task: {x}")
# Simulate work
for _ in range(10):
if _event.is_set():
print(f"Interrupted Task: {x}")
# Save partial results
return
time.sleep(1)
print(f"Completed Task: {x}")


def run_thread(_executor, var):
e = Event()
future = _executor.submit(take_time, var, e)
return future, e


def interrupt(future, e):
"""Cancel the task, just in case it is not yet running, and set the Event flag"""
future.cancel()
e.set()


#####################
# Exploiting above code example
#####################


with ThreadPoolExecutor() as executor:
task, event = run_thread(executor, "A")
interrupt(task, event)

```

## Related Guidelines

|||
|:---|:---|
|[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)|
|[MITRE CWE](http://cwe.mitre.org/)|Class [CWE-400: Uncontrolled Resource Consumption (4.12)](https://cwe.mitre.org/data/definitions/400.html)|
|[SEI CERT Coding Standard for Java](https://wiki.sei.cmu.edu/confluence/display/java/SEI+CERT+Oracle+Coding+Standard+for+Java)|[TPS02-J. Ensure that tasks submitted to a thread pool are interruptible](https://wiki.sei.cmu.edu/confluence/display/java/TPS02-J.+Ensure+that+tasks+submitted+to+a+thread+pool+are+interruptible)|

## Bibliography

|||
|:---|:---|
|[[Python 3.10.4 docs Future.cancel]](https://docs.python.org/3/library/concurrent.futures.html)|concurrent.futures — Launching parallel tasks — Python 3.10.4 documentation. Available from: <https://docs.python.org/3/library/concurrent.futures.html> \[Last Accessed May 2024]|
|[[Python 3.10.4 docs on threading.Event]](https://docs.python.org/3/library/threading.html#event-objects)|threading — Thread-based parallelism - Event Objects. Available from: <https://docs.python.org/3/library/threading.html#event-objects> \[Last Accessed May 2024]|
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

Promote secure products by knowing the difference between secure compliant
and non-compliant code with `CPython >= 3.9` using modules listed on

[[Python Module Index 2023]](https://docs.python.org/3.9/py-modindex.html) \[Python 2023].

This page is in initiative by Ericsson to improve secure coding in Python by providing a location for study. Its structure is based on
Expand Down Expand Up @@ -41,7 +42,7 @@ It is **not production code** and requires code-style or python best practices t
|:-----------------------------------------------------------------------------------------------------------------------------------------------|:----|
|[CWE-134: Use of Externally-Controlled Format String](CWE-664/CWE-134/.)|[CVE-2022-27177](https://www.cvedetails.com/cve/CVE-2022-27177/),<br>CVSSv3.1: **9.8**,<br>EPSS:**00.37**(01.12.2023)|
|[CWE-197: Numeric Truncation Error](CWE-664/CWE-197/.)||
|[CWE-400: Uncontrolled Resource Consumption](CWE-664/CWE-400/.)||
|[CWE-400: Uncontrolled Resource Consumption](CWE-664/CWE-400/README.md)||
|[CWE-409: Improper Handling of Highly Compressed Data (Data Amplification)](CWE-664/CWE-409/.)||
|[CWE-410: Insufficient Resource Pool](CWE-664/CWE-410/.)||
|[CWE-502: Deserialization of Untrusted Data)](CWE-664/CWE-502/.)||
Expand Down