mirror of
https://github.com/anthropic-experimental/sandbox-runtime.git
synced 2026-05-06 21:52:30 +08:00
Fix enableWeakerNestedSandbox after apply-seccomp namespace changes
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.
This commit is contained in:
15
package-lock.json
generated
15
package-lock.json
generated
@@ -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"
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
8
vendor/seccomp-src/apply-seccomp.c
vendored
8
vendor/seccomp-src/apply-seccomp.c
vendored
@@ -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)");
|
||||
}
|
||||
|
||||
|
||||
BIN
vendor/seccomp/arm64/apply-seccomp
vendored
BIN
vendor/seccomp/arm64/apply-seccomp
vendored
Binary file not shown.
BIN
vendor/seccomp/x64/apply-seccomp
vendored
BIN
vendor/seccomp/x64/apply-seccomp
vendored
Binary file not shown.
Reference in New Issue
Block a user