-
Notifications
You must be signed in to change notification settings - Fork 6
Port IPMatcher from firewall-node #357
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,62 +1,32 @@ | ||||||
| package dev.aikido.agent_api.helpers.net; | ||||||
|
|
||||||
| import inet.ipaddr.IPAddress; | ||||||
| import inet.ipaddr.IPAddressString; | ||||||
| import inet.ipaddr.format.util.DualIPv4v6Tries; | ||||||
| import java.util.Collection; | ||||||
| import java.util.List; | ||||||
|
|
||||||
| public class IPList { | ||||||
| private final DualIPv4v6Tries ipAddresses; | ||||||
| private IPMatcher matcher; | ||||||
|
|
||||||
| public IPList() { | ||||||
| this.ipAddresses = new DualIPv4v6Tries(); | ||||||
| matcher = IPMatcher.from(List.of()); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The no-argument constructor duplicates initialization logic from the collection constructor. Delegate with
Suggested change
Details✨ AI Reasoning Reply |
||||||
| } | ||||||
|
|
||||||
| public IPList(Collection<String> ipAddresses) { | ||||||
| matcher = IPMatcher.from(ipAddresses); | ||||||
| } | ||||||
|
|
||||||
| public void add(String ipOrCIDR) { | ||||||
| if (ipOrCIDR == null) { | ||||||
| return; // Don't add if IP is null | ||||||
| } | ||||||
| IPAddress ip = new IPAddressString(ipOrCIDR).getAddress(); | ||||||
| if (ip == null) { | ||||||
| return; | ||||||
| } | ||||||
| // Normalize IPv4-mapped IPv6 addresses to their IPv4 form so matching is symmetric. | ||||||
| if (ip.isIPv6() && ip.toIPv6().isIPv4Convertible()) { | ||||||
| IPAddress ipv4 = ip.toIPv6().toIPv4(); | ||||||
| if (ipv4 != null) { | ||||||
| ip = ipv4; | ||||||
| } | ||||||
| } | ||||||
| if (ipOrCIDR.contains("/")) { | ||||||
| ip = ip.toPrefixBlock(); | ||||||
| } | ||||||
| ipAddresses.add(ip); | ||||||
| matcher = matcher.add(ipOrCIDR); | ||||||
| } | ||||||
|
|
||||||
| public boolean matches(String ip) { | ||||||
| IPAddressString ipAddressString = new IPAddressString(ip); | ||||||
| if (!ipAddressString.isValid()) { | ||||||
| return false; // Invalid IP address | ||||||
| } | ||||||
| IPAddress ipAddress = ipAddressString.getAddress(); | ||||||
|
|
||||||
| if (containsAddress(ipAddress)) { | ||||||
| return true; | ||||||
| } | ||||||
|
|
||||||
| // Also try the embedded IPv4 form for IPv4-mapped IPv6 addresses (e.g. ::ffff:23.45.67.89) | ||||||
| if (ipAddress.isIPv6() && ipAddress.toIPv6().isIPv4Convertible()) { | ||||||
| IPAddress ipv4 = ipAddress.toIPv6().toIPv4(); | ||||||
| if (ipv4 != null && containsAddress(ipv4)) { | ||||||
| return true; | ||||||
| } | ||||||
| } | ||||||
| return false; | ||||||
| return matcher.matches(ip); | ||||||
| } | ||||||
|
|
||||||
| private boolean containsAddress(IPAddress ipAddress) { | ||||||
| return ipAddresses.elementContains(ipAddress); | ||||||
| public boolean matchesWithMappedCheck(String ip) { | ||||||
| return matcher.matchesWithMappedCheck(ip); | ||||||
| } | ||||||
|
|
||||||
| public int length() { | ||||||
| return ipAddresses.size(); | ||||||
| return matcher.size(); | ||||||
| } | ||||||
| } | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 Medium - Mapped-address expansion breaks legacy IPv4 allowlist and bypass entries
createIPListWithMappedAddressesnow prepends::ffff:to every colon-free entry, but shorthand IPv4 forms that this matcher still accepts as valid configuration, such as127.1or10.*.*.*, are not valid embedded-IPv4 syntax inside IPv6 literals. Those synthesized entries are ignored, and the affected call sites then use plainmatches(...)instead of the mapped fallback, so an incoming::ffff:client address no longer matches the equivalent configured allowlist or bypass rule. In deployments where reverse proxies or the JVM expose clients as IPv4-mapped IPv6, this causes endpoint allowlists to deny legitimate traffic and bypass lists to stop exempting the intended clients.Show fix
Canonicalize supported legacy IPv4 forms to a real IPv4 address/network before generating
::ffff:variants, or perform mapped-address fallback at lookup time for these call sites instead of synthesizing mapped strings from the raw configuration text.More info - Reply on this comment to give feedback or ignore the issue.