From de17918659d1906c152db5ee3cdc49ba5cecabb2 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sat, 4 Apr 2026 07:34:07 +0000 Subject: [PATCH] Secure Process Execution for docker system prune Replaced shell wrapper execution with direct binary execution in `dockerPrune` using `Process`. This aligns with defense-in-depth principles by eliminating the intermediate shell environment and its associated attack surface. Redirections are handled securely in Swift by sharing a single `Pipe` between stdout and stderr. Co-authored-by: acebytes <2820910+acebytes@users.noreply.github.com> --- .jules/sentinel.md | 4 ++++ Sources/Cacheout/ViewModels/CacheoutViewModel.swift | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 .jules/sentinel.md diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000..6f7d6e3 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2024-05-24 - Secure Process Execution for docker system prune +**Vulnerability:** Use of shell wrapper `/bin/bash -c "docker system prune -f 2>&1"` for external command execution. While no dynamic input is passed in this specific case, using a shell wrapper for fixed commands is an anti-pattern that violates defense-in-depth principles and increases the attack surface (e.g., if PATH or environment was manipulated). +**Learning:** Shell redirections like `2>&1` can be implemented securely in Foundation.Process without needing a shell by assigning the same `Pipe()` object to both `standardOutput` and `standardError`. +**Prevention:** Always execute binary commands directly via `Process` (e.g., `/usr/bin/env docker`) using the `.arguments` array rather than wrapping them in a shell command string. diff --git a/Sources/Cacheout/ViewModels/CacheoutViewModel.swift b/Sources/Cacheout/ViewModels/CacheoutViewModel.swift index 13a9811..e50a217 100644 --- a/Sources/Cacheout/ViewModels/CacheoutViewModel.swift +++ b/Sources/Cacheout/ViewModels/CacheoutViewModel.swift @@ -231,8 +231,8 @@ class CacheoutViewModel: ObservableObject { let process = Process() let pipe = Pipe() - process.executableURL = URL(fileURLWithPath: "/bin/bash") - process.arguments = ["-c", "docker system prune -f 2>&1"] + process.executableURL = URL(fileURLWithPath: "/usr/bin/env") + process.arguments = ["docker", "system", "prune", "-f"] process.standardOutput = pipe process.standardError = pipe process.environment = [