diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000..e3424c8 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2024-05-14 - Prevent Command Injection in `is_reachable` +**Vulnerability:** The `is_reachable` function in `testping1.py` passed unsanitized user input (`ip`) directly to `subprocess.Popen` when executing the `ping` command. This allowed for potential command injection if a malicious user provided a crafted IP string (e.g., `192.168.1.1; rm -rf /`). +**Learning:** Even simple scripts meant for network scanning need strict input validation to prevent arbitrary command execution, especially when interacting with the system shell or executing external binaries. +**Prevention:** Always validate and sanitize user input before passing it to system commands. In this case, use Python's built-in `ipaddress` module to ensure the input strictly conforms to a valid IPv4 or IPv6 address format. \ No newline at end of file diff --git a/test_testping1.py b/test_testping1.py index 9be1547..ee8eed9 100644 --- a/test_testping1.py +++ b/test_testping1.py @@ -25,6 +25,13 @@ def test_is_reachable_failure(self, mock_popen): self.assertFalse(is_reachable('10.0.0.1')) + @patch('testping1.subprocess.Popen') + def test_is_reachable_invalid_ip(self, mock_popen): + """Test is_reachable returns False for an invalid IP address and does not call subprocess.""" + self.assertFalse(is_reachable('192.168.1.1; rm -rf /')) + self.assertFalse(is_reachable('invalid_ip')) + mock_popen.assert_not_called() + @patch('testping1.subprocess.Popen') def test_is_reachable_calls_ping_correctly(self, mock_popen): """Test is_reachable calls the ping command with correct arguments.""" diff --git a/testping1.py b/testping1.py index 6925ac1..4ccd8fe 100644 --- a/testping1.py +++ b/testping1.py @@ -1,4 +1,5 @@ import subprocess +import ipaddress from tqdm import tqdm # Install with `pip install tqdm` def is_reachable(ip, timeout=1): @@ -11,6 +12,11 @@ def is_reachable(ip, timeout=1): Returns: bool: True if the ping is successful, False otherwise. """ + # Security enhancement: Validate IP address to prevent command injection + try: + ipaddress.ip_address(ip) + except ValueError: + return False command = ["ping", "-c", "1", "-W", str(timeout), ip] # -W for timeout in seconds (Linux) process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)