1
/**2
* Internal platform-profile builders for the local sandbox provider.3
*4
* @module @deepseek-ai/dsh-sandbox-local/profiles5
*/7
import { grantArgs as landlockGrantArgs } from '@deepseek-ai/node-addon-system/landlock-run'8
import { writableRoots } from '@deepseek-ai/dsh-sandbox'9
import type { SandboxPolicy } from '@deepseek-ai/dsh-sandbox'11
/**12
* Build the bwrap profile arguments for one file-effect policy.13
* @param policy - file-effect policy to express as bwrap mounts.14
* @returns profile arguments before the trailing separator and command argv.15
*/16
export function bwrapProfileArgs(policy: SandboxPolicy): string[] {17
const args = ['--ro-bind', '/', '/', '--dev', '/dev', '--unshare-pid', '--proc', '/proc', '--die-with-parent']18
if (policy.mode === 'workspace-write') {19
args.push('--tmpfs', '/tmp')20
args.push('--bind', policy.workspaceRoot, policy.workspaceRoot)21
}22
return args23
}25
/**26
* Build the Landlock launcher grants for one file-effect policy.27
* @param policy - file-effect policy to express as Landlock allow-list grants.28
* @returns launcher grant arguments before the trailing separator and command argv.29
*/30
export function landlockProfileArgs(policy: SandboxPolicy): string[] {31
const readWrite = ['/dev/null']32
if (policy.mode === 'workspace-write') {33
readWrite.push('/tmp', policy.workspaceRoot)34
}35
return landlockGrantArgs({ readOnly: ['/'], readWrite })36
}38
/** Quote one path as an SBPL string literal. */39
function sbplString(path: string): string {40
return `"${path.replaceAll('\\', String.raw`\\`).replaceAll('"', String.raw`\"`)}"`41
}43
/**44
* Build the sandbox-exec arguments and SBPL profile for one policy. The45
* writable roots come from the shared {@link writableRoots} helper (canonical,46
* deduplicated) so the Seatbelt grant and the in-process fs fence47
* (`@deepseek-ai/dsh-fs-sandbox`) can never drift apart.48
* @param policy - file-effect policy to express as an SBPL profile.49
* @returns sandbox-exec arguments before the trailing separator and command argv.50
*/51
export function seatbeltProfileArgs(policy: SandboxPolicy): string[] {52
const forms = ['(version 1)', '(allow default)', '(deny file-write*)', `(allow file-write* (literal ${sbplString('/dev/null')}))`]53
const roots = writableRoots(policy)54
if (roots.length > 0) {55
forms.push(`(allow file-write* ${roots.map(root => `(subpath ${sbplString(root)})`).join(' ')})`)56
}57
return ['-p', forms.join(' ')]58
}