Skip to content

Don't block literal IPs for outbound domain blocking - #397

Merged
hansott merged 1 commit into
mainfrom
skip-ip
Oct 22, 2026
Merged

hansott merged 1 commit into
mainfrom
skip-ip

Conversation

@hansott

@hansott hansott commented Oct 22, 2026

Copy link
Copy Markdown
Member

As we don't report them

Comment on lines 45 to 55
} else if (!IPValidator.isIP(hostname)) {
// Skip literal IPs with no pending port: usually inbound IP parsing rather than an outbound request,
// and we can't tell them apart here. A real outbound one still hits the blocking/SSRF checks below.
// and we can't tell them apart here. A real outbound one still hits the SSRF checks below.
HostnamesStore.incrementHits(hostname, 0);
}

// Checked here, not at the HTTP client, since not all clients are instrumented and port/context isn't always available.
if (ServiceConfigStore.shouldBlockOutgoingRequest(hostname)) {
if (!IPValidator.isIP(hostname) && ServiceConfigStore.shouldBlockOutgoingRequest(hostname)) {
logger.debug("Blocking DNS lookup for domain: %s", hostname);
throw BlockedOutboundException.get();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Low - Bracketed IPv6 URLs remain blocked in outbound lockdown

An application makes an HTTP(S) request to a literal IPv6 URL such as http://[::1]:8080 while new outbound connections are blocked. URLCollector and the DNS advice preserve the bracketed host, but IPValidator.isIP does not accept brackets, so DNSRecordCollector still applies the unknown-host outbound rule and throws BlockedOutboundException. This contradicts the PR's literal-IPv6 exemption and can prevent legitimate direct IPv6 connections from being made.

Show fix
Suggested change
} else if (!IPValidator.isIP(hostname)) {
// Skip literal IPs with no pending port: usually inbound IP parsing rather than an outbound request,
// and we can't tell them apart here. A real outbound one still hits the blocking/SSRF checks below.
// and we can't tell them apart here. A real outbound one still hits the SSRF checks below.
HostnamesStore.incrementHits(hostname, 0);
}
// Checked here, not at the HTTP client, since not all clients are instrumented and port/context isn't always available.
if (ServiceConfigStore.shouldBlockOutgoingRequest(hostname)) {
if (!IPValidator.isIP(hostname) && ServiceConfigStore.shouldBlockOutgoingRequest(hostname)) {
logger.debug("Blocking DNS lookup for domain: %s", hostname);
throw BlockedOutboundException.get();
}
} else if (!IPValidator.isIP(hostname)
&& !(hostname.startsWith("[")
&& hostname.endsWith("]")
&& IPValidator.isIP(hostname.substring(1, hostname.length() - 1)))) {
// Skip literal IPs with no pending port: usually inbound IP parsing rather than an outbound request,
// and we can't tell them apart here. A real outbound one still hits the SSRF checks below.
HostnamesStore.incrementHits(hostname, 0);
}
// Checked here, not at the HTTP client, since not all clients are instrumented and port/context isn't always available.
if (!IPValidator.isIP(hostname)
&& !(hostname.startsWith("[")
&& hostname.endsWith("]")
&& IPValidator.isIP(hostname.substring(1, hostname.length() - 1)))
&& ServiceConfigStore.shouldBlockOutgoingRequest(hostname)) {
logger.debug("Blocking DNS lookup for domain: %s", hostname);
throw BlockedOutboundException.get();
}

More info - Reply on this comment to give feedback or ignore the issue.

@codecov

codecov Bot commented Oct 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@hansott
hansott merged commit 1dad937 into main Oct 22, 2026
284 checks passed
@hansott
hansott deleted the skip-ip branch October 22, 2026 13:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants