From 72e477b62d8a88596a07f01eadfaf95a56f7d5fa Mon Sep 17 00:00:00 2001 From: Dylan Conway Date: Tue, 31 Mar 2026 12:21:57 -0700 Subject: [PATCH] Fix enableWeakerNestedSandbox after apply-seccomp namespace changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit apply-seccomp now creates a nested userns and writes /proc/self/setgroups and uid_map before applying the seccomp filter. That broke enableWeakerNestedSandbox in two ways: 1. Without --proc, bwrap's --ro-bind / / leaves /proc read-only. apply-seccomp's setgroups write dies with EROFS. 2. In unprivileged Docker (the flag's target), apply-seccomp's proc remount fails the kernel domination check — Docker's /proc masks are MNT_LOCKED in the less-privileged nested userns. And the reason bwrap never got that far in Docker: bwrap only auto-adds --unshare-user when EUID != 0. Docker's default is EUID=0 without CAP_SYS_ADMIN; bwrap assumes it has caps, tries direct clone(NEWPID), and EPERMs before apply-seccomp runs. Changes: - bwrap args for weak mode: --unshare-user (force userns even as EUID=0) and --bind /proc /proc (restore rw /proc for setgroups) - apply-seccomp: tolerate mount(/proc) EPERM. The nested userns is the isolation boundary; the proc remount only hides outer PIDs from `ls /proc`. Fixes the two failing mandatory-deny-paths tests that exercise enableWeakerNestedSandbox. No test changes required. Bump version to 0.0.46. --- package-lock.json | 15 ++++----------- package.json | 2 +- src/sandbox/linux-sandbox-utils.ts | 10 ++++++++++ vendor/seccomp-src/apply-seccomp.c | 8 +++++++- vendor/seccomp/arm64/apply-seccomp | Bin 550976 -> 560256 bytes vendor/seccomp/x64/apply-seccomp | Bin 831952 -> 831952 bytes 6 files changed, 22 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index c155a84..c49a227 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@anthropic-ai/sandbox-runtime", - "version": "0.0.45", + "version": "0.0.46", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@anthropic-ai/sandbox-runtime", - "version": "0.0.45", + "version": "0.0.46", "license": "Apache-2.0", "dependencies": { "@pondwader/socks5-server": "^1.0.10", @@ -502,7 +502,6 @@ "integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.46.2", "@typescript-eslint/types": "8.46.2", @@ -1003,7 +1002,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1455,7 +1453,8 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.2.tgz", "integrity": "sha512-D80T+tiqkd/8B0xNlbstWDG4x6aqVfO52+OlSUNIdkTvmNw0uQpJLeos2J/2XvpyidAFuTPmpad+tUxLndwj6g==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/data-view-buffer": { "version": "1.0.2", @@ -1802,7 +1801,6 @@ "integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -1892,7 +1890,6 @@ "integrity": "sha512-/IGJ6+Dka158JnP5n5YFMOszjDWrXggGz1LaK/guZq9vZTmniaKlHcsscvkAhn9y4U+BU3JuUdYvtAMcv30y4A==", "dev": true, "license": "MIT", - "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -2013,7 +2010,6 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -3734,7 +3730,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -3781,7 +3776,6 @@ "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -4634,7 +4628,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index 0e98338..786b9ff 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@anthropic-ai/sandbox-runtime", - "version": "0.0.45", + "version": "0.0.46", "description": "Anthropic Sandbox Runtime (ASRT) - A general-purpose tool for wrapping security boundaries around arbitrary processes", "type": "module", "main": "./dist/index.js", diff --git a/src/sandbox/linux-sandbox-utils.ts b/src/sandbox/linux-sandbox-utils.ts index c37617f..03b3e38 100644 --- a/src/sandbox/linux-sandbox-utils.ts +++ b/src/sandbox/linux-sandbox-utils.ts @@ -1212,6 +1212,16 @@ export async function wrapCommandWithSandboxLinux( if (!enableWeakerNestedSandbox) { // Mount fresh /proc if PID namespace is isolated (secure mode) bwrapArgs.push('--proc', '/proc') + } else { + // --unshare-user: bwrap only auto-adds this when EUID != 0. In an + // unprivileged container (Docker's default: EUID=0 without + // CAP_SYS_ADMIN), bwrap assumes it has caps, tries direct clone, + // and EPERMs. Force the userns path so bwrap starts at all. + // + // --bind /proc /proc: apply-seccomp's nested-userns path writes + // /proc/self/setgroups and uid_map. Without --proc above, the + // --ro-bind / / leaves /proc read-only and those writes EROFS. + bwrapArgs.push('--unshare-user', '--bind', '/proc', '/proc') } // apply-seccomp obtains CAP_SYS_ADMIN for its nested PID+mount unshare diff --git a/vendor/seccomp-src/apply-seccomp.c b/vendor/seccomp-src/apply-seccomp.c index 3a34cb3..81c9511 100644 --- a/vendor/seccomp-src/apply-seccomp.c +++ b/vendor/seccomp-src/apply-seccomp.c @@ -246,7 +246,13 @@ int main(int argc, char *argv[]) { if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL) < 0) { die("apply-seccomp: mount(MS_PRIVATE)"); } - if (mount("proc", "/proc", "proc", MS_NOSUID | MS_NODEV | MS_NOEXEC, NULL) < 0) { + /* EPERM here means a masked /proc is underneath (unprivileged Docker) + * and the kernel domination check refused the overmount. The nested + * userns above is the isolation boundary; this remount only hides + * outer PIDs from `ls /proc`. enableWeakerNestedSandbox targets + * exactly this environment. */ + if (mount("proc", "/proc", "proc", MS_NOSUID | MS_NODEV | MS_NOEXEC, NULL) < 0 + && errno != EPERM) { die("apply-seccomp: mount(/proc)"); } diff --git a/vendor/seccomp/arm64/apply-seccomp b/vendor/seccomp/arm64/apply-seccomp index 001b312f6421c374a2fd9523f2f6c175bf059897..9801e1242dfd84b62116a432cb59774f24957cad 100755 GIT binary patch delta 218216 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