Skip to content

Commit 05cf658

Browse files
pySCG: adding CWE-397: Declaration of Throws for Generic Exception (#964)
pySCG: adding CWE-397: Declaration of Throws for Generic Exception Signed-off-by: edanhub <[email protected]> Co-authored-by: Bartlomiej Karas <[email protected]>
1 parent 6c0f5f3 commit 05cf658

File tree

4 files changed

+227
-0
lines changed

4 files changed

+227
-0
lines changed
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
# CWE-397: Declaration of Throws for Generic Exception
2+
3+
Avoid raising exceptions that aren't informative on specific errors.
4+
5+
`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)].
6+
7+
## Non-Compliant Code Example
8+
9+
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`.
10+
11+
_[noncompliant01.py](noncompliant01.py):_
12+
13+
```python
14+
# SPDX-FileCopyrightText: OpenSSF project contributors
15+
# SPDX-License-Identifier: MIT
16+
"""Compliant Code Example"""
17+
18+
19+
def divide(divided: int, divisor: int) -> float:
20+
"""Function that divides two numbers"""
21+
if divisor == 0:
22+
raise Exception("Cannot divide by zero")
23+
return divided / divisor
24+
25+
26+
#####################
27+
# exploiting above code example
28+
#####################
29+
try:
30+
divide(1, 0)
31+
except SystemError:
32+
print("Something wrong with the system!")
33+
except ZeroDivisionError:
34+
print("I divided by zero!")
35+
except Exception:
36+
print("Something went wrong and I have no clue what!")
37+
38+
```
39+
40+
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.
41+
42+
## Compliant Solution
43+
44+
In this specific instance, Python has a built-in exception `ZeroDivisionError` that can be thrown instead of the generic `Exception`.
45+
46+
_[compliant01.py](compliant01.py):_
47+
48+
```python
49+
# SPDX-FileCopyrightText: OpenSSF project contributors
50+
# SPDX-License-Identifier: MIT
51+
"""Compliant Code Example"""
52+
53+
54+
def divide(divided: int, divisor: int) -> float:
55+
"""Function that divides two numbers"""
56+
if divisor == 0:
57+
raise ZeroDivisionError("Cannot divide by zero")
58+
return divided / divisor
59+
60+
61+
#####################
62+
# exploiting above code example
63+
#####################
64+
try:
65+
divide(1, 0)
66+
except SystemError:
67+
print("Something wrong with the system!")
68+
except ZeroDivisionError:
69+
print("I divided by zero!")
70+
except Exception:
71+
print("Something went wrong and I have no clue what!")
72+
73+
```
74+
75+
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.
76+
77+
## Automated Detection
78+
79+
<table>
80+
<hr>
81+
<td>Tool</td>
82+
<td>Version</td>
83+
<td>Checker</td>
84+
<td>Description</td>
85+
</hr>
86+
<tr>
87+
<td>Bandit</td>
88+
<td>1.7.4 on Python 3.10.4</td>
89+
<td>Not Available</td>
90+
<td></td>
91+
</tr>
92+
<tr>
93+
<td>Flake8</td>
94+
<td>8-4.0.1 on Python 3.10.4</td>
95+
<td>Not Available</td>
96+
<td></td>
97+
</tr>
98+
</table>
99+
100+
## Related Guidelines
101+
102+
<table>
103+
<tr>
104+
<td>
105+
<a href="https://wiki.sei.cmu.edu/confluence/display/java/SEI+CERT+Oracle+Coding+Standard+for+Java">
106+
SEI CERT Oracle Coding Standard for Java
107+
</a>
108+
</td>
109+
<td>
110+
<a href="https://wiki.sei.cmu.edu/confluence/display/java/ERR07-J.+Do+not+throw+RuntimeException%2C+Exception%2C+or+Throwable">
111+
ERR07-J. Do not throw RuntimeException, Exception, or Throwable
112+
</a>
113+
</td>
114+
</tr>
115+
<tr>
116+
<td>
117+
<a href="http://cwe.mitre.org/">
118+
MITRE CWE
119+
</a>
120+
</td>
121+
<td>
122+
Pillar:
123+
<a href="https://cwe.mitre.org/data/definitions/703.html">
124+
CWE-703: Improper Check or Handling of Exceptional Conditions
125+
</a>
126+
</td>
127+
</tr>
128+
<tr>
129+
<td>
130+
<a href="http://cwe.mitre.org/">
131+
MITRE CWE
132+
</a>
133+
</td>
134+
<td>
135+
Base:
136+
<a href="https://cwe.mitre.org/data/definitions/397.html">
137+
CWE-397, Declaration of Throws for Generic Exception (4.12)
138+
</a>
139+
</td>
140+
</tr>
141+
</table>
142+
143+
## Bibliography
144+
145+
<table>
146+
<tr>
147+
<td>
148+
[
149+
<a href="https://docs.python.org/3/library/exceptions.html#Exception">
150+
Python docs 2025
151+
</a>
152+
]
153+
</td>
154+
<td>
155+
Python Software Foundation. (2025). Built in exceptions [online].<br>
156+
Available from:
157+
<a href="https://docs.python.org/3/library/exceptions.html#Exception">
158+
https://docs.python.org/3/library/exceptions.html#Exception
159+
</a><br>
160+
[Accessed 29 July 2025]
161+
</td>
162+
</tr>
163+
<tr>
164+
<td>
165+
[
166+
<a href="https://peps.python.org/pep-0352/#exception-hierarchy-changes">
167+
PEP 2024
168+
</a>
169+
]
170+
</td>
171+
<td>
172+
Python Enhancement Proposal 352. (2024). Required Superclass for Exceptions [online].<br>
173+
Available from:
174+
<a href="https://peps.python.org/pep-0352/#exception-hierarchy-changes">
175+
https://peps.python.org/pep-0352/#exception-hierarchy-changes
176+
</a><br>
177+
[Accessed 29 July 2025]
178+
</td>
179+
</tr>
180+
</table>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# SPDX-FileCopyrightText: OpenSSF project contributors
2+
# SPDX-License-Identifier: MIT
3+
"""Compliant Code Example"""
4+
5+
6+
def divide(divided: int, divisor: int) -> float:
7+
"""Function that divides two numbers"""
8+
if divisor == 0:
9+
raise ZeroDivisionError("Cannot divide by zero")
10+
return divided / divisor
11+
12+
13+
#####################
14+
# exploiting above code example
15+
#####################
16+
try:
17+
divide(1, 0)
18+
except SystemError:
19+
print("Something wrong with the system!")
20+
except ZeroDivisionError:
21+
print("I divided by zero!")
22+
except Exception:
23+
print("Something went wrong and I have no clue what!")
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# SPDX-FileCopyrightText: OpenSSF project contributors
2+
# SPDX-License-Identifier: MIT
3+
"""Compliant Code Example"""
4+
5+
6+
def divide(divided: int, divisor: int) -> float:
7+
"""Function that divides two numbers"""
8+
if divisor == 0:
9+
raise Exception("Cannot divide by zero")
10+
return divided / divisor
11+
12+
13+
#####################
14+
# exploiting above code example
15+
#####################
16+
try:
17+
divide(1, 0)
18+
except SystemError:
19+
print("Something wrong with the system!")
20+
except ZeroDivisionError:
21+
print("I divided by zero!")
22+
except Exception:
23+
print("Something went wrong and I have no clue what!")

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ It is __not production code__ and requires code-style or python best practices t
9797
|[CWE-252: Unchecked Return Value](CWE-703/CWE-252/README.md)||
9898
|[CWE-390: Detection of Error Condition without Action](CWE-703/CWE-390/README.md)||
9999
|[CWE-392: Missing Report of Error Condition](CWE-703/CWE-392/README.md)||
100+
|[CWE-397: Declaration of Throws for Generic Exception](CWE-703/CWE-397/README.md)||
100101
|[CWE-476: NULL Pointer Dereference](CWE-703/CWE-476/README.md)||
101102
|[CWE-754: Improper Check for Unusual or Exceptional Conditions - float](CWE-703/CWE-754/README.md)||
102103
|[CWE-755: Improper Handling of Exceptional Conditions](CWE-703/CWE-755/README.md)|[CVE-2024-39560](https://www.cvedetails.com/cve/CVE-2024-39560),<br/>CVSSv3.1: __6.5__,<br/>EPSS: __0.04__ (01.11.2024)|

0 commit comments

Comments
 (0)