fix: canonicalize the writeable paths used in seatbelt policy (#275)
closes #207 I'd be lying if I said I was familiar with these particulars more than a couple hours ago, but after investigating and testing locally, this does fix the go issue, I prefer it over #272 which is a lot of code and a one off fix ---- cc @bolinfest do you mind taking a look here? 1. Seatbelt compares the paths it gets from the kernal to its policies 1. Go is attempting to write to the os.tmpdir, which we have allowlisted. 1. The kernel rewrites /var/… to /private/var/… before the sandbox check. 1. The policy still said /var/…, so writes were denied. Fix: canonicalise every writable root we feed into the policy (realpathSync(...)). We do not have to touch runtime file paths—the kernel already canonicalises those. ### before see that the command exited 1, and that the command was reported to be prohibited, despite using the allowlisted tmpdir https://github.com/user-attachments/assets/23911101-0ec0-4a59-a0a1-423be04063f0 ### after command exits 0 https://github.com/user-attachments/assets/6ab2bcd6-68bd-4f89-82bb-2c8612e39ac3
This commit is contained in:
@@ -3,6 +3,7 @@ import type { SpawnOptions } from "child_process";
|
||||
|
||||
import { exec } from "./raw-exec.js";
|
||||
import { log } from "../log.js";
|
||||
import { realpathSync } from "fs";
|
||||
import { CONFIG_DIR } from "src/utils/config.js";
|
||||
|
||||
function getCommonRoots() {
|
||||
@@ -29,7 +30,9 @@ export function execWithSeatbelt(
|
||||
const { policies, params } = writableRoots
|
||||
.map((root, index) => ({
|
||||
policy: `(subpath (param "WRITABLE_ROOT_${index}"))`,
|
||||
param: `-DWRITABLE_ROOT_${index}=${root}`,
|
||||
// the kernel resolves symlinks before handing them to seatbelt for checking
|
||||
// so store the canonicalized form in the policy to be compared against
|
||||
param: `-DWRITABLE_ROOT_${index}=${realpathSync(root)}`,
|
||||
}))
|
||||
.reduce(
|
||||
(
|
||||
|
||||
Reference in New Issue
Block a user