kgretzky/evilginx2 · error

failed to list certificates in directory '%s': %v

Error message

failed to list certificates in directory '%s': %v

What it means

setUnmanagedSync scans the 'sites' subdirectory of the certificate cache to discover per-site certificate directories, and throws this when os.ReadDir on that directory fails. This typically means the cache directory structure is missing or unreadable, so unmanaged certificate synchronization cannot proceed.

Source

Thrown at core/certdb.go:177

	if err != nil {
		return err
	}
	return nil
}

func (o *CertDb) setManagedSync(hosts []string, t time.Duration) error {
	ctx, cancel := context.WithTimeout(context.Background(), t)
	err := o.magic.ManageSync(ctx, hosts)
	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())) {

View on GitHub (pinned to 4c0988a1d9)

Solutions

  1. Ensure the cache_dir and its sites/ subdirectory exist and are readable (mkdir -p, chmod)
  2. Fix cache_dir configuration to point to the correct directory
  3. Check volume is mounted and writable by the process user
  4. Reinitialize the cache directory and let the tool recreate the structure

Example fix

// before
-o c2.domain cache_dir=/mnt/missing/certs
// after
mkdir -p /var/lib/evilginx/cache/sites && chmod 700 /var/lib/evilginx/cache
# then start with cache_dir=/var/lib/evilginx/cache
Defensive patterns

Strategy: validation

Validate before calling

sitesDir := filepath.Join(cacheDir, "sites")
if st, err := os.Stat(sitesDir); err != nil || !st.IsDir() {
    os.MkdirAll(sitesDir, 0700)
}

Try / catch

if err := db.setUnmanagedSync(true); err != nil {
    if strings.HasPrefix(err.Error(), "failed to list certificates in directory") {
        os.MkdirAll(filepath.Join(cacheDir, "sites"), 0700)
        err = db.setUnmanagedSync(true)
    }
    if err != nil { log.Fatal(err) }
}

Prevention

When it happens

Trigger: os.ReadDir(sitesDir) returns an error: cache_dir/sites was deleted, cache_dir points to a nonexistent path, wrong permissions on the directory, or cache_dir configured to a file rather than a directory.

Common situations: First run with a wiped cache before directory creation; cache_dir on a read-only or unmounted volume; running as a different user after generating certs as root (permission denied); typo in cache_dir configuration.

Understand the failure class

Related errors


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