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:
@@ -16,7 +16,7 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
const version = "0.1.0"
|
const version = "0.1.1"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := &cli.Command{
|
app := &cli.Command{
|
||||||
|
|||||||
@@ -25,6 +25,15 @@ type Client struct {
|
|||||||
|
|
||||||
// Connect establishes a connection to NATS using NKey authentication.
|
// Connect establishes a connection to NATS using NKey authentication.
|
||||||
func Connect(cfg Config) (*Client, error) {
|
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)
|
seed, err := os.ReadFile(cfg.NKeyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to read nkey file: %w", err)
|
return nil, fmt.Errorf("failed to read nkey file: %w", err)
|
||||||
|
|||||||
@@ -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) {
|
func TestConnect_InvalidNKeySeed(t *testing.T) {
|
||||||
// Create a temp file with invalid content
|
// Create a temp file with invalid content
|
||||||
tmpDir := t.TempDir()
|
tmpDir := t.TempDir()
|
||||||
|
|||||||
Reference in New Issue
Block a user