Skip to content

fix(runner): accept IPv6 inputs without a port - #1032

Merged
Mzack9999 merged 1 commit into
projectdiscovery:mainfrom
RaphaelFakhri:fix/ipv6-input
Nov 3, 2026
Merged

Mzack9999 merged 1 commit into
projectdiscovery:mainfrom
RaphaelFakhri:fix/ipv6-input

Conversation

@RaphaelFakhri

@RaphaelFakhri RaphaelFakhri commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #1031.

getHostPortFromInput passes every input that contains : to net.SplitHostPort. For an IPv6 address without a port (::1, [::1], https://[::1]), SplitHostPort fails and the function returns an empty host, so tlsx dials :443 and reports requires valid address.

This change keeps the existing host:port path. When SplitHostPort fails, it strips optional brackets. If the result is an IPv6 address, the function returns it as the host with no port, so the -p ports (or the default port) apply.

Changes

  • internal/runner/runner.go: fall back to an IPv6 address with no port when net.SplitHostPort fails.
  • internal/runner/runner_test.go: add Test_InputIPv6_processInputItem covering bare, bracketed, bracketed with port, and URL forms.

Proof

Unit test before the fix (3 of 5 subtests fail):

$ go test -count=1 -run Test_InputIPv6 ./internal/runner/
--- FAIL: Test_InputIPv6_processInputItem (0.00s)
    --- FAIL: Test_InputIPv6_processInputItem/2001:db8::1 (0.00s)
    --- FAIL: Test_InputIPv6_processInputItem/[2001:db8::1] (0.00s)
    --- FAIL: Test_InputIPv6_processInputItem/https://[2001:db8::1] (0.00s)
FAIL	github.com/projectdiscovery/tlsx/internal/runner

After the fix (5 of 5 pass):

$ go test -count=1 -v -run Test_InputIPv6 ./internal/runner/
--- PASS: Test_InputIPv6_processInputItem (0.00s)
    --- PASS: Test_InputIPv6_processInputItem/2001:db8::1 (0.00s)
    --- PASS: Test_InputIPv6_processInputItem/[2001:db8::1] (0.00s)
    --- PASS: Test_InputIPv6_processInputItem/[2001:db8::1]:8443 (0.00s)
    --- PASS: Test_InputIPv6_processInputItem/https://[2001:db8::1] (0.00s)
    --- PASS: Test_InputIPv6_processInputItem/https://[2001:db8::1]:8443/path (0.00s)
ok  	github.com/projectdiscovery/tlsx/internal/runner

CLI against a local server (openssl s_server -accept '[::1]:18443' -6 ...):

# before
$ tlsx -u ::1 -p 18443 -v -nc
[INF] Processing input :18443
[WRN] Could not connect input :18443: cause="tlsx requires valid address got port=%v,hostname=%v,ip=%v" 18443= !BADKEY=

# after
$ tlsx -u ::1 -p 18443 -silent -cn -san
::1:18443 [localhost]
$ tlsx -u '[::1]' -p 18443 -silent -cn -san
::1:18443 [localhost]
$ tlsx -u 'https://[::1]' -p 18443 -silent -cn -san
::1:18443 [localhost]

Summary by CodeRabbit

  • Bug Fixes
    • Improved handling of IPv6 addresses when entered on their own, in brackets, or as part of HTTPS URLs. Addresses with explicit ports and URLs with paths are also parsed correctly.
    • Inputs containing colons that cannot be interpreted as a host and port now return empty host and port values.

@coderabbitai

coderabbitai Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Walkthrough

The host and port parser now accepts bare and bracketed IPv6 addresses without an explicit port. Tests cover those forms, addresses with explicit ports, and HTTPS URLs containing IPv6 addresses.

Changes

IPv6 input parsing

Layer / File(s) Summary
Host and port parsing and input tests
internal/runner/runner.go, internal/runner/runner_test.go
getHostPortFromInput returns the host and port when splitting succeeds. If splitting fails, it accepts bare or bracketed IPv6 addresses as hosts. Tests verify five IPv6 input forms, including default and explicit ports and a URL path.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: mzack9999

Merge Risk: Minimal · up to c722e

The IPv6 parsing change has no supported merge-blocking risk remaining.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed 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 clearly and concisely describes the main change: accepting IPv6 inputs without an explicit port.
Linked Issues check Passed [#1031] The objective is that bare (::1), bracketed ([::1]), and URL-form (https://[::1]) IPv6 inputs without a port yield the IPv6 host with an empty port, so the -p or default ports apply.

…
Out of Scope Changes check Passed The diff at head against the merge base f77159c touches two files.

- internal/runner/runner.go (+6/-3): changes only the net.SplitHostPort failure path in getHostPortFromInput. The successful…
Full details: Linked Issues check

Explanation

[#1031] The objective is that bare (::1), bracketed ([::1]), and URL-form (https://[::1]) IPv6 inputs without a port yield the IPv6 host with an empty port, so the -p or default ports apply.

Code at head (internal/runner/runner.go, getHostPortFromInput):

  • :// inputs go through url.Parse, which sets host to [::1] for https://[::1].
  • If net.SplitHostPort succeeds, the function returns its host and port. This keeps [::1]:8443 and https://[::1]:8443/path working.
  • If it fails, the new branch strips one leading [ and one trailing ]. If iputil.IsIPv6 accepts the result, the function returns (ip, ""). Bare ::1 and bracketed [::1] both reach this branch.
  • Empty values are returned only for other colon-containing inputs that do not parse as IPv6.

The caller processInputItem then applies r.options.Ports when the port is empty, as the issue requires.

Test coverage: Test_InputIPv6_processInputItem in runner_test.go covers all four input forms from the issue, plus [2001:db8::1]:8443 and https://[2001:db8::1]:8443/path. It asserts the expected taskInput host and port with Ports: ["443"].

Limits of evidence: I did not run the test suite. The PR reports a before/after test run and CLI checks. I did not verify the -4/-6 path (processInputForMultipleIPs), which the issue does not describe. Behavior of the iputil.IsIPv6 helper is inferred from its name and usage, not read from its source.

Full details: Out of Scope Changes check

Explanation

The diff at head against the merge base f77159c touches two files.

  • internal/runner/runner.go (+6/-3): changes only the net.SplitHostPort failure path in getHostPortFromInput. The successful split path and the URL-parsing path are unchanged. The iputil import already exists in the file.
  • internal/runner/runner_test.go (+32): adds Test_InputIPv6_processInputItem, which tests the same IPv6 input forms from #1031.

No unrelated file or behavior change appears in the reviewed diff. The host:port path that already worked is preserved. The only new accepted input shape is an IPv6 literal with no port, which is the requested behavior.

Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 1 functions across 2 files.

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches
Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

A rabbit hops past colons bright
Bare IPv6 now holds its ground
Brackets frame the host just right
Ports stay clear when they are found
URL paths fall away from sight
The rabbit nibbles, pleased and sound

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.
Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: dd7482a5-326f-454c-8370-0e71df2e1579
Commits

Reviewing files that changed from the base of the PR and between f77159c and c722e0d.

Files selected for processing: 2
  • internal/runner/runner.go
  • internal/runner/runner_test.go

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.

@Mzack9999
Mzack9999 merged commit 12808b1 into projectdiscovery:main Nov 3, 2026
6 checks passed
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.

IPv6 inputs without a port are dropped with "requires valid address"

2 participants