kgretzky/evilginx2 · error

failed to list certificate directory '%s': %v

Error message

failed to list certificate directory '%s': %v

What it means

setUnmanagedSync throws this when os.ReadDir fails on an individual per-site certificate directory inside cache_dir/sites. The parent sites/ directory was readable, but at least one site subdirectory could not be listed, aborting the whole sync loop.

Source

Thrown at core/certdb.go:186

	cancel()
	return err
}

func (o *CertDb) setUnmanagedSync(verbose bool) error {
	sitesDir := filepath.Join(o.cache_dir, "sites")

	files, err := os.ReadDir(sitesDir)
	if err != nil {
		return fmt.Errorf("failed to list certificates in directory '%s': %v", sitesDir, err)
	}

	for _, f := range files {
		if f.IsDir() {
			certDir := filepath.Join(sitesDir, f.Name())

			certFiles, err := os.ReadDir(certDir)
			if err != nil {
				return fmt.Errorf("failed to list certificate directory '%s': %v", certDir, err)
			}

			var certPath, keyPath string

			var pemCnt, crtCnt, keyCnt int
			for _, cf := range certFiles {
				//log.Debug("%s", cf.Name())
				if !cf.IsDir() {
					switch strings.ToLower(filepath.Ext(cf.Name())) {
					case ".pem":
						pemCnt += 1
						if certPath == "" {
							certPath = filepath.Join(certDir, cf.Name())
						}
						if cf.Name() == "fullchain.pem" {
							certPath = filepath.Join(certDir, cf.Name())
						}
						if cf.Name() == "privkey.pem" {

View on GitHub (pinned to 4c0988a1d9)

Solutions

  1. Fix ownership/permissions on the offending site directory (chown -R / chmod u+rx)
  2. Remove stale or broken site directories from sites/ so the scan can complete
  3. Run the tool as the user that owns the cache
  4. Recreate the sites directory structure and re-sync certificates

Example fix

// before
ls -l ~/.evilginx/cache/sites/  # drwx------ root root mysite
// after
sudo chown -R $USER ~/.evilginx/cache/sites && chmod -R u+rwX ~/.evilginx/cache/sites
Defensive patterns

Strategy: validation

Validate before calling

sitesDir := filepath.Join(cacheDir, "sites")
entries, err := os.ReadDir(sitesDir)
if err == nil {
    for _, e := range entries {
        if e.IsDir() {
            if _, err := os.ReadDir(filepath.Join(sitesDir, e.Name())); err != nil {
                log.Printf("unreadable site dir %s: %v — fix before sync", e.Name(), err)
            }
        }
    }
}

Try / catch

if err := db.setUnmanagedSync(true); err != nil {
    if strings.HasPrefix(err.Error(), "failed to list certificate directory") {
        // extract dir from message, chown/chmod or delete the stale dir, retry
        log.Printf("fix permissions on the named site dir, then retry: %v", err)
    }
}

Prevention

When it happens

Trigger: A site directory exists in sites/ but ReadDir fails on it: permission mismatch (dir created as root, process runs as another user), the entry is a broken symlink to a directory, or the directory was removed concurrently mid-iteration.

Common situations: Mixed-permission caches after running the tool with sudo once; cleanup scripts partially deleting site dirs; stale site folders left after cache migration; NFS/network filesystem hiccups.

Understand the failure class

Related errors


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