1
0
mirror of https://github.com/nicoverbruggen/phpmon.git synced 2026-03-28 15:00:06 +01:00

🐛 Refactor custom environment variables

This commit is contained in:
2026-02-06 14:39:41 +01:00
parent ee5971e806
commit ae4f436b09
2 changed files with 18 additions and 26 deletions

View File

@@ -13,7 +13,7 @@ class RealShell: ShellProtocol, @unchecked Sendable {
init(binPath: String) { init(binPath: String) {
self.binPath = binPath self.binPath = binPath
self._PATH = RealShell.getPath() self._PATH = RealShell.getPath()
self._exports = "" self._exports = [:]
} }
private(set) var binPath: String private(set) var binPath: String
@@ -38,8 +38,9 @@ class RealShell: ShellProtocol, @unchecked Sendable {
/** /**
Exports are additional environment variables set by the user via the custom configuration. Exports are additional environment variables set by the user via the custom configuration.
These are populated when the configuration file is being loaded. These are populated when the configuration file is being loaded.
These are now set via via Process.environment to avoid security issues, like shell injection.
*/ */
internal var exports: String { internal var exports: [String: String] {
get { shellQueue.sync { _exports } } get { shellQueue.sync { _exports } }
set { shellQueue.sync { _exports = newValue } } set { shellQueue.sync { _exports = newValue } }
} }
@@ -49,7 +50,7 @@ class RealShell: ShellProtocol, @unchecked Sendable {
/** Thread-safe access to PATH and exports is ensured via this queue. */ /** Thread-safe access to PATH and exports is ensured via this queue. */
private let shellQueue = DispatchQueue(label: "com.nicoverbruggen.phpmon.shell_queue") private let shellQueue = DispatchQueue(label: "com.nicoverbruggen.phpmon.shell_queue")
private var _PATH: String private var _PATH: String
private var _exports: String private var _exports: [String: String]
// MARK: - Methods // MARK: - Methods
@@ -75,22 +76,23 @@ class RealShell: ShellProtocol, @unchecked Sendable {
This process still needs to be started, or one can attach output handlers. This process still needs to be started, or one can attach output handlers.
*/ */
private func getShellProcess(for command: String) -> Process { private func getShellProcess(for command: String) -> Process {
var completeCommand = "" let completeCommand = "export PATH=\(binPath):$PATH && " + command
// Basic export (PATH)
completeCommand += "export PATH=\(binPath):$PATH && "
// Put additional exports (as defined by the user) in between
if !self.exports.isEmpty {
completeCommand += "\(self.exports) && "
}
completeCommand += command
let task = Process() let task = Process()
task.launchPath = self.launchPath task.launchPath = self.launchPath
task.arguments = ["--noprofile", "-norc", "--login", "-c", completeCommand] task.arguments = ["--noprofile", "-norc", "--login", "-c", completeCommand]
// Set user-defined environment variables safely via Process API
// instead of interpolating them into the shell command string.
let currentExports = self.exports
if !currentExports.isEmpty {
var env = ProcessInfo.processInfo.environment
for (key, value) in currentExports {
env[key] = value
}
task.environment = env
}
return task return task
} }
@@ -148,9 +150,7 @@ class RealShell: ShellProtocol, @unchecked Sendable {
These will be exported when a command is executed. These will be exported when a command is executed.
*/ */
public func setCustomEnvironmentVariables(_ variables: [String: String]) { public func setCustomEnvironmentVariables(_ variables: [String: String]) {
self.exports = variables.map { (key, value) in self.exports = variables
return "export \(key)=\(value)"
}.joined(separator: "&&")
} }
// MARK: - Shellable Protocol // MARK: - Shellable Protocol

View File

@@ -14,14 +14,6 @@ struct CustomPrefs: Decodable {
let services: [String]? let services: [String]?
let environmentVariables: [String: String]? let environmentVariables: [String: String]?
var exportAsString: String {
return self.environmentVariables!
.map { (key, value) in
return "export \(key)=\(value)"
}
.joined(separator: "&&")
}
public func hasPresets() -> Bool { public func hasPresets() -> Bool {
return self.presets != nil && !self.presets!.isEmpty return self.presets != nil && !self.presets!.isEmpty
} }
@@ -89,7 +81,7 @@ extension Preferences {
if customPreferences.hasEnvironmentVariables() { if customPreferences.hasEnvironmentVariables() {
Log.info("Configuring the additional exports...") Log.info("Configuring the additional exports...")
if let shell = App.shared.container.shell as? RealShell { if let shell = App.shared.container.shell as? RealShell {
shell.exports = customPreferences.exportAsString shell.exports = customPreferences.environmentVariables ?? [:]
} }
} }
} catch { } catch {