Repository navigation
validate: trim every trailing dot and read Unicode full stops as labels - #282
Merged
TMHSDigital merged 1 commit intoNov 14, 2026
Merged
Conversation
NormalizeDomain removed at most one trailing dot and only after the IDN conversion, so "example.com.." came back as "example.com." and "bücher.example。" turned the ideographic full stop into a label of its own. Domain() then accepted the trailing-dot form, leaving two entry points with different ideas of the canonical name. Map U+3002, U+FF0E and U+FF61 to "." before anything else and trim all trailing dots, then reject a trailing dot in Domain so callers cannot reintroduce the non-canonical form. Normalizing an accepted domain now returns the input unchanged, which is what FuzzNormalizeDomain checks. Fixes TMHSDigital#281
TMHSDigital
added a commit
that referenced
this pull request
Nov 14, 2026
#282 fixed the trailing-dot and Unicode full stop handling that FuzzNormalizeDomain found; credit it in the changelog and stop the fuzz target's comment saying the bug is still there. Refs #281 Co-Authored-By: Claude Opus 5.5 <[email protected]>
Owner
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
NormalizeDomaincan return a name that still ends in a dot, and it treats Unicode full stops (。,.,。) as ordinary label characters instead of IDNA label separators.FuzzNormalizeDomain(added for #259) finds both:example.com..normalizes toexample.com., andbücher.example。comes back asxn--bcher-kva.xn--example-dp3f. Normalising the result again gives a different answer, so two entry points can disagree on the canonical name. Reported in #281.Root cause
Two separate gaps in
internal/validate/validate.go:NormalizeDomainusedstrings.TrimSuffix(s, "."), which removes one dot at most, and did it before the IDN conversion — so a dot left over from a pasted domain was converted as part of a label, not trimmed..by IDNA (UTS Release linux/amd64 binary is dynamically linked, contradicting the "single static binary" claim #46), but nothing did that mapping, so a trailing ideographic full stop became a label.Domainalso trimmed one trailing dot itself, so it accepted the non-canonical form thatNormalizeDomainwas supposed to have removed.Fix
.while the input is still being read, via a package-levelstrings.Replacerand a smallnormalizeFullStopshelper.strings.TrimRight(s, ".")so every trailing dot is removed.Domainoutright; the only caller that could produce one is normalisation, and normalisation now trims it, so this closes the path instead of hiding it.Testing
TestNormalizeDomain(example.com..,example.com。,bücher.example。,bücher.example.。,example.com) andexample.com.to the invalid list forDomain. All of them fail on the parent commit (--- FAIL: TestNormalizeDomain/example.com..,--- FAIL: TestDomain/invalid_example.com., …) and pass with the change.go test ./...— all packages pass.go vet ./internal/validate/clean,gofmt -l internal/validate/reports nothing.Diff: +19/-2 across two files.
Fixes #281