From 50f136a1f0223fd4c39789ffdd273c30b1ad6b06 Mon Sep 17 00:00:00 2001 From: "Kai (Tam Nhu) Tran" <61256810+kaitranntt@users.noreply.github.com> Date: Tue, 16 Jun 2026 08:28:31 -0400 Subject: [PATCH] fix(macos-bar): launch dashboard without shell (#1549) Launches the dashboard without going through a shell, avoiding unescaped-command exposure. --- macos-bar/Sources/CCSBarApp/DashboardLauncher.swift | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/macos-bar/Sources/CCSBarApp/DashboardLauncher.swift b/macos-bar/Sources/CCSBarApp/DashboardLauncher.swift index bdaa0485..137ee48f 100644 --- a/macos-bar/Sources/CCSBarApp/DashboardLauncher.swift +++ b/macos-bar/Sources/CCSBarApp/DashboardLauncher.swift @@ -48,12 +48,16 @@ enum DashboardLauncher { return } - // Server isn't up. Start it via `ccs config`, fully detached (nohup) so it - // survives this app quitting; it opens the dashboard on its own. + // Server isn't up. Start it via `ccs config`; it opens the dashboard on its + // own. Avoid a shell here: candidate paths can include user-controlled + // components, and Process can pass the executable and arguments directly. if let bin = ccsBinary() { let proc = Process() - proc.executableURL = URL(fileURLWithPath: "/bin/sh") - proc.arguments = ["-c", "nohup \"\(bin)\" config >/dev/null 2>&1 &"] + proc.executableURL = URL(fileURLWithPath: bin) + proc.arguments = ["config"] + let null = FileHandle(forWritingAtPath: "/dev/null") + proc.standardOutput = null + proc.standardError = null try? proc.run() return }