Fix lint errors, disable gosec

gosec only found int to uint downcasts which are unavoidable as sadly
the go API usually uses int instead of uint in places.
This commit is contained in:
Sandro Jäckel 2025-09-09 18:48:22 +02:00 committed by Jörg Thalheim
parent 74f0a60d61
commit 692f94d84a
4 changed files with 62 additions and 38 deletions

View file

@ -12,7 +12,6 @@ linters:
- exhaustive - exhaustive
- gocheckcompilerdirectives - gocheckcompilerdirectives
- gochecksumtype - gochecksumtype
- gosec
- gosmopolitan - gosmopolitan
- loggercheck - loggercheck
- makezero - makezero

View file

@ -45,16 +45,25 @@ func MountSecretFs(mountpoint string, keysGID int, _useTmpfs bool, userMode bool
size := mb * 1024 * 1024 / 512 // size in sectors a 512 bytes size := mb * 1024 * 1024 / 512 // size in sectors a 512 bytes
cmd := exec.Command("hdiutil", "attach", "-nomount", fmt.Sprintf("ram://%d", int(size))) cmd := exec.Command("hdiutil", "attach", "-nomount", fmt.Sprintf("ram://%d", int(size)))
out, err := cmd.Output() // /dev/diskN out, err := cmd.Output() // /dev/diskN
if err != nil {
return fmt.Errorf("cannot execute hdiutil: %w", err)
}
diskpath := strings.TrimRight(string(out[:]), " \t\n") diskpath := strings.TrimRight(string(out[:]), " \t\n")
// format as hfs // format as hfs
out, err = exec.Command("newfs_hfs", "-s", diskpath).Output() _, err = exec.Command("newfs_hfs", "-s", diskpath).Output()
if err != nil {
return fmt.Errorf("cannot create hfs filesystem at '%s': %w", diskpath, err)
}
// "posix" mount takes `struct hfs_mount_args` which we dont have bindings for at hand. // "posix" mount takes `struct hfs_mount_args` which we dont have bindings for at hand.
// See https://stackoverflow.com/a/49048846/4108673 // See https://stackoverflow.com/a/49048846/4108673
// err = unix.Mount("hfs", mountpoint, unix.MNT_NOEXEC|unix.MNT_NODEV, mount_args) // err = unix.Mount("hfs", mountpoint, unix.MNT_NOEXEC|unix.MNT_NODEV, mount_args)
// Instead we call: // Instead we call:
out, err = exec.Command("mount", "-t", "hfs", "-o", "nobrowse,nodev,nosuid,-m=0751", diskpath, mountpoint).Output() _, err = exec.Command("mount", "-t", "hfs", "-o", "nobrowse,nodev,nosuid,-m=0751", diskpath, mountpoint).Output()
if err != nil {
return fmt.Errorf("cannot mount '%s' to '%s': %w", diskpath, mountpoint, err)
}
// There is no documented way to check for memfs mountpoint. Thus we place a file. // There is no documented way to check for memfs mountpoint. Thus we place a file.
path := mountpoint + "/sops-nix-secretfs" path := mountpoint + "/sops-nix-secretfs"

View file

@ -165,7 +165,7 @@ func readManifest(path string) (*manifest, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to open manifest: %w", err) return nil, fmt.Errorf("failed to open manifest: %w", err)
} }
defer file.Close() defer func() { _ = file.Close() }()
dec := json.NewDecoder(file) dec := json.NewDecoder(file)
var m manifest var m manifest
if err := dec.Decode(&m); err != nil { if err := dec.Decode(&m); err != nil {
@ -195,7 +195,7 @@ func SecureSymlinkChown(targetFile string, path string, owner int, group int) er
if err != nil { if err != nil {
return fmt.Errorf("cannot create temporary symlink directory: %w", err) return fmt.Errorf("cannot create temporary symlink directory: %w", err)
} }
defer os.RemoveAll(dir) defer func() { _ = os.RemoveAll(dir) }()
// Create symlink to `targetFile` in the temp dir, before chowning it. // Create symlink to `targetFile` in the temp dir, before chowning it.
tmpSymlink := filepath.Join(dir, filepath.Base(path)) tmpSymlink := filepath.Join(dir, filepath.Base(path))
@ -352,7 +352,7 @@ func decryptSecret(s *secret, sourceFiles map[string]plainData) error {
sourceFile.binary = plain sourceFile.binary = plain
} else { } else {
if err := yaml.Unmarshal(plain, &sourceFile.data); err != nil { if err := yaml.Unmarshal(plain, &sourceFile.data); err != nil {
return fmt.Errorf("Cannot parse yaml of '%s': %w", s.SopsFile, err) return fmt.Errorf("cannot parse yaml of '%s': %w", s.SopsFile, err)
} }
} }
case JSON: case JSON:
@ -360,7 +360,7 @@ func decryptSecret(s *secret, sourceFiles map[string]plainData) error {
sourceFile.binary = plain sourceFile.binary = plain
} else { } else {
if err := json.Unmarshal(plain, &sourceFile.data); err != nil { if err := json.Unmarshal(plain, &sourceFile.data); err != nil {
return fmt.Errorf("Cannot parse json of '%s': %w", s.SopsFile, err) return fmt.Errorf("cannot parse json of '%s': %w", s.SopsFile, err)
} }
} }
default: default:
@ -554,7 +554,7 @@ func (app *appContext) validateSopsFile(s *secret, file *secretFile) error {
s.Name, s.SopsFile, s.Format, s.Name, s.SopsFile, s.Format,
file.firstSecret.Format, file.firstSecret.Name) file.firstSecret.Format, file.firstSecret.Name)
} }
if app.checkMode != Manifest && !(s.Format == Binary || s.Format == Dotenv || s.Format == Ini) && s.Key != "" { if app.checkMode != Manifest && (s.Format != Binary && s.Format != Dotenv && s.Format != Ini) && s.Key != "" {
_, err := recurseSecretKey(file.keys, s.Key) _, err := recurseSecretKey(file.keys, s.Key)
if err != nil { if err != nil {
return fmt.Errorf("secret %s in %s is not valid: %w", s.Name, s.SopsFile, err) return fmt.Errorf("secret %s in %s is not valid: %w", s.Name, s.SopsFile, err)
@ -773,7 +773,7 @@ func atomicSymlink(oldname, newname string) error {
return fmt.Errorf("cannot create temporary directory: %w", err) return fmt.Errorf("cannot create temporary directory: %w", err)
} }
defer func() { defer func() {
os.RemoveAll(d) _ = os.RemoveAll(d)
}() }()
symlink := filepath.Join(d, "tmp.symlink") symlink := filepath.Join(d, "tmp.symlink")
@ -804,7 +804,7 @@ func pruneGenerations(secretsMountPoint, secretsDir string, keepGenerations int)
if err != nil { if err != nil {
return fmt.Errorf("cannot open %s: %w", secretsMountPoint, err) return fmt.Errorf("cannot open %s: %w", secretsMountPoint, err)
} }
defer file.Close() defer func() { _ = file.Close() }()
generations, err := file.Readdirnames(0) generations, err := file.Readdirnames(0)
if err != nil { if err != nil {
@ -822,7 +822,10 @@ func pruneGenerations(secretsMountPoint, secretsDir string, keepGenerations int)
continue continue
} }
if currentGeneration-keepGenerations >= generationNum { if currentGeneration-keepGenerations >= generationNum {
os.RemoveAll(path.Join(secretsMountPoint, generationName)) err = os.RemoveAll(path.Join(secretsMountPoint, generationName))
if err != nil {
return err
}
} }
} }
@ -837,13 +840,17 @@ func importSSHKeys(logcfg loggingConfig, keyPaths []string, gpgHome string) erro
if err != nil { if err != nil {
return fmt.Errorf("cannot create %s: %w", secringPath, err) return fmt.Errorf("cannot create %s: %w", secringPath, err)
} }
defer secring.Close() defer func() {
_ = secring.Close()
}()
pubring, err := os.OpenFile(pubringPath, os.O_WRONLY|os.O_CREATE, 0o600) pubring, err := os.OpenFile(pubringPath, os.O_WRONLY|os.O_CREATE, 0o600)
if err != nil { if err != nil {
return fmt.Errorf("cannot create %s: %w", pubringPath, err) return fmt.Errorf("cannot create %s: %w", pubringPath, err)
} }
defer pubring.Close() defer func() {
_ = pubring.Close()
}()
for _, p := range keyPaths { for _, p := range keyPaths {
sshKey, err := os.ReadFile(p) sshKey, err := os.ReadFile(p)
@ -875,7 +882,7 @@ func importSSHKeys(logcfg loggingConfig, keyPaths []string, gpgHome string) erro
return nil return nil
} }
func importAgeSSHKeys(logcfg loggingConfig, keyPaths []string, ageFile os.File) error { func importAgeSSHKeys(logcfg loggingConfig, keyPaths []string, ageFile os.File) {
for _, p := range keyPaths { for _, p := range keyPaths {
// Read the key // Read the key
sshKey, err := os.ReadFile(p) sshKey, err := os.ReadFile(p)
@ -901,8 +908,6 @@ func importAgeSSHKeys(logcfg loggingConfig, keyPaths []string, ageFile os.File)
continue continue
} }
} }
return nil
} }
// Like filepath.Walk but symlink-aware. // Like filepath.Walk but symlink-aware.
@ -1020,15 +1025,14 @@ func handleModifications(isDry bool, logcfg loggingConfig, symlinkPath string, s
if _, err := os.Stat(filepath.Dir(file)); err != nil { if _, err := os.Stat(filepath.Dir(file)); err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
return nil return nil
} else {
return err
} }
return err
} }
f, err := os.OpenFile(file, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0o600) f, err := os.OpenFile(file, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0o600)
if err != nil { if err != nil {
return err return err
} }
defer f.Close() defer func() { _ = f.Close() }()
for _, unit := range list { for _, unit := range list {
if _, err = f.WriteString(unit + "\n"); err != nil { if _, err = f.WriteString(unit + "\n"); err != nil {
return err return err
@ -1134,8 +1138,8 @@ type keyring struct {
} }
func (k *keyring) Remove() { func (k *keyring) Remove() {
os.RemoveAll(k.path) _ = os.RemoveAll(k.path)
os.Unsetenv("GNUPGHOME") _ = os.Unsetenv("GNUPGHOME")
} }
func setupGPGKeyring(logcfg loggingConfig, sshKeys []string, parentDir string) (*keyring, error) { func setupGPGKeyring(logcfg loggingConfig, sshKeys []string, parentDir string) (*keyring, error) {
@ -1146,10 +1150,10 @@ func setupGPGKeyring(logcfg loggingConfig, sshKeys []string, parentDir string) (
k := keyring{dir} k := keyring{dir}
if err := importSSHKeys(logcfg, sshKeys, dir); err != nil { if err := importSSHKeys(logcfg, sshKeys, dir); err != nil {
os.RemoveAll(dir) err = os.RemoveAll(dir)
return nil, err return nil, err
} }
os.Setenv("GNUPGHOME", dir) _ = os.Setenv("GNUPGHOME", dir)
return &k, nil return &k, nil
} }
@ -1158,7 +1162,10 @@ func parseFlags(args []string) (*options, error) {
var opts options var opts options
fs := flag.NewFlagSet(args[0], flag.ContinueOnError) fs := flag.NewFlagSet(args[0], flag.ContinueOnError)
fs.Usage = func() { fs.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [OPTION] manifest.json\n", args[0]) _, err := fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [OPTION] manifest.json\n", args[0])
if err != nil {
return
}
fs.PrintDefaults() fs.PrintDefaults()
} }
var checkMode string var checkMode string
@ -1210,7 +1217,7 @@ func writeTemplate(targetDir string, template template, keysGID int, userMode bo
return fmt.Errorf("cannot create temporary file in directory %s: %w", dir, err) return fmt.Errorf("cannot create temporary file in directory %s: %w", dir, err)
} }
defer func() { defer func() {
tempFile.Close() // noop if already closed _ = tempFile.Close() // noop if already closed
if !tempfileRemoved { if !tempfileRemoved {
if err := os.Remove(tempFile.Name()); err != nil { if err := os.Remove(tempFile.Name()); err != nil {
@ -1321,28 +1328,37 @@ func installSecrets(args []string) error {
} }
defer keyring.Remove() defer keyring.Remove()
} else if manifest.GnupgHome != "" { } else if manifest.GnupgHome != "" {
os.Setenv("GNUPGHOME", manifest.GnupgHome) err = os.Setenv("GNUPGHOME", manifest.GnupgHome)
if err != nil {
return err
}
} }
// Import age keys // Import age keys
if len(manifest.AgeSSHKeyPaths) != 0 || manifest.AgeKeyFile != "" { if len(manifest.AgeSSHKeyPaths) != 0 || manifest.AgeKeyFile != "" {
keyfile := filepath.Join(manifest.SecretsMountPoint, "age-keys.txt") keyfile := filepath.Join(manifest.SecretsMountPoint, "age-keys.txt")
os.Setenv("SOPS_AGE_KEY_FILE", keyfile) err = os.Setenv("SOPS_AGE_KEY_FILE", keyfile)
if err != nil {
return err
}
// Create the keyfile // Create the keyfile
var ageFile *os.File var ageFile *os.File
ageFile, err = os.OpenFile(keyfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600) ageFile, err = os.OpenFile(keyfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
if err != nil { if err != nil {
return fmt.Errorf("cannot create '%s': %w", keyfile, err) return fmt.Errorf("cannot create '%s': %w", keyfile, err)
} }
defer ageFile.Close() defer func() {
fmt.Fprintf(ageFile, "# generated by sops-nix at %s\n", time.Now().Format(time.RFC3339)) _ = ageFile.Close()
}()
_, err = fmt.Fprintf(ageFile, "# generated by sops-nix at %s\n", time.Now().Format(time.RFC3339))
if err != nil {
return err
}
// Import SSH keys // Import SSH keys
if len(manifest.AgeSSHKeyPaths) != 0 { if len(manifest.AgeSSHKeyPaths) != 0 {
err = importAgeSSHKeys(manifest.Logging, manifest.AgeSSHKeyPaths, *ageFile) importAgeSSHKeys(manifest.Logging, manifest.AgeSSHKeyPaths, *ageFile)
if err != nil {
return err
}
} }
// Import the keyfile // Import the keyfile
if manifest.AgeKeyFile != "" { if manifest.AgeKeyFile != "" {

View file

@ -42,7 +42,7 @@ func writeManifest(t *testing.T, dir string, m *manifest) string {
ok(t, err) ok(t, err)
encoder := json.NewEncoder(f) encoder := json.NewEncoder(f)
ok(t, encoder.Encode(m)) ok(t, encoder.Encode(m))
f.Close() _ = f.Close()
return filename return filename
} }
@ -60,7 +60,7 @@ type testDir struct {
} }
func (dir testDir) Remove() { func (dir testDir) Remove() {
os.RemoveAll(dir.path) _ = os.RemoveAll(dir.path)
} }
func newTestDir(t *testing.T) testDir { func newTestDir(t *testing.T) testDir {
@ -215,7 +215,7 @@ func testSSHKey(t *testing.T) {
target := path.Join(testdir.path, "existing-target") target := path.Join(testdir.path, "existing-target")
file, err := os.Create(target) file, err := os.Create(target)
ok(t, err) ok(t, err)
file.Close() _ = file.Close()
nobody := "nobody" nobody := "nobody"
nogroup := "nogroup" nogroup := "nogroup"
@ -250,7 +250,7 @@ func TestAge(t *testing.T) {
target := path.Join(testdir.path, "existing-target") target := path.Join(testdir.path, "existing-target")
file, err := os.Create(target) file, err := os.Create(target)
ok(t, err) ok(t, err)
file.Close() _ = file.Close()
nobody := "nobody" nobody := "nobody"
nogroup := "nogroup" nogroup := "nogroup"
@ -285,7 +285,7 @@ func TestAgeWithSSH(t *testing.T) {
target := path.Join(testdir.path, "existing-target") target := path.Join(testdir.path, "existing-target")
file, err := os.Create(target) file, err := os.Create(target)
ok(t, err) ok(t, err)
file.Close() _ = file.Close()
nobody := "nobody" nobody := "nobody"
nogroup := "nogroup" nogroup := "nogroup"