@kendoo.agentdesk/agentdesk 0.18.3 → 0.18.4
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 +5 -0
- package/cli/session-isolation.mjs +44 -33
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,11 @@ All user-facing changes to AgentDesk. Each entry is tagged:
|
|
|
8
8
|
|
|
9
9
|
Internal refactors, infrastructure changes, and architectural notes are not listed here.
|
|
10
10
|
|
|
11
|
+
## [0.18.4] — 2026-04-18
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
- `[CLI]` Sandbox was too strict: the "deny all writes except project+scratch+tmp" rule blocked Claude and other tools from writing to their own state directories (`~/.claude`, `~/.npm`, etc.), causing sessions to crash in under 3 seconds with a misleading "hit rate/context limit" handoff. The sandbox now allows reads and writes by default and denies a specific list of sensitive paths (`~/.ssh`, `~/.aws`, `~/.gcloud`, `~/.config/gh`, `~/.docker`, `~/.kube`, `~/.agentdesk`, `~/.gitconfig`, `~/.netrc`, `~/.npmrc`, `~/.pypirc`, shell rc files). Identity-isolation goal preserved; compatibility restored.
|
|
15
|
+
|
|
11
16
|
## [0.18.3] — 2026-04-18
|
|
12
17
|
|
|
13
18
|
### Fixed
|
|
@@ -83,10 +83,10 @@ export function wrapIsolatedSpawn({ cmd, args, cwd, scratchHome, sessionId }) {
|
|
|
83
83
|
|
|
84
84
|
function macosProfile({ cwd, scratchHome }) {
|
|
85
85
|
const home = homedir();
|
|
86
|
-
// Known-sensitive
|
|
87
|
-
//
|
|
88
|
-
//
|
|
89
|
-
const
|
|
86
|
+
// Known-sensitive paths: reads AND writes denied, even though general
|
|
87
|
+
// access is allowed, so a confused agent can't slurp up other projects'
|
|
88
|
+
// tokens or clobber the user's SSH keys / shell config.
|
|
89
|
+
const denyPathsSubpath = [
|
|
90
90
|
join(home, ".ssh"),
|
|
91
91
|
join(home, ".aws"),
|
|
92
92
|
join(home, ".gcloud"),
|
|
@@ -96,36 +96,27 @@ function macosProfile({ cwd, scratchHome }) {
|
|
|
96
96
|
join(home, ".agentdesk"),
|
|
97
97
|
join(home, ".config", "agentdesk"),
|
|
98
98
|
];
|
|
99
|
-
const
|
|
99
|
+
const denyPathsLiteral = [
|
|
100
100
|
join(home, ".netrc"),
|
|
101
101
|
join(home, ".gitconfig"), // real gitconfig (scratch has its own)
|
|
102
102
|
join(home, ".npmrc"),
|
|
103
103
|
join(home, ".pypirc"),
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
scratchHome,
|
|
110
|
-
"/tmp",
|
|
111
|
-
"/private/tmp",
|
|
112
|
-
"/private/var/folders", // macOS TMPDIR lives here
|
|
104
|
+
join(home, ".zshrc"),
|
|
105
|
+
join(home, ".zprofile"),
|
|
106
|
+
join(home, ".bashrc"),
|
|
107
|
+
join(home, ".bash_profile"),
|
|
108
|
+
join(home, ".profile"),
|
|
113
109
|
];
|
|
114
110
|
|
|
115
111
|
const sb = [
|
|
116
112
|
`(version 1)`,
|
|
117
113
|
`(allow default)`,
|
|
118
114
|
``,
|
|
119
|
-
`; Deny
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
`(deny file-write*)`,
|
|
125
|
-
...writeSubpaths.map(p => `(allow file-write* (subpath ${sbString(p)}))`),
|
|
126
|
-
``,
|
|
127
|
-
`; Allow writes to devices so stdio, /dev/null, tty, ptys all work`,
|
|
128
|
-
`(allow file-write* (subpath "/dev"))`,
|
|
115
|
+
`; Deny access (read + write) to known credential and shell-config paths.`,
|
|
116
|
+
`; Agents can't read other projects' tokens, can't overwrite SSH keys or`,
|
|
117
|
+
`; rewrite the user's shell rc files.`,
|
|
118
|
+
...denyPathsSubpath.map(p => `(deny file-read* file-write* (subpath ${sbString(p)}))`),
|
|
119
|
+
...denyPathsLiteral.map(p => `(deny file-read* file-write* (literal ${sbString(p)}))`),
|
|
129
120
|
``,
|
|
130
121
|
].join("\n");
|
|
131
122
|
|
|
@@ -139,22 +130,42 @@ function sbString(s) {
|
|
|
139
130
|
// --- Linux bwrap args --------------------------------------------------------
|
|
140
131
|
|
|
141
132
|
function bwrapArgs({ cwd, scratchHome }) {
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
//
|
|
133
|
+
// Bind the whole filesystem normally so tools that need to write state
|
|
134
|
+
// (claude, npm, pip, yarn, etc.) keep working. Then cover the sensitive
|
|
135
|
+
// credential/config paths with tmpfs mounts so the agent can't read or
|
|
136
|
+
// write them — other projects' .env, SSH keys, shell rc files, etc.
|
|
145
137
|
const home = homedir();
|
|
146
|
-
|
|
147
|
-
|
|
138
|
+
const denyPaths = [
|
|
139
|
+
join(home, ".ssh"),
|
|
140
|
+
join(home, ".aws"),
|
|
141
|
+
join(home, ".gcloud"),
|
|
142
|
+
join(home, ".config", "gh"),
|
|
143
|
+
join(home, ".docker"),
|
|
144
|
+
join(home, ".kube"),
|
|
145
|
+
join(home, ".agentdesk"),
|
|
146
|
+
join(home, ".config", "agentdesk"),
|
|
147
|
+
join(home, ".netrc"),
|
|
148
|
+
join(home, ".gitconfig"),
|
|
149
|
+
join(home, ".npmrc"),
|
|
150
|
+
join(home, ".pypirc"),
|
|
151
|
+
join(home, ".zshrc"),
|
|
152
|
+
join(home, ".zprofile"),
|
|
153
|
+
join(home, ".bashrc"),
|
|
154
|
+
join(home, ".bash_profile"),
|
|
155
|
+
join(home, ".profile"),
|
|
156
|
+
];
|
|
157
|
+
const args = [
|
|
158
|
+
"--bind", "/", "/",
|
|
148
159
|
"--dev-bind", "/dev", "/dev",
|
|
149
160
|
"--proc", "/proc",
|
|
150
|
-
"--tmpfs", "/tmp",
|
|
151
|
-
"--tmpfs", home, // blank user home
|
|
152
|
-
"--bind", cwd, cwd, // project dir writable
|
|
153
|
-
"--bind", scratchHome, scratchHome, // scratch writable (HOME env var points here)
|
|
154
161
|
"--die-with-parent",
|
|
155
162
|
"--unshare-ipc",
|
|
156
163
|
"--unshare-uts",
|
|
157
164
|
"--unshare-pid",
|
|
158
165
|
// Network is NOT unshared — agents need network for tracker APIs and git.
|
|
159
166
|
];
|
|
167
|
+
for (const p of denyPaths) args.push("--tmpfs", p);
|
|
168
|
+
// scratch HOME + project dir stay writable (already bound via --bind / /
|
|
169
|
+
// above — tmpfs blanks only the specific deny paths, not the rest).
|
|
170
|
+
return args;
|
|
160
171
|
}
|