Skip to content

Commit

Permalink
Merge pull request #692 from NASA-AMMOS/feature-plugin-ip
Browse files Browse the repository at this point in the history
Add a plugin for IPAddress (ipv4)
  • Loading branch information
lorenzodb1 committed Apr 30, 2024
2 parents 0473f8e + 5fc4ed6 commit e98e137
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 0 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ If you love `detect-secrets`, please star our project on GitHub to show your sup

<!--
### Unreleased
##### May 15th, 2023
#### :tada: New Features
- Added a detector for IPPublic (ipv4) ([#692])
[#692]: https://github.com/Yelp/detect-secrets/pull/692
-->

### v1.4.0
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ Base64HighEntropyString
HexHighEntropyString
IbmCloudIamDetector
IbmCosHmacDetector
IPPublicDetector
JwtTokenDetector
KeywordDetector
MailchimpDetector
Expand Down
45 changes: 45 additions & 0 deletions detect_secrets/plugins/ip_public.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
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.
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"""
(?<![\w.]) # Negative lookbehind: Ensures no preceding word character or dot
( # Start of the main capturing group
(?! # Negative lookahead: Ensures the following pattern doesn't match
192\.168\. # Exclude "192.168."
|127\. # Exclude "127."
|10\. # Exclude "10."
|172\.(?:1[6-9]|2[0-9]|3[01]) # Exclude "172." with specific ranges
)
(?: # Non-capturing group for octets
# Match numbers 0-255 followed by dot, properly handle leading zeros
(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.
){3} # Repeat for three octets
# Match final octet (0-255), properly handle leading zeros
(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])
(?: # Optional non-capturing group for port number
:\d{1,5} # Match colon followed by 1 to 5 digits
)?
) # End of the main capturing group
(?![\w.]) # Negative lookahead: Ensures no following word character or dot
"""

denylist = [
re.compile(denylist_ipv4_address, flags=re.IGNORECASE | re.VERBOSE),
]
54 changes: 54 additions & 0 deletions tests/plugins/ip_public_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import pytest

from detect_secrets.plugins.ip_public import IPPublicDetector


class TestIPPublicDetector:

class TestIPv4:
"""
Testing strategy
Cover the cartesian product of these partitions:
1. Partition on ip address format:
a. Valid ipv4 address
2. Partition on ip address type:
a. Public
b. Non-public
And cover this case:
1. Partition on ip address format:
a. Invalid ipv4 address
"""

@pytest.mark.parametrize(
'payload, should_flag',
[
# Valid IPv4 addresses, Public
('133.133.133.133', True),
('This line has an IP address 133.133.133.133@something else', True),
('133.133.133.133:8080', True),
('This line has an IP address: 133.133.133.133:8080@something else', True),
('1.1.1.1', True),
# Valid IPv4 addresses, Non-public
('127.0.0.1', False),
('10.0.0.1', False),
('172.16.0.1', False),
('192.168.0.1', False),
# Invalid IPv4 addresses
('256.256.256.256', False),
('1.2.3', False),
('1.2.3.4.5.6', False),
('1.2.3.4.5.6.7.8', False),
('1.2.3.04', False),
('noreply@github.com', False),
('github.com', False),
],
)
def test_analyze_line(self, payload, should_flag):
logic = IPPublicDetector()

output = logic.analyze_line(filename='mock_filename', line=payload)
assert len(output) == int(should_flag)

0 comments on commit e98e137

Please sign in to comment.