fix(macos): fail closed on env-modified shell wrappers
This commit is contained in:
parent
e4b70ea497
commit
1d45febea8
@ -77,6 +77,11 @@ struct ExecCommandResolution {
|
||||
guard depth <= ExecWrapperResolution.maxWrapperDepth, !command.isEmpty else {
|
||||
return []
|
||||
}
|
||||
if ExecWrapperResolution.hasEnvManipulationBeforeShellWrapper(command) {
|
||||
// Fail closed for semantic env wrappers that can alter shell lookup
|
||||
// semantics before we would analyze inner shell payloads.
|
||||
return []
|
||||
}
|
||||
|
||||
let shell = ExecShellWrapperParser.extract(command: command, rawCommand: rawCommand)
|
||||
if shell.isWrapper {
|
||||
@ -194,6 +199,12 @@ struct ExecCommandResolution {
|
||||
guard depth <= Self.maxAllowAlwaysTraversalDepth, !command.isEmpty else {
|
||||
return
|
||||
}
|
||||
if ExecWrapperResolution.hasEnvManipulationBeforeShellWrapper(command) {
|
||||
// Mirror the conservative node-host policy for env-modified shell
|
||||
// launches: require explicit approval each time instead of persisting
|
||||
// an inner-executable pattern that the modified environment can subvert.
|
||||
return
|
||||
}
|
||||
|
||||
// Allow-always persistence intentionally peels known dispatch wrappers
|
||||
// directly so approvals stay scoped to the launched executable instead of
|
||||
|
||||
@ -382,6 +382,17 @@ struct ExecAllowlistTests {
|
||||
#expect(resolutions[0].executableName == "env")
|
||||
}
|
||||
|
||||
@Test func `resolve for allowlist fails closed on env manipulation before shell wrapper`() {
|
||||
let command = ["/usr/bin/env", "PATH=/tmp", "/bin/sh", "-lc", "whoami"]
|
||||
let resolutions = ExecCommandResolution.resolveForAllowlist(
|
||||
command: command,
|
||||
rawCommand: nil,
|
||||
cwd: nil,
|
||||
env: ["PATH": "/usr/bin:/bin"])
|
||||
|
||||
#expect(resolutions.isEmpty)
|
||||
}
|
||||
|
||||
@Test func `resolve for allowlist preserves env wrapper with modifiers`() {
|
||||
let command = ["/usr/bin/env", "FOO=bar", "/usr/bin/printf", "ok"]
|
||||
let resolutions = ExecCommandResolution.resolveForAllowlist(
|
||||
@ -435,6 +446,15 @@ struct ExecAllowlistTests {
|
||||
#expect(patterns == ["/usr/bin/printf"])
|
||||
}
|
||||
|
||||
@Test func `allow always patterns fail closed on env manipulation before shell wrapper`() {
|
||||
let patterns = ExecCommandResolution.resolveAllowAlwaysPatterns(
|
||||
command: ["/usr/bin/env", "PATH=/tmp", "/bin/sh", "-lc", "whoami"],
|
||||
cwd: nil,
|
||||
env: ["PATH": "/usr/bin:/bin"])
|
||||
|
||||
#expect(patterns.isEmpty)
|
||||
}
|
||||
|
||||
@Test func `allow always patterns unwrap dispatch wrappers before shell wrappers`() throws {
|
||||
let tmp = try makeTempDirForTests()
|
||||
let whoami = tmp.appendingPathComponent("whoami")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user