Add enableWeakerNetworkIsolation option to conditionally allow trustd.agent mach-lookup

This commit is contained in:
David Dworken
2026-02-05 12:33:22 -08:00
parent d34c93c5f4
commit 4e007b9ed0
5 changed files with 56 additions and 9 deletions

View File

@@ -270,7 +270,8 @@ srt --settings /path/to/srt-settings.json <command>
"git push": ["/usr/bin/nc"],
"npm": ["/private/tmp"]
},
"enableWeakerNestedSandbox": false
"enableWeakerNestedSandbox": false,
"enableWeakerNetworkIsolation": false
}
```
@@ -341,6 +342,7 @@ Examples:
- `ignoreViolations` - Object mapping command patterns to arrays of paths where violations should be ignored
- `enableWeakerNestedSandbox` - Enable weaker sandbox mode for Docker environments (boolean, default: false)
- `enableWeakerNetworkIsolation` - Allow access to `com.apple.trustd.agent` in the macOS sandbox (boolean, default: false). This is needed for Go programs (`gh`, `gcloud`, `terraform`, `kubectl`, etc.) to verify TLS certificates when using `httpProxyPort` with a MITM proxy and custom CA. **Security warning:** enabling this opens a potential data exfiltration vector through the trustd service.
### Common Configuration Recipes
@@ -637,6 +639,7 @@ Users should be aware of potential risks that come from allowing broad domains l
- Privilege Escalation via Unix Sockets: The `allowUnixSockets` configuration can inadvertently grant access to powerful system services that could lead to sandbox bypasses. For example, if it is used to allow access to `/var/run/docker.sock` this would effectively grant access to the host system through exploiting the docker socket. Users are encouraged to carefully consider any unix sockets that they allow through the sandbox.
- Filesystem Permission Escalation: Overly broad filesystem write permissions can enable privilege escalation attacks. Allowing writes to directories containing executables in `$PATH`, system configuration directories, or user shell configuration files (`.bashrc`, `.zshrc`) can lead to code execution in different security contexts when other users or system processes access these files.
- Linux Sandbox Strength: The Linux implementation provides strong filesystem and network isolation but includes an `enableWeakerNestedSandbox` mode that enables it to work inside of Docker environments without privileged namespaces. This option considerably weakens security and should only be used incases where additional isolation is otherwise enforced.
- Weaker Network Isolation (macOS): The `enableWeakerNetworkIsolation` option re-enables access to `com.apple.trustd.agent`, which is needed for Go programs to verify TLS certificates via the macOS Security framework. This opens a potential data exfiltration vector through the trustd service and should only be enabled when Go TLS verification is required (e.g., when using `httpProxyPort` with a MITM proxy and custom CA).
### Known Limitations and Future Work

View File

@@ -33,6 +33,7 @@ export interface MacOSSandboxParams {
ignoreViolations?: IgnoreViolationsConfig | undefined
allowPty?: boolean
allowGitConfig?: boolean
enableWeakerNetworkIsolation?: boolean
binShell?: string
}
@@ -328,6 +329,7 @@ function generateSandboxProfile({
allowLocalBinding,
allowPty,
allowGitConfig = false,
enableWeakerNetworkIsolation = false,
logTag,
}: {
readConfig: FsReadRestrictionConfig | undefined
@@ -340,6 +342,7 @@ function generateSandboxProfile({
allowLocalBinding?: boolean
allowPty?: boolean
allowGitConfig?: boolean
enableWeakerNetworkIsolation?: boolean
logTag: string
}): string {
const profile: string[] = [
@@ -377,6 +380,13 @@ function generateSandboxProfile({
' (global-name "com.apple.coreservices.launchservicesd")',
')',
'',
...(enableWeakerNetworkIsolation
? [
'; trustd.agent - needed for Go TLS certificate verification (weaker network isolation)',
'(allow mach-lookup (global-name "com.apple.trustd.agent"))',
]
: []),
'',
'; POSIX IPC - shared memory',
'(allow ipc-posix-shm)',
'',
@@ -615,6 +625,7 @@ export function wrapCommandWithSandboxMacOS(
writeConfig,
allowPty,
allowGitConfig = false,
enableWeakerNetworkIsolation = false,
binShell,
} = params
@@ -646,6 +657,7 @@ export function wrapCommandWithSandboxMacOS(
allowLocalBinding,
allowPty,
allowGitConfig,
enableWeakerNetworkIsolation,
logTag,
})

View File

@@ -189,6 +189,15 @@ export const SandboxRuntimeConfigSchema = z.object({
.boolean()
.optional()
.describe('Enable weaker nested sandbox mode (for Docker environments)'),
enableWeakerNetworkIsolation: z
.boolean()
.optional()
.describe(
'Enable weaker network isolation to allow access to com.apple.trustd.agent (macOS only). ' +
'This is needed for Go programs (gh, gcloud, terraform, kubectl, etc.) to verify TLS certificates ' +
'when using httpProxyPort with a MITM proxy and custom CA. Enabling this opens a potential data ' +
'exfiltration vector through the trustd service. Only enable if you need Go TLS verification.',
),
ripgrep: RipgrepConfigSchema.optional().describe(
'Custom ripgrep configuration (default: { command: "rg" })',
),

View File

@@ -451,6 +451,10 @@ function getEnableWeakerNestedSandbox(): boolean | undefined {
return config?.enableWeakerNestedSandbox
}
function getEnableWeakerNetworkIsolation(): boolean | undefined {
return config?.enableWeakerNetworkIsolation
}
function getRipgrepConfig(): { command: string; args?: string[] } {
return config?.ripgrep ?? { command: 'rg' }
}
@@ -581,6 +585,7 @@ async function wrapWithSandbox(
ignoreViolations: getIgnoreViolations(),
allowPty,
allowGitConfig: getAllowGitConfig(),
enableWeakerNetworkIsolation: getEnableWeakerNetworkIsolation(),
binShell,
})

View File

@@ -106,6 +106,7 @@ describe('Config Validation', () => {
'git push': ['/usr/bin/nc'],
},
enableWeakerNestedSandbox: true,
enableWeakerNetworkIsolation: false,
}
const result = SandboxRuntimeConfigSchema.safeParse(config)
@@ -127,16 +128,12 @@ describe('Config Validation', () => {
})
test('should validate wildcard domains correctly', () => {
const validWildcards = [
'*.example.com',
'*.github.io',
'*.co.uk',
]
const validWildcards = ['*.example.com', '*.github.io', '*.co.uk']
const invalidWildcards = [
'*example.com', // Missing dot after asterisk
'*.com', // No subdomain
'*.', // Invalid format
'*example.com', // Missing dot after asterisk
'*.com', // No subdomain
'*.', // Invalid format
]
for (const domain of validWildcards) {
@@ -158,6 +155,27 @@ describe('Config Validation', () => {
}
})
test('should validate config with enableWeakerNetworkIsolation', () => {
const config = {
network: {
allowedDomains: ['example.com'],
deniedDomains: [],
},
filesystem: {
denyRead: [],
allowWrite: [],
denyWrite: [],
},
enableWeakerNetworkIsolation: true,
}
const result = SandboxRuntimeConfigSchema.safeParse(config)
expect(result.success).toBe(true)
if (result.success) {
expect(result.data.enableWeakerNetworkIsolation).toBe(true)
}
})
test('should validate config with custom ripgrep command', () => {
const config = {
network: {