{"record":{"id":"c579943ca46d5be3","repo":"kgretzky/evilginx2","slug":"credentials-missing-custom-search-field","errorCode":null,"errorMessage":"credentials: missing custom `search` field","messagePattern":"credentials: missing custom `search` field","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/phishlet.go","lineNumber":676,"sourceCode":"\t\treturn fmt.Errorf(\"login: `domain` must contain a value of one of the hostnames (`orig_subdomain` + `domain`) defined in `proxy_hosts` section\")\n\t}\n\n\tp.login.path = p.paramVal(*fp.LoginItem.Path)\n\tif p.login.path == \"\" {\n\t\tp.login.path = \"/\"\n\t}\n\tif p.login.path[0] != '/' {\n\t\tp.login.path = \"/\" + p.login.path\n\t}\n\n\tif fp.Credentials.Custom != nil {\n\t\tfor _, cp := range *fp.Credentials.Custom {\n\t\t\tvar err error\n\t\t\tif cp.Key == nil {\n\t\t\t\treturn fmt.Errorf(\"credentials: missing custom `key` field\")\n\t\t\t}\n\t\t\tif cp.Search == nil {\n\t\t\t\treturn fmt.Errorf(\"credentials: missing custom `search` field\")\n\t\t\t}\n\t\t\to := PostField{}\n\t\t\to.key, err = regexp.Compile(p.paramVal(*cp.Key))\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"credentials: %v\", err)\n\t\t\t}\n\t\t\to.search, err = regexp.Compile(p.paramVal(*cp.Search))\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\to.tp = cp.Type\n\t\t\tif o.tp == \"\" {\n\t\t\t\to.tp = \"post\"\n\t\t\t}\n\t\t\to.key_s = p.paramVal(*cp.Key)\n\t\t\tp.custom = append(p.custom, o)\n\t\t}\n\t}","sourceCodeStart":658,"sourceCodeEnd":694,"githubUrl":"https://github.com/kgretzky/evilginx2/blob/4c0988a1d9db4d172a185e979a38bfd0efdb5830/core/phishlet.go#L658-L694","documentation":"Each `credentials.custom` entry needs both a `key` (field name regex) and a `search` (regex to extract the value). This error is raised when a custom entry defines `key` but omits `search`, so no extraction pattern exists for that field.","triggerScenarios":"A `credentials.custom` list item with `key:` present but no `search:` line; indentation errors putting `search` on the wrong item.","commonSituations":"Half-finished custom field config; author assuming a bare key match suffices; deleting a broken search regex and leaving the entry incomplete.","solutions":["Add a `search:` regex capturing the value group, e.g. `search: 'value=\"([^\"]+)\"'` for the same entry.","Ensure each list item contains both key and search at the same indentation level.","Temporarily remove the incomplete custom entry to get the phishlet loading, then re-add it correctly.","Reload and verify no further custom-field validation errors."],"exampleFix":"// before\ncustom:\n  - key: 'otp'\n// after\ncustom:\n  - key: 'otp'\n    search: '[otp value=\"([0-9]+)\"']","handlingStrategy":"validation","validationCode":"for i, c := range pl.Credentials.Custom {\n    if c.Search == nil || *c.Search == \"\" {\n        return fmt.Errorf(\"credentials.custom[%d] (key=%v) missing search regex\", i, c.Key)\n    }\n}","typeGuard":"func hasSearch(c *CustomField) bool { return c != nil && c.Search != nil && *c.Search != \"\" }","tryCatchPattern":"if err := pl.Load(cfg); err != nil {\n    if strings.Contains(err.Error(), \"missing custom `search`\") {\n        log.Printf(\"add a search regex next to key %q in %s\", keyName, pl.Name)\n    }\n}","preventionTips":["Treat key+search as an atomic pair in your phishlet templates.","Include a capture group in every search regex.","Lint custom entries for missing fields in CI.","Avoid leaving half-finished entries in shipped phishlets."],"tags":["configuration","phishlet","yaml","missing-field"],"backgroundTag":"missing-required-argument","analyzedSha":"4c0988a1d9db4d172a185e979a38bfd0efdb5830","analyzedAt":"2026-09-05T19:23:07.238Z","contentChangedAt":"2026-09-05T19:23:07.238Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}