From 239b790d690a35cccaf18e985d850d85004c6695 Mon Sep 17 00:00:00 2001 From: Pepe Fagoaga Date: Sat, 14 Mar 2026 16:57:32 +0100 Subject: [PATCH 1/3] feat(ip_public): Add IPPublicDetector plugin Port the IPPublicDetector from Yelp/detect-secrets upstream. Detects public IPv4 addresses while excluding private ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), loopback (127.0.0.0/8), and link-local (169.254.0.0/16) addresses. --- detect_secrets/plugins/ip_public.py | 47 ++++++++++++++++++++++++ tests/plugins/ip_public_test.py | 55 +++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 detect_secrets/plugins/ip_public.py create mode 100644 tests/plugins/ip_public_test.py diff --git a/detect_secrets/plugins/ip_public.py b/detect_secrets/plugins/ip_public.py new file mode 100644 index 000000000..f9a435904 --- /dev/null +++ b/detect_secrets/plugins/ip_public.py @@ -0,0 +1,47 @@ +import re + +from .base import RegexBasedDetector + + +class IPPublicDetector(RegexBasedDetector): + """Scans for public ip address (ipv4) + + Some non-public ipv4 addresses are ignored, such as: + - 127. + - 10. + - 172.(16-31) + - 192.168. + - 169.254. - Link Local Address IPv4 + + Reference: + https://www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xhtml + https://en.wikipedia.org/wiki/Private_network + """ + secret_type = 'Public IP (ipv4)' + + denylist_ipv4_address = r""" + (? Date: Sat, 14 Mar 2026 17:12:15 +0100 Subject: [PATCH 2/3] fix: address Copilot suggestions --- detect_secrets/plugins/ip_public.py | 2 +- tests/plugins/ip_public_test.py | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/detect_secrets/plugins/ip_public.py b/detect_secrets/plugins/ip_public.py index f9a435904..cb46a7b85 100644 --- a/detect_secrets/plugins/ip_public.py +++ b/detect_secrets/plugins/ip_public.py @@ -27,7 +27,7 @@ class IPPublicDetector(RegexBasedDetector): |127\. # Exclude "127." |10\. # Exclude "10." |169\.254\. # Exclude IPv4 Link Local Address (169.254.0.0/16) - |172\.(?:1[6-9]|2[0-9]|3[01]) # Exclude "172." with specific ranges + |172\.(?:1[6-9]|2[0-9]|3[01])\. # Exclude "172.16-31." with specific ranges ) (?: # Non-capturing group for octets # Match numbers 0-255 followed by dot, properly handle leading zeros diff --git a/tests/plugins/ip_public_test.py b/tests/plugins/ip_public_test.py index 77c9da95b..5a8fa77ec 100644 --- a/tests/plugins/ip_public_test.py +++ b/tests/plugins/ip_public_test.py @@ -38,6 +38,10 @@ class TestIPv4: ('172.16.0.1', False), ('192.168.0.1', False), ('169.254.169.254', False), + # 172.x boundary: 172.15 and 172.32 are public, 172.16-31 are private + ('172.15.0.1', True), + ('172.32.0.1', True), + ('172.160.0.1', True), # Invalid IPv4 addresses ('256.256.256.256', False), ('1.2.3', False), @@ -51,5 +55,5 @@ class TestIPv4: def test_analyze_line(self, payload, should_flag): logic = IPPublicDetector() - output = logic.analyze_line(filename='mock_filename', line=payload) + output = logic.analyze_line(payload, 1, 'mock_filename') assert len(output) == int(should_flag) From 092e460698256cf02c0b06333f64345d30cbf66a Mon Sep 17 00:00:00 2001 From: Pepe Fagoaga Date: Sat, 14 Mar 2026 17:23:16 +0100 Subject: [PATCH 3/3] fix: enable plugin --- detect_secrets/core/usage.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/detect_secrets/core/usage.py b/detect_secrets/core/usage.py index 5d532f3d0..c35fd7221 100644 --- a/detect_secrets/core/usage.py +++ b/detect_secrets/core/usage.py @@ -618,6 +618,12 @@ class PluginOptions: help_text='Disables scans for GitHub credentials', filename='github_token', ), + PluginDescriptor( + classname='IPPublicDetector', + flag_text='--no-ip-public-scan', + help_text='Disables scans for public IPv4 addresses', + filename='ip_public', + ), ] opt_in_plugins = [ PluginDescriptor(