kgretzky/evilginx2 · error
phishlet '%s' can't be deleted - you can only delete child p
Error message
phishlet '%s' can't be deleted - you can only delete child phishlets.
What it means
DeleteSubPhishlet only allows deletion of child (inherited) phishlets. If the phishlet identified by `site` has no ParentName (i.e. it is a top-level phishlet), the config refuses to delete it and returns this error, protecting base phishlets from accidental removal.
Source
Thrown at core/config.go:592
if err != nil {
return err
}
sub_pl.ParentName = parent_site
c.phishletNames = append(c.phishletNames, site)
c.phishlets[site] = sub_pl
c.VerifyPhishlets()
return nil
}
func (c *Config) DeleteSubPhishlet(site string) error {
pl, err := c.GetPhishlet(site)
if err != nil {
return err
}
if pl.ParentName == "" {
return fmt.Errorf("phishlet '%s' can't be deleted - you can only delete child phishlets.", site)
}
c.phishletNames = removeString(site, c.phishletNames)
delete(c.phishlets, site)
delete(c.phishletConfig, site)
c.SavePhishlets()
return nil
}
func (c *Config) LoadSubPhishlets() {
var subphishlets []*SubPhishlet
c.cfg.UnmarshalKey(CFG_SUBPHISHLETS, &subphishlets)
for _, spl := range subphishlets {
err := c.AddSubPhishlet(spl.Name, spl.ParentName, spl.Params)
if err != nil {
log.Error("phishlets: %s", err)
}
}View on GitHub (pinned to 4c0988a1d9)
Solutions
- Only call DeleteSubPhishlet for phishlets whose ParentName is non-empty; delete base phishlets through a different path if the API exposes one
- Check c.phishlets[site].ParentName before calling, and skip base phishlets
- Verify the site name refers to the child phishlet, not its parent
Example fix
// before
cfg.DeleteSubPhishlet("linkedin")
// after
pl, _ := cfg.GetPhishlet("linkedin")
if pl.ParentName != "" {
cfg.DeleteSubPhishlet("linkedin")
} Defensive patterns
Strategy: validation
Validate before calling
func canDeleteSub(cfg *core.Config, site string) bool {
pl, err := cfg.GetPhishlet(site)
return err == nil && pl != nil && pl.ParentName != ""
} Try / catch
if err := cfg.DeleteSubPhishlet(site); err != nil {
log.Printf("skip %s: %v", site, err)
} Prevention
- Check ParentName before deleting
- Enumerate only child phishlets when bulk-deleting
- Confirm the exact child phishlet name
When it happens
Trigger: Calling cfg.DeleteSubPhishlet(site) with the name of a standalone/base phishlet (one created directly, not via CreateSubPhishlet), so pl.ParentName == "".
Common situations: Developers managing evilginx-style phishlet trees iterate over all phishlet names and call DeleteSubPhishlet on each, hitting the base phishlets; or they pass a typo'd name that resolves to a base phishlet instead of the intended child.
Related errors
- phishlet '%s' not found
- index out of bounds: %d
- lure for path '%s' not found
- auth_tokens: 'search' not found for body auth token
- auth_tokens: 'domain' not found for http auth token
AI-assisted analysis of kgretzky/evilginx2@4c0988a1d9 (2026-09-05).
Data as JSON: /api/errors/4f006ea6e4426dd5.
Report an issue: GitHub.