kgretzky/evilginx2 · error

missing `login` section

Error message

missing `login` section

What it means

Thrown when the phishlet defines credentials but lacks the required top-level `login` section (fp.LoginItem is nil). The `login` section specifies the login URL path and domain on the target site, which Evilginx uses to redirect victims to the real login page and detect successful authentication.

Source

Thrown at core/phishlet.go:393

	}

	if fp.ProxyHosts == nil {
		return fmt.Errorf("missing `proxy_hosts` section")
	}
	if fp.AuthTokens == nil {
		return fmt.Errorf("missing `auth_tokens` section")
	}
	if fp.Credentials == nil {
		return fmt.Errorf("missing `credentials` section")
	}
	if fp.Credentials.Username == nil {
		return fmt.Errorf("credentials: missing `username` section")
	}
	if fp.Credentials.Password == nil {
		return fmt.Errorf("credentials: missing `password` section")
	}
	if fp.LoginItem == nil {
		return fmt.Errorf("missing `login` section")
	}

	for _, ph := range *fp.ProxyHosts {
		if ph.PhishSub == nil {
			return fmt.Errorf("proxy_hosts: missing `phish_sub` field")
		}
		if ph.OrigSub == nil {
			return fmt.Errorf("proxy_hosts: missing `orig_sub` field")
		}
		if ph.Domain == nil {
			return fmt.Errorf("proxy_hosts: missing `domain` field")
		}
		auto_filter := true
		if ph.AutoFilter != nil {
			auto_filter = *ph.AutoFilter
		}
		p.addProxyHost(p.paramVal(*ph.PhishSub), p.paramVal(*ph.OrigSub), p.paramVal(*ph.Domain), ph.Session, ph.IsLanding, auto_filter)
	}

View on GitHub (pinned to 4c0988a1d9)

Solutions

  1. Add a top-level `login:` section to the phishlet YAML
  2. Include `domain:` and `path:` fields pointing at the site's real login endpoint
  3. Reload the phishlet after the edit

Example fix

// before
credentials:
  username:
    key: username
  password:
    key: password
// after
credentials:
  username:
    key: username
  password:
    key: password
login:
  domain: accounts.example.com
  path: /login
Defensive patterns

Strategy: validation

Validate before calling

var fp struct {
	LoginItem *struct {
		Domain *string `yaml:"domain"`
		Path   *string `yaml:"path"`
	} `yaml:"login"`
}
yaml.Unmarshal(data, &fp)
if fp.LoginItem == nil {
	return errors.New("phishlet must define a top-level `login:` section with domain and path")
}

Type guard

func hasLogin(fp *PhishletConfig) bool {
	return fp != nil && fp.LoginItem != nil
}

Try / catch

err := cfg.AddPhishlet("local", name)
if err != nil {
	if strings.Contains(err.Error(), "missing `login` section") {
		log.Fatalf("phishlet %s: add a login block with domain and path", name)
	}
	return err
}

Prevention

When it happens

Trigger: Loading a phishlet YAML that includes proxy_hosts and credentials but omits the `login:` block, or has it mis-indented so it does not bind to the struct.

Common situations: Trimming a phishlet down and removing the login block by mistake; renaming `login` to something like `signin`; YAML anchor/tag errors that leave the field nil.

Related errors


AI-assisted analysis of kgretzky/evilginx2@4c0988a1d9 (2026-09-05). Data as JSON: /api/errors/abd28d0da23578c8. Report an issue: GitHub.