Detect and handle missing numberic values explicitly, either by removing, validating or converting them, before performing comparisons, sorting, or statistics, in order to avoid surprising or undefined behaviour.
The NaN value should be stripped before as they can cause surprising or undefined behaviours in the statistics functions that sort or count occurrences [2024 doc.python.org].
In python, some datasets use NaN (not-a-number) to represent the missing data. This can be problematic as the NaN values are unordered. Any ordered comparison of a number to a not-a-number value are False. A counter-intuitive implication is that not-a-number values are not equal to themselves.
This behavior is compliant with IEEE 754[543-2019 - IEEE Standard for Floating-Point Arithmetic] a hardware induced compromise.
The example01.py code demonstrates various comparisons of float('NaN') all resulting in False.
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
""" Code Example """
foo = float('NaN')
print(f"foo={foo} type = {type(foo)}")
print(foo == float("NaN") or
foo is float("NaN") or
foo < 3 or
foo == foo or
foo is None
)
This noncompliant code example [2024 docs.python.org] attempts a direct comparison with NaN in _value == float("NaN").
noncompliant01.py:
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
""" Non-compliant Code Example """
def balance_is_positive(value: str) -> bool:
"""Returns True if there is still enough value for a transaction"""
_value = float(value)
if _value == float("NaN") or _value is float("NaN") or _value is None:
raise ValueError("Expected a float")
if _value <= 0:
return False
else:
return True
#####################
# attempting to exploit above code example
#####################
print(balance_is_positive("0.01"))
print(balance_is_positive("0.001"))
print(balance_is_positive("NaN"))
In the compliant01.py code example, the method Decimal.quantize is used to gain control over known rounding errors in floating point values.
The decision by the balance_is_positive method is to ROUND_DOWN instead of the default ROUND_HALF_EVEN.
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
""" Compliant Code Example """
from decimal import ROUND_DOWN, Decimal
def balance_is_positive(value: str) -> bool:
"""Returns True if there is still enough value for a transaction"""
# TODO: additional input sanitation for expected type
_value = Decimal(value)
# TODO: exception handling
return _value.quantize(Decimal(".01"), rounding=ROUND_DOWN) > Decimal("0.00")
#####################
# attempting to exploit above code example
#####################
print(balance_is_positive("0.01"))
print(balance_is_positive("0.001"))
print(balance_is_positive("NaN"))
Decimal throws a decimal.InvalidOperation for NaN values, the controlled rounding causes only "0.01" to return True.
In compliant02.py we use the math.isnan to verify if the value passed is a valid float value.
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
""" Compliant Code Example """
import math
def balance_is_positive(value: str) -> bool:
"""Returns True if there is still enough value for a transaction"""
_value = float(value)
if math.isnan(_value) or _value is None:
raise ValueError("Expected a float")
if _value < 0.01:
return False
else:
return True
#####################
# attempting to exploit above code example
#####################
print(balance_is_positive("0.01"))
print(balance_is_positive("0.001"))
print(balance_is_positive("NaN"))
The balance_is_poitive method will raise an ValueError for NaN values.
| Tool | Version | Checker | Description |
|---|---|---|---|
| Bandit | 1.7.4 on Python 3.10.4 | Not Available | |
| flake8 | flake8-4.0.1 on python 3.10.4 | Not Available |
| [Python 3.10.4 docs] | Format String Syntax. Available from: https://docs.python.org/3/library/string.html#formatstrings [Accessed 22 July 2025] |
| Python docs | https://docs.python.org/3/library/math.html#math.nan [Accessed 22 July 2025] |
| Python docs | Python Value comparisonshttps://docs.python.org/3/reference/expressions.html#value-comparisons [Accessed 22 July 2025] |
| [IEEE Xplore] | IEEE 754: https://ieeexplore.ieee.org/document/8766229 [Accessed 20 October 2025] |