From 83bade262712a0675ff6b932fb775c623d4a8614 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 27 Mar 2026 06:35:57 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[security?= =?UTF-8?q?=20improvement]=20Avoid=20shell=20wrapper=20in=20docker=20prune?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactored `docker system prune` execution in `CacheoutViewModel` to run directly via `/usr/bin/env docker` instead of through `/bin/bash -c`. This mitigates command injection risks associated with shell wrappers. Replicated the `2>&1` functionality securely by assigning a single `Pipe` to both standardOutput and standardError. Co-authored-by: acebytes <2820910+acebytes@users.noreply.github.com> --- .jules/sentinel.md | 4 ++++ Sources/Cacheout/ViewModels/CacheoutViewModel.swift | 6 ++++-- 2 files changed, 8 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..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 = [