{"record":{"id":"68fc256b98a55874","repo":"kgretzky/evilginx2","slug":"sub-filters-missing-triggers-on-field","errorCode":null,"errorMessage":"sub_filters: missing `triggers_on` field","messagePattern":"sub_filters: missing `triggers_on` field","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/phishlet.go","lineNumber":439,"sourceCode":"\t}\n\tif !session_set {\n\t\tp.proxyHosts[0].handle_session = true\n\t}\n\tlanding_set := false\n\tfor _, ph := range p.proxyHosts {\n\t\tif ph.is_landing {\n\t\t\tlanding_set = true\n\t\t\tbreak\n\t\t}\n\t}\n\tif !landing_set {\n\t\tp.proxyHosts[0].is_landing = true\n\t}\n\n\tif fp.SubFilters != nil {\n\t\tfor _, sf := range *fp.SubFilters {\n\t\t\tif sf.Hostname == nil {\n\t\t\t\treturn fmt.Errorf(\"sub_filters: missing `triggers_on` field\")\n\t\t\t}\n\t\t\tif sf.Sub == nil {\n\t\t\t\treturn fmt.Errorf(\"sub_filters: missing `orig_sub` field\")\n\t\t\t}\n\t\t\tif sf.Domain == nil {\n\t\t\t\treturn fmt.Errorf(\"sub_filters: missing `domain` field\")\n\t\t\t}\n\t\t\tif sf.Mimes == nil {\n\t\t\t\treturn fmt.Errorf(\"sub_filters: missing `mimes` field\")\n\t\t\t}\n\t\t\tif sf.Search == nil {\n\t\t\t\treturn fmt.Errorf(\"sub_filters: missing `search` field\")\n\t\t\t}\n\t\t\tif sf.Replace == nil {\n\t\t\t\treturn fmt.Errorf(\"sub_filters: missing `replace` field\")\n\t\t\t}\n\t\t\tif sf.WithParams == nil {\n\t\t\t\tsf.WithParams = &[]string{}","sourceCodeStart":421,"sourceCodeEnd":457,"githubUrl":"https://github.com/kgretzky/evilginx2/blob/4c0988a1d9db4d172a185e979a38bfd0efdb5830/core/phishlet.go#L421-L457","documentation":"Thrown when iterating `sub_filters` entries and an entry lacks the field that should map to `triggers_on`. Note the message is misleading: the check is sf.Hostname == nil, i.e. the missing YAML key is actually `triggers_on`'s counterpart `hostname`? In upstream Evilginx3 the sub_filter fields are `triggers_on`, `orig_sub`, `domain`, `search`, `replace` mapped to struct fields where Hostname corresponds to `triggers_on` - so a missing `triggers_on:` key produces this error. sub_filters let a phishlet rewrite response bodies (e.g. strip logout links).","triggerScenarios":"A `sub_filters:` entry in the phishlet YAML omits `triggers_on: <hostname>` (or misspells/mis-indents it) so sf.Hostname stays nil during validation.","commonSituations":"Adding a sub_filter with only search/replace; typo like `trigger_on`; indentation nesting triggers_on under another key.","solutions":["Add `triggers_on:` with the target hostname to each sub_filters entry","Format triggers_on as the hostname string (e.g. accounts.example.com) that the filter applies to","Keep orig_sub, domain, search, and replace present as well since each is checked next"],"exampleFix":"// before\nsub_filters:\n  - orig_sub: accounts\n    domain: example.com\n    search: 'href=\"logout\"'\n    replace: '#'\n// after\nsub_filters:\n  - triggers_on: 'accounts.example.com'\n    orig_sub: accounts\n    domain: example.com\n    search: 'href=\"logout\"'\n    replace: '#'\n","handlingStrategy":"validation","validationCode":"type subFilter struct {\n\tHostname *string `yaml:\"triggers_on\"`\n\tSub      *string `yaml:\"orig_sub\"`\n\tDomain   *string `yaml:\"domain\"`\n\tMimes    []string `yaml:\"mimes\"`\n}\nvar fp struct { SubFilters *[]subFilter `yaml:\"sub_filters\"` }\nyaml.Unmarshal(data, &fp)\nfor i, sf := range *fp.SubFilters {\n\tif sf.Hostname == nil {\n\t\treturn fmt.Errorf(\"sub_filters[%d]: missing triggers_on\", i)\n\t}\n}","typeGuard":"func hasTriggersOn(sf SubFilter) bool {\n\treturn sf.Hostname != nil\n}","tryCatchPattern":"err := cfg.AddPhishlet(\"local\", name)\nif err != nil {\n\tif strings.Contains(err.Error(), \"sub_filters: missing `triggers_on`\") {\n\t\tlog.Fatalf(\"phishlet %s: each sub_filters entry must start with triggers_on hostname\", name)\n\t}\n\treturn err\n}","preventionTips":["Start every sub_filters entry with triggers_on followed by orig_sub, domain, search, replace","Copy the six-field order from official phishlets","Quote hostname values to avoid YAML parsing surprises","Lint sub_filters indentation so all fields are siblings"],"tags":["phishlet","sub-filters","config-validation"],"backgroundTag":"phishlet-schema-validation","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"}