@iinm/plain-agent 1.8.10 → 1.8.11

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/README.md CHANGED
@@ -322,17 +322,15 @@ Files are loaded in the following order. Settings in later files override earlie
322
322
  └── .plain-agent/
323
323
  ├── (3) config.json # Project-specific configuration
324
324
  ├── (4) config.local.json # Project-specific local configuration (including secrets)
325
- ├── memory/ # Task-specific memory files (auto-approvable, writable in sandbox)
326
- ├── tmp/ # Agent scratch space (auto-approvable, writable in sandbox)
327
- ├── claude-code-plugins/ # Cached Claude Code plugins (auto-approvable, writable in sandbox)
325
+ ├── memory/ # Task-specific memory files (auto-approvable)
326
+ ├── tmp/ # Agent scratch space (auto-approvable)
327
+ ├── claude-code-plugins/ # Cached Claude Code plugins
328
328
  ├── prompts/ # Project-specific prompts
329
329
  ├── agents/ # Project-specific agent roles
330
- ├── sandbox/ # Sandbox runner scripts (run.sh, Dockerfile)
330
+ ├── sandbox/ # Sandbox runner scripts (run.sh, Dockerfile); always require approval
331
331
  └── setup.sh # Initial setup script
332
332
  ```
333
333
 
334
- Within `.plain-agent/`, only `memory/`, `tmp/`, and `claude-code-plugins/` are auto-approvable as tool input; everything else is executed on the host or changes agent behavior, so writes/reads require explicit approval. The sandbox runner mounts `.plain-agent/` read-only and re-overlays those three scratch directories as writable.
335
-
336
334
  ### Example
337
335
 
338
336
  <details>
@@ -76,22 +76,18 @@ Generate `.plain-agent/sandbox/run.sh`. Use the following Node.js example as the
76
76
  set -eu -o pipefail
77
77
 
78
78
  # Mount .plain-agent/ as read-only over the writable project root, then
79
- # re-overlay the agent's scratch directories as writable. This prevents
80
- # in-sandbox modification of host-executed scripts (sandbox/run.sh,
81
- # setup.sh) and agent config (config.json, prompts/, agents/, ...).
79
+ # re-overlay only memory/ and tmp/ as writable scratch space.
82
80
  working_dir=$(pwd)
83
81
  metadata_dir="$working_dir/.plain-agent"
84
82
  mkdir -p \
85
83
  "$metadata_dir/memory" \
86
- "$metadata_dir/tmp" \
87
- "$metadata_dir/claude-code-plugins"
84
+ "$metadata_dir/tmp"
88
85
 
89
86
  options=(
90
87
  --allow-write
91
88
  --mount-readonly "$metadata_dir:$metadata_dir"
92
89
  --mount-writable "$metadata_dir/memory:$metadata_dir/memory"
93
90
  --mount-writable "$metadata_dir/tmp:$metadata_dir/tmp"
94
- --mount-writable "$metadata_dir/claude-code-plugins:$metadata_dir/claude-code-plugins"
95
91
  --volume plain-sandbox--global--home-npm:/home/sandbox/.npm
96
92
  --volume node_modules
97
93
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iinm/plain-agent",
3
- "version": "1.8.10",
3
+ "version": "1.8.11",
4
4
  "description": "A lightweight CLI-based coding agent",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -9,6 +9,17 @@ import {
9
9
  } from "./env.mjs";
10
10
  import { noThrowSync } from "./utils/noThrow.mjs";
11
11
 
12
+ // Paths that must never be auto-approvable as tool input, even when
13
+ // git-managed. Sandbox scripts run on the host and the project config files
14
+ // drive auto-approval policy itself, so silent in-sandbox modification of
15
+ // either could lead to host code execution or self-granted privilege
16
+ // escalation.
17
+ const UNSAFE_PROJECT_PATHS = [
18
+ path.join(AGENT_PROJECT_METADATA_DIR, "sandbox"),
19
+ path.join(AGENT_PROJECT_METADATA_DIR, "config.json"),
20
+ path.join(AGENT_PROJECT_METADATA_DIR, "config.local.json"),
21
+ ];
22
+
12
23
  /**
13
24
  * @param {unknown} input
14
25
  * @returns {boolean}
@@ -65,15 +76,14 @@ export function isSafeToolInputItem(arg) {
65
76
  return false;
66
77
  }
67
78
 
68
- // Inside the agent metadata directory, only the agent's known scratch
69
- // directories (memory, tmp, claude-code-plugins) are auto-approvable
70
- // (and that exception applies even when those subdirectories are
71
- // git-ignored). Other entries (sandbox/, setup.sh, config.json,
72
- // prompts/, agents/, ...) are executed on the host or change agent
73
- // behavior across sessions, so tool uses targeting them must require
74
- // explicit approval even if the file is git-managed.
75
- if (isInsideAgentMetadataDir(realPath)) {
76
- return isSafePath(realPath);
79
+ // Always require approval for these, even if git-managed.
80
+ if (isUnsafeProjectPath(realPath)) {
81
+ return false;
82
+ }
83
+
84
+ // Always allow these even if git-ignored.
85
+ if (isSafePath(realPath)) {
86
+ return true;
77
87
  }
78
88
 
79
89
  // Deny git ignored files (which may contain sensitive information or should not be accessed)
@@ -166,12 +176,18 @@ function isSafePath(targetPath) {
166
176
  * @param {string} targetPath
167
177
  * @returns {boolean}
168
178
  */
169
- function isInsideAgentMetadataDir(targetPath) {
170
- const metadataAbsPath = path.resolve(AGENT_PROJECT_METADATA_DIR);
171
- return (
172
- targetPath === metadataAbsPath ||
173
- targetPath.startsWith(`${metadataAbsPath}${path.sep}`)
174
- );
179
+ function isUnsafeProjectPath(targetPath) {
180
+ for (const unsafePath of UNSAFE_PROJECT_PATHS) {
181
+ const unsafeAbsPath = path.resolve(unsafePath);
182
+ if (
183
+ targetPath === unsafeAbsPath ||
184
+ targetPath.startsWith(`${unsafeAbsPath}${path.sep}`)
185
+ ) {
186
+ return true;
187
+ }
188
+ }
189
+
190
+ return false;
175
191
  }
176
192
 
177
193
  /**