fix: verify NKey file has secure permissions before reading

Reject NKey files that are readable by group or others (permissions
more permissive than 0600). This prevents accidental exposure of
private keys through overly permissive file permissions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-07 04:40:53 +01:00
parent 95fbfb2339
commit f51058964d
3 changed files with 33 additions and 1 deletions

View File

@@ -25,6 +25,15 @@ type Client struct {
// Connect establishes a connection to NATS using NKey authentication.
func Connect(cfg Config) (*Client, error) {
// Verify NKey file has secure permissions (no group/other access)
info, err := os.Stat(cfg.NKeyFile)
if err != nil {
return nil, fmt.Errorf("failed to stat nkey file: %w", err)
}
if perm := info.Mode().Perm(); perm&0o077 != 0 {
return nil, fmt.Errorf("nkey file has insecure permissions %04o: must not be accessible by group or others", perm)
}
seed, err := os.ReadFile(cfg.NKeyFile)
if err != nil {
return nil, fmt.Errorf("failed to read nkey file: %w", err)

View File

@@ -21,6 +21,29 @@ func TestConnect_InvalidNKeyFile(t *testing.T) {
}
}
func TestConnect_InsecureNKeyFilePermissions(t *testing.T) {
// Create a temp file with insecure permissions
tmpDir := t.TempDir()
keyFile := filepath.Join(tmpDir, "insecure.nkey")
if err := os.WriteFile(keyFile, []byte("test-content"), 0644); err != nil {
t.Fatalf("failed to write temp file: %v", err)
}
cfg := Config{
URL: "nats://localhost:4222",
NKeyFile: keyFile,
Name: "test",
}
_, err := Connect(cfg)
if err == nil {
t.Error("expected error for insecure nkey file permissions")
}
if err != nil && !contains(err.Error(), "insecure permissions") {
t.Errorf("expected insecure permissions error, got: %v", err)
}
}
func TestConnect_InvalidNKeySeed(t *testing.T) {
// Create a temp file with invalid content
tmpDir := t.TempDir()