diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000..0a83945 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2024-05-24 - Process execution via shell wrapper +**Vulnerability:** Execution of command `docker system prune -f 2>&1` via `/bin/bash -c` in `CacheoutViewModel.swift`. Although there wasn't dynamic input here, using shell wrappers is a systemic risk for command injection in Swift. +**Learning:** Shell redirections like `2>&1` can be replicated securely in Swift by assigning the same `Pipe()` instance to both `process.standardOutput` and `process.standardError` without needing `/bin/bash`. +**Prevention:** Avoid shell wrappers (`/bin/bash -c`). Use direct executable invocation (e.g., `/usr/bin/env` with binary name) with an explicitly defined `arguments` array. Set stdout and stderr to the same `Pipe()` instance to capture combined output instead of relying on shell operators. diff --git a/Sources/Cacheout/ViewModels/CacheoutViewModel.swift b/Sources/Cacheout/ViewModels/CacheoutViewModel.swift index 13a9811..48a56c3 100644 --- a/Sources/Cacheout/ViewModels/CacheoutViewModel.swift +++ b/Sources/Cacheout/ViewModels/CacheoutViewModel.swift @@ -231,8 +231,10 @@ class CacheoutViewModel: ObservableObject { let process = Process() let pipe = Pipe() - process.executableURL = URL(fileURLWithPath: "/bin/bash") - process.arguments = ["-c", "docker system prune -f 2>&1"] + // Run direct binary without shell wrapper to avoid command injection risks. + // The previous 2>&1 redirection is handled by assigning `pipe` to both stdout/stderr. + process.executableURL = URL(fileURLWithPath: "/usr/bin/env") + process.arguments = ["docker", "system", "prune", "-f"] process.standardOutput = pipe process.standardError = pipe process.environment = [