{"record":{"id":"269574997cd2cffd","repo":"getsops/sops","slug":"empty-gnupghome-path","errorCode":null,"errorMessage":"empty GNUPGHOME path","messagePattern":"empty GNUPGHOME path","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pgp/keysource.go","lineNumber":193,"sourceCode":"\t}\n\treturn d.Import(b)\n}\n\n// Cleanup deletes the GnuPGHome if it passes Validate.\n// It returns an error if the GnuPGHome does not pass Validate, or if the\n// removal failed.\nfunc (d GnuPGHome) Cleanup() error {\n\tif err := d.Validate(); err != nil {\n\t\treturn err\n\t}\n\treturn os.RemoveAll(d.String())\n}\n\n// Validate ensures the GnuPGHome is a valid GnuPG home directory path.\n// When validation fails, it returns a descriptive reason as error.\nfunc (d GnuPGHome) Validate() error {\n\tif d == \"\" {\n\t\treturn fmt.Errorf(\"empty GNUPGHOME path\")\n\t}\n\tif !filepath.IsAbs(d.String()) {\n\t\treturn fmt.Errorf(\"GNUPGHOME must be an absolute path\")\n\t}\n\tfi, err := os.Lstat(d.String())\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn fmt.Errorf(\"GNUPGHOME does not exist\")\n\t\t}\n\t\treturn fmt.Errorf(\"cannot stat GNUPGHOME: %w\", err)\n\t}\n\tif !fi.IsDir() {\n\t\treturn fmt.Errorf(\"GNUGPHOME is not a directory\")\n\t}\n\tif perm := fi.Mode().Perm(); perm != 0o700 {\n\t\treturn fmt.Errorf(\"GNUPGHOME has invalid permissions: got %#o wanted %#o\", perm, 0o700)\n\t}\n\treturn nil","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/getsops/sops/blob/13442bb98183887d7a9ac09ec8ab0564673a59d8/pgp/keysource.go#L175-L211","documentation":"GnuPGHome.Validate rejects a zero-length home path with this message. ImportContext, Cleanup, and ApplyToMasterKey all call Validate first, so any use of an empty GnuPGHome (e.g. the zero value of the string type) is blocked with this descriptive error rather than passed to gpg.","triggerScenarios":"Declaring `var d pgp.GnuPGHome` without initializing, a failed NewGnuPGHome whose error was ignored leaving \"\", or code paths that blank out the field.","commonSituations":"Ignoring the error from NewGnuPGHome and using the returned zero value; struct literal pgp.GnuPGHome{} in tests; accidental reset of the field during copy.","solutions":["Initialize the home with pgp.NewGnuPGHome() and check the returned error before use.","If you keep the error from NewGnuPGHome, return early instead of using the zero value.","Add a Validate() call before Import/Cleanup in your own code to fail fast with clear context."],"exampleFix":"// before\nhome, _ := pgp.NewGnuPGHome() // error ignored -> home == \"\"\nhome.Import(key)\n// after\nhome, err := pgp.NewGnuPGHome()\nif err != nil { return err }\nif err := home.Validate(); err != nil { return err }","handlingStrategy":"validation","validationCode":"// Go\nfunc ensureHome(home pgp.GnuPGHome) error {\n  if home == \"\" { return errors.New(\"GnuPGHome not initialized: call pgp.NewGnuPGHome()\") }\n  return home.Validate()\n}","typeGuard":"func initialized(home pgp.GnuPGHome) bool { return home != \"\" }","tryCatchPattern":"// Go\nif err := home.Validate(); err != nil && strings.Contains(err.Error(), \"empty GNUPGHOME path\") {\n  return fmt.Errorf(\"GnuPGHome was never initialized: %w\", err)\n}","preventionTips":["Never ignore the error return of pgp.NewGnuPGHome()","Run Validate() immediately after obtaining a home to fail fast","In tests, use constructor helpers rather than struct literals"],"tags":["gnupg","pgp","validation"],"backgroundTag":"empty-path-validation","analyzedSha":"13442bb98183887d7a9ac09ec8ab0564673a59d8","analyzedAt":"2026-09-01T03:53:00.447Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}