@agenshield/sandbox 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -25,10 +25,10 @@ export declare const GUARDED_SHELL_CONTENT = "#!/bin/zsh\n# guarded-shell: launc
25
25
  * ZDOTDIR .zshenv — runs after /etc/zshenv (which calls path_helper on macOS).
26
26
  * Overrides PATH to only include $HOME/bin.
27
27
  */
28
- export declare const ZDOT_ZSHENV_CONTENT = "# AgenShield restricted .zshenv\n# Runs AFTER /etc/zshenv \u2014 overrides path_helper's full system PATH.\n\n# ALWAYS set HOME based on actual user, never inherit\nexport HOME=\"/Users/$(id -un)\"\nexport PATH=\"$HOME/bin\"\nexport SHELL=\"/usr/local/bin/guarded-shell\"\n\n# Clear any leftover env tricks\nunset DYLD_LIBRARY_PATH DYLD_FALLBACK_LIBRARY_PATH DYLD_INSERT_LIBRARIES\nunset PYTHONPATH NODE_PATH RUBYLIB PERL5LIB\nunset SSH_ASKPASS LD_PRELOAD\n";
28
+ export declare const ZDOT_ZSHENV_CONTENT = "# AgenShield restricted .zshenv\n# Runs AFTER /etc/zshenv \u2014 overrides path_helper's full system PATH.\n\n# ALWAYS set HOME based on actual user, never inherit\nexport HOME=\"/Users/$(id -un)\"\nexport HISTFILE=\"$HOME/.zsh_history\"\n\n# Suppress locale to prevent /etc/zshrc from calling locale command\nexport LC_ALL=C LANG=C\n\nexport PATH=\"$HOME/bin\"\nexport SHELL=\"/usr/local/bin/guarded-shell\"\n\n# Clear any leftover env tricks\nunset DYLD_LIBRARY_PATH DYLD_FALLBACK_LIBRARY_PATH DYLD_INSERT_LIBRARIES\nunset PYTHONPATH NODE_PATH RUBYLIB PERL5LIB\nunset SSH_ASKPASS LD_PRELOAD\n";
29
29
  /**
30
30
  * ZDOTDIR .zshrc — interactive shell restrictions.
31
31
  * Applies RESTRICTED mode, locks variables, disables builtins, installs hooks.
32
32
  */
33
- export declare const ZDOT_ZSHRC_CONTENT = "# AgenShield restricted .zshrc\n# Applied to every interactive shell for the agent user.\n\nemulate -LR zsh\n\n# ---- Shell options ----\n# Note: NOT using setopt RESTRICTED as it disables cd entirely.\n# Instead we use preexec hooks and builtin disable for enforcement.\nsetopt NO_CASE_GLOB\nsetopt NO_BEEP\n\n# ---- Lock critical variables (readonly) ----\ntypeset -r PATH HOME SHELL\n\n# ---- Enforcement helpers ----\ndeny() {\n print -r -- \"Denied by policy\"\n return 126\n}\n\nis_allowed_cmd() {\n local cmd=\"$1\"\n\n # Allow shell builtins we explicitly permit\n case \"\\$cmd\" in\n cd|pwd|echo|printf|test|true|false|exit|return|break|continue|shift|set|unset|export|typeset|local|declare|readonly|let|read|print|pushd|popd|dirs|jobs|fg|bg|kill|wait|times|ulimit|umask|history|fc|type|whence|which|where|rehash)\n return 0\n ;;\n esac\n\n # Deny path execution outright\n [[ \"$cmd\" == */* ]] && return 1\n\n # Resolve command path\n local resolved\n resolved=\"\\$(whence -p -- \"\\$cmd\" 2>/dev/null)\" || return 1\n\n # Must live under HOME/bin exactly\n [[ \"\\$resolved\" == \"$HOME/bin/\"* ]] && return 0\n return 1\n}\n\n# ---- Block dangerous builtins ----\ndisable -r builtin command exec eval hash nohup setopt source unfunction functions alias unalias 2>/dev/null || true\n\n# ---- Intercept every interactive command before execution ----\npreexec() {\n local line=\"$1\"\n local cmd=\"${line%%[[:space:]]*}\"\n\n # Empty / whitespace lines\n [[ -z \"\\$cmd\" ]] && return 0\n\n # Deny anything with slash in the command token (direct path execution)\n [[ \"\\$cmd\" == */* ]] && { print -r -- \"Denied: direct path execution\"; kill -KILL $$; }\n\n # Deny anything not allowed\n if ! is_allowed_cmd \"\\$cmd\"; then\n print -r -- \"Denied: \\$cmd (not in \\$HOME/bin)\"\n kill -KILL $$\n fi\n}\n\n# ---- Also intercept non-interactive \\`zsh -c\\` cases ----\nTRAPDEBUG() {\n local line=\"${ZSH_DEBUG_CMD:-$1}\"\n local cmd=\"${line%%[[:space:]]*}\"\n [[ -z \"\\$cmd\" ]] && return 0\n\n [[ \"\\$cmd\" == */* ]] && { print -r -- \"Denied: direct path execution\"; return 126; }\n is_allowed_cmd \"\\$cmd\" || { print -r -- \"Denied: \\$cmd\"; return 126; }\n return 0\n}\n\n# ---- Ensure accessible working directory ----\ncd \"$HOME\" 2>/dev/null || cd /\n";
33
+ export declare const ZDOT_ZSHRC_CONTENT = "# AgenShield restricted .zshrc\n# Applied to every interactive shell for the agent user.\n\nemulate -LR zsh\n\n# ---- Shell options ----\n# Note: NOT using setopt RESTRICTED as it disables cd entirely.\n# Instead we use preexec hooks and builtin disable for enforcement.\nsetopt NO_CASE_GLOB\nsetopt NO_BEEP\n\n# ---- Lock critical variables (readonly) ----\ntypeset -r PATH HOME SHELL\n\n# ---- Enforcement helpers ----\ndeny() {\n print -r -- \"Denied by policy\"\n return 126\n}\n\nis_allowed_cmd() {\n local cmd=\"$1\"\n\n # Allow shell builtins we explicitly permit\n case \"$cmd\" in\n cd|pwd|echo|printf|test|true|false|exit|return|break|continue|shift|set|unset|export|typeset|local|declare|readonly|let|read|print|pushd|popd|dirs|jobs|fg|bg|kill|wait|times|ulimit|umask|history|fc|type|whence|which|where|rehash)\n return 0\n ;;\n esac\n\n # Deny path execution outright\n [[ \"$cmd\" == */* ]] && return 1\n\n # Resolve command path\n local resolved\n resolved=\"$(whence -p -- \"$cmd\" 2>/dev/null)\" || return 1\n\n # Must live under HOME/bin exactly\n [[ \"$resolved\" == \"$HOME/bin/\"* ]] && return 0\n return 1\n}\n\n# ---- Block dangerous builtins ----\ndisable -r builtin command exec eval hash nohup setopt source unfunction functions alias unalias 2>/dev/null || true\n\n# ---- Intercept every interactive command before execution ----\npreexec() {\n local line=\"$1\"\n local cmd=\"${line%%[[:space:]]*}\"\n\n # Empty / whitespace lines\n [[ -z \"$cmd\" ]] && return 0\n\n # Deny anything with slash in the command token (direct path execution)\n [[ \"$cmd\" == */* ]] && { print -r -- \"Denied: direct path execution\"; kill -KILL $$; }\n\n # Deny anything not allowed\n if ! is_allowed_cmd \"$cmd\"; then\n print -r -- \"Denied: $cmd (not in $HOME/bin)\"\n kill -KILL $$\n fi\n}\n\n# ---- Also intercept non-interactive \\`zsh -c\\` cases ----\nTRAPDEBUG() {\n local line=\"${ZSH_DEBUG_CMD:-$1}\"\n local cmd=\"${line%%[[:space:]]*}\"\n [[ -z \"$cmd\" ]] && return 0\n\n [[ \"$cmd\" == */* ]] && { print -r -- \"Denied: direct path execution\"; return 126; }\n is_allowed_cmd \"$cmd\" || { print -r -- \"Denied: $cmd\"; return 126; }\n return 0\n}\n\n# ---- Ensure accessible working directory ----\ncd \"$HOME\" 2>/dev/null || cd /\n";
34
34
  //# sourceMappingURL=guarded-shell.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"guarded-shell.d.ts","sourceRoot":"","sources":["../src/guarded-shell.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,kBAAkB,iCAAiC,CAAC;AACjE,eAAO,MAAM,QAAQ,yBAAyB,CAAC;AAE/C;;;GAGG;AACH,eAAO,MAAM,qBAAqB,mjBAgBjC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,8cAY/B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,gyEA4E9B,CAAC"}
1
+ {"version":3,"file":"guarded-shell.d.ts","sourceRoot":"","sources":["../src/guarded-shell.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,kBAAkB,iCAAiC,CAAC;AACjE,eAAO,MAAM,QAAQ,yBAAyB,CAAC;AAE/C;;;GAGG;AACH,eAAO,MAAM,qBAAqB,mjBAgBjC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,ulBAiB/B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,swEA4E9B,CAAC"}
package/index.js CHANGED
@@ -45,6 +45,11 @@ exec /bin/zsh
45
45
 
46
46
  # ALWAYS set HOME based on actual user, never inherit
47
47
  export HOME="/Users/$(id -un)"
48
+ export HISTFILE="$HOME/.zsh_history"
49
+
50
+ # Suppress locale to prevent /etc/zshrc from calling locale command
51
+ export LC_ALL=C LANG=C
52
+
48
53
  export PATH="$HOME/bin"
49
54
  export SHELL="/usr/local/bin/guarded-shell"
50
55
 
@@ -77,7 +82,7 @@ is_allowed_cmd() {
77
82
  local cmd="$1"
78
83
 
79
84
  # Allow shell builtins we explicitly permit
80
- case "\\$cmd" in
85
+ case "$cmd" in
81
86
  cd|pwd|echo|printf|test|true|false|exit|return|break|continue|shift|set|unset|export|typeset|local|declare|readonly|let|read|print|pushd|popd|dirs|jobs|fg|bg|kill|wait|times|ulimit|umask|history|fc|type|whence|which|where|rehash)
82
87
  return 0
83
88
  ;;
@@ -88,10 +93,10 @@ is_allowed_cmd() {
88
93
 
89
94
  # Resolve command path
90
95
  local resolved
91
- resolved="\\$(whence -p -- "\\$cmd" 2>/dev/null)" || return 1
96
+ resolved="$(whence -p -- "$cmd" 2>/dev/null)" || return 1
92
97
 
93
98
  # Must live under HOME/bin exactly
94
- [[ "\\$resolved" == "$HOME/bin/"* ]] && return 0
99
+ [[ "$resolved" == "$HOME/bin/"* ]] && return 0
95
100
  return 1
96
101
  }
97
102
 
@@ -104,14 +109,14 @@ preexec() {
104
109
  local cmd="\${line%%[[:space:]]*}"
105
110
 
106
111
  # Empty / whitespace lines
107
- [[ -z "\\$cmd" ]] && return 0
112
+ [[ -z "$cmd" ]] && return 0
108
113
 
109
114
  # Deny anything with slash in the command token (direct path execution)
110
- [[ "\\$cmd" == */* ]] && { print -r -- "Denied: direct path execution"; kill -KILL $$; }
115
+ [[ "$cmd" == */* ]] && { print -r -- "Denied: direct path execution"; kill -KILL $$; }
111
116
 
112
117
  # Deny anything not allowed
113
- if ! is_allowed_cmd "\\$cmd"; then
114
- print -r -- "Denied: \\$cmd (not in \\$HOME/bin)"
118
+ if ! is_allowed_cmd "$cmd"; then
119
+ print -r -- "Denied: $cmd (not in $HOME/bin)"
115
120
  kill -KILL $$
116
121
  fi
117
122
  }
@@ -120,10 +125,10 @@ preexec() {
120
125
  TRAPDEBUG() {
121
126
  local line="\${ZSH_DEBUG_CMD:-$1}"
122
127
  local cmd="\${line%%[[:space:]]*}"
123
- [[ -z "\\$cmd" ]] && return 0
128
+ [[ -z "$cmd" ]] && return 0
124
129
 
125
- [[ "\\$cmd" == */* ]] && { print -r -- "Denied: direct path execution"; return 126; }
126
- is_allowed_cmd "\\$cmd" || { print -r -- "Denied: \\$cmd"; return 126; }
130
+ [[ "$cmd" == */* ]] && { print -r -- "Denied: direct path execution"; return 126; }
131
+ is_allowed_cmd "$cmd" || { print -r -- "Denied: $cmd"; return 126; }
127
132
  return 0
128
133
  }
129
134
 
@@ -1265,22 +1270,25 @@ function createDirectoryStructure(config) {
1265
1270
  group: socketGroupName
1266
1271
  },
1267
1272
  [`${agentHome}/bin`]: {
1268
- mode: 493,
1269
- // only owner can write
1273
+ mode: 1533,
1274
+ // setgid + group-writable
1270
1275
  owner: brokerUsername,
1271
1276
  // broker owns bin, can create skill wrappers
1272
1277
  group: socketGroupName
1273
1278
  // agent can read+exec via group
1274
1279
  },
1275
1280
  [`${agentHome}/.openclaw`]: {
1276
- mode: 493,
1277
- owner: "root",
1281
+ mode: 1533,
1282
+ // setgid + group-writable for broker
1283
+ owner: brokerUsername,
1284
+ // broker needs write access
1278
1285
  group: socketGroupName
1279
1286
  },
1280
1287
  [`${agentHome}/.openclaw/skills`]: {
1281
1288
  mode: 1533,
1282
1289
  // setgid bit, group-writable for broker to create subdirectories
1283
- owner: "root",
1290
+ owner: brokerUsername,
1291
+ // broker needs write access
1284
1292
  group: socketGroupName
1285
1293
  },
1286
1294
  [`${agentHome}/workspace`]: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenshield/sandbox",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "description": "User isolation and sandboxing utilities for AgenShield",
6
6
  "main": "./index.js",