From 52debae984d85e220266526068773818b0893bc3 Mon Sep 17 00:00:00 2001 From: John Menke Date: Sun, 1 Nov 2026 14:14:06 -0500 Subject: [PATCH] Fail committed addresses written with a leading zero. ipaddress rejects those dotted quads, and the scan treated the parse error as no address. Co-authored-by: Cursor --- src/local_coding_slm/safety.py | 26 +++++++++++++++++++------- tests/test_safety.py | 8 ++++++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/local_coding_slm/safety.py b/src/local_coding_slm/safety.py index a6af58f..4f4f6a6 100644 --- a/src/local_coding_slm/safety.py +++ b/src/local_coding_slm/safety.py @@ -268,18 +268,30 @@ def classify_local_listeners( ) +def _leading_zero_ipv4(match: str) -> bool: + """True when a dotted quad uses a leading zero, which ipaddress rejects.""" + parts = match.split(".") + if len(parts) != 4 or not all(part.isdigit() for part in parts): + return False + return any(len(part) > 1 and part.startswith("0") for part in parts) + + +def _is_committed_ip_hit(match: str) -> bool: + try: + addr = ipaddress.ip_address(match) + except ValueError: + return _leading_zero_ipv4(match) + if match in PLACEHOLDER_IPV4 or addr.is_loopback or addr.is_unspecified: + return False + return bool(addr.is_private or addr.is_global) + + def classify_tracked_ipv4(paths_and_text: Iterable[tuple[str, str]]) -> CheckResult: """Fail committed files that contain non-placeholder private or public IPs.""" hits: list[str] = [] for path, text in paths_and_text: for match in IPV4_RE.findall(text): - try: - addr = ipaddress.ip_address(match) - except ValueError: - continue - if match in PLACEHOLDER_IPV4 or addr.is_loopback or addr.is_unspecified: - continue - if addr.is_private or addr.is_global: + if _is_committed_ip_hit(match): hits.append(f"{path}:{match}") if hits: return CheckResult( diff --git a/tests/test_safety.py b/tests/test_safety.py index cf36946..f4ee001 100644 --- a/tests/test_safety.py +++ b/tests/test_safety.py @@ -171,6 +171,14 @@ def test_real_private_ip_fails(self) -> None: result = classify_tracked_ipv4([("README.md", "use 10.0.0.65")]) self.assertEqual(result.status, "fail") + def test_leading_zero_ipv4_fails(self) -> None: + """A dotted quad Python rejects is still an address if an octet has a leading zero.""" + for text in ("010.010.010.010", "008.008.008.008"): + with self.subTest(text=text): + result = classify_tracked_ipv4([("README.md", f"host {text}")]) + self.assertEqual(result.status, "fail") + self.assertIn(text, result.message) + def test_committed_workflow_yaml_ip_fails(self) -> None: """GitHub workflow YAML is committed text, so an address there must fail.""" import subprocess