{"id":"d59749cec25c9950","repo":"gofiber/fiber","slug":"domain-pattern-s-contains-invalid-parameter-nam","errorCode":null,"errorMessage":"Domain pattern '%s' contains invalid parameter name '%s' with character '%c'","messagePattern":"Domain pattern '(.+?)' contains invalid parameter name '(.+?)' with character '%c'","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"domain.go","lineNumber":102,"sourceCode":"\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\n\t\t\tm.parts[i] = part                              // keep \":param\" marker for matching\n\t\t} else {\n\t\t\t// Only lowercase constant labels (RFC 4343)\n\t\t\t// Enforce RFC 1035 per-label length limit (63 characters)\n\t\t\tif len(part) > 63 {\n\t\t\t\tpanic(fmt.Sprintf(\"Domain pattern '%s' has label '%s' exceeding RFC 1035 limit of 63 characters (%d chars)\",\n\t\t\t\t\tpattern, part, len(part)))\n\t\t\t}\n\t\t\t// Validate label contains only valid ASCII domain characters (a-z, 0-9, hyphen).\n\t\t\tnormalized := utilsstrings.ToLower(part)\n\t\t\tfor _, ch := range normalized {\n\t\t\t\tif !isASCIIAlphanumeric(ch) && ch != '-' {\n\t\t\t\t\tpanic(fmt.Sprintf(\"Domain pattern '%s' contains invalid character '%c' in label '%s'\", pattern, ch, part))\n\t\t\t\t}","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/domain.go#L84-L120","documentation":"Panics from domain.go:102 when a domain parameter name contains a character outside the allowed set (ASCII a-z, A-Z, 0-9, underscore, hyphen). DNS-safe names keep matching and DomainParam lookups predictable; non-ASCII or punctuation in a param name is rejected.","triggerScenarios":"app.Domain(\":user-id.example.com\") is fine (hyphen allowed); app.Domain(\":us/r.example.com\") panics on '/'; app.Domain(\":user.example.com\") with a unicode char or space in the name panics. Reachable when parameter names are built from untrusted input.","commonSituations":"Using tenant IDs or emails as parameter names that include '@', '/', spaces, or unicode; templating that injects raw user input into the pattern.","solutions":["Restrict parameter names to [A-Za-z0-9_-]; sanitize or reject input used as a param name.","Use a fixed, safe parameter name and capture the variable part at match time via DomainParam.","Validate with a regex like ^[A-Za-z0-9_-]+$ before constructing the pattern."],"exampleFix":"// before\nname := r.URL.Query().Get(\"name\") // could be \"foo bar\"\napp.Domain(\":\" + name + \".example.com\").Get(\"/\", h)\n\n// after\nname := r.URL.Query().Get(\"name\")\nif !paramNameRe.MatchString(name) {\n    return fmt.Errorf(\"invalid domain parameter name\")\n}\napp.Domain(\":\" + name + \".example.com\").Get(\"/\", h)","handlingStrategy":"validation","validationCode":"var paramNameRe = regexp.MustCompile(`^[A-Za-z0-9_-]+$`)\nfor _, label := range strings.Split(pattern, \".\") {\n    if strings.HasPrefix(label, \":\") && !paramNameRe.MatchString(label[1:]) {\n        return fmt.Errorf(\"invalid domain parameter name: %s\", label[1:])\n    }\n}\napp.Domain(pattern).Get(\"/\", h)","typeGuard":"func isValidParamName(name string) bool {\n    for _, ch := range name {\n        if !((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '_' || ch == '-') {\n            return false\n        }\n    }\n    return name != \"\"\n}","tryCatchPattern":null,"preventionTips":["Never inject raw user input as a parameter name.","Constrain parameter names to [A-Za-z0-9_-] at the source.","Use fixed parameter names and read values via DomainParam."],"tags":["routing","domain","validation","parameter","ascii","panic"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}