fix(runtime): make dev IPC checks CI-safe
- commit
- b200f6b1e2a559bf3c31857064d780107255fb24
- author
- brice · · 2026-06-26 15:39 UTC
- parent
- b13ad36
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +14 -5
M internal/infrastructure/config/xdg_test.go +7 -0
| @@ -1,6 +1,7 @@ | |||
| 1 | 1 | package config | |
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | + | "os" | |
| 4 | 5 | "path/filepath" | |
| 5 | 6 | "testing" | |
| 6 | 7 | ||
| @@ -29,6 +30,12 @@ func TestGetXDGDirs_DevUsesSharedSandboxLayout(t *testing.T) { | |||
| 29 | 30 | t.Chdir(wd) | |
| 30 | 31 | ||
| 31 | 32 | t.Setenv("ENV", "dev") | |
| 33 | + | runtimeDir, err := os.MkdirTemp("", "dbr-") | |
| 34 | + | require.NoError(t, err) | |
| 35 | + | t.Cleanup(func() { | |
| 36 | + | _ = os.RemoveAll(runtimeDir) | |
| 37 | + | }) | |
| 38 | + | t.Setenv("XDG_RUNTIME_DIR", runtimeDir) | |
| 32 | 39 | dirs, err := GetXDGDirs() | |
| 33 | 40 | require.NoError(t, err) | |
| 34 | 41 | require.Equal(t, filepath.Join(wd, ".dev", appName, "config"), dirs.ConfigHome) | |
| @@ -1,6 +1,7 @@ | |||||
| 1 | package config | 1 | package config | ||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | + | "os" | |||
| 4 | "path/filepath" | 5 | "path/filepath" | ||
| 5 | "testing" | 6 | "testing" | ||
| 6 | 7 | ||||
| @@ -29,6 +30,12 @@ func TestGetXDGDirs_DevUsesSharedSandboxLayout(t *testing.T) { | |||||
| 29 | t.Chdir(wd) | 30 | t.Chdir(wd) | ||
| 30 | 31 | ||||
| 31 | t.Setenv("ENV", "dev") | 32 | t.Setenv("ENV", "dev") | ||
| 33 | + | runtimeDir, err := os.MkdirTemp("", "dbr-") | |||
| 34 | + | require.NoError(t, err) | |||
| 35 | + | t.Cleanup(func() { | |||
| 36 | + | _ = os.RemoveAll(runtimeDir) | |||
| 37 | + | }) | |||
| 38 | + | t.Setenv("XDG_RUNTIME_DIR", runtimeDir) | |||
| 32 | dirs, err := GetXDGDirs() | 39 | dirs, err := GetXDGDirs() | ||
| 33 | require.NoError(t, err) | 40 | require.NoError(t, err) | ||
| 34 | require.Equal(t, filepath.Join(wd, ".dev", appName, "config"), dirs.ConfigHome) | 41 | require.Equal(t, filepath.Join(wd, ".dev", appName, "config"), dirs.ConfigHome) | ||
M internal/infrastructure/desktop/browser_launch_relay.go +7 -5
| @@ -187,7 +187,8 @@ func setBrowserLaunchConnDeadline(ctx context.Context, conn net.Conn) error { | |||
| 187 | 187 | } | |
| 188 | 188 | ||
| 189 | 189 | func validateBrowserLaunchSocketDirOwned(socketPath string, expectedUID uint32) error { | |
| 190 | - | for dir := filepath.Dir(socketPath); ; dir = filepath.Dir(dir) { | |
| 190 | + | socketDir := filepath.Dir(socketPath) | |
| 191 | + | for dir := socketDir; ; dir = filepath.Dir(dir) { | |
| 191 | 192 | info, err := os.Stat(dir) | |
| 192 | 193 | if err != nil { | |
| 193 | 194 | return fmt.Errorf("stat browser launch dir: %w", err) | |
| @@ -196,13 +197,14 @@ func validateBrowserLaunchSocketDirOwned(socketPath string, expectedUID uint32) | |||
| 196 | 197 | if !ok { | |
| 197 | 198 | return nil | |
| 198 | 199 | } | |
| 200 | + | ||
| 201 | + | isSocketDir := dir == socketDir | |
| 199 | 202 | if stat.Uid != expectedUID { | |
| 200 | - | if stat.Uid == 0 { | |
| 201 | - | return nil | |
| 203 | + | if isSocketDir || stat.Uid != 0 { | |
| 204 | + | return fmt.Errorf("browser launch dir owner mismatch: %s owned by uid %d, want uid %d", dir, stat.Uid, expectedUID) | |
| 202 | 205 | } | |
| 203 | - | return fmt.Errorf("browser launch dir owner mismatch: %s owned by uid %d, want uid %d", dir, stat.Uid, expectedUID) | |
| 204 | 206 | } | |
| 205 | - | if info.Mode().Perm()&0o022 != 0 { | |
| 207 | + | if info.Mode().Perm()&0o022 != 0 && (isSocketDir || info.Mode()&os.ModeSticky == 0) { | |
| 206 | 208 | return fmt.Errorf("browser launch dir permissions too broad: %s has mode %04o", dir, info.Mode().Perm()) | |
| 207 | 209 | } | |
| 208 | 210 | if parent := filepath.Dir(dir); parent == dir { | |
| @@ -187,7 +187,8 @@ func setBrowserLaunchConnDeadline(ctx context.Context, conn net.Conn) error { | |||||
| 187 | } | 187 | } | ||
| 188 | 188 | ||||
| 189 | func validateBrowserLaunchSocketDirOwned(socketPath string, expectedUID uint32) error { | 189 | func validateBrowserLaunchSocketDirOwned(socketPath string, expectedUID uint32) error { | ||
| 190 | - | for dir := filepath.Dir(socketPath); ; dir = filepath.Dir(dir) { | 190 | + | socketDir := filepath.Dir(socketPath) |
| 191 | + | for dir := socketDir; ; dir = filepath.Dir(dir) { | |||
| 191 | info, err := os.Stat(dir) | 192 | info, err := os.Stat(dir) | ||
| 192 | if err != nil { | 193 | if err != nil { | ||
| 193 | return fmt.Errorf("stat browser launch dir: %w", err) | 194 | return fmt.Errorf("stat browser launch dir: %w", err) | ||
| @@ -196,13 +197,14 @@ func validateBrowserLaunchSocketDirOwned(socketPath string, expectedUID uint32) | |||||
| 196 | if !ok { | 197 | if !ok { | ||
| 197 | return nil | 198 | return nil | ||
| 198 | } | 199 | } | ||
| 200 | + | ||||
| 201 | + | isSocketDir := dir == socketDir | |||
| 199 | if stat.Uid != expectedUID { | 202 | if stat.Uid != expectedUID { | ||
| 200 | - | if stat.Uid == 0 { | 203 | + | if isSocketDir || stat.Uid != 0 { |
| 201 | - | return nil | 204 | + | return fmt.Errorf("browser launch dir owner mismatch: %s owned by uid %d, want uid %d", dir, stat.Uid, expectedUID) |
| 202 | } | 205 | } | ||
| 203 | - | return fmt.Errorf("browser launch dir owner mismatch: %s owned by uid %d, want uid %d", dir, stat.Uid, expectedUID) | |||
| 204 | } | 206 | } | ||
| 205 | - | if info.Mode().Perm()&0o022 != 0 { | 207 | + | if info.Mode().Perm()&0o022 != 0 && (isSocketDir || info.Mode()&os.ModeSticky == 0) { |
| 206 | return fmt.Errorf("browser launch dir permissions too broad: %s has mode %04o", dir, info.Mode().Perm()) | 208 | return fmt.Errorf("browser launch dir permissions too broad: %s has mode %04o", dir, info.Mode().Perm()) | ||
| 207 | } | 209 | } | ||
| 208 | if parent := filepath.Dir(dir); parent == dir { | 210 | if parent := filepath.Dir(dir); parent == dir { | ||