Skip to content

fix: auto-bracket bare IPv6 literals in serpent.URL.Set - #33

Open
rowansmithau wants to merge 4 commits into
mainfrom
rowan/serpent_ipv6_auto_bracket
Open

fix: auto-bracket bare IPv6 literals in serpent.URL.Set#33
rowansmithau wants to merge 4 commits into
mainfrom
rowan/serpent_ipv6_auto_bracket

Conversation

@rowansmithau

@rowansmithau rowansmithau commented Jul 23, 2026

Copy link
Copy Markdown
Member

An attempt to solve 27266 in coder/coder.

net/url.Parse cannot disambiguate an unbracketed IPv6 host from its trailing port (e.g. "http://2600:2222::22:8080" fails with "invalid port ... after host"). This breaks CODER_DERP_SERVER_RELAY_URL when set from a Kubernetes IPv6 pod IP.

This adds detection of IPv6 address add brackets them accordingly.

Tested on a local build of coder with a replace directive.

➜  Downloads CODER_DERP_SERVER_RELAY_URL="http://2407:8800:bcc2:7700:81d:fc1b:cec5:8064:8080" ./coder-ipv6-test server \
  --http-address :3000 \
  --access-url http://192.168.51.15:3000
Coder v2.35.2-devel+80f8e4f624 - Your Self-Hosted Remote Development Platform
➜  Downloads CODER_DERP_SERVER_RELAY_URL="http://[2407:8800:bcc2:7700:81d:fc1b:cec5:8064]:8080" ./coder-ipv6-test server \
  --http-address :3000 \
  --access-url http://192.168.51.15:3000
Coder v2.35.2-devel+80f8e4f624 - Your Self-Hosted Remote Development Platform

I ran go mod edit -replace github.com/coder/serpent=github.com/coder/serpent@rowan/serpent_ipv6_auto_bracket && go mod tidy followed by make test on coder's main branch and those tests still passed.

net/url.Parse cannot disambiguate an unbracketed IPv6 host from its
trailing port (e.g. "http://2600:2222::22:8080" fails with
"invalid port ... after host"). This breaks CODER_DERP_SERVER_RELAY_URL
when set from a Kubernetes IPv6 pod IP (coder/coder#27266).

Detect this shape in the authority component and wrap the IPv6
literal in brackets before delegating to url.Parse. IPv4 hosts,
hostnames, and already-bracketed IPv6 hosts are left untouched, so
this is a strict superset of previously-accepted input.
blink-so Bot added 3 commits July 29, 2026 20:44
Improves the URL parsing heuristic added in the previous commit:

- Split userinfo ("user[:pass]@") off the authority before host
  detection so credentials containing colons are not mistaken for
  part of an IPv6 literal.
- Terminate the authority at the first of "/", "?", or "#" (not
  just "/") so bare IPv6 hosts followed by a query or fragment are
  handled correctly.
- Use netip.ParseAddr + Is6() instead of net.ParseIP so IPv4 hosts
  that would parse successfully (e.g. "::ffff:1.2.3.4" forms) are
  not misclassified as bracket-worthy IPv6.
- Strip optional IPv6 zone identifiers ("%eth0") before parsing.

Adds test coverage for the new cases and for an invalid-but-
IPv6-shaped host, which must fall through to url.Parse and error
rather than being silently accepted.
The userinfo case (http://user:pass@ipv6:port) is not exercised by
any real Coder configuration; the reported bug is exclusively about
bare IPv6 literals from Kubernetes pod IPs, which never carry
credentials. Keeping the change minimal reduces review surface and
avoids maintaining a heuristic for a shape that already produces a
reasonable url.Parse error today.
strconv.Atoi already rejects empty strings, signs, and non-digits,
matching net/url's own port validation. Removes 12 lines of
unnecessary helper code.
@uzair-coder07

Copy link
Copy Markdown

@rowansmithau Those commits that you see from Blink - That is me and blink trying to come up with what we can to fix this.

@uzair-coder07

Copy link
Copy Markdown

I am going to run this against a live deployment and will report back.

@uzair-coder07

uzair-coder07 commented Jul 29, 2026

Copy link
Copy Markdown

Okay. So I had to do the following in order to test this out:

Resolve the branch to a SHA:
git ls-remote https://github.com/coder/serpent refs/heads/rowan/serpent_ipv6_auto_bracket

Then use the short SHA from the above command's output:
go get github.com/coder/serpent@<commit-sha>

After go get github.com/coder/serpent@<commit-sha>, go.mod and go.sum are already updated so a go mod edit -replace isn't really required.

Ran a tidy:
go mod tidy

Ran 3 tests with different values for CODER_DERP_SERVER_RELAY_URL:

  1. With http://[2407:8800:bcc2:7700:81d:fc1b:cec5:8064]:8080
  2. With http://2407:8800:bcc2:7700:81d:fc1b:cec5:8064:8080
  3. With http://192.168.1.2:8080

All 3 cases passed and seemed to have worked correctly.

Output of 1 & 2:
Screenshot 2026-07-29 at 4 51 31 PM

Output of 3:
Screenshot 2026-07-29 at 4 52 45 PM

@uzair-coder07

Copy link
Copy Markdown

I have removed the experimental label and will mark this draft pull request as 'ready for review' to get feedback from engineering. If all is well, We can publish a new release of serpent and have it consumed within coder/coder.

@uzair-coder07
uzair-coder07 marked this pull request as ready for review July 30, 2026 20:40
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