getsops/sops · error

GNUPGHOME has invalid permissions: got %#o wanted %#o

Error message

GNUPGHOME has invalid permissions: got %#o wanted %#o

What it means

GnuPGHome.Validate() enforces that the GNUPGHOME directory has exactly permission bits 0700 (owner read/write/execute, no group/other access). If the mode differs, it returns this error with the got/wanted octal values. gpg itself refuses to operate on a permissive home directory, so sops rejects it up front.

Source

Thrown at pgp/keysource.go:209

func (d GnuPGHome) Validate() error {
	if d == "" {
		return fmt.Errorf("empty GNUPGHOME path")
	}
	if !filepath.IsAbs(d.String()) {
		return fmt.Errorf("GNUPGHOME must be an absolute path")
	}
	fi, err := os.Lstat(d.String())
	if err != nil {
		if os.IsNotExist(err) {
			return fmt.Errorf("GNUPGHOME does not exist")
		}
		return fmt.Errorf("cannot stat GNUPGHOME: %w", err)
	}
	if !fi.IsDir() {
		return fmt.Errorf("GNUGPHOME is not a directory")
	}
	if perm := fi.Mode().Perm(); perm != 0o700 {
		return fmt.Errorf("GNUPGHOME has invalid permissions: got %#o wanted %#o", perm, 0o700)
	}
	return nil
}

// String returns the GnuPGHome as a string. It does not Validate.
func (d GnuPGHome) String() string {
	return string(d)
}

// ApplyToMasterKey configures the GnuPGHome on the provided key if it passes
// Validate.
func (d GnuPGHome) ApplyToMasterKey(key *MasterKey) {
	if err := d.Validate(); err == nil {
		key.gnuPGHomeDir = d.String()
	}
}

// DisableOpenPGP disables encrypt and decrypt operations using OpenPGP.

View on GitHub (pinned to 13442bb981)

Solutions

  1. chmod 700 on the directory: chmod 700 "$GNUPGHOME"
  2. Recreate the directory with strict perms: rm -rf and mkdir -p + chmod 700
  3. In CI, avoid mounting GNUPGHOME from a volume that forces group/other bits; copy into a fresh 0700 dir instead
  4. Call pgp.GnuPGHome(path).Validate() before use and surface the got/wanted message to the operator

Example fix

// before
os.MkdirAll(gnupgHome, 0o755)
// after
os.MkdirAll(gnupgHome, 0o700) // and chmod 700 if it pre-existed with lax perms
Defensive patterns

Strategy: validation

Validate before calling

if err := pgp.GnuPGHome(path).Validate(); err != nil {
    // message includes got/wanted octal perms; surface it
    log.Fatal(err)
}
// proactively repair:
if fi, err := os.Stat(path); err == nil && fi.IsDir() && fi.Mode().Perm() != 0o700 {
    os.Chmod(path, 0o700)
}

Type guard

func hasSafeGnuPGPerms(h pgp.GnuPGHome) bool {
    fi, err := os.Stat(string(h))
    return err == nil && fi.IsDir() && fi.Mode().Perm() == 0o700
}

Prevention

When it happens

Trigger: ImportContext, Cleanup, or ApplyToMasterKey on a GnuPGHome whose directory mode is anything other than 0700 (e.g. 0755 after mkdir without chmod, or 0777 from a shared/tmpfs location).

Common situations: Created the directory with umask 022 leaving 0755; copied a home dir with cp preserving lax perms; running on Windows/CI mounts where perms translate oddly; group-shared GNUPGHOME.

Related errors


AI-assisted analysis of getsops/sops@13442bb981 (2026-09-01). Data as JSON: /api/errors/0f047a0f5cb3b591. Report an issue: GitHub.