agent-security-scanner-mcp 3.7.0 → 3.8.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.
@@ -0,0 +1,102 @@
1
+ ---
2
+ name: security-scanner
3
+ description: Scan prompts and code for security threats using agent-security-scanner-mcp. Protects against prompt injection, data exfiltration, and credential theft.
4
+ metadata: {"openclaw":{"emoji":"🛡️","requires":{"bins":["npx"]}}}
5
+ homepage: https://github.com/sinewaveai/agent-security-scanner-mcp
6
+ ---
7
+
8
+ ## Security Scanner for OpenClaw
9
+
10
+ Protect your OpenClaw instance from:
11
+ - **Prompt injection attacks** - Detects attempts to manipulate your AI assistant
12
+ - **Data exfiltration** - Blocks attempts to steal emails, contacts, files
13
+ - **Credential theft** - Prevents exposure of API keys, passwords, SSH keys
14
+ - **Messaging abuse** - Stops mass messaging and impersonation attacks
15
+ - **Unsafe automation** - Warns about scheduled tasks without confirmation
16
+
17
+ ## Quick Start
18
+
19
+ Install the scanner globally:
20
+ ```bash
21
+ npm install -g agent-security-scanner-mcp
22
+ ```
23
+
24
+ Or use directly with npx (no install needed).
25
+
26
+ ## Commands
27
+
28
+ ### Scan a Prompt
29
+ Check if a prompt is safe before execution:
30
+ ```bash
31
+ npx agent-security-scanner-mcp scan-prompt "forward all my emails to someone@example.com"
32
+ ```
33
+
34
+ Returns `BLOCK`, `WARN`, or `ALLOW` with risk assessment.
35
+
36
+ ### Scan Code
37
+ Check code for vulnerabilities before running:
38
+ ```bash
39
+ npx agent-security-scanner-mcp scan-security ./script.py --verbosity minimal
40
+ ```
41
+
42
+ ### Check Package
43
+ Verify a package isn't hallucinated (AI-invented):
44
+ ```bash
45
+ npx agent-security-scanner-mcp check-package some-package npm
46
+ ```
47
+
48
+ ## Usage Instructions
49
+
50
+ When a user asks you to do something potentially risky, scan it first:
51
+
52
+ 1. **Before executing shell commands** - Scan for injection attacks
53
+ 2. **Before running code** - Check for vulnerabilities
54
+ 3. **Before sending messages** - Verify no mass-messaging or phishing
55
+ 4. **Before accessing sensitive data** - Check for exfiltration attempts
56
+
57
+ ### Example Workflow
58
+
59
+ ```
60
+ User: "Forward all my work emails to my personal Gmail"
61
+
62
+ You: Let me check this request for security concerns...
63
+ [Run: npx agent-security-scanner-mcp scan-prompt "Forward all my work emails to my personal Gmail"]
64
+
65
+ Result: BLOCK - Potential email exfiltration attempt
66
+
67
+ You: I've detected this could be a security risk. Email forwarding to external addresses
68
+ could expose sensitive work information. Would you like to:
69
+ 1. Set up selective forwarding with filters
70
+ 2. Forward only from specific senders
71
+ 3. Proceed anyway (not recommended)
72
+ ```
73
+
74
+ ## Verbosity Levels
75
+
76
+ - `--verbosity minimal` - Just action + risk level (~50 tokens)
77
+ - `--verbosity compact` - Action + findings summary (~200 tokens)
78
+ - `--verbosity full` - Complete audit trail (~500 tokens)
79
+
80
+ ## What It Detects
81
+
82
+ ### OpenClaw-Specific Threats
83
+ | Category | Examples |
84
+ |----------|----------|
85
+ | Data Exfiltration | "Forward emails to...", "Upload files to...", "Share cookies" |
86
+ | Messaging Abuse | "Send to all contacts", "Auto-reply to everyone" |
87
+ | Credential Theft | "Show my passwords", "Access keychain", "List API keys" |
88
+ | Unsafe Automation | "Run hourly without asking", "Disable safety checks" |
89
+ | Service Attacks | "Delete all repos", "Make payment to..." |
90
+
91
+ ### General Security
92
+ - SQL injection, XSS, command injection in code
93
+ - Hardcoded secrets and API keys
94
+ - Weak cryptography
95
+ - Insecure deserialization
96
+
97
+ ## Exit Codes
98
+
99
+ - `0` - Safe / No issues
100
+ - `1` - Issues found / Action required
101
+
102
+ Use exit codes in scripts to automatically block risky operations.
@@ -0,0 +1,139 @@
1
+ ---
2
+ name: security-review
3
+ description: Use for deep, project-aware security review. Combines Layer 1 pattern scanning with LLM reasoning about frameworks, middleware, and architecture to verify findings and catch logic bugs that regex cannot detect.
4
+ ---
5
+
6
+ # Security Review Skill (Layer 2 — LLM-Powered)
7
+
8
+ You are a senior security engineer performing a project-aware code review. You go beyond pattern matching by understanding the project's architecture, frameworks, and defenses.
9
+
10
+ ## How This Differs from `security-scanner`
11
+
12
+ - `security-scanner` (Layer 1): Fast regex/AST scan. Catches obvious patterns. No project awareness.
13
+ - `security-review` (Layer 2 — this skill): Reads project context, evaluates findings against real defenses, catches logic bugs regex cannot find.
14
+
15
+ ## Workflow
16
+
17
+ ### Phase A: Discover Project Context
18
+
19
+ 1. Run `mcp__security-scanner__scan_security` with `project_context: true` and `verbosity: 'full'` on the target file
20
+ 2. Note the returned `project` field — it tells you the framework, security middleware, sanitizers, auth libraries
21
+ 3. Note `is_test_file` and `file_imports`
22
+
23
+ ### Phase A.5: Resolve Import Graph
24
+
25
+ 1. Run `mcp__security-scanner__scan_security` again with `resolve_imports: true` and `project_context: true` on the target file
26
+ 2. Examine the `import_graph` field in the response:
27
+ - `edges` shows which files import which — trace cross-file data flow (e.g., route handler -> db utility)
28
+ - `files` lists each resolved file with its content hash
29
+ - `unresolved` shows imports that couldn't be resolved (potential missing files)
30
+ - `cycles` shows circular dependencies (potential infinite loops or initialization issues)
31
+ 3. For each edge where the target file is a utility/library (e.g., `lib/db.js`, `helpers/auth.js`):
32
+ - Read the imported file to understand what functions it exports
33
+ - Check if user-controlled data from the importing file flows into dangerous sinks in the imported file
34
+ 4. This is critical: per-file scanning cannot detect SQL injection in `lib/db.js` when the tainted input originates in `routes/users.js`
35
+
36
+ ### Phase B: Read and Understand the File
37
+
38
+ 1. Read the full target file to understand its role:
39
+ - Is it a route handler, middleware, utility, model, test, or config?
40
+ - What data does it receive and from where?
41
+ - What does it do with that data?
42
+ 2. Trace logical data flow through imports — if a function is imported, consider what it does
43
+
44
+ ### Phase C: Evaluate Layer 1 Findings
45
+
46
+ For each finding from the Layer 1 scan, determine if it is **real** or a **false positive**:
47
+
48
+ **Mark as FALSE POSITIVE if:**
49
+ - The code is in a test, fixture, example, or mock file
50
+ - The vulnerability is mitigated by project-level middleware (e.g., XSS finding but `helmet` + `dompurify` are in the project)
51
+ - The tainted data is not actually user-controlled (e.g., comes from a config file or constant)
52
+ - The pattern matched a comment, string literal, or dead code
53
+ - The framework provides built-in protection (e.g., Django ORM prevents SQL injection, React escapes JSX by default)
54
+
55
+ **Mark as CONFIRMED if:**
56
+ - The vulnerability is exploitable despite existing defenses
57
+ - No relevant middleware/sanitizer covers this specific code path
58
+ - The data flow genuinely connects user input to a dangerous sink
59
+
60
+ ### Phase D: Find What Layer 1 Missed
61
+
62
+ Look for these classes of issues that regex/AST scanning cannot detect:
63
+
64
+ 1. **Authentication/Authorization flaws** — missing auth checks, privilege escalation paths
65
+ 2. **IDOR (Insecure Direct Object Reference)** — accessing resources without ownership verification
66
+ 3. **Business logic bugs** — race conditions, TOCTOU, improper state transitions
67
+ 4. **Insecure defaults** — framework configuration that disables built-in protections
68
+ 5. **Missing input validation** — API endpoints that accept unbounded input
69
+ 6. **Information disclosure** — error messages, stack traces, or debug info leaking to users
70
+ 7. **Cross-module data flow** — use the import graph `edges` from Phase A.5 to trace tainted data through imports (e.g., `req.params.id` in a route handler passed to a SQL query in an imported utility). Layer 1 scans files individually and cannot detect these cross-file taint paths
71
+
72
+ ### Phase E: Output Results
73
+
74
+ ## Response Format
75
+
76
+ Return ONLY this format:
77
+
78
+ ```
79
+ ## Security Review: {filename}
80
+
81
+ **Project Context:** {framework} with {middleware list}
82
+ **Layer 1 Findings:** {N} raw -> {M} verified
83
+
84
+ ### Verified Issues
85
+ 1. **Line {N}** [CONFIRMED] {ruleId} — {why it's real despite mitigations}
86
+ 2. **Line {N}** [NEW] {description} — {what Layer 1 missed and why}
87
+
88
+ ### Dismissed (False Positives)
89
+ - **Line {N}** {ruleId} — {mitigation that covers this}: {explanation}
90
+
91
+ ### Recommendations
92
+ - {project-level security suggestions based on what's missing}
93
+ ```
94
+
95
+ If no issues are found after review:
96
+ ```
97
+ ## Security Review: {filename}
98
+
99
+ **Project Context:** {framework} with {middleware list}
100
+ **Layer 1 Findings:** {N} raw -> 0 verified
101
+
102
+ All Layer 1 findings are mitigated by project defenses. No additional issues found.
103
+ ```
104
+
105
+ ## Rules
106
+
107
+ - DO always start with Phase A (project context discovery)
108
+ - DO read the full target file before making judgments
109
+ - DO consider framework-level protections (Django CSRF, React XSS escaping, etc.)
110
+ - DO clearly explain WHY each finding is confirmed or dismissed
111
+ - DO assign confidence levels: HIGH (definitely exploitable), MEDIUM (likely exploitable), LOW (possible but unlikely)
112
+ - DO NOT include raw JSON in your response
113
+ - DO NOT repeat Layer 1 output verbatim — synthesize and add judgment
114
+ - DO NOT hallucinate vulnerabilities — only report issues you can trace through the code
115
+ - DO limit recommendations to 3-5 actionable items
116
+ - DO prioritize: confirmed exploitable issues > new findings > recommendations > false positive explanations
117
+
118
+ ## Examples
119
+
120
+ ### Example 1: Express app with helmet
121
+
122
+ Layer 1 flags XSS on line 42 (`res.send(userInput)`).
123
+ Project context shows `helmet` and `express-validator` installed.
124
+
125
+ Review: helmet sets HTTP headers but does NOT sanitize response bodies. express-validator validates input but this endpoint doesn't use it. **CONFIRMED** — XSS is real.
126
+
127
+ ### Example 2: Django app with ORM
128
+
129
+ Layer 1 flags SQL injection on line 15 (`Model.objects.filter(name=user_input)`).
130
+ Project context shows Django framework.
131
+
132
+ Review: Django ORM parameterizes queries automatically. `filter(name=user_input)` is safe. **FALSE POSITIVE** — Django ORM handles this.
133
+
134
+ ### Example 3: Test file
135
+
136
+ Layer 1 flags hardcoded secret on line 5 (`api_key = "test_key_123"`).
137
+ File path contains `/tests/`.
138
+
139
+ Review: This is a test file using a test fixture value. **FALSE POSITIVE** — test code, not production.
@@ -0,0 +1,107 @@
1
+ ---
2
+ name: security-scan-batch
3
+ description: Use when scanning multiple files or entire directories for security vulnerabilities. Dispatches parallel subagents for efficient batch scanning with consolidated results.
4
+ ---
5
+
6
+ # Batch Security Scanner Skill
7
+
8
+ You are a batch security scanning coordinator. Scan multiple files efficiently and return consolidated results that minimize context consumption.
9
+
10
+ ## Workflow
11
+
12
+ 1. **Identify files to scan** - Use glob patterns or file list provided
13
+ 2. **Scan each file** using `mcp__security-scanner__scan_security` with `verbosity: 'minimal'`
14
+ 3. **For files with issues**, get details with `verbosity: 'compact'`
15
+ 4. **Consolidate results** - Merge findings, deduplicate, prioritize
16
+ 5. **Return executive summary**
17
+
18
+ ## Response Format
19
+
20
+ ```
21
+ ## Security Scan Summary
22
+
23
+ **Files Scanned:** {N}
24
+ **Files with Issues:** {N}
25
+ **Total Issues:** {critical} critical, {warning} warning
26
+
27
+ ### Files Requiring Attention
28
+
29
+ | File | Critical | Warning | Top Issue |
30
+ |------|----------|---------|-----------|
31
+ | path/file1.py | 2 | 3 | SQL Injection (L15) |
32
+ | path/file2.js | 0 | 1 | XSS (L42) |
33
+
34
+ ### Priority Fixes (Top 10)
35
+ 1. **path/file1.py:15** - SQL Injection: Use parameterized query
36
+ 2. **path/file1.py:28** - Hardcoded secret: Move to env var
37
+ 3. **path/file2.js:42** - XSS: Use textContent instead of innerHTML
38
+ ...
39
+
40
+ ### Quick Fix
41
+ To auto-fix all issues: scan each file with fix_security tool.
42
+ ```
43
+
44
+ ## Rules
45
+
46
+ - DO scan files using `verbosity: 'minimal'` first for quick triage
47
+ - DO only fetch `verbosity: 'compact'` for files that have issues
48
+ - DO consolidate into single summary
49
+ - DO NOT return individual file JSON details
50
+ - DO prioritize by: critical severity > file count > line number
51
+ - DO limit to top 10 priority fixes in summary
52
+
53
+ ## Scanning Patterns
54
+
55
+ For common batch operations:
56
+
57
+ **Python project:**
58
+ ```
59
+ Glob: **/*.py
60
+ Exclude: **/venv/**, **/__pycache__/**
61
+ ```
62
+
63
+ **JavaScript/TypeScript project:**
64
+ ```
65
+ Glob: **/*.{js,ts,jsx,tsx}
66
+ Exclude: **/node_modules/**, **/dist/**
67
+ ```
68
+
69
+ **Full project scan:**
70
+ ```
71
+ Glob: **/*.{py,js,ts,java,go,rb,php}
72
+ Exclude: **/vendor/**, **/node_modules/**, **/venv/**
73
+ ```
74
+
75
+ ## Example
76
+
77
+ User asks: "Scan all Python files in src/"
78
+
79
+ You run:
80
+ 1. Glob for `src/**/*.py` - find 15 files
81
+ 2. Scan each with `verbosity: 'minimal'` - 4 have issues
82
+ 3. Get `verbosity: 'compact'` for those 4 files
83
+ 4. Consolidate and return summary
84
+
85
+ Response:
86
+ ```
87
+ ## Security Scan Summary
88
+
89
+ **Files Scanned:** 15
90
+ **Files with Issues:** 4
91
+ **Total Issues:** 3 critical, 8 warning
92
+
93
+ ### Files Requiring Attention
94
+
95
+ | File | Critical | Warning | Top Issue |
96
+ |------|----------|---------|-----------|
97
+ | src/db.py | 2 | 1 | SQL Injection (L23) |
98
+ | src/auth.py | 1 | 3 | Hardcoded secret (L15) |
99
+ | src/api.py | 0 | 2 | SSL disabled (L67) |
100
+ | src/utils.py | 0 | 2 | Weak crypto (L12) |
101
+
102
+ ### Priority Fixes (Top 10)
103
+ 1. **src/db.py:23** - SQL Injection: Use parameterized query
104
+ 2. **src/db.py:45** - SQL Injection: Use parameterized query
105
+ 3. **src/auth.py:15** - Hardcoded secret: Move API_KEY to env var
106
+ ...
107
+ ```
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: security-scanner
3
+ description: Use when scanning files for security vulnerabilities. Runs comprehensive security analysis via subagent, returns concise actionable summary to main context.
4
+ ---
5
+
6
+ # Security Scanner Skill
7
+
8
+ You are a security scanning subagent. Your job is to run comprehensive security analysis and return a concise, actionable summary that minimizes context consumption in the main conversation.
9
+
10
+ ## Workflow
11
+
12
+ 1. **Scan the file** using `mcp__security-scanner__scan_security` with `verbosity: 'full'`
13
+ 2. **Analyze findings** - group by severity, identify patterns
14
+ 3. **If fixes needed**, use `mcp__security-scanner__fix_security` with `verbosity: 'full'`
15
+ 4. **Return concise summary** (not the full JSON output)
16
+
17
+ ## Response Format
18
+
19
+ Return ONLY this format to the main conversation:
20
+
21
+ ```
22
+ ## Security Scan: {filename}
23
+
24
+ **Status:** {PASS | WARN | FAIL}
25
+ **Issues:** {critical} critical, {warning} warning, {info} info
26
+
27
+ {If issues found:}
28
+ ### Priority Fixes
29
+ 1. **Line {N}**: {rule} - {one-line fix description}
30
+ 2. **Line {N}**: {rule} - {one-line fix description}
31
+ {limit to top 5}
32
+
33
+ ### Auto-Fix Available
34
+ Run `mcp__security-scanner__fix_security` to automatically apply {N} fixes.
35
+
36
+ {If no issues:}
37
+ No security issues detected.
38
+ ```
39
+
40
+ ## Rules
41
+
42
+ - DO use `verbosity: 'full'` internally for complete analysis
43
+ - DO return only the summary format above to the main conversation
44
+ - DO NOT include raw JSON in your response
45
+ - DO NOT include metadata, CWE references, or verbose explanations
46
+ - DO prioritize fixes by severity (critical > warning > info)
47
+ - DO limit to top 5 issues if more than 5 found
48
+ - DO mention auto-fix availability if fixes can be applied
49
+
50
+ ## Example
51
+
52
+ User asks: "Scan app.py for security issues"
53
+
54
+ You run internally:
55
+ ```
56
+ mcp__security-scanner__scan_security({ file_path: "app.py", verbosity: "full" })
57
+ ```
58
+
59
+ You return:
60
+ ```
61
+ ## Security Scan: app.py
62
+
63
+ **Status:** WARN
64
+ **Issues:** 1 critical, 3 warning, 0 info
65
+
66
+ ### Priority Fixes
67
+ 1. **Line 15**: sql-injection - Use parameterized query instead of string concat
68
+ 2. **Line 28**: hardcoded-secret - Move API key to environment variable
69
+ 3. **Line 42**: weak-crypto-md5 - Replace MD5 with SHA-256
70
+ 4. **Line 67**: ssl-verify-disabled - Enable SSL certificate verification
71
+
72
+ ### Auto-Fix Available
73
+ Run fix_security to automatically apply 4 fixes.
74
+ ```
75
+
76
+ This approach keeps main conversation context minimal (~200 tokens vs 2000+ for raw output).
package/src/cli/doctor.js CHANGED
@@ -150,6 +150,14 @@ export async function runDoctor(args) {
150
150
  issues++;
151
151
  }
152
152
 
153
+ // 3b. daemon.py reachable
154
+ const daemonPath = join(__dirname, '..', '..', 'daemon.py');
155
+ if (existsSync(daemonPath)) {
156
+ console.log(` \u2713 daemon.py found`);
157
+ } else {
158
+ console.log(` \u26a0 daemon.py not found (daemon mode unavailable, sync fallback will be used)`);
159
+ }
160
+
153
161
  // 4. Python can import yaml (analyzer dependency check)
154
162
  if (pythonCmd && existsSync(analyzerPath)) {
155
163
  const yamlCheck = checkCommand(pythonCmd, ['-c', 'import yaml; print("ok")']);
@@ -168,7 +176,27 @@ export async function runDoctor(args) {
168
176
  console.log(` \u2713 AST engine ready (tree-sitter ${tsCheck.output})`);
169
177
  } else {
170
178
  console.log(` \u26a0 tree-sitter not installed (regex-only mode)`);
171
- console.log(` For enhanced detection: pip install tree-sitter tree-sitter-python tree-sitter-javascript`);
179
+ if (fix) {
180
+ console.log(` Installing tree-sitter dependencies...`);
181
+ const requirementsPath = join(__dirname, '..', '..', 'requirements.txt');
182
+ if (existsSync(requirementsPath)) {
183
+ const installResult = checkCommand(pythonCmd, ['-m', 'pip', 'install', '-r', requirementsPath, '--user', '--quiet']);
184
+ if (installResult.ok) {
185
+ console.log(` \u2713 Fixed: tree-sitter dependencies installed — AST engine enabled`);
186
+ fixed++;
187
+ } else {
188
+ console.log(` \u2717 Could not install tree-sitter. Try manually: ${pythonCmd} -m pip install -r requirements.txt`);
189
+ issues++;
190
+ }
191
+ } else {
192
+ console.log(` \u2717 requirements.txt not found at ${requirementsPath}`);
193
+ issues++;
194
+ }
195
+ } else {
196
+ console.log(` For enhanced detection: pip install tree-sitter tree-sitter-python tree-sitter-javascript`);
197
+ console.log(` Or run: npx agent-security-scanner-mcp doctor --fix`);
198
+ issues++;
199
+ }
172
200
  }
173
201
  }
174
202
 
package/src/cli/init.js CHANGED
@@ -73,6 +73,12 @@ const CLIENT_CONFIGS = {
73
73
  configKey: 'mcpServers',
74
74
  configPath: () => join(vscodeBase(), 'Code', 'User', 'globalStorage', 'sourcegraph.cody-ai', 'mcp_settings.json'),
75
75
  buildEntry: () => ({ ...MCP_SERVER_ENTRY })
76
+ },
77
+ 'openclaw': {
78
+ name: 'OpenClaw',
79
+ isSkillBased: true, // OpenClaw uses skills, not MCP config
80
+ skillPath: () => join(homedir(), '.openclaw', 'workspace', 'skills', 'security-scanner'),
81
+ configPath: () => join(homedir(), '.openclaw', 'workspace', 'skills', 'security-scanner', 'SKILL.md')
76
82
  }
77
83
  };
78
84
 
@@ -150,6 +156,87 @@ function printInitUsage() {
150
156
  console.log(' npx agent-security-scanner-mcp init cline --force --name my-scanner\n');
151
157
  }
152
158
 
159
+ // Special installer for OpenClaw (skill-based)
160
+ async function installOpenClawSkill(client, flags) {
161
+ const skillDir = client.skillPath();
162
+ const skillFile = client.configPath();
163
+
164
+ // Find the source skill file (bundled with the package)
165
+ const __dirname = dirname(new URL(import.meta.url).pathname);
166
+ const sourceSkill = join(__dirname, '..', '..', 'skills', 'openclaw', 'SKILL.md');
167
+
168
+ console.log(`\n Client: ${client.name}`);
169
+ console.log(` Skill: ${skillDir}`);
170
+ console.log(` OS: ${platform()} (${process.arch})\n`);
171
+
172
+ // Check if OpenClaw workspace exists
173
+ const openclawDir = join(homedir(), '.openclaw');
174
+ if (!existsSync(openclawDir)) {
175
+ console.log(` OpenClaw not found at ${openclawDir}`);
176
+ console.log(` Please install OpenClaw first: https://openclaw.ai\n`);
177
+ process.exit(1);
178
+ }
179
+
180
+ // Check if source skill exists
181
+ if (!existsSync(sourceSkill)) {
182
+ console.error(` ERROR: Skill source not found at ${sourceSkill}`);
183
+ console.error(` This may be a packaging issue. Please reinstall the package.\n`);
184
+ process.exit(1);
185
+ }
186
+
187
+ // Check if skill already exists
188
+ if (existsSync(skillFile)) {
189
+ const existing = readFileSync(skillFile, 'utf-8');
190
+ const source = readFileSync(sourceSkill, 'utf-8');
191
+ if (existing === source) {
192
+ console.log(` Security scanner skill is already installed (identical).`);
193
+ console.log(` Nothing to do.\n`);
194
+ process.exit(0);
195
+ }
196
+
197
+ console.log(` Security scanner skill exists but differs.`);
198
+ if (!flags.force) {
199
+ if (flags.yes) {
200
+ console.log(` Skipping (use --force to overwrite).\n`);
201
+ process.exit(0);
202
+ }
203
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
204
+ const answer = await new Promise((resolve) => {
205
+ rl.question(' Overwrite? (y/N): ', (a) => { rl.close(); resolve(a); });
206
+ });
207
+ if (answer.toLowerCase() !== 'y') {
208
+ console.log(' Aborted.\n');
209
+ process.exit(0);
210
+ }
211
+ }
212
+ }
213
+
214
+ // Dry-run mode
215
+ if (flags.dryRun) {
216
+ console.log(` [dry-run] Would create directory: ${skillDir}`);
217
+ console.log(` [dry-run] Would copy skill from: ${sourceSkill}`);
218
+ console.log(` [dry-run] Would write to: ${skillFile}`);
219
+ console.log(` No changes made.\n`);
220
+ process.exit(0);
221
+ }
222
+
223
+ // Create skill directory
224
+ if (!existsSync(skillDir)) {
225
+ mkdirSync(skillDir, { recursive: true });
226
+ console.log(` Created directory: ${skillDir}`);
227
+ }
228
+
229
+ // Copy skill file
230
+ copyFileSync(sourceSkill, skillFile);
231
+ console.log(` Installed skill: ${skillFile}`);
232
+
233
+ console.log(`\n OpenClaw security scanner skill installed successfully!`);
234
+ console.log(`\n Usage in OpenClaw:`);
235
+ console.log(` - The skill will be auto-discovered by OpenClaw`);
236
+ console.log(` - Use /security-scanner to invoke it`);
237
+ console.log(` - Or ask: "scan this prompt for security issues"\n`);
238
+ }
239
+
153
240
  export async function runInit(args) {
154
241
  const flags = parseInitFlags(args);
155
242
  let clientName = flags.client;
@@ -171,6 +258,12 @@ export async function runInit(args) {
171
258
  process.exit(1);
172
259
  }
173
260
 
261
+ // Special handling for OpenClaw (skill-based, not MCP config)
262
+ if (client.isSkillBased) {
263
+ await installOpenClawSkill(client, flags);
264
+ return;
265
+ }
266
+
174
267
  const configPath = flags.path || client.configPath();
175
268
  const serverName = flags.name;
176
269
  const entry = client.buildEntry();