Skip to content

Commit 3d511ab

Browse files
committed
Automatically tighten the data directory permissions and create new configs with secure defaults to keep upgrades painless.
1 parent 2312829 commit 3d511ab

File tree

4 files changed

+42
-14
lines changed

4 files changed

+42
-14
lines changed

internal/config/loader.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func LoadFromFile(configPath string) (*Config, error) {
3939
}
4040

4141
// Create data directory if it doesn't exist
42-
if err := os.MkdirAll(cfg.DataDir, 0755); err != nil {
42+
if err := os.MkdirAll(cfg.DataDir, 0700); err != nil {
4343
return nil, fmt.Errorf("failed to create data directory %s: %w", cfg.DataDir, err)
4444
}
4545

@@ -91,7 +91,7 @@ func Load() (*Config, error) {
9191
}
9292

9393
// Create data directory if it doesn't exist
94-
if err := os.MkdirAll(cfg.DataDir, 0755); err != nil {
94+
if err := os.MkdirAll(cfg.DataDir, 0700); err != nil {
9595
return nil, fmt.Errorf("failed to create data directory %s: %w", cfg.DataDir, err)
9696
}
9797

@@ -124,7 +124,7 @@ func Load() (*Config, error) {
124124
}
125125

126126
// Create data directory if it doesn't exist
127-
if err := os.MkdirAll(cfg.DataDir, 0755); err != nil {
127+
if err := os.MkdirAll(cfg.DataDir, 0700); err != nil {
128128
return nil, fmt.Errorf("failed to create data directory %s: %w", cfg.DataDir, err)
129129
}
130130

@@ -350,7 +350,7 @@ func SaveConfig(cfg *Config, path string) error {
350350

351351
// Ensure directory exists
352352
dir := filepath.Dir(path)
353-
if err := os.MkdirAll(dir, 0755); err != nil {
353+
if err := os.MkdirAll(dir, 0700); err != nil {
354354
fmt.Printf("[DEBUG] SaveConfig - MkdirAll failed: %v\n", err)
355355
return fmt.Errorf("failed to create config directory: %w", err)
356356
}

internal/runtime/apply_config_restart_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ func TestApplyConfig_SaveFailure(t *testing.T) {
138138
err = os.Chmod(tmpDir, 0555)
139139
require.NoError(t, err)
140140
defer func() {
141-
_ = os.Chmod(tmpDir, 0755)
141+
_ = os.Chmod(tmpDir, 0700)
142142
}()
143143

144144
// Create new config

internal/server/listener_permissions_unix.go

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,38 @@ func validateDataDirectoryPermissionsPlatform(dataDir string, info os.FileInfo,
2626
// Unix: Check permissions are secure (0700 or stricter)
2727
perm := info.Mode().Perm()
2828
if perm&0077 != 0 {
29-
return fmt.Errorf(
30-
"data directory has insecure permissions %#o, must be 0700 or stricter\n"+
31-
"Security risk: Other users can access mcpproxy data and control socket\n"+
32-
"To fix, run: chmod 0700 %s",
33-
perm, dataDir,
34-
)
29+
logger.Warn("Data directory has insecure permissions; attempting automatic repair",
30+
zap.String("path", dataDir),
31+
zap.String("current_permissions", fmt.Sprintf("%#o", perm)))
32+
33+
if err := os.Chmod(dataDir, 0700); err != nil {
34+
return fmt.Errorf(
35+
"data directory has insecure permissions %#o, must be 0700 or stricter\n"+
36+
"automatic repair failed: %w\n"+
37+
"Security risk: Other users can access mcpproxy data and control socket\n"+
38+
"To fix manually, run: chmod 0700 %s",
39+
perm, err, dataDir,
40+
)
41+
}
42+
43+
updatedInfo, err := os.Stat(dataDir)
44+
if err != nil {
45+
return fmt.Errorf("failed to recheck data directory after permission repair: %w", err)
46+
}
47+
perm = updatedInfo.Mode().Perm()
48+
if perm&0077 != 0 {
49+
return fmt.Errorf(
50+
"data directory remains with insecure permissions %#o even after automatic repair, must be 0700 or stricter\n"+
51+
"Security risk: Other users can access mcpproxy data and control socket\n"+
52+
"To fix manually, run: chmod 0700 %s",
53+
perm, dataDir,
54+
)
55+
}
56+
57+
logger.Info("Data directory permissions tightened automatically",
58+
zap.String("path", dataDir),
59+
zap.String("permissions", fmt.Sprintf("%#o", perm)))
60+
return nil
3561
}
3662

3763
logger.Info("Data directory security validation passed",

internal/server/listener_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,11 @@ func TestValidateDataDirectory_InsecurePermissions(t *testing.T) {
167167
require.NoError(t, err)
168168

169169
err = ValidateDataDirectory(tmpDir, logger)
170-
assert.Error(t, err)
171-
assert.Contains(t, err.Error(), "insecure permissions")
172-
assert.Contains(t, err.Error(), "chmod 0700")
170+
require.NoError(t, err)
171+
172+
info, statErr := os.Stat(tmpDir)
173+
require.NoError(t, statErr)
174+
assert.Equal(t, os.FileMode(0700), info.Mode().Perm(), "validate should tighten permissions automatically")
173175
}
174176

175177
func TestValidateDataDirectory_CreateIfNotExists(t *testing.T) {

0 commit comments

Comments
 (0)