{"record":{"id":"9ebc682061291112","repo":"kgretzky/evilginx2","slug":"login-missing-domain-field","errorCode":null,"errorMessage":"login: missing `domain` field","messagePattern":"login: missing `domain` field","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/phishlet.go","lineNumber":636,"sourceCode":"\n\tp.password.search, err = regexp.Compile(p.paramVal(*fp.Credentials.Password.Search))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"credentials: %v\", err)\n\t}\n\n\tp.username.tp = fp.Credentials.Username.Type\n\tif p.username.tp == \"\" {\n\t\tp.username.tp = \"post\"\n\t}\n\tp.password.tp = fp.Credentials.Password.Type\n\tif p.password.tp == \"\" {\n\t\tp.password.tp = \"post\"\n\t}\n\tp.username.key_s = p.paramVal(*fp.Credentials.Username.Key)\n\tp.password.key_s = p.paramVal(*fp.Credentials.Password.Key)\n\n\tif fp.LoginItem.Domain == nil {\n\t\treturn fmt.Errorf(\"login: missing `domain` field\")\n\t}\n\tif fp.LoginItem.Path == nil {\n\t\treturn fmt.Errorf(\"login: missing `path` field\")\n\t}\n\tp.login.domain = p.paramVal(*fp.LoginItem.Domain)\n\tif p.login.domain == \"\" {\n\t\treturn fmt.Errorf(\"login: `domain` field cannot be empty\")\n\t}\n\tlogin_domain_ok := false\n\tfor _, h := range p.proxyHosts {\n\t\tvar check_host string\n\t\tif h.orig_subdomain != \"\" {\n\t\t\tcheck_host = h.orig_subdomain + \".\"\n\t\t}\n\t\tcheck_host += h.domain\n\t\tif strings.ToLower(check_host) == strings.ToLower(p.login.domain) {\n\t\t\tlogin_domain_ok = true\n\t\t\tbreak","sourceCodeStart":618,"sourceCodeEnd":654,"githubUrl":"https://github.com/kgretzky/evilginx2/blob/4c0988a1d9db4d172a185e979a38bfd0efdb5830/core/phishlet.go#L618-L654","documentation":"Phishlet validation requires the `login` section to declare a `domain` field, which tells Evilginx which proxy host the login form belongs to. When the parsed `login.domain` key is absent (nil) from the YAML, loading aborts with this message.","triggerScenarios":"Loading a phishlet YAML whose `login:` block omits the `domain:` key entirely, e.g. only `login: { username: ..., password: ... }` or a completely missing `login` mapping for the relevant subfilter.","commonSituations":"Older phishlet formats (pre-2.x) that used a different login schema; hand-trimming phishlets and accidentally deleting the `domain` line; copy-pasting only part of a phishlet.","solutions":["Add a `domain:` key under the `login:` section with one of the hostnames from `proxy_hosts` (orig_subdomain + \".\" + domain).","Compare with a working phishlet for the same site and copy the login block structure.","Ensure the file targets the phishlet format version your build expects (2.x+ requires login.domain).","Reload the phishlet after editing; validation runs in order, so fix later login errors next."],"exampleFix":"// before\nlogin:\n  path: /login\n// after\nlogin:\n  domain: accounts.example.com\n  path: /login","handlingStrategy":"validation","validationCode":"if pl.Login == nil || pl.Login.Domain == nil || pl.Login.Domain == \"\" {\n    return errors.New(\"phishlet: login.domain is required and must match a proxy_hosts hostname\")\n}","typeGuard":"func loginDomainSet(l *LoginItem) bool { return l != nil && l.Domain != nil && *l.Domain != \"\" }","tryCatchPattern":"if err := pl.Load(cfg); err != nil {\n    if strings.Contains(err.Error(), \"missing `domain`\") {\n        log.Printf(\"phishlet %s needs login.domain (e.g. accounts.example.com)\", pl.Name)\n    }\n}","preventionTips":["Always define domain, path, username, and password in the login section.","Copy the login block structure from a known-good phishlet.","Use a JSON/YAML schema validator for phishlet files.","Never hand-trim phishlet sections without re-validating."],"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"}