zames_pro 2.90.13 → 2.90.15

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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.90.15] - 2026-10-29
11
+
12
+ ### Changed
13
+
14
+ - test(browser): pin the headless user-agent sanitizer contract
15
+
16
+ ## [2.90.14] - 2026-10-29
17
+
18
+ ### Fixed
19
+
20
+ - **sandbox:** block a recursive rm of an absolute or outside path
21
+
10
22
  ## [2.90.13] - 2026-10-29
11
23
 
12
24
  ### Fixed
package/dist/shell.js CHANGED
@@ -70,6 +70,48 @@ export function assertCommandInsideRoot(root, command) {
70
70
  if (/\bchroot\b/i.test(cmd)) {
71
71
  throw new Error('Sandbox: chroot is forbidden');
72
72
  }
73
+ // A RECURSIVE deletion aimed at an absolute path, `~`, `.`, `..` or the root
74
+ // itself can never be "inside the root": a single typo in a cleanup command
75
+ // destroyed the whole project tree (and the directories above it) in a real
76
+ // session. Only the destructive form is refused — `rm file.txt` and
77
+ // `rm -rf tmp/build` stay allowed.
78
+ const rmRe = /(?:^|[;&|(]\s*)\s*(?:sudo\s+)?rm\s+([^;&|)]+)/gi;
79
+ let rm;
80
+ while ((rm = rmRe.exec(cmd))) {
81
+ const words = rm[1].trim().split(/\s+/);
82
+ const recursive = words.some((w) => w === '--recursive' || /^-[a-zA-Z]*[rR][a-zA-Z]*$/.test(w));
83
+ if (!recursive)
84
+ continue;
85
+ for (const w of words) {
86
+ if (w.startsWith('-'))
87
+ continue;
88
+ const raw = w.replace(/["']/g, '');
89
+ if (!raw)
90
+ continue;
91
+ if (raw === '/' ||
92
+ raw === '.' ||
93
+ raw === '..' ||
94
+ raw === '~' ||
95
+ raw.startsWith('~/') ||
96
+ raw.startsWith('/') ||
97
+ raw.startsWith('..')) {
98
+ throw new Error('Sandbox: recursive rm of an absolute/outside path is forbidden (' +
99
+ raw +
100
+ ')');
101
+ }
102
+ // A RELATIVE target is resolved against the root; anything that escapes
103
+ // (a `../` inside a longer path) is refused too.
104
+ const target = path.resolve(root, raw);
105
+ const rel = path.relative(root, target);
106
+ if (rel.startsWith('..') || path.isAbsolute(rel)) {
107
+ throw new Error('Sandbox: recursive rm outside ' +
108
+ root +
109
+ ' is forbidden (' +
110
+ raw +
111
+ ')');
112
+ }
113
+ }
114
+ }
73
115
  }
74
116
  function formatExecResult(err, stdout, stderr, timeout, okExitCodes) {
75
117
  const out = (stdout || '').toString();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zames_pro",
3
- "version": "2.90.13",
3
+ "version": "2.90.15",
4
4
  "description": "Terminal coding agent that drives a real browser to chat with DeepSeek, Qwen or GLM — no API key required. Reads and edits files, runs commands, commits to git, like Claude Code / Codex CLI.",
5
5
  "type": "module",
6
6
  "bin": {