diff options
| author | James O'Doherty <james@theodohertyfamily.com> | 2026-06-07 21:51:48 -0400 |
|---|---|---|
| committer | James O'Doherty <james@theodohertyfamily.com> | 2026-06-07 21:51:48 -0400 |
| commit | 7010768877c227c9410a06908e4cb3e54db403bd (patch) | |
| tree | 317512603d9358b272240d53ea4b09b1b81eacd3 | |
| parent | 184deac4efe2062db6ecd2285ec8db1e919f9441 (diff) | |
security: restrict permissions of imported WireGuard profiles to 0600
WireGuard profile files contain sensitive private keys. Previously, these files were written with 0644 permissions, making them world-readable. This commit changes the file mode to 0600 to ensure only the owner can read and write the profiles.
- Updated `handleProfileImport` to use 0600 permissions.
- Added tests to verify that imported profiles have the correct permissions.
| -rw-r--r-- | internal/cli/cli.go | 2 | ||||
| -rw-r--r-- | internal/cli/profile_test.go | 17 |
2 files changed, 17 insertions, 2 deletions
diff --git a/internal/cli/cli.go b/internal/cli/cli.go index a4b9a9a..d100d4f 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -324,7 +324,7 @@ func (a *App) handleProfileImport(srcPath string, name string) error { return fmt.Errorf("failed to read source file: %w", err) } - if err := os.WriteFile(destPath, data, 0644); err != nil { + if err := os.WriteFile(destPath, data, 0600); err != nil { return fmt.Errorf("failed to write profile to %s: %w", destPath, err) } diff --git a/internal/cli/profile_test.go b/internal/cli/profile_test.go index e08ffc5..d373e95 100644 --- a/internal/cli/profile_test.go +++ b/internal/cli/profile_test.go @@ -50,11 +50,19 @@ func TestProfileImport(t *testing.T) { t.Errorf("expected no error, got %v", err) } - // Verify the file was actually copied to derived name + // Verify the file was actually copied to derived name and has correct permissions destFile := filepath.Join(profilesDir, "source.conf") if _, err := os.Stat(destFile); os.IsNotExist(err) { t.Errorf("expected profile to be imported to %s", destFile) } + var info os.FileInfo + info, err = os.Stat(destFile) + if err != nil { + t.Fatalf("failed to stat imported profile: %v", err) + } + if info.Mode().Perm() != 0600 { + t.Errorf("expected imported profile to have permissions 0600, got %o", info.Mode().Perm()) + } // 2. Test importing with explicit name argument customName := "custom-vpn" @@ -70,6 +78,13 @@ func TestProfileImport(t *testing.T) { if _, err := os.Stat(destCustomFile); os.IsNotExist(err) { t.Errorf("expected profile to be imported to %s", destCustomFile) } + info, err = os.Stat(destCustomFile) + if err != nil { + t.Fatalf("failed to stat imported profile: %v", err) + } + if info.Mode().Perm() != 0600 { + t.Errorf("expected imported profile to have permissions 0600, got %o", info.Mode().Perm()) + } // 3. Test duplicate import (should fail) appDup := NewApp([]string{"wg-wrap", "profile", "import", srcFile, customName}) |
