use seatbelt on macos, with two profiles: minimal (default) which only restricts writes, and strict, which is deny-by-default and only allows specific operations (#283)
This commit is contained in:
parent
34fe142894
commit
d524309e3c
|
@ -45,10 +45,14 @@ export const Footer: React.FC<FooterProps> = ({
|
|||
justifyContent="center"
|
||||
display="flex"
|
||||
>
|
||||
{process.env.SANDBOX ? (
|
||||
{process.env.SANDBOX && process.env.SANDBOX !== 'sandbox-exec' ? (
|
||||
<Text color="green"> {process.env.SANDBOX} </Text>
|
||||
) : process.env.SANDBOX === 'sandbox-exec' ? (
|
||||
<Text color={Colors.AccentYellow}>
|
||||
using macos seatbelt ({process.env.SANDBOX_EXEC_PROFILE})
|
||||
</Text>
|
||||
) : (
|
||||
<Text color={Colors.AccentRed}> WARNING: OUTSIDE SANDBOX </Text>
|
||||
<Text color={Colors.AccentRed}> WARNING: SANDBOX NOT ENABLED </Text>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
(version 1)
|
||||
|
||||
;; allow everything by default
|
||||
(allow default)
|
||||
|
||||
;; deny all writes EXCEPT under project directory, temp directory, stdout/stderr and /dev/null
|
||||
(deny file-write*)
|
||||
(allow file-write*
|
||||
(subpath (param "TARGET_DIR"))
|
||||
(subpath (param "TMP_DIR"))
|
||||
(literal "/dev/stdout")
|
||||
(literal "/dev/stderr")
|
||||
(literal "/dev/null")
|
||||
)
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
(version 1)
|
||||
|
||||
;; deny everything by default
|
||||
(deny default)
|
||||
|
||||
;; allow reading files from anywhere on host
|
||||
(allow file-read*)
|
||||
|
||||
;; allow exec/fork (children inherit policy)
|
||||
(allow process-exec)
|
||||
(allow process-fork)
|
||||
|
||||
;; allow signals to self, e.g. SIGPIPE on write to closed pipe
|
||||
(allow signal (target self))
|
||||
|
||||
;; allow read access to specific information about system
|
||||
;; from https://source.chromium.org/chromium/chromium/src/+/main:sandbox/policy/mac/common.sb;l=273-319;drc=7b3962fe2e5fc9e2ee58000dc8fbf3429d84d3bd
|
||||
(allow sysctl-read
|
||||
(sysctl-name "hw.activecpu")
|
||||
(sysctl-name "hw.busfrequency_compat")
|
||||
(sysctl-name "hw.byteorder")
|
||||
(sysctl-name "hw.cacheconfig")
|
||||
(sysctl-name "hw.cachelinesize_compat")
|
||||
(sysctl-name "hw.cpufamily")
|
||||
(sysctl-name "hw.cpufrequency_compat")
|
||||
(sysctl-name "hw.cputype")
|
||||
(sysctl-name "hw.l1dcachesize_compat")
|
||||
(sysctl-name "hw.l1icachesize_compat")
|
||||
(sysctl-name "hw.l2cachesize_compat")
|
||||
(sysctl-name "hw.l3cachesize_compat")
|
||||
(sysctl-name "hw.logicalcpu_max")
|
||||
(sysctl-name "hw.machine")
|
||||
(sysctl-name "hw.ncpu")
|
||||
(sysctl-name "hw.nperflevels")
|
||||
(sysctl-name "hw.optional.arm.FEAT_BF16")
|
||||
(sysctl-name "hw.optional.arm.FEAT_DotProd")
|
||||
(sysctl-name "hw.optional.arm.FEAT_FCMA")
|
||||
(sysctl-name "hw.optional.arm.FEAT_FHM")
|
||||
(sysctl-name "hw.optional.arm.FEAT_FP16")
|
||||
(sysctl-name "hw.optional.arm.FEAT_I8MM")
|
||||
(sysctl-name "hw.optional.arm.FEAT_JSCVT")
|
||||
(sysctl-name "hw.optional.arm.FEAT_LSE")
|
||||
(sysctl-name "hw.optional.arm.FEAT_RDM")
|
||||
(sysctl-name "hw.optional.arm.FEAT_SHA512")
|
||||
(sysctl-name "hw.optional.armv8_2_sha512")
|
||||
(sysctl-name "hw.packages")
|
||||
(sysctl-name "hw.pagesize_compat")
|
||||
(sysctl-name "hw.physicalcpu_max")
|
||||
(sysctl-name "hw.tbfrequency_compat")
|
||||
(sysctl-name "hw.vectorunit")
|
||||
(sysctl-name "kern.hostname")
|
||||
(sysctl-name "kern.maxfilesperproc")
|
||||
(sysctl-name "kern.osproductversion")
|
||||
(sysctl-name "kern.osrelease")
|
||||
(sysctl-name "kern.ostype")
|
||||
(sysctl-name "kern.osvariant_status")
|
||||
(sysctl-name "kern.osversion")
|
||||
(sysctl-name "kern.secure_kernel")
|
||||
(sysctl-name "kern.usrstack64")
|
||||
(sysctl-name "kern.version")
|
||||
(sysctl-name "sysctl.proc_cputype")
|
||||
(sysctl-name-prefix "hw.perflevel")
|
||||
)
|
||||
|
||||
;; allow writes to project directory, temp directory, stdout/stderr and /dev/null
|
||||
(allow file-write*
|
||||
(subpath (param "TARGET_DIR"))
|
||||
(subpath (param "TMP_DIR"))
|
||||
(literal "/dev/stdout")
|
||||
(literal "/dev/stderr")
|
||||
(literal "/dev/null")
|
||||
)
|
||||
|
||||
;; allow outbound network connections
|
||||
(allow network-outbound)
|
||||
|
||||
;; allow communication with sysmond for process listing (e.g. for pgrep)
|
||||
(allow mach-lookup (global-name "com.apple.sysmond"))
|
||||
|
||||
;; enable terminal access required by ink
|
||||
;; fixes setRawMode EPERM failure (at node:tty:81:24)
|
||||
(allow file-ioctl (regex #"^/dev/tty.*"))
|
|
@ -45,6 +45,14 @@ export function sandbox_command(sandbox?: string | boolean): string {
|
|||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
// if we are on macOS (Darwin) and sandbox-exec is available, use that for minimal sandboxing
|
||||
if (
|
||||
os.platform() === 'darwin' &&
|
||||
execSync('command -v sandbox-exec || true').toString().trim()
|
||||
) {
|
||||
return 'sandbox-exec';
|
||||
}
|
||||
|
||||
return ''; // no sandbox
|
||||
}
|
||||
}
|
||||
|
@ -133,6 +141,27 @@ function entrypoint(workdir: string): string[] {
|
|||
}
|
||||
|
||||
export async function start_sandbox(sandbox: string) {
|
||||
if (sandbox === 'sandbox-exec') {
|
||||
process.env.SANDBOX_EXEC_PROFILE ??= 'minimal';
|
||||
const args = [
|
||||
'-D',
|
||||
`TARGET_DIR=${process.cwd()}`,
|
||||
'-D',
|
||||
`TMP_DIR=${fs.realpathSync(os.tmpdir())}`,
|
||||
'-f',
|
||||
new URL(
|
||||
`sandbox-macos-${process.env.SANDBOX_EXEC_PROFILE}.sb`,
|
||||
import.meta.url,
|
||||
).pathname,
|
||||
'bash',
|
||||
'-c',
|
||||
'SANDBOX=sandbox-exec ' +
|
||||
process.argv.map((arg) => quote([arg])).join(' '),
|
||||
];
|
||||
spawnSync(sandbox, args, { stdio: 'inherit' });
|
||||
return;
|
||||
}
|
||||
|
||||
// determine full path for gemini-code to distinguish linked vs installed setting
|
||||
const gcPath = execSync(`realpath $(which gemini-code)`).toString().trim();
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ fi
|
|||
tsc --build
|
||||
|
||||
# copy .{md,json} files (replace -q with -i to see itemized changes)
|
||||
rsync -aq --delete --include='*.md' --include='*.json' --include='*/' --exclude='*' ./src/ ./dist/src/
|
||||
rsync -aq --delete --include='*.md' --include='*.json' --include='*.sb' --include='*/' --exclude='*' ./src/ ./dist/src/
|
||||
|
||||
# touch dist/.last_build
|
||||
touch dist/.last_build
|
||||
|
|
Loading…
Reference in New Issue