kgretzky/evilginx2 · error

credentials: missing custom `key` field

Error message

credentials: missing custom `key` field

What it means

Entries in the `credentials.custom` list are used to capture extra POST fields; each entry must specify a `key` (regex matching the POST field name). When a custom entry lacks `key` (nil), phishlet loading aborts with this message.

Source

Thrown at core/phishlet.go:673

		}
	}
	if !login_domain_ok {
		return fmt.Errorf("login: `domain` must contain a value of one of the hostnames (`orig_subdomain` + `domain`) defined in `proxy_hosts` section")
	}

	p.login.path = p.paramVal(*fp.LoginItem.Path)
	if p.login.path == "" {
		p.login.path = "/"
	}
	if p.login.path[0] != '/' {
		p.login.path = "/" + p.login.path
	}

	if fp.Credentials.Custom != nil {
		for _, cp := range *fp.Credentials.Custom {
			var err error
			if cp.Key == nil {
				return fmt.Errorf("credentials: missing custom `key` field")
			}
			if cp.Search == nil {
				return fmt.Errorf("credentials: missing custom `search` field")
			}
			o := PostField{}
			o.key, err = regexp.Compile(p.paramVal(*cp.Key))
			if err != nil {
				return fmt.Errorf("credentials: %v", err)
			}
			o.search, err = regexp.Compile(p.paramVal(*cp.Search))
			if err != nil {
				return err
			}
			o.tp = cp.Type
			if o.tp == "" {
				o.tp = "post"
			}
			o.key_s = p.paramVal(*cp.Key)

View on GitHub (pinned to 4c0988a1d9)

Solutions

  1. Add a `key:` regex to every entry under `credentials.custom`, e.g. `key: '^(csrf|otp)$'`.
  2. Check YAML indentation so each list item is a mapping containing key, search, and optionally type.
  3. Remove empty placeholder items (e.g. a bare `-` dash) from the custom list.
  4. Reload the phishlet and fix any subsequent custom-field errors.

Example fix

// before
custom:
  - search: '[csrf="([^"]+)"'
// after
custom:
  - key: 'csrf'
    search: '[csrf="([^"]+)"']
Defensive patterns

Strategy: validation

Validate before calling

for i, c := range pl.Credentials.Custom {
    if c.Key == nil || c.Search == nil {
        return fmt.Errorf("credentials.custom[%d] needs both key and search", i)
    }
}

Type guard

func customFieldComplete(c *CustomField) bool { return c != nil && c.Key != nil && *c.Key != "" && c.Search != nil && *c.Search != "" }

Try / catch

if err := pl.Load(cfg); err != nil {
    if strings.Contains(err.Error(), "missing custom `key`") {
        log.Printf("every credentials.custom entry in %s needs a key regex", pl.Name)
    }
}

Prevention

When it happens

Trigger: A phishlet YAML with `credentials: custom: [...]` where one list item has only `search`/`type` and no `key:` field, or a mis-indented item causing its `key` to land on a different mapping.

Common situations: Adding custom capture fields by hand and forgetting the key; YAML indentation shifting keys between sibling entries so one item loses its `key`; copying a partial example snippet.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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