kgretzky/evilginx2 · error

proxy_hosts: list cannot be empty

Error message

proxy_hosts: list cannot be empty

What it means

After parsing all proxy_hosts entries, the validator checks len(p.proxyHosts) == 0 and rejects the phishlet if nothing was added. This happens when the `proxy_hosts` section is present but contains no valid entries (empty list, null items, or every entry failing earlier checks that were skipped). A phishlet with no proxied hosts has nothing to serve and is unusable.

Source

Thrown at core/phishlet.go:413

	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)
	}
	if len(p.proxyHosts) == 0 {
		return fmt.Errorf("proxy_hosts: list cannot be empty")
	}
	session_set := false
	for _, ph := range p.proxyHosts {
		if ph.handle_session {
			session_set = true
			break
		}
	}
	if !session_set {
		p.proxyHosts[0].handle_session = true
	}
	landing_set := false
	for _, ph := range p.proxyHosts {
		if ph.is_landing {
			landing_set = true
			break
		}
	}

View on GitHub (pinned to 4c0988a1d9)

Solutions

  1. Ensure `proxy_hosts:` contains at least one complete entry with phish_sub, orig_sub, and domain
  2. Un-comment or restore entries removed during testing
  3. Validate the YAML structure with a parser to confirm the list actually binds

Example fix

# before
proxy_hosts: []
# after
proxy_hosts:
  - phish_sub: www
    orig_sub: www
    domain: example.com
login:
  domain: www.example.com
  path: /login
Defensive patterns

Strategy: validation

Validate before calling

var fp struct { ProxyHosts *[]ProxyHost `yaml:"proxy_hosts"` }
yaml.Unmarshal(data, &fp)
if fp.ProxyHosts == nil || len(*fp.ProxyHosts) == 0 {
	return errors.New("proxy_hosts must contain at least one entry")
}

Type guard

func hasProxyHosts(fp *PhishletConfig) bool {
	return fp != nil && fp.ProxyHosts != nil && len(*fp.ProxyHosts) > 0
}

Try / catch

err := cfg.AddPhishlet("local", name)
if err != nil {
	if strings.Contains(err.Error(), "list cannot be empty") {
		log.Fatalf("phishlet %s: proxy_hosts needs at least one complete entry", name)
	}
	return err
}

Prevention

When it happens

Trigger: YAML like `proxy_hosts: []` or `proxy_hosts:` with no entries; entries that fail to bind (e.g. wrong types) leaving p.proxyHosts empty after the loop.

Common situations: Commenting out all entries during testing and forgetting to restore them; a list whose items are indented wrongly so nothing deserializes; truncation during copy-paste.

Related errors


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