diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000..34d1a17 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2024-11-06 - Replacing Shell Wrapper with Direct Execution for Docker Prune +**Vulnerability:** Execution of `docker system prune` via `/bin/bash -c` in `dockerPrune()` could potentially be susceptible to command injection if arguments are ever dynamically inserted, and generally violates the principle of least privilege by running an unnecessary shell. +**Learning:** Shell redirections like `2>&1` can be securely replicated natively in Swift's `Process` by assigning the exact same `Pipe` instance to both `standardOutput` and `standardError` properties. +**Prevention:** Avoid `/bin/bash -c` for external commands unless shell-specific features (like complex pipelines or globs) are strictly required. Use `/usr/bin/env` with direct arguments instead, and handle output redirection directly via the `Process` API. diff --git a/Sources/Cacheout/ViewModels/CacheoutViewModel.swift b/Sources/Cacheout/ViewModels/CacheoutViewModel.swift index 13a9811..66f8af3 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"] + // 🛡️ SECURITY: Use direct execution instead of shell wrapper to prevent injection vulnerabilities. + // The shell redirection (2>&1) is securely replicated by assigning the same Pipe to stdout and stderr. + process.executableURL = URL(fileURLWithPath: "/usr/bin/env") + process.arguments = ["docker", "system", "prune", "-f"] process.standardOutput = pipe process.standardError = pipe process.environment = [