From 31c05549566e9dd4a1a6b34803bc8f9b4830ec82 Mon Sep 17 00:00:00 2001 From: edanhub Date: Thu, 14 Aug 2025 12:46:12 +0200 Subject: [PATCH 1/2] pySCG: adding CWE-397: Declaration of Throws for Generic Exception Signed-off-by: edanhub --- .../CWE-703/CWE-397/README.md | 180 ++++++++++++++++++ .../CWE-703/CWE-397/compliant01.py | 23 +++ .../CWE-703/CWE-397/noncompliant01.py | 23 +++ docs/Secure-Coding-Guide-for-Python/readme.md | 1 + 4 files changed, 227 insertions(+) create mode 100644 docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-397/README.md create mode 100644 docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-397/compliant01.py create mode 100644 docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-397/noncompliant01.py diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-397/README.md b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-397/README.md new file mode 100644 index 00000000..aa737759 --- /dev/null +++ b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-397/README.md @@ -0,0 +1,180 @@ +# CWE-397: Declaration of Throws for Generic Exception + +Avoid raising exceptions that aren't informative on specific errors. + +`Exception` is the base class of all non-system-exiting exceptions [[Python docs 2025](https://docs.python.org/3/library/exceptions.html#Exception)]. Specific exceptions allow to determine why they were raised and attempt recovery. To catch a generic `Exception`, all more specific exceptions that subclass it would have to be caught. Raising `Exception` is likely to hide bugs and and prevents using more specialized except statements. The problem is even more severe when raising `BaseException`, which additionally includes subclasses signifying termination signals, such as `KeyboardInterrupt` and `SystemExit` [[PEP 2024](https://peps.python.org/pep-0352/#exception-hierarchy-changes)]. + +## Non-Compliant Code Example + +The `noncompliant01.py` code example consists of a function that divides two given numbers. In case the `divisor` is zero, the `divide()` function throws a generic `Exception`. + +_[noncompliant01.py](noncompliant01.py):_ + +```python +# SPDX-FileCopyrightText: OpenSSF project contributors +# SPDX-License-Identifier: MIT +"""Compliant Code Example""" + + +def divide(divided: int, divisor: int) -> float: + """Function that divides two numbers""" + if divisor == 0: + raise Exception("Cannot divide by zero") + return divided / divisor + + +##################### +# exploiting above code example +##################### +try: + divide(1, 0) +except SystemError: + print("Something wrong with the system!") +except ZeroDivisionError: + print("I divided by zero!") +except Exception: + print("Something went wrong and I have no clue what!") + +``` + +Despite including the reason for the exception in its message, the client, having expected this particular mistake to result in a `ZeroDivisionError`, will not handle it the intended way. + +## Compliant Solution + +In this specific instance, Python has a built-in exception `ZeroDivisionError` that can be thrown instead of the generic `Exception`. + +_[compliant01.py](compliant01.py):_ + +```python +# SPDX-FileCopyrightText: OpenSSF project contributors +# SPDX-License-Identifier: MIT +"""Compliant Code Example""" + + +def divide(divided: int, divisor: int) -> float: + """Function that divides two numbers""" + if divisor == 0: + raise ZeroDivisionError("Cannot divide by zero") + return divided / divisor + + +##################### +# exploiting above code example +##################### +try: + divide(1, 0) +except SystemError: + print("Something wrong with the system!") +except ZeroDivisionError: + print("I divided by zero!") +except Exception: + print("Something went wrong and I have no clue what!") + +``` + +The same exception would have been thrown when directly dividing a number by zero. Nonetheless, using specific exceptions is useful when handling different errors and edge cases. + +## Automated Detection + + +
+ + + + + + + + + + + + + + + + + +
ToolVersionCheckerDescription
Bandit1.7.4 on Python 3.10.4Not Available
Flake88-4.0.1 on Python 3.10.4Not Available
+ +## Related Guidelines + + + + + + + + + + + + + + +
+ + SEI CERT Oracle Coding Standard for Java + + + + ERR07-J. Do not throw RuntimeException, Exception, or Throwable + +
+ + MITRE CWE + + + Pillar: + + CWE-703: Improper Check or Handling of Exceptional Conditions + +
+ + MITRE CWE + + + Base: + + CWE-397, Declaration of Throws for Generic Exception (4.12) + +
+ +## Bibliography + + + + + + + + + + +
+ [ + + Python docs 2025 + + ] + + Python Software Foundation. (2025). Built in exceptions [online].
+ Available from: + + https://docs.python.org/3/library/exceptions.html#Exception +
+ [Accessed 29 July 2025] +
+ [ + + PEP 2024 + + ] + + Python Enhancement Proposal 352. (2024). Required Superclass for Exceptions [online].
+ Available from: + + https://peps.python.org/pep-0352/#exception-hierarchy-changes +
+ [Accessed 29 July 2025] +
diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-397/compliant01.py b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-397/compliant01.py new file mode 100644 index 00000000..f4501e0e --- /dev/null +++ b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-397/compliant01.py @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: OpenSSF project contributors +# SPDX-License-Identifier: MIT +"""Compliant Code Example""" + + +def divide(divided: int, divisor: int) -> float: + """Function that divides two numbers""" + if divisor == 0: + raise ZeroDivisionError("Cannot divide by zero") + return divided / divisor + + +##################### +# exploiting above code example +##################### +try: + divide(1, 0) +except SystemError: + print("Something wrong with the system!") +except ZeroDivisionError: + print("I divided by zero!") +except Exception: + print("Something went wrong and I have no clue what!") diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-397/noncompliant01.py b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-397/noncompliant01.py new file mode 100644 index 00000000..fde9b8d3 --- /dev/null +++ b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-397/noncompliant01.py @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: OpenSSF project contributors +# SPDX-License-Identifier: MIT +"""Compliant Code Example""" + + +def divide(divided: int, divisor: int) -> float: + """Function that divides two numbers""" + if divisor == 0: + raise Exception("Cannot divide by zero") + return divided / divisor + + +##################### +# exploiting above code example +##################### +try: + divide(1, 0) +except SystemError: + print("Something wrong with the system!") +except ZeroDivisionError: + print("I divided by zero!") +except Exception: + print("Something went wrong and I have no clue what!") diff --git a/docs/Secure-Coding-Guide-for-Python/readme.md b/docs/Secure-Coding-Guide-for-Python/readme.md index 9dab3587..0718edf5 100644 --- a/docs/Secure-Coding-Guide-for-Python/readme.md +++ b/docs/Secure-Coding-Guide-for-Python/readme.md @@ -97,6 +97,7 @@ It is __not production code__ and requires code-style or python best practices t |[CWE-252: Unchecked Return Value](CWE-703/CWE-252/README.md)|| |[CWE-390: Detection of Error Condition without Action](CWE-703/CWE-390/README.md)|| |[CWE-392: Missing Report of Error Condition](CWE-703/CWE-392/README.md)|| +|[CWE-397: Declaration of Throws for Generic Exception](CWE-703/CWE-397/README.md)|| |[CWE-476: NULL Pointer Dereference](CWE-703/CWE-476/README.md)|| |[CWE-754: Improper Check for Unusual or Exceptional Conditions - float](CWE-703/CWE-754/README.md)|| |[CWE-755: Improper Handling of Exceptional Conditions](CWE-703/CWE-755/README.md)|[CVE-2024-39560](https://www.cvedetails.com/cve/CVE-2024-39560),
CVSSv3.1: __6.5__,
EPSS: __0.04__ (01.11.2024)| From 43b7e1fbdca68eb1a32b9ead1487f1343d42295e Mon Sep 17 00:00:00 2001 From: Hubert Daniszewski <61824500+s19110@users.noreply.github.com> Date: Thu, 21 Aug 2025 12:20:52 +0200 Subject: [PATCH 2/2] Update docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-397/README.md Co-authored-by: Bartlomiej Karas Signed-off-by: Hubert Daniszewski <61824500+s19110@users.noreply.github.com> --- docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-397/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-397/README.md b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-397/README.md index aa737759..2cbc1896 100644 --- a/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-397/README.md +++ b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-397/README.md @@ -2,7 +2,7 @@ Avoid raising exceptions that aren't informative on specific errors. -`Exception` is the base class of all non-system-exiting exceptions [[Python docs 2025](https://docs.python.org/3/library/exceptions.html#Exception)]. Specific exceptions allow to determine why they were raised and attempt recovery. To catch a generic `Exception`, all more specific exceptions that subclass it would have to be caught. Raising `Exception` is likely to hide bugs and and prevents using more specialized except statements. The problem is even more severe when raising `BaseException`, which additionally includes subclasses signifying termination signals, such as `KeyboardInterrupt` and `SystemExit` [[PEP 2024](https://peps.python.org/pep-0352/#exception-hierarchy-changes)]. +`Exception` is the base class of all non-system-exiting exceptions [[Python docs 2025](https://docs.python.org/3/library/exceptions.html#Exception)]. Specific exceptions allow to determine why they were raised and attempt recovery. To catch a generic `Exception`, you must also account for any more specific exceptions that inherit from it. Raising `Exception` is likely to hide bugs and and prevents using more specialized except statements. The problem is even more severe when raising `BaseException`, which additionally includes subclasses signifying termination signals, such as `KeyboardInterrupt` and `SystemExit` [[PEP 2024](https://peps.python.org/pep-0352/#exception-hierarchy-changes)]. ## Non-Compliant Code Example