diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 1e6421a..e46f5d4 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -22,3 +22,7 @@ **Vulnerability:** The application used `shutil.which("ping") or "ping"`. If `ping` was not found in the system `PATH`, it fell back to executing the relative string `"ping"`. This could allow arbitrary code execution or local privilege escalation if run from a directory containing a malicious executable named `ping`. **Learning:** Never fallback to relative command names when a system binary is expected. If a required binary is missing from the system path, the application should fail securely rather than attempting a risky, unverified local execution. **Prevention:** Remove fallback logic for critical system commands. Use `shutil.which()` and raise an exception (e.g., `RuntimeError`) if the expected binary is `None`. +## 2024-05-24 - Unhandled OverflowError converting infinity to int +**Vulnerability:** The application converts the `timeout` parameter to an integer using `int()`. Passing `float('inf')` or `float('nan')` causes Python to raise an `OverflowError` (in the case of inf) or ValueError (in the case of nan, which is already caught), but `OverflowError` was not caught. This unhandled exception could crash worker threads if manipulated input (e.g. from JSON deserialization containing Infinity) reaches this function. +**Learning:** `int()` conversion of user input can raise not only `ValueError` and `TypeError`, but also `OverflowError` when provided with float infinities. Secondary parameters can still crash worker threads if specific types are not fully accounted for in error handling. +**Prevention:** Catch `OverflowError` alongside `ValueError` and `TypeError` when explicitly casting variables to `int()` to ensure graceful failure on infinite or NaN values. diff --git a/test_testping1.py b/test_testping1.py index a8f94a2..48ed57f 100644 --- a/test_testping1.py +++ b/test_testping1.py @@ -77,6 +77,11 @@ def test_is_reachable_invalid_timeout(self, mock_call): # 🛡️ Sentinel: Test resource exhaustion prevention self.assertFalse(is_reachable('192.168.1.1', timeout=101)) mock_call.assert_not_called() + # 🛡️ Sentinel: Test overflow prevention + self.assertFalse(is_reachable('192.168.1.1', timeout=float('inf'))) + mock_call.assert_not_called() + self.assertFalse(is_reachable('192.168.1.1', timeout=float('nan'))) + mock_call.assert_not_called() @patch('testping1.subprocess.call') def test_is_reachable_timeout_too_long(self, mock_call): diff --git a/testping1.py b/testping1.py index 786e20a..8dee1a8 100644 --- a/testping1.py +++ b/testping1.py @@ -72,7 +72,8 @@ def is_reachable(ip, timeout=1): timeout_val = int(timeout) if timeout_val <= 0 or timeout_val > 100: raise ValueError("Timeout must be a positive integer <= 100") - except (ValueError, TypeError): + except (ValueError, TypeError, OverflowError): + # 🛡️ Sentinel: Catch OverflowError (e.g. float('inf')) alongside ValueError/TypeError # 🛡️ Sentinel: Sanitize log input to prevent CRLF/Log Injection logging.error(f"Invalid timeout value: {repr(timeout)}") return False