Skip to content
Merged
72 changes: 41 additions & 31 deletions docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-460/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,92 +10,101 @@ A consequence of this is that the code is left in a bad state.

One of the ways to mitigate this is to make sure that cleanup happens or that you should exit the program. Use throwing exceptions sparsely.

Another way to mitigate this is to use the ‘with’ statement. It simplifies resource management by automatically handling setup and cleanup tasks. It's commonly used with files, network connections and databases to ensure resources are properly released even if errors occur making your code cleaner.
Another way to mitigate this is to use the `with` statement. It simplifies resource management by automatically handling setup and cleanup tasks. It's commonly used with files, network connections and databases to ensure resources are properly released even if errors occur making your code cleaner.

Not using the `with` statement requires to use `lock.aquire()` and `lock.release()` as demonstrated in the `example01.py` code.

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

```python
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT

import threading

lock = threading.Lock()
lock.acquire()
try:
...
finally:
lock.release()

```

It is best practice to use `with` statement in such cases as it will make sure the resource gets released even if an exception occurs in the execution.

## Non-Compliant Code Example

In the noncompliant.py example, a thread gets locked, but not unlocked due to an exception being thrown before it can be closed. This might lead to the lock remaining closed and inaccessible for further use.
In the `noncompliant01.py` example, a thread gets locked, but not unlocked due to an exception being thrown before it can be closed. This might lead to the lock remaining closed and inaccessible for further use.

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

```python
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT

"""Non-compliant Code Example"""

import threading


lock = threading.Lock()


def perform_critical_operation():
# the lock has been acquired for performing a critical operation
lock.acquire()
print("Lock acquired, performing critical operation...")
# simulating an error before it can be released
raise ValueError("Something went wrong!")
lock.release() # This line is never reached due to the exception


try:
perform_critical_operation()
except ValueError as e:
print(f"Caught exception: {e}")

# Next attempt to acquire the lock will block forever — deadlock!

# Next attempt to acquire the lock will block forever; as there is a deadlock!
lock.acquire()
print("This will never print because the lock was never released.")
print("This will not print because the lock was never released.")

```

In the above code example, the acquired lock never gets released, as an error gets thrown before it can be released.
In the `noncompliant01.py` code example, the acquired lock never gets released, as an error gets thrown before it can be released.

## Compliant Solution

In compliant01.py we use the with statement to ensure that the lock is released properly even if an error is to occur.
The `compliant01.py` is using the `with` statement to ensure that the lock is released properly even if an error is to occur.

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

## Compliant Code Example

```python
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
"""Compliant Code Example"""

""" Compliant Code Example """
import threading

lock = threading.Lock()

def compliant_example():

def perform_critical_operation():
with lock:
# the lock has been acquired using the 'with' statement and will be released when the block exits; even if an exception occurs
print("Lock acquired, performing critical operation...")
# raising an exception
raise ValueError("Something went wrong!")
# This line will not be reached because of the exception above
print("Lock released.")


try:
compliant_example()
perform_critical_operation()
except ValueError as e:
print(f"Caught exception: {e}")
```

### with lock: is shorthand for

```python
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT

lock.acquire()
try:
...
finally:
lock.release()

```

It is best practice to use 'with' in such cases as it will make sure the resource gets released even if an exception occurs in the execution.

## Automated Detection

|||||
Expand All @@ -106,4 +115,5 @@ It is best practice to use 'with' in such cases as it will make sure the resourc

|||
|:---|:---|
|[CWE MITRE Pillar](http://cwe.mitre.org/)|[https://cwe.mitre.org/data/definitions/460.html]|
|[SEI CERT](https://wiki.sei.cmu.edu/confluence/display/java/SEI+CERT+Oracle+Coding+Standard+for+Java)|[ERR03-J. Restore prior object state on method failure - SEI CERT Oracle Coding Standard for Java - Confluence (cmu.edu)](https://wiki.sei.cmu.edu/confluence/display/java/ERR03-J.+Restore+prior+object+state+on+method+failure)|
|[CWE MITRE Pillar](http://cwe.mitre.org/)|<http://cwe.mitre.org/data/definitions/460.html>|
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
<!--
SPDX-FileCopyrightText: OpenSSF project contributors
SPDX-License-Identifier: MIT
-->
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
"""Compliant Code Example"""

## Compliant Code Example

```python
import threading

lock = threading.Lock()
Expand All @@ -15,9 +11,8 @@ def perform_critical_operation():
with lock:
# the lock has been acquired using the 'with' statement and will be released when the block exits; even if an exception occurs
print("Lock acquired, performing critical operation...")
# raising an exception
raise ValueError("Something went wrong!")
# This line will not be reached because of the exception above,
# This line will not be reached because of the exception above
print("Lock released.")


Expand Down
11 changes: 11 additions & 0 deletions docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-460/example01.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT

import threading

lock = threading.Lock()
lock.acquire()
try:
...
finally:
lock.release()
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
""" Non-compliant Code Example """
"""Non-compliant Code Example"""

import threading


Expand All @@ -23,4 +24,3 @@ def perform_critical_operation():
# Next attempt to acquire the lock will block forever; as there is a deadlock!
lock.acquire()
print("This will not print because the lock was never released.")

1 change: 1 addition & 0 deletions docs/Secure-Coding-Guide-for-Python/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ It is __not production code__ and requires code-style or python best practices t
|[CWE-410: Insufficient Resource Pool](CWE-664/CWE-410/README.md)||
|[CWE-426: Untrusted Search Path](CWE-664/CWE-426/README.md)|[CVE-2015-1326](https://www.cvedetails.com/cve/CVE-2015-1326),<br/>CVSSv3.0: __8.8__,<br/>EPSS: __00.20__ (23.11.2023)|
|[CWE-459: Incomplete Cleanup](CWE-664/CWE-459/README.md)||
|[CWE-460: Improper Cleanup on Thrown Exception](CWE-664/CWE-460/README.md)|[CVE-2008-0002](https://www.cvedetails.com/cve/CVE-2008-0002),<br/>CVSSv3.1: __5.8__,<br/>EPSS: __04.10__ (04.09.2025)|
|[CWE-501: Trust Boundary Violation)](CWE-664/CWE-501/README.md)|[CVE-2023-28597](https://www.cvedetails.com/cve/CVE-2023-28597),<br/>CVSSv3.0: __7.5__,<br/>EPSS: __00.11__ (05.11.2024)|
|[CWE-502: Deserialization of Untrusted Data)](CWE-664/CWE-502/.)|[CVE-2018-8021](https://www.cvedetails.com/cve/CVE-2018-8021),<br/>CVSSv3.0: __9.8__,<br/>EPSS: __93.54__ (05.11.2024)|
|[CWE-532: Insertion of Sensitive Information into Log File](CWE-664/CWE-532/README.md)|[CVE-2023-45585](https://www.cvedetails.com/cve/CVE-2023-45585),<br/>CVSSv3.1: __9.8__,<br/>EPSS: __0.04__ (01.11.2024)|
Expand Down