{"record":{"id":"73386deba7397f35","repo":"owasp-amass/amass","slug":"exceeded-maximum-mask-size-3-s","errorCode":null,"errorMessage":"exceeded maximum mask size (3): %s","messagePattern":"exceeded maximum mask size \\(3\\): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/wordlist.go","lineNumber":33,"sourceCode":"\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/caffix/stringset\"\n)\n\nconst (\n\tmaskLetters = \"abcdefghijklmnopqrstuvwxyz\"\n\tmaskDigits  = \"0123456789\"\n\tmaskSpecial = \"-\"\n)\n\n// ExpandMask will return a slice of words that a \"hashcat-style\" mask matches.\nfunc ExpandMask(word string) ([]string, error) {\n\tvar expanded []string\n\tvar chars string\n\n\tif strings.Count(word, \"?\") > 3 {\n\t\treturn expanded, fmt.Errorf(\"exceeded maximum mask size (3): %s\", word)\n\t}\n\n\tparts := strings.SplitN(word, \"?\", 2)\n\tif len(parts) > 1 {\n\t\tif len(parts[1]) > 0 {\n\t\t\tswitch parts[1][0] {\n\t\t\tcase 'a':\n\t\t\t\tchars = maskLetters + maskDigits + maskSpecial\n\t\t\tcase 'd':\n\t\t\t\tchars = maskDigits\n\t\t\tcase 'u':\n\t\t\t\tfallthrough\n\t\t\tcase 'l':\n\t\t\t\tchars = maskLetters\n\t\t\tcase 's':\n\t\t\t\tchars = maskSpecial\n\t\t\tdefault:\n\t\t\t\treturn expanded, fmt.Errorf(\"improper mask used: %s\", word)","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/owasp-amass/amass/blob/79299dce87b0085db0f2f4ef3e9c52cccb49f514/config/wordlist.go#L15-L51","documentation":"ExpandMask expands hashcat-style masks (e.g. ?l?d) into candidate words, and this library caps a mask at 3 placeholders to bound expansion size. If the input word contains more than three '?' characters, expansion is refused. It protects against combinatorial blowup and accidental '?' usage.","triggerScenarios":"Calling ExpandMask, ExpandMaskWordlist, or TestExpandMask with a string containing 4+ '?' characters, or a plain word that legitimately contains question marks (e.g. a URL fragment).","commonSituations":"Feeding dictionary words containing '?' into mask expansion; misremembering the mask limit; recursive expansion producing words that re-enter ExpandMask.","solutions":["Reduce the mask to at most 3 placeholders (e.g. ?l?l?d instead of ?l?l?l?d)","Pre-process input words to strip or escape literal '?' characters","Expand in multiple passes if more placeholders are genuinely needed"],"exampleFix":"// before\nwords, err := ExpandMask(\"?l?l?l?d\")\n// after\nwords, err := ExpandMask(\"?l?l?d\")","handlingStrategy":"validation","validationCode":"if strings.Count(mask, \"?\") > 3 { return errors.New(\"mask has more than 3 placeholders\") }","typeGuard":"func isValidMask(w string) bool { return strings.Count(w, \"?\") <= 3 }\n","tryCatchPattern":"words, err := ExpandMask(m)\nif err != nil {\n  if strings.HasPrefix(err.Error(), \"exceeded maximum mask size\") {\n    // reduce mask or expand in multiple passes\n  }\n  return err\n}","preventionTips":["Cap masks at 3 placeholders by design","Strip literal '?' from dictionary words before mask expansion","Document the 3-placeholder limit for config authors"],"tags":["wordlist","mask","limit"],"backgroundTag":"value-out-of-range","analyzedSha":"79299dce87b0085db0f2f4ef3e9c52cccb49f514","analyzedAt":"2026-09-06T08:22:48.198Z","contentChangedAt":"2026-09-06T08:22:48.198Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}