agent-security-scanner-mcp 3.10.3 → 3.12.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.
- package/README.md +41 -4
- package/analyzer.py +4 -0
- package/index.js +37 -14
- package/openclaw.plugin.json +3 -3
- package/package.json +3 -1
- package/skills/clawhub/CLAWPROOF.md +448 -0
- package/src/cli/audit.js +10 -3
- package/src/cli/demo.js +3 -13
- package/src/cli/doctor.js +15 -13
- package/src/cli/harden.js +10 -3
- package/src/cli/init.js +11 -5
- package/src/cli/scan-clawhub-full.js +518 -0
- package/src/cli/scan-clawhub-safe.js +393 -0
- package/src/cli/scan-clawhub.js +308 -0
- package/src/config.js +4 -1
- package/src/daemon-client.js +3 -1
- package/src/python.js +54 -0
- package/src/tools/scan-action.js +222 -2
- package/src/tools/scan-prompt.js +34 -0
- package/src/tools/scan-skill-prompt.js +547 -0
- package/src/tools/scan-skill.js +438 -80
- package/src/utils.js +71 -12
package/src/cli/audit.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// src/cli/audit.js — OpenClaw configuration security audit (stub)
|
|
2
2
|
|
|
3
3
|
export async function runAudit(args) {
|
|
4
|
-
|
|
4
|
+
const allowStub = args.includes('--allow-stub');
|
|
5
|
+
|
|
6
|
+
console.log('\n Security Audit [NOT YET IMPLEMENTED]\n');
|
|
5
7
|
console.log(' This command will check your OpenClaw configuration for security issues.');
|
|
6
|
-
console.log('
|
|
7
|
-
console.log(' WARNING: This is an experimental stub. No actual checks are performed.\n');
|
|
8
|
+
console.log(' Implementation is in progress.\n');
|
|
8
9
|
console.log(' Planned checks (60+):');
|
|
9
10
|
console.log(' - Gateway: bind mode, auth, token strength, HTTPS, CORS');
|
|
10
11
|
console.log(' - Permissions: config files, credentials, session transcripts');
|
|
@@ -15,4 +16,10 @@ export async function runAudit(args) {
|
|
|
15
16
|
console.log(' - Plugins: unsigned, permissive, outdated');
|
|
16
17
|
console.log(' - Credentials: plaintext secrets, exposed API keys\n');
|
|
17
18
|
console.log(' OWASP ASI Top 10 mapping for all findings.\n');
|
|
19
|
+
|
|
20
|
+
if (!allowStub) {
|
|
21
|
+
console.error(' ERROR: audit is not yet implemented. No checks were performed.');
|
|
22
|
+
console.error(' Pass --allow-stub to suppress this error in CI.\n');
|
|
23
|
+
throw new Error('audit command is not yet implemented');
|
|
24
|
+
}
|
|
18
25
|
}
|
package/src/cli/demo.js
CHANGED
|
@@ -4,6 +4,7 @@ import { join } from "path";
|
|
|
4
4
|
import { createInterface } from "readline";
|
|
5
5
|
import { dirname } from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
|
+
import { resolvePythonCommand, pythonArgs } from "../python.js";
|
|
7
8
|
|
|
8
9
|
// Handle both ESM and CJS bundling (Smithery bundles to CJS)
|
|
9
10
|
let __dirname;
|
|
@@ -178,22 +179,11 @@ export async function runDemo(args) {
|
|
|
178
179
|
|
|
179
180
|
// Run the analyzer
|
|
180
181
|
const analyzerPath = join(__dirname, '..', '..', 'analyzer.py');
|
|
181
|
-
|
|
182
|
-
const py3 = checkCommand('python3', ['--version']);
|
|
183
|
-
if (!py3.ok) {
|
|
184
|
-
const py = checkCommand('python', ['--version']);
|
|
185
|
-
if (py.ok && py.output.includes('3.')) {
|
|
186
|
-
pythonCmd = 'python';
|
|
187
|
-
} else {
|
|
188
|
-
console.log(` Error: Python 3 not found. Run "npx agent-security-scanner-mcp doctor" to diagnose.\n`);
|
|
189
|
-
unlinkSync(filepath);
|
|
190
|
-
process.exit(1);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
182
|
+
const pythonCmd = resolvePythonCommand();
|
|
193
183
|
|
|
194
184
|
let results;
|
|
195
185
|
try {
|
|
196
|
-
const output = execFileSync(pythonCmd, [analyzerPath, filepath], { timeout: 30000, encoding: 'utf-8' });
|
|
186
|
+
const output = execFileSync(pythonCmd, [...pythonArgs(), analyzerPath, filepath], { timeout: 30000, encoding: 'utf-8' });
|
|
197
187
|
results = JSON.parse(output);
|
|
198
188
|
} catch (e) {
|
|
199
189
|
console.log(` Error running analyzer: ${e.message}\n`);
|
package/src/cli/doctor.js
CHANGED
|
@@ -4,6 +4,7 @@ import { dirname, join } from "path";
|
|
|
4
4
|
import { homedir, platform } from "os";
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
6
|
import { getDaemonClient } from '../daemon-client.js';
|
|
7
|
+
import { resolvePythonCommand, pythonArgs } from '../python.js';
|
|
7
8
|
|
|
8
9
|
// Handle both ESM and CJS bundling (Smithery bundles to CJS)
|
|
9
10
|
let __dirname;
|
|
@@ -123,22 +124,23 @@ export async function runDoctor(args) {
|
|
|
123
124
|
issues++;
|
|
124
125
|
}
|
|
125
126
|
|
|
126
|
-
// 2. Python 3
|
|
127
|
+
// 2. Python 3 (uses the same resolver as the runtime)
|
|
127
128
|
let pythonCmd = null;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const py = checkCommand('python', ['--version']);
|
|
134
|
-
if (py.ok && py.output.includes('3.')) {
|
|
135
|
-
pythonCmd = 'python';
|
|
136
|
-
console.log(` \u2713 ${py.output}`);
|
|
129
|
+
try {
|
|
130
|
+
pythonCmd = resolvePythonCommand();
|
|
131
|
+
const pyVer = checkCommand(pythonCmd, [...pythonArgs(), '--version']);
|
|
132
|
+
if (pyVer.ok) {
|
|
133
|
+
console.log(` \u2713 ${pyVer.output} (resolved as '${pythonCmd}${pythonArgs().length ? ' ' + pythonArgs().join(' ') : ''}')`);
|
|
137
134
|
} else {
|
|
135
|
+
pythonCmd = null;
|
|
138
136
|
console.log(` \u2717 Python 3 not found`);
|
|
139
137
|
console.log(` Install: https://python.org/downloads/`);
|
|
140
138
|
issues++;
|
|
141
139
|
}
|
|
140
|
+
} catch {
|
|
141
|
+
console.log(` \u2717 Python 3 not found`);
|
|
142
|
+
console.log(` Install: https://python.org/downloads/`);
|
|
143
|
+
issues++;
|
|
142
144
|
}
|
|
143
145
|
|
|
144
146
|
// 3. analyzer.py reachable
|
|
@@ -173,7 +175,7 @@ export async function runDoctor(args) {
|
|
|
173
175
|
|
|
174
176
|
// 4. Python can import yaml (analyzer dependency check)
|
|
175
177
|
if (pythonCmd && existsSync(analyzerPath)) {
|
|
176
|
-
const yamlCheck = checkCommand(pythonCmd, ['-c', 'import yaml; print("ok")']);
|
|
178
|
+
const yamlCheck = checkCommand(pythonCmd, [...pythonArgs(), '-c', 'import yaml; print("ok")']);
|
|
177
179
|
if (yamlCheck.ok && yamlCheck.output === 'ok') {
|
|
178
180
|
console.log(` \u2713 Analyzer engine ready (PyYAML installed)`);
|
|
179
181
|
} else {
|
|
@@ -184,7 +186,7 @@ export async function runDoctor(args) {
|
|
|
184
186
|
|
|
185
187
|
// 5. tree-sitter AST engine (optional but recommended)
|
|
186
188
|
if (pythonCmd) {
|
|
187
|
-
const tsCheck = checkCommand(pythonCmd, ['-c', 'import tree_sitter; print(tree_sitter.__version__)']);
|
|
189
|
+
const tsCheck = checkCommand(pythonCmd, [...pythonArgs(), '-c', 'import tree_sitter; print(tree_sitter.__version__)']);
|
|
188
190
|
if (tsCheck.ok && tsCheck.output) {
|
|
189
191
|
console.log(` \u2713 AST engine ready (tree-sitter ${tsCheck.output})`);
|
|
190
192
|
} else {
|
|
@@ -193,7 +195,7 @@ export async function runDoctor(args) {
|
|
|
193
195
|
console.log(` Installing tree-sitter dependencies...`);
|
|
194
196
|
const requirementsPath = join(__dirname, '..', '..', 'requirements.txt');
|
|
195
197
|
if (existsSync(requirementsPath)) {
|
|
196
|
-
const installResult = checkCommand(pythonCmd, ['-m', 'pip', 'install', '-r', requirementsPath, '--user', '--quiet']);
|
|
198
|
+
const installResult = checkCommand(pythonCmd, [...pythonArgs(), '-m', 'pip', 'install', '-r', requirementsPath, '--user', '--quiet']);
|
|
197
199
|
if (installResult.ok) {
|
|
198
200
|
console.log(` \u2713 Fixed: tree-sitter dependencies installed — AST engine enabled`);
|
|
199
201
|
fixed++;
|
package/src/cli/harden.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// src/cli/harden.js — OpenClaw auto-hardening (stub)
|
|
2
2
|
|
|
3
3
|
export async function runHarden(args) {
|
|
4
|
-
|
|
4
|
+
const allowStub = args.includes('--allow-stub');
|
|
5
|
+
|
|
6
|
+
console.log('\n Auto-Hardening [NOT YET IMPLEMENTED]\n');
|
|
5
7
|
console.log(' This command will automatically fix security issues in your OpenClaw config.');
|
|
6
|
-
console.log('
|
|
7
|
-
console.log(' WARNING: This is an experimental stub. No actions are performed.\n');
|
|
8
|
+
console.log(' Implementation is in progress.\n');
|
|
8
9
|
console.log(' Planned actions:');
|
|
9
10
|
console.log(' - Bind gateway to 127.0.0.1');
|
|
10
11
|
console.log(' - Enable token authentication');
|
|
@@ -12,4 +13,10 @@ export async function runHarden(args) {
|
|
|
12
13
|
console.log(' - Disable mDNS discovery');
|
|
13
14
|
console.log(' - Remove plaintext credentials\n');
|
|
14
15
|
console.log(' Usage: agent-security-scanner-mcp harden --fix [--dry-run]\n');
|
|
16
|
+
|
|
17
|
+
if (!allowStub) {
|
|
18
|
+
console.error(' ERROR: harden is not yet implemented. No actions were performed.');
|
|
19
|
+
console.error(' Pass --allow-stub to suppress this error in CI.\n');
|
|
20
|
+
throw new Error('harden command is not yet implemented');
|
|
21
|
+
}
|
|
15
22
|
}
|
package/src/cli/init.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFileSync, existsSync, writeFileSync, copyFileSync, mkdirSync } from "fs";
|
|
2
2
|
import { spawnSync } from "child_process";
|
|
3
3
|
import { dirname, join } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
4
5
|
import { homedir, platform } from "os";
|
|
5
6
|
import { createInterface } from "readline";
|
|
6
7
|
|
|
@@ -167,8 +168,13 @@ async function installOpenClawSkill(client, flags) {
|
|
|
167
168
|
const skillFile = client.configPath();
|
|
168
169
|
|
|
169
170
|
// Find the source skill file (bundled with the package)
|
|
170
|
-
|
|
171
|
-
|
|
171
|
+
let __initDir;
|
|
172
|
+
try {
|
|
173
|
+
__initDir = dirname(fileURLToPath(import.meta.url));
|
|
174
|
+
} catch {
|
|
175
|
+
__initDir = process.cwd();
|
|
176
|
+
}
|
|
177
|
+
const sourceSkill = join(__initDir, '..', '..', 'skills', 'openclaw', 'SKILL.md');
|
|
172
178
|
|
|
173
179
|
console.log(`\n Client: ${client.name}`);
|
|
174
180
|
console.log(` Skill: ${skillDir}`);
|
|
@@ -248,9 +254,9 @@ async function installCodexMCP(flags, serverName) {
|
|
|
248
254
|
console.log(` Config: ~/.codex/config.toml (managed by codex CLI)`);
|
|
249
255
|
console.log(` OS: ${platform()} (${process.arch})\n`);
|
|
250
256
|
|
|
251
|
-
// Check codex CLI is available
|
|
252
|
-
const
|
|
253
|
-
if (
|
|
257
|
+
// Check codex CLI is available (cross-platform: probe directly instead of using which/where)
|
|
258
|
+
const codexCheck = spawnSync('codex', ['--version'], { encoding: 'utf-8', timeout: 10000, stdio: ['pipe', 'pipe', 'pipe'] });
|
|
259
|
+
if (codexCheck.status !== 0 || codexCheck.error) {
|
|
254
260
|
console.error(` ERROR: 'codex' CLI not found in PATH.`);
|
|
255
261
|
console.error(` Install it first: https://github.com/openai/codex\n`);
|
|
256
262
|
process.exit(1);
|