{"record":{"id":"6b4f3f00249a5121","repo":"gofiber/fiber","slug":"domain-pattern-s-contains-empty-label-at-positi","errorCode":null,"errorMessage":"Domain pattern '%s' contains empty label at position %d","messagePattern":"Domain pattern '(.+?)' contains empty label at position (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"domain.go","lineNumber":88,"sourceCode":"\t}\n\n\tparts := strings.Split(pattern, \".\")\n\n\t// Prevent DoS from patterns with excessive label counts\n\tif len(parts) > maxDomainParts {\n\t\tpanic(fmt.Sprintf(\"Domain pattern '%s' has %d parts, which exceeds the maximum of %d\",\n\t\t\tpattern, len(parts), maxDomainParts))\n\t}\n\n\tm := domainMatcher{\n\t\tparts:    make([]string, len(parts)),\n\t\tnumParts: len(parts),\n\t}\n\n\tfor i, part := range parts {\n\t\t// Validate no empty labels (e.g., \"example..com\" is invalid)\n\t\tif part == \"\" {\n\t\t\tpanic(fmt.Sprintf(\"Domain pattern '%s' contains empty label at position %d\", pattern, i))\n\t\t}\n\n\t\tif part[0] == ':' {\n\t\t\t// Validate parameter name is not empty\n\t\t\tif len(part) == 1 {\n\t\t\t\tpanic(fmt.Sprintf(\"Domain pattern '%s' contains empty parameter name at position %d\", pattern, i))\n\t\t\t}\n\t\t\tparamName := part[1:]\n\t\t\t// Validate parameter name contains only ASCII-safe characters (a-z, A-Z, 0-9, underscore, hyphen).\n\t\t\t// Using explicit ASCII ranges rather than unicode.IsLetter/IsDigit to reject non-ASCII\n\t\t\t// characters that are invalid in DNS names.\n\t\t\tfor _, ch := range paramName {\n\t\t\t\tif !isASCIIAlphanumeric(ch) && ch != '_' && ch != '-' {\n\t\t\t\t\tpanic(fmt.Sprintf(\"Domain pattern '%s' contains invalid parameter name '%s' with character '%c'\", pattern, paramName, ch))\n\t\t\t\t}\n\t\t\t}\n\t\t\tm.paramIdx = append(m.paramIdx, i)\n\t\t\tm.paramNames = append(m.paramNames, paramName) // preserve original case","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/domain.go#L70-L106","documentation":"After splitting on '.', each label must be non-empty; an empty label indicates a malformed pattern such as \"example..com\" (double dot) or a leading/trailing dot. parseDomainPattern panics with the offending position to make the malformed label easy to locate.","triggerScenarios":"Passing a pattern with two consecutive dots, or one that starts/ends with a dot after the trailing-dot normalization (e.g. \".example.com\" or \"example.com.\").","commonSituations":"Concatenating segments with \".\" where one segment is empty; user input not trimmed; trailing-dot removal leaving an empty leading label; templating bug producing \"..\".","solutions":["Sanitize the pattern: remove empty segments with slices.DeleteFunc(strings.Split(p, \".\"), func(s string) bool { return s == \"\"}).","Validate before registering: reject patterns containing \"..\" or starting with '.'.","Trim and normalize input from config before using it as a domain pattern."],"exampleFix":"// before\napp.Domain(\"example..com\")\n\n// after\np := strings.Trim(p, \".\")\nif strings.Contains(p, \"..\") { return errors.New(\"malformed domain\") }\napp.Domain(p)","handlingStrategy":"validation","validationCode":"// Reject malformed patterns with empty labels\nfunc validateNoEmptyLabels(p string) error {\n    if strings.HasPrefix(p, \".\") || strings.HasSuffix(p, \".\") || strings.Contains(p, \"..\") {\n        return errors.New(\"malformed domain: empty label\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Trim and sanitize user-supplied domains before use.","Reject '..' and leading/trailing dots at the input boundary.","Use a single normalization helper across all Domain calls."],"tags":["routing","domain","validation","malformed-input","startup"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}