Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1c6d6f3
is_private_ip: Use IPMatcher
bitterpanda63 Dec 8, 2025
e968e77
use singleton structure
bitterpanda63 Dec 8, 2025
64d263e
add benchmarking script
bitterpanda63 Dec 8, 2025
d873fdf
Install pytricia
bitterpanda63 Dec 8, 2025
9ddede9
Merge remote-tracking branch 'origin/main' into test-with-pytricia
bitterpanda63 Dec 8, 2025
09e98c6
Switch ip matcher up: use pytricia
bitterpanda63 Dec 8, 2025
c4dfc10
remove useless code in favor of pytricia
bitterpanda63 Dec 8, 2025
828d265
pytricia add support for ipv6
bitterpanda63 Dec 8, 2025
66eb7b2
linting
bitterpanda63 Dec 8, 2025
eb5e75f
re-lock sample apps
bitterpanda63 Dec 9, 2025
b1e95a7
Allow for a "freeze()" command to be run
bitterpanda63 Dec 9, 2025
fc2fb7a
update benchmark to freeze
bitterpanda63 Dec 9, 2025
4c89db1
update is_private_ip to test frozen
bitterpanda63 Dec 9, 2025
848fbdf
freeze should return IPMatcher
bitterpanda63 Dec 9, 2025
0d09bbb
imds: Use constructor instead
bitterpanda63 Dec 9, 2025
64679b8
bypassed_ips: use constructor instead
bitterpanda63 Dec 9, 2025
3cecdb2
is_private_ip use constructor
bitterpanda63 Dec 9, 2025
3844902
IPMatcher always freeze on init
bitterpanda63 Dec 9, 2025
27812b6
ip matcher benhcmakr update: is always frozen on init
bitterpanda63 Dec 9, 2025
944fe15
remove .freeze() incompat
bitterpanda63 Dec 9, 2025
f3e248e
finally remove the freeze command from IPMatcher
bitterpanda63 Dec 9, 2025
4cfae74
Add a preparse function to IPMatcher
bitterpanda63 Dec 9, 2025
061ef75
Fix thread_cache_test cases because add is now not working anymore
bitterpanda63 Dec 9, 2025
9244f8b
check ipv4 mapped ipv6
bitterpanda63 Dec 9, 2025
dd2ad34
Fix one test case in ip_matcher
bitterpanda63 Dec 9, 2025
7e31023
change py version
bitterpanda63 Dec 9, 2025
52e2d88
Revert "change py version"
bitterpanda63 Dec 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions aikido_zen/background_process/service_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,7 @@ def get_endpoints(self, route_metadata):

def set_bypassed_ips(self, bypassed_ips):
"""Creates an IPMatcher from the given bypassed ip set"""
self.bypassed_ips = IPMatcher()
for ip in bypassed_ips:
self.bypassed_ips.add(ip)
self.bypassed_ips = IPMatcher(bypassed_ips)

def is_bypassed_ip(self, ip):
"""Checks if the IP is on the bypass list"""
Expand Down
66 changes: 30 additions & 36 deletions aikido_zen/helpers/ip_matcher/__init__.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,43 @@
"""
Based on https://github.com/demskie/netparser
MIT License - Copyright (c) 2019 alex
"""
import ipaddress

from .shared import parse_base_network, sort_networks, summarize_sorted_networks
from .sort import binary_search_for_insertion_index
import pytricia


def preparse(network: str) -> str:
# Remove the brackets around IPv6 addresses if they are there.
network = network.strip("[]")
Copy link

@aikido-pr-checks aikido-pr-checks bot Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function parameter 'network' is reassigned with network = network.strip("[]") in preparse; reassigning input parameters reduces clarity.

Details

✨ AI Reasoning
​​1) The new function preparse(network) strips surrounding brackets and may convert IPv6 mapped addresses to IPv4; it reassigns the parameter 'network' via network = network.strip("[]").
​2) Reassigning the function parameter can obscure the original input value and make debugging or future changes harder to follow.
​3) This change was introduced in this diff (preparse was added) and thus constitutes a new instance of argument reassignment, so it violates the rule.

🔧 How do I fix it?
Create new local variables instead of reassigning parameters. Use different variable names to clearly distinguish between input and modified values.

More info - Comment @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.

try:
ip = ipaddress.IPv6Address(network)
if ip.ipv4_mapped:
return str(ip.ipv4_mapped)
except ValueError:
Copy link

@aikido-pr-checks aikido-pr-checks bot Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty except ValueError in preparse silently swallows parsing errors for IPv6 addresses

Details

✨ AI Reasoning
​​1) preparse strips brackets and tries to parse IPv6; the except ValueError is used to ignore parse failures and continue.
​2) Silently swallowing ValueError without comment hides unexpected input errors and makes debugging harder.
​3) This was introduced in the PR (lines added here) and therefore worsens error handling by adding an empty catch.

🔧 How do I fix it?
Add proper error handling in catch blocks. Log the error, show user feedback, or rethrow if needed.

More info - Comment @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.

pass
return network


class IPMatcher:
def __init__(self, networks=None):
self.sorted = []
self.trie = pytricia.PyTricia(128)
if networks is not None:
subnets = []
for s in networks:
net = parse_base_network(s, False)
if net and net.is_valid():
subnets.append(net)
sort_networks(subnets)
self.sorted = summarize_sorted_networks(subnets)
self._add(s)
# We freeze in constructor ensuring that after initialization the IPMatcher is always frozen.
self.trie.freeze()

def has(self, network):
"""
Checks if the given IP address is in the list of networks.
"""
net = parse_base_network(network, False)
if not net or not net.is_valid():
try:
return self.trie.get(preparse(network)) is not None
except ValueError:
return False
idx = binary_search_for_insertion_index(net, self.sorted)
if idx < 0:
return False
if idx < len(self.sorted) and self.sorted[idx].contains(net):
return True
if idx - 1 >= 0 and self.sorted[idx - 1].contains(net):
return True
return False

def add(self, network):
net = parse_base_network(network, False)
if not net or not net.is_valid():
return self
idx = binary_search_for_insertion_index(net, self.sorted)
if idx < len(self.sorted) and self.sorted[idx].compare(net) == 0:
return self
self.sorted.insert(idx, net)

def _add(self, network):
try:
self.trie[preparse(network)] = True
except ValueError:
Copy link

@aikido-pr-checks aikido-pr-checks bot Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The _add method swallows ValueError and SystemError exceptions (bypassing error handling) which can hide failures when adding networks.

Details

🔧 How do I fix it?
Remove debugging statements like console.log, debugger, dd(), or logic bypasses like || true. Keep legitimate logging for monitoring and error handling.

More info - Comment @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.

pass
except SystemError:
pass
return self

def is_empty(self):
return len(self.sorted) == 0
return len(self.trie) == 0
119 changes: 0 additions & 119 deletions aikido_zen/helpers/ip_matcher/address.py

This file was deleted.

49 changes: 0 additions & 49 deletions aikido_zen/helpers/ip_matcher/address_test.py

This file was deleted.

5 changes: 2 additions & 3 deletions aikido_zen/helpers/ip_matcher/init_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,7 @@ def test_add_ips_later():
matcher = IPMatcher()
assert matcher.has("2001:db8::0") == False
assert matcher.has("2002:db8::1") == False
for ip in input_list:
matcher.add(ip)
matcher = IPMatcher(input_list)
assert matcher.has("2001:db8::1") == False
assert matcher.has("2001:db8::0") == False
assert matcher.has("2002:db8::1") == True
Expand All @@ -145,7 +144,7 @@ def test_strange_ips():
matcher = IPMatcher(input_list)
assert matcher.has("::ffff:0.0.0.0") == True
assert matcher.has("::ffff:127.0.0.1") == True
assert matcher.has("::ffff:123") == False
assert matcher.has("::ffff:123") == True
assert matcher.has("2001:db8::1") == False
assert matcher.has("[::ffff:0.0.0.0]") == True
assert matcher.has("::ffff:0:0:0:0") == True
Expand Down
111 changes: 0 additions & 111 deletions aikido_zen/helpers/ip_matcher/network.py

This file was deleted.

Loading
Loading