Skip to content

fix(utils): normalize unbracketed IPv6 literals for probing#7045

Open
dwisiswant0 wants to merge 1 commit intodevfrom
dwisiswant0/fix/utils/normalize-unbracketed-IPv6-literals-for-probing
Open

fix(utils): normalize unbracketed IPv6 literals for probing#7045
dwisiswant0 wants to merge 1 commit intodevfrom
dwisiswant0/fix/utils/normalize-unbracketed-IPv6-literals-for-probing

Conversation

@dwisiswant0
Copy link
Member

@dwisiswant0 dwisiswant0 commented Feb 26, 2026

Proposed changes

fix(utils): normalize unbracketed IPv6 literals for probing

Fix ambiguous interpretation of IPv6 addresses
like "::1:8065" by bracketing them before URL
formation to make sure they are treated as hosts
rather than "host:port" pairs.

Close #6960

Proof

$ go test -v -run "^(TestDetermineSchemeOrder|TestDetermineSchemeOrderWithHighPorts|TestDetermineSchemeOrderAmbiguousIPv6Literal|TestNormalizeProbeInput)$" ./pkg/utils
=== RUN   TestDetermineSchemeOrder
=== RUN   TestDetermineSchemeOrder/example.com
=== RUN   TestDetermineSchemeOrder/example.com:443
=== RUN   TestDetermineSchemeOrder/127.0.0.1
=== RUN   TestDetermineSchemeOrder/[fe80::1]:443
=== RUN   TestDetermineSchemeOrder/example.com:80
=== RUN   TestDetermineSchemeOrder/example.com:8080
=== RUN   TestDetermineSchemeOrder/127.0.0.1:80
=== RUN   TestDetermineSchemeOrder/127.0.0.1:8080
=== RUN   TestDetermineSchemeOrder/fe80::1
=== RUN   TestDetermineSchemeOrder/[fe80::1]:80
=== RUN   TestDetermineSchemeOrder/[fe80::1]:8080
--- PASS: TestDetermineSchemeOrder (0.00s)
    --- PASS: TestDetermineSchemeOrder/example.com (0.00s)
    --- PASS: TestDetermineSchemeOrder/example.com:443 (0.00s)
    --- PASS: TestDetermineSchemeOrder/127.0.0.1 (0.00s)
    --- PASS: TestDetermineSchemeOrder/[fe80::1]:443 (0.00s)
    --- PASS: TestDetermineSchemeOrder/example.com:80 (0.00s)
    --- PASS: TestDetermineSchemeOrder/example.com:8080 (0.00s)
    --- PASS: TestDetermineSchemeOrder/127.0.0.1:80 (0.00s)
    --- PASS: TestDetermineSchemeOrder/127.0.0.1:8080 (0.00s)
    --- PASS: TestDetermineSchemeOrder/fe80::1 (0.00s)
    --- PASS: TestDetermineSchemeOrder/[fe80::1]:80 (0.00s)
    --- PASS: TestDetermineSchemeOrder/[fe80::1]:8080 (0.00s)
=== RUN   TestDetermineSchemeOrderWithHighPorts
=== RUN   TestDetermineSchemeOrderWithHighPorts/example.com:2048
=== RUN   TestDetermineSchemeOrderWithHighPorts/example.com:8081
=== RUN   TestDetermineSchemeOrderWithHighPorts/[fe80::1]:2048
=== RUN   TestDetermineSchemeOrderWithHighPorts/[fe80::1]:12345
--- PASS: TestDetermineSchemeOrderWithHighPorts (0.00s)
    --- PASS: TestDetermineSchemeOrderWithHighPorts/example.com:2048 (0.00s)
    --- PASS: TestDetermineSchemeOrderWithHighPorts/example.com:8081 (0.00s)
    --- PASS: TestDetermineSchemeOrderWithHighPorts/[fe80::1]:2048 (0.00s)
    --- PASS: TestDetermineSchemeOrderWithHighPorts/[fe80::1]:12345 (0.00s)
=== RUN   TestDetermineSchemeOrderAmbiguousIPv6Literal
=== RUN   TestDetermineSchemeOrderAmbiguousIPv6Literal/::1:8065
=== RUN   TestDetermineSchemeOrderAmbiguousIPv6Literal/[::1]:8065
--- PASS: TestDetermineSchemeOrderAmbiguousIPv6Literal (0.00s)
    --- PASS: TestDetermineSchemeOrderAmbiguousIPv6Literal/::1:8065 (0.00s)
    --- PASS: TestDetermineSchemeOrderAmbiguousIPv6Literal/[::1]:8065 (0.00s)
=== RUN   TestNormalizeProbeInput
=== RUN   TestNormalizeProbeInput/::1:8065
=== RUN   TestNormalizeProbeInput/fe80::1
=== RUN   TestNormalizeProbeInput/[::1]:8065
=== RUN   TestNormalizeProbeInput/127.0.0.1:8080
=== RUN   TestNormalizeProbeInput/example.com:443
--- PASS: TestNormalizeProbeInput (0.00s)
    --- PASS: TestNormalizeProbeInput/::1:8065 (0.00s)
    --- PASS: TestNormalizeProbeInput/fe80::1 (0.00s)
    --- PASS: TestNormalizeProbeInput/[::1]:8065 (0.00s)
    --- PASS: TestNormalizeProbeInput/127.0.0.1:8080 (0.00s)
    --- PASS: TestNormalizeProbeInput/example.com:443 (0.00s)
PASS
ok  	github.com/projectdiscovery/nuclei/v3/pkg/utils	0.133s

Checklist

  • Pull request is created against the dev branch
  • All checks passed (lint, unit/integration/regression tests etc.) with my changes
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)

Summary by CodeRabbit

Bug Fixes

  • IPv6 addresses without brackets are now automatically normalized to the correct bracketed format during HTTP probing operations to ensure proper URL formation.

Tests

  • Added test coverage to verify IPv6 address normalization behavior and scheme determination logic for ambiguous IPv6 literals and various input formats.

@auto-assign auto-assign bot requested a review from dogancanbakir February 26, 2026 01:09
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 26, 2026

Walkthrough

Adds IPv6 input normalization to the HTTP probe utility. A new helper function normalizeProbeInput parses unbracketed IPv6 literals and returns them in bracketed form, while preserving inputs that already contain schemes or brackets. The ProbeURL function now uses normalized input for scheme determination and URL formation.

Changes

Cohort / File(s) Summary
IPv6 Normalization Logic
pkg/utils/http_probe.go
Adds normalizeProbeInput helper function to parse and bracket IPv6 addresses. Imports net/netip and strings packages. Updates ProbeURL to compute normalized input and use it for scheme order determination and URL formatting.
Test Coverage
pkg/utils/http_probe_test.go
Adds TestNormalizeProbeInput to verify normalization behavior for IPv6 literals, bracketed forms, and plain host:port combinations. Adds TestDetermineSchemeOrderAmbiguousIPv6Literal to validate scheme order for ambiguous IPv6 literals after normalization.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 Brackets make the IPv6 bright,
No ambiguity in sight,
Where once lived confusion's call,
Normalization conquers all!
A hoppy fix for URLs tall! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: normalizing unbracketed IPv6 literals for probing, which is the core fix implemented.
Linked Issues check ✅ Passed Changes implement the fix for issue #6960 by normalizing unbracketed IPv6 literals before URL formation, treating valid IPv6 addresses as hosts rather than splitting on colons.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing IPv6 literal normalization: additions to http_probe.go for normalization logic and comprehensive test coverage in http_probe_test.go.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dwisiswant0/fix/utils/normalize-unbracketed-IPv6-literals-for-probing

Comment @coderabbitai help to get the list of available commands and usage tips.

Fix ambiguous interpretation of IPv6 addresses
like "::1:8065" by bracketing them before URL
formation to make sure they are treated as hosts
rather than "host:port" pairs.

Close #6960

Signed-off-by: Dwi Siswanto <git@dw1.io>
@dwisiswant0 dwisiswant0 force-pushed the dwisiswant0/fix/utils/normalize-unbracketed-IPv6-literals-for-probing branch from 131f31a to 0eba859 Compare February 26, 2026 01:11
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
pkg/utils/http_probe_test.go (1)

78-96: Consider adding edge case coverage.

The normalization tests cover the main scenarios well. For completeness, consider adding test cases for:

  • Input already containing a scheme: "http://example.com""http://example.com"
  • Bare IPv4 without port: "127.0.0.1""127.0.0.1"

These are explicitly handled by normalizeProbeInput but not exercised by tests.

🧪 Suggested additional test cases
 	tests := []struct {
 		input    string
 		expected string
 	}{
 		{"::1:8065", "[::1:8065]"},
 		{"fe80::1", "[fe80::1]"},
 		{"[::1]:8065", "[::1]:8065"},
 		{"127.0.0.1:8080", "127.0.0.1:8080"},
 		{"example.com:443", "example.com:443"},
+		{"http://example.com", "http://example.com"},
+		{"127.0.0.1", "127.0.0.1"},
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/utils/http_probe_test.go` around lines 78 - 96, Add two edge-case
table-driven tests to TestNormalizeProbeInput to cover inputs with an explicit
scheme and a bare IPv4 address: include the cases `"http://example.com"`
expecting `"http://example.com"` and `"127.0.0.1"` expecting `"127.0.0.1"`, so
normalizeProbeInput is exercised for those branches; update the tests slice in
TestNormalizeProbeInput to include these two entries and run the same
t.Run/require.Equal assertion flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/utils/http_probe_test.go`:
- Around line 78-96: Add two edge-case table-driven tests to
TestNormalizeProbeInput to cover inputs with an explicit scheme and a bare IPv4
address: include the cases `"http://example.com"` expecting
`"http://example.com"` and `"127.0.0.1"` expecting `"127.0.0.1"`, so
normalizeProbeInput is exercised for those branches; update the tests slice in
TestNormalizeProbeInput to include these two entries and run the same
t.Run/require.Equal assertion flow.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 72b6919 and 0eba859.

📒 Files selected for processing (2)
  • pkg/utils/http_probe.go
  • pkg/utils/http_probe_test.go

@neo-by-projectdiscovery-dev
Copy link

neo-by-projectdiscovery-dev bot commented Feb 26, 2026

Neo - PR Security Review

No security issues found

Highlights

  • Adds normalizeProbeInput() function to bracket unbracketed IPv6 literals before URL formation
  • Fixes ambiguous interpretation of IPv6 addresses like '::1:8065' by ensuring they are treated as complete IPv6 addresses rather than host:port pairs
  • Uses Go's standard netip.ParseAddr for secure IPv6 validation

Comment @neo help for available commands. · Open in Neo

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.

[BUG] IPv6 handling issues

1 participant