diff --git a/test_testping1.py b/test_testping1.py index 17fd0a1..c8175b5 100644 --- a/test_testping1.py +++ b/test_testping1.py @@ -350,5 +350,43 @@ def test_is_reachable_calls_ping_correctly(self, mock_call): stdout=DEVNULL_FD, stderr=DEVNULL_FD, close_fds=False, timeout=7 ) + def test_main_block_log_injection(self): + """Test that the main block escapes exceptions properly to prevent log injection.""" + import tempfile + import os + + import sys + + # We will dynamically execute the __main__ block code and mock start_ip with malicious payload + with open("testping1.py", "r") as f: + code = f.read() + + # Find the main block and extract its body + main_block_idx = code.find('if __name__ == "__main__":') + self.assertNotEqual(main_block_idx, -1) + + import re + # Replace the hardcoded IPs to trigger ValueError with newline + malicious_code = re.sub( + r'start_ip\s*=\s*["\'].*?["\']', + 'start_ip = "192.168.43.1\\\\nERROR: system compromised"', + code + ) + + with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".py") as tmp: + tmp.write(malicious_code) + tmp_name = tmp.name + + try: + result = subprocess.run( + [sys.executable, tmp_name], + capture_output=True, + text=True + ) + self.assertIn(r"Invalid scan range configuration: " + '"' + r"'192.168.43.1\\nERROR: system compromised' does not appear to be an IPv4 or IPv6 address" + '"', result.stderr) + self.assertNotIn("\nERROR: system compromised", result.stderr) + finally: + os.unlink(tmp_name) + if __name__ == '__main__': unittest.main() diff --git a/testping1.py b/testping1.py index fa70655..fe8e461 100644 --- a/testping1.py +++ b/testping1.py @@ -275,7 +275,7 @@ def is_reachable(ip, timeout=1): raise ValueError(f"Scan range too large ({total_ips} IPs). Maximum 256 IPs allowed per scan.") except (ValueError, TypeError, RecursionError) as e: - logging.error(f"Invalid scan range configuration: {e}") + logging.error(f"Invalid scan range configuration: {repr(str(e))}") exit(1) # ⚡ Bolt: Optimize sequential IP address generation