autoclaw 1.3.3 → 1.3.5
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 +303 -289
- package/README.zh-CN.md +15 -1
- package/dist/agent.js +92 -7
- package/dist/batch.js +2 -0
- package/dist/index.js +5 -4
- package/dist/sandbox.js +94 -0
- package/dist/shell.js +55 -32
- package/dist/tools/background.js +165 -0
- package/dist/tools/core.js +44 -3
- package/dist/tools/index.js +5 -1
- package/package.json +1 -1
package/dist/tools/core.js
CHANGED
|
@@ -3,6 +3,8 @@ import * as path from 'path';
|
|
|
3
3
|
import inquirer from 'inquirer';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import { execShellCommand } from '../shell.js';
|
|
6
|
+
import { resolveSandboxMode, sandboxBackend, sandboxedInvocation } from '../sandbox.js';
|
|
7
|
+
import * as os from 'os';
|
|
6
8
|
const DEFAULT_SHELL_TIMEOUT_MS = 120000;
|
|
7
9
|
const SHELL_MAX_BUFFER = 10 * 1024 * 1024;
|
|
8
10
|
// Bounded reads keep a huge file from exhausting memory or the model context;
|
|
@@ -27,6 +29,24 @@ export function matchDangerousPattern(command) {
|
|
|
27
29
|
const hit = DANGEROUS_PATTERNS.find(p => p.re.test(command));
|
|
28
30
|
return hit ? hit.label : null;
|
|
29
31
|
}
|
|
32
|
+
// An unattended agent reads web pages and repos; a prompt injection must not
|
|
33
|
+
// end up reading AutoClaw's own credential stores (or classic .env files)
|
|
34
|
+
// and exfiltrating them. Blocked for read_file/write_file unless
|
|
35
|
+
// --allow-dangerous. execute_shell_command is not pattern-restricted here.
|
|
36
|
+
export function isSensitivePath(p) {
|
|
37
|
+
const norm = path.normalize(String(p)).toLowerCase();
|
|
38
|
+
const protectedFiles = [
|
|
39
|
+
path.join(os.homedir(), '.autoclaw', 'setting.json').toLowerCase(),
|
|
40
|
+
path.join(os.homedir(), '.autoclaw', '.env').toLowerCase(),
|
|
41
|
+
path.join(process.cwd(), '.autoclaw', 'setting.json').toLowerCase()
|
|
42
|
+
];
|
|
43
|
+
if (protectedFiles.includes(norm))
|
|
44
|
+
return true;
|
|
45
|
+
return path.basename(norm).startsWith('.env');
|
|
46
|
+
}
|
|
47
|
+
function sensitivePathBlock(p, verb) {
|
|
48
|
+
return `Error: ${p} is blocked by AutoClaw safety policy (credential/secret store). It was NOT ${verb === 'read' ? 'read' : 'written'}. If this task genuinely requires it, restart AutoClaw with --allow-dangerous.`;
|
|
49
|
+
}
|
|
30
50
|
export const ShellTool = {
|
|
31
51
|
name: "Shell Execution",
|
|
32
52
|
definition: {
|
|
@@ -56,6 +76,21 @@ export const ShellTool = {
|
|
|
56
76
|
}
|
|
57
77
|
}
|
|
58
78
|
const timeoutMs = Number(config?.shellTimeout || process.env.AUTOCLOW_SHELL_TIMEOUT || DEFAULT_SHELL_TIMEOUT_MS);
|
|
79
|
+
// Sandbox policy: non-default modes wrap the invocation in a platform
|
|
80
|
+
// backend, or refuse (fail-closed) when no backend exists.
|
|
81
|
+
const sandboxMode = resolveSandboxMode(config);
|
|
82
|
+
let sandboxed;
|
|
83
|
+
if (sandboxMode !== 'danger-full-access') {
|
|
84
|
+
const backend = sandboxBackend();
|
|
85
|
+
if (!backend.available) {
|
|
86
|
+
return `Error: sandbox mode "${sandboxMode}" is configured but no sandbox backend is available: ${backend.detail}`;
|
|
87
|
+
}
|
|
88
|
+
const inv = sandboxedInvocation(args.command, sandboxMode, process.cwd());
|
|
89
|
+
if ('blocked' in inv) {
|
|
90
|
+
return `Error: sandbox mode "${sandboxMode}" cannot wrap this command: ${inv.detail}`;
|
|
91
|
+
}
|
|
92
|
+
sandboxed = inv;
|
|
93
|
+
}
|
|
59
94
|
// Check for auto-confirm flag
|
|
60
95
|
if (!config?.autoConfirm) {
|
|
61
96
|
if (!process.stdin.isTTY) {
|
|
@@ -78,7 +113,7 @@ export const ShellTool = {
|
|
|
78
113
|
console.log(chalk.gray("(Auto-confirming command execution due to --yes flag)"));
|
|
79
114
|
}
|
|
80
115
|
try {
|
|
81
|
-
const r = await execShellCommand(args.command, { timeoutMs, maxBuffer: SHELL_MAX_BUFFER });
|
|
116
|
+
const r = await execShellCommand(args.command, { timeoutMs, maxBuffer: SHELL_MAX_BUFFER, sandboxed });
|
|
82
117
|
if (r.timedOut) {
|
|
83
118
|
return `Command timed out after ${timeoutMs}ms and was terminated.\nStdout: ${r.stdout}\nStderr: ${r.stderr}`;
|
|
84
119
|
}
|
|
@@ -107,7 +142,10 @@ export const ReadFileTool = {
|
|
|
107
142
|
}
|
|
108
143
|
}
|
|
109
144
|
},
|
|
110
|
-
handler: async (args) => {
|
|
145
|
+
handler: async (args, config) => {
|
|
146
|
+
if (!config?.allowDangerous && isSensitivePath(args.path)) {
|
|
147
|
+
return sensitivePathBlock(args.path, 'read');
|
|
148
|
+
}
|
|
111
149
|
let fh;
|
|
112
150
|
try {
|
|
113
151
|
fh = await fs.open(args.path, 'r');
|
|
@@ -151,7 +189,10 @@ export const WriteFileTool = {
|
|
|
151
189
|
}
|
|
152
190
|
}
|
|
153
191
|
},
|
|
154
|
-
handler: async (args) => {
|
|
192
|
+
handler: async (args, config) => {
|
|
193
|
+
if (!config?.allowDangerous && isSensitivePath(args.path)) {
|
|
194
|
+
return sensitivePathBlock(args.path, 'write');
|
|
195
|
+
}
|
|
155
196
|
try {
|
|
156
197
|
await fs.mkdir(path.dirname(args.path), { recursive: true });
|
|
157
198
|
await fs.writeFile(args.path, args.content, 'utf-8');
|
package/dist/tools/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { BrowserTool } from './browser.js';
|
|
|
6
6
|
import { ScreenshotTool } from './screenshot.js';
|
|
7
7
|
import { ImageTool } from './image.js';
|
|
8
8
|
import { PromptOptimizerTool } from './prompt-optimizer.js';
|
|
9
|
+
import { CheckBackgroundProcessTool, StartBackgroundProcessTool, StopBackgroundProcessTool } from './background.js';
|
|
9
10
|
// Central Registry of all available tools
|
|
10
11
|
export const toolRegistry = [
|
|
11
12
|
ShellTool,
|
|
@@ -18,7 +19,10 @@ export const toolRegistry = [
|
|
|
18
19
|
NotifyTool,
|
|
19
20
|
BrowserTool,
|
|
20
21
|
ScreenshotTool,
|
|
21
|
-
ImageTool
|
|
22
|
+
ImageTool,
|
|
23
|
+
StartBackgroundProcessTool,
|
|
24
|
+
CheckBackgroundProcessTool,
|
|
25
|
+
StopBackgroundProcessTool
|
|
22
26
|
];
|
|
23
27
|
export function getToolDefinitions(config) {
|
|
24
28
|
return toolRegistry
|