agent-security-scanner-mcp 3.2.0 → 3.3.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 CHANGED
@@ -1,11 +1,13 @@
1
1
  # agent-security-scanner-mcp
2
2
 
3
- Security scanner MCP server for AI coding agents. Scans code for vulnerabilities, detects hallucinated packages, and blocks prompt injection — all in real-time via the Model Context Protocol.
3
+ Security scanner for AI coding agents and autonomous assistants. Scans code for vulnerabilities, detects hallucinated packages, and blocks prompt injection — via MCP (Claude Code, Cursor, Windsurf, Cline) or CLI (OpenClaw, CI/CD).
4
4
 
5
5
  [![npm downloads](https://img.shields.io/npm/dt/agent-security-scanner-mcp.svg)](https://www.npmjs.com/package/agent-security-scanner-mcp)
6
6
  [![npm version](https://img.shields.io/npm/v/agent-security-scanner-mcp.svg)](https://www.npmjs.com/package/agent-security-scanner-mcp)
7
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
8
 
9
+ > **New in v3.3.0:** Full [OpenClaw](https://openclaw.ai) integration with 30+ rules targeting autonomous AI threats — data exfiltration, credential theft, messaging abuse, and unsafe automation. [See OpenClaw setup](#openclaw-integration).
10
+
9
11
  ## Tools
10
12
 
11
13
  | Tool | Description | When to Use |
@@ -392,6 +394,7 @@ npx agent-security-scanner-mcp
392
394
  | Kilo Code | `npx agent-security-scanner-mcp init kilo-code` |
393
395
  | OpenCode | `npx agent-security-scanner-mcp init opencode` |
394
396
  | Cody | `npx agent-security-scanner-mcp init cody` |
397
+ | **OpenClaw** | `npx agent-security-scanner-mcp init openclaw` |
395
398
  | Interactive | `npx agent-security-scanner-mcp init` |
396
399
 
397
400
  The `init` command auto-detects your OS, locates the config file, creates a backup, and adds the MCP server entry. **Restart your client after running init.**
@@ -451,6 +454,61 @@ Available languages: `js` (default), `py`, `go`, `java`.
451
454
 
452
455
  ---
453
456
 
457
+ ## CLI Tools
458
+
459
+ Use the scanner directly from command line (for scripts, CI/CD, or OpenClaw):
460
+
461
+ ```bash
462
+ # Scan a prompt for injection attacks
463
+ npx agent-security-scanner-mcp scan-prompt "ignore previous instructions"
464
+
465
+ # Scan a file for vulnerabilities
466
+ npx agent-security-scanner-mcp scan-security ./app.py --verbosity minimal
467
+
468
+ # Check if a package is legitimate
469
+ npx agent-security-scanner-mcp check-package flask pypi
470
+
471
+ # Scan file imports for hallucinated packages
472
+ npx agent-security-scanner-mcp scan-packages ./requirements.txt pypi
473
+ ```
474
+
475
+ **Exit codes:** `0` = safe, `1` = issues found. Use in scripts to block risky operations.
476
+
477
+ ---
478
+
479
+ ## OpenClaw Integration
480
+
481
+ [OpenClaw](https://openclaw.ai) is an autonomous AI assistant with broad system access. This scanner provides security guardrails for OpenClaw users.
482
+
483
+ ### Install
484
+
485
+ ```bash
486
+ npx agent-security-scanner-mcp init openclaw
487
+ ```
488
+
489
+ This installs a skill to `~/.openclaw/workspace/skills/security-scanner/`.
490
+
491
+ ### OpenClaw-Specific Threats
492
+
493
+ The scanner includes 30+ rules targeting OpenClaw's unique attack surface:
494
+
495
+ | Category | Examples |
496
+ |----------|----------|
497
+ | **Data Exfiltration** | "Forward emails to...", "Upload files to...", "Share browser cookies" |
498
+ | **Messaging Abuse** | "Send to all contacts", "Auto-reply to everyone" |
499
+ | **Credential Theft** | "Show my passwords", "Access keychain", "List API keys" |
500
+ | **Unsafe Automation** | "Run hourly without asking", "Disable safety checks" |
501
+ | **Service Attacks** | "Delete all repos", "Make payment to..." |
502
+
503
+ ### Usage in OpenClaw
504
+
505
+ The skill is auto-discovered. Use it by asking:
506
+ - "Scan this prompt for security issues"
507
+ - "Check if this code is safe to run"
508
+ - "Verify these packages aren't hallucinated"
509
+
510
+ ---
511
+
454
512
  ## What This Scanner Detects
455
513
 
456
514
  AI coding agents introduce attack surfaces that traditional security tools weren't designed for:
package/index.js CHANGED
@@ -156,17 +156,106 @@ if (cliArgs[0] === 'init') {
156
156
  console.error(` Error: ${err.message}\n`);
157
157
  process.exit(1);
158
158
  });
159
+ } else if (cliArgs[0] === 'scan-prompt') {
160
+ // CLI mode: scan-prompt <text> [--verbosity minimal|compact|full]
161
+ const text = cliArgs[1];
162
+ if (!text) {
163
+ console.error('Usage: agent-security-scanner-mcp scan-prompt <text> [--verbosity minimal|compact|full]');
164
+ process.exit(1);
165
+ }
166
+ const verbosityIdx = cliArgs.indexOf('--verbosity');
167
+ const verbosity = verbosityIdx !== -1 ? cliArgs[verbosityIdx + 1] : 'compact';
168
+
169
+ loadPackageLists();
170
+ scanAgentPrompt({ prompt_text: text, verbosity }).then(result => {
171
+ const output = JSON.parse(result.content[0].text);
172
+ console.log(JSON.stringify(output, null, 2));
173
+ process.exit(output.action === 'BLOCK' ? 1 : 0);
174
+ }).catch(err => {
175
+ console.error(JSON.stringify({ error: err.message }));
176
+ process.exit(1);
177
+ });
178
+ } else if (cliArgs[0] === 'scan-security') {
179
+ // CLI mode: scan-security <file> [--verbosity minimal|compact|full] [--format json|sarif]
180
+ const filePath = cliArgs[1];
181
+ if (!filePath) {
182
+ console.error('Usage: agent-security-scanner-mcp scan-security <file> [--verbosity minimal|compact|full] [--format json|sarif]');
183
+ process.exit(1);
184
+ }
185
+ const verbosityIdx = cliArgs.indexOf('--verbosity');
186
+ const verbosity = verbosityIdx !== -1 ? cliArgs[verbosityIdx + 1] : 'compact';
187
+ const formatIdx = cliArgs.indexOf('--format');
188
+ const outputFormat = formatIdx !== -1 ? cliArgs[formatIdx + 1] : 'json';
189
+
190
+ loadPackageLists();
191
+ scanSecurity({ file_path: filePath, verbosity, output_format: outputFormat }).then(result => {
192
+ const output = JSON.parse(result.content[0].text);
193
+ console.log(JSON.stringify(output, null, 2));
194
+ process.exit(output.issues_count > 0 || output.total > 0 ? 1 : 0);
195
+ }).catch(err => {
196
+ console.error(JSON.stringify({ error: err.message }));
197
+ process.exit(1);
198
+ });
199
+ } else if (cliArgs[0] === 'check-package') {
200
+ // CLI mode: check-package <name> <ecosystem>
201
+ const packageName = cliArgs[1];
202
+ const ecosystem = cliArgs[2];
203
+ if (!packageName || !ecosystem) {
204
+ console.error('Usage: agent-security-scanner-mcp check-package <name> <ecosystem>');
205
+ console.error('Ecosystems: npm, pypi, rubygems, crates, dart, perl, raku');
206
+ process.exit(1);
207
+ }
208
+
209
+ loadPackageLists();
210
+ checkPackage({ package_name: packageName, ecosystem }).then(result => {
211
+ const output = JSON.parse(result.content[0].text);
212
+ console.log(JSON.stringify(output, null, 2));
213
+ process.exit(output.legitimate ? 0 : 1);
214
+ }).catch(err => {
215
+ console.error(JSON.stringify({ error: err.message }));
216
+ process.exit(1);
217
+ });
218
+ } else if (cliArgs[0] === 'scan-packages') {
219
+ // CLI mode: scan-packages <file> <ecosystem> [--verbosity minimal|compact|full]
220
+ const filePath = cliArgs[1];
221
+ const ecosystem = cliArgs[2];
222
+ if (!filePath || !ecosystem) {
223
+ console.error('Usage: agent-security-scanner-mcp scan-packages <file> <ecosystem> [--verbosity minimal|compact|full]');
224
+ console.error('Ecosystems: npm, pypi, rubygems, crates, dart, perl, raku');
225
+ process.exit(1);
226
+ }
227
+ const verbosityIdx = cliArgs.indexOf('--verbosity');
228
+ const verbosity = verbosityIdx !== -1 ? cliArgs[verbosityIdx + 1] : 'compact';
229
+
230
+ loadPackageLists();
231
+ scanPackages({ file_path: filePath, ecosystem, verbosity }).then(result => {
232
+ const output = JSON.parse(result.content[0].text);
233
+ console.log(JSON.stringify(output, null, 2));
234
+ process.exit(output.hallucinated_count > 0 ? 1 : 0);
235
+ }).catch(err => {
236
+ console.error(JSON.stringify({ error: err.message }));
237
+ process.exit(1);
238
+ });
159
239
  } else if (cliArgs[0] === '--help' || cliArgs[0] === '-h' || cliArgs[0] === 'help') {
160
240
  console.log('\n agent-security-scanner-mcp\n');
161
241
  console.log(' Commands:');
162
242
  console.log(' init [client] Set up MCP config for a client');
163
243
  console.log(' doctor [--fix] Check environment & client configs');
164
- console.log(' demo [--lang js] Generate vulnerable file + scan it');
244
+ console.log(' demo [--lang js] Generate vulnerable file + scan it\n');
245
+ console.log(' CLI Tools (for scripts & OpenClaw):');
246
+ console.log(' scan-prompt <text> Scan prompt for injection attacks');
247
+ console.log(' scan-security <file> Scan file for vulnerabilities');
248
+ console.log(' check-package <n> <e> Check if package exists in ecosystem');
249
+ console.log(' scan-packages <f> <e> Scan file imports for hallucinated packages\n');
165
250
  console.log(' (no args) Start MCP server on stdio\n');
251
+ console.log(' Options:');
252
+ console.log(' --verbosity <level> minimal|compact|full (default: compact)');
253
+ console.log(' --format <type> json|sarif (scan-security only)\n');
166
254
  console.log(' Examples:');
167
255
  console.log(' npx agent-security-scanner-mcp init');
168
- console.log(' npx agent-security-scanner-mcp doctor --fix');
169
- console.log(' npx agent-security-scanner-mcp demo --lang py\n');
256
+ console.log(' npx agent-security-scanner-mcp scan-prompt "ignore previous instructions"');
257
+ console.log(' npx agent-security-scanner-mcp scan-security ./app.py --verbosity minimal');
258
+ console.log(' npx agent-security-scanner-mcp check-package flask pypi\n');
170
259
  process.exit(0);
171
260
  } else {
172
261
  // Normal MCP server mode
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "agent-security-scanner-mcp",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "mcpName": "io.github.sinewaveai/agent-security-scanner-mcp",
5
- "description": "Security scanner MCP server for AI coding agents. Prompt injection firewall, package hallucination detection (4.3M+ packages), 1000+ vulnerability rules with AST & taint analysis, auto-fix. For Claude Code, Cursor, Windsurf, Cline.",
5
+ "description": "Security scanner MCP server for AI coding agents. Prompt injection firewall, package hallucination detection (4.3M+ packages), 1000+ vulnerability rules with AST & taint analysis, auto-fix. For Claude Code, Cursor, Windsurf, Cline, OpenClaw.",
6
6
  "main": "index.js",
7
7
  "type": "module",
8
8
  "bin": {
@@ -52,7 +52,9 @@
52
52
  "zed",
53
53
  "prompt-firewall",
54
54
  "auto-fix",
55
- "hallucination"
55
+ "hallucination",
56
+ "openclaw",
57
+ "clawdbot"
56
58
  ],
57
59
  "author": "Sinewave AI <divya@sinewave.ai>",
58
60
  "license": "MIT",
@@ -89,7 +91,8 @@
89
91
  "taint_analyzer.py",
90
92
  "requirements.txt",
91
93
  "rules/**",
92
- "packages/**"
94
+ "packages/**",
95
+ "skills/**"
93
96
  ],
94
97
  "devDependencies": {
95
98
  "all-the-package-names": "^2.0.2349",
@@ -0,0 +1,283 @@
1
+ # OpenClaw-specific security rules
2
+ # Detects attacks targeting autonomous AI assistants with broad system access
3
+ # These rules are loaded by scan_agent_prompt for OpenClaw integration
4
+
5
+ rules:
6
+ # ===========================================
7
+ # DATA EXFILTRATION
8
+ # ===========================================
9
+ - id: openclaw.exfiltration.email-forward
10
+ severity: CRITICAL
11
+ category: data_exfiltration
12
+ patterns:
13
+ - "forward\\s+(all\\s+)?(my\\s+)?emails?\\s+to"
14
+ - "send\\s+(all\\s+)?(my\\s+)?emails?\\s+to"
15
+ - "copy\\s+(all\\s+)?(my\\s+)?emails?\\s+to"
16
+ - "export\\s+(all\\s+)?(my\\s+)?emails?\\s+to"
17
+ - "redirect\\s+(my\\s+)?mail\\s+to"
18
+ message: "Potential email exfiltration attempt"
19
+ action: BLOCK
20
+
21
+ - id: openclaw.exfiltration.contacts-export
22
+ severity: CRITICAL
23
+ category: data_exfiltration
24
+ patterns:
25
+ - "export\\s+(all\\s+)?(my\\s+)?contacts\\s+to"
26
+ - "send\\s+(all\\s+)?(my\\s+)?contacts\\s+to"
27
+ - "send\\s+(my\\s+)?contact\\s+list\\s+to"
28
+ - "share\\s+(my\\s+)?address\\s+book"
29
+ - "upload\\s+(my\\s+)?contacts"
30
+ message: "Potential contacts exfiltration attempt"
31
+ action: BLOCK
32
+
33
+ - id: openclaw.exfiltration.calendar-export
34
+ severity: HIGH
35
+ category: data_exfiltration
36
+ patterns:
37
+ - "export\\s+(all\\s+)?(my\\s+)?calendar"
38
+ - "share\\s+(my\\s+)?schedule\\s+with"
39
+ - "send\\s+(my\\s+)?appointments\\s+to"
40
+ - "upload\\s+(my\\s+)?calendar"
41
+ message: "Potential calendar data exfiltration"
42
+ action: WARN
43
+
44
+ - id: openclaw.exfiltration.file-upload
45
+ severity: CRITICAL
46
+ category: data_exfiltration
47
+ patterns:
48
+ - "upload\\s+(all\\s+)?(my\\s+)?files?\\s+to"
49
+ - "send\\s+(all\\s+)?(my\\s+)?documents?\\s+to"
50
+ - "transfer\\s+(my\\s+)?data\\s+to"
51
+ - "copy\\s+(my\\s+)?files?\\s+to\\s+(external|remote|cloud)"
52
+ - "sync\\s+(my\\s+)?files?\\s+to\\s+\\S+\\.(com|io|net|org)"
53
+ message: "Potential file exfiltration to external service"
54
+ action: BLOCK
55
+
56
+ - id: openclaw.exfiltration.browser-session
57
+ severity: CRITICAL
58
+ category: data_exfiltration
59
+ patterns:
60
+ - "share\\s+(my\\s+)?browser\\s+(cookies?|session)"
61
+ - "export\\s+(my\\s+)?cookies?"
62
+ - "send\\s+(my\\s+)?session\\s+(data|tokens?)"
63
+ - "copy\\s+(my\\s+)?browser\\s+data"
64
+ - "extract\\s+(my\\s+)?login\\s+sessions?"
65
+ message: "Potential browser session/cookie theft"
66
+ action: BLOCK
67
+
68
+ - id: openclaw.exfiltration.browsing-history
69
+ severity: HIGH
70
+ category: data_exfiltration
71
+ patterns:
72
+ - "export\\s+(my\\s+)?browsing\\s+history"
73
+ - "send\\s+(my\\s+)?browser\\s+history"
74
+ - "share\\s+(my\\s+)?search\\s+history"
75
+ message: "Potential browsing history exfiltration"
76
+ action: WARN
77
+
78
+ # ===========================================
79
+ # MESSAGING ABUSE
80
+ # ===========================================
81
+ - id: openclaw.messaging.mass-send
82
+ severity: CRITICAL
83
+ category: messaging_abuse
84
+ patterns:
85
+ - "send\\s+(this\\s+)?message\\s+to\\s+all\\s+(my\\s+)?contacts"
86
+ - "message\\s+everyone\\s+in\\s+(my\\s+)?contacts?"
87
+ - "broadcast\\s+to\\s+all\\s+(my\\s+)?(contacts|friends)"
88
+ - "send\\s+to\\s+all\\s+(my\\s+)?(whatsapp|telegram|discord|slack)"
89
+ - "spam\\s+(all\\s+)?(my\\s+)?contacts"
90
+ message: "Mass messaging to all contacts detected"
91
+ action: BLOCK
92
+
93
+ - id: openclaw.messaging.auto-reply
94
+ severity: HIGH
95
+ category: messaging_abuse
96
+ patterns:
97
+ - "auto(-|\\s)?reply\\s+to\\s+(all|every)\\s+message"
98
+ - "automatically\\s+respond\\s+to\\s+(all|every)"
99
+ - "reply\\s+to\\s+all\\s+messages?\\s+with"
100
+ - "set\\s+up\\s+auto(-|\\s)?responder"
101
+ message: "Auto-reply configuration may be abused"
102
+ action: WARN
103
+
104
+ - id: openclaw.messaging.impersonation
105
+ severity: CRITICAL
106
+ category: messaging_abuse
107
+ patterns:
108
+ - "pretend\\s+to\\s+be\\s+(me|someone)"
109
+ - "impersonate\\s+(me|someone)"
110
+ - "send\\s+as\\s+if\\s+(from\\s+)?(me|I)"
111
+ - "message\\s+(them|him|her)\\s+as\\s+(me|if)"
112
+ message: "Potential impersonation/social engineering"
113
+ action: BLOCK
114
+
115
+ - id: openclaw.messaging.phishing-content
116
+ severity: CRITICAL
117
+ category: messaging_abuse
118
+ patterns:
119
+ - "send\\s+.*(urgent|verify|confirm)\\s+(your\\s+)?(account|password|login)"
120
+ - "message\\s+.*click\\s+(this|here|the)\\s+link"
121
+ - "tell\\s+(them|everyone)\\s+to\\s+(update|verify|confirm)"
122
+ message: "Potential phishing content in message"
123
+ action: BLOCK
124
+
125
+ # ===========================================
126
+ # CREDENTIAL/SECRET THEFT
127
+ # ===========================================
128
+ - id: openclaw.credentials.api-keys
129
+ severity: CRITICAL
130
+ category: credential_theft
131
+ patterns:
132
+ - "show\\s+(me\\s+)?(my\\s+)?api\\s+keys?"
133
+ - "list\\s+(all\\s+)?(my\\s+)?api\\s+keys?"
134
+ - "what\\s+(are|is)\\s+(my\\s+)?api\\s+(key|token|secret)"
135
+ - "display\\s+(my\\s+)?tokens?"
136
+ - "reveal\\s+(my\\s+)?secrets?"
137
+ message: "Attempt to access API keys/tokens"
138
+ action: BLOCK
139
+
140
+ - id: openclaw.credentials.passwords
141
+ severity: CRITICAL
142
+ category: credential_theft
143
+ patterns:
144
+ - "show\\s+(me\\s+)?(my\\s+)?(saved\\s+)?passwords?"
145
+ - "what\\s+(are|is)\\s+(my\\s+)?passwords?"
146
+ - "list\\s+(all\\s+)?(my\\s+)?passwords?"
147
+ - "display\\s+(my\\s+)?login\\s+credentials?"
148
+ - "export\\s+(my\\s+)?passwords?"
149
+ message: "Attempt to access saved passwords"
150
+ action: BLOCK
151
+
152
+ - id: openclaw.credentials.keychain
153
+ severity: CRITICAL
154
+ category: credential_theft
155
+ patterns:
156
+ - "access\\s+(my\\s+)?keychain"
157
+ - "read\\s+(from\\s+)?(my\\s+)?keychain"
158
+ - "export\\s+(my\\s+)?keychain"
159
+ - "dump\\s+(my\\s+)?credential\\s+store"
160
+ - "show\\s+(my\\s+)?secure\\s+storage"
161
+ message: "Attempt to access system keychain/credential store"
162
+ action: BLOCK
163
+
164
+ - id: openclaw.credentials.env-secrets
165
+ severity: CRITICAL
166
+ category: credential_theft
167
+ patterns:
168
+ - "show\\s+(me\\s+)?(all\\s+)?environment\\s+variables?"
169
+ - "print\\s+(all\\s+)?env\\s+vars?"
170
+ - "list\\s+.env\\s+file"
171
+ - "cat\\s+.*\\.env"
172
+ - "display\\s+(my\\s+)?secrets?"
173
+ message: "Attempt to access environment secrets"
174
+ action: BLOCK
175
+
176
+ - id: openclaw.credentials.ssh-keys
177
+ severity: CRITICAL
178
+ category: credential_theft
179
+ patterns:
180
+ - "show\\s+(me\\s+)?(my\\s+)?ssh\\s+keys?"
181
+ - "read\\s+(my\\s+)?private\\s+key"
182
+ - "export\\s+(my\\s+)?ssh\\s+keys?"
183
+ - "copy\\s+(my\\s+)?\\.ssh"
184
+ - "send\\s+(my\\s+)?id_rsa"
185
+ message: "Attempt to access SSH private keys"
186
+ action: BLOCK
187
+
188
+ # ===========================================
189
+ # AUTONOMOUS HARM / SAFETY BYPASS
190
+ # ===========================================
191
+ - id: openclaw.autonomous.scheduled-harm
192
+ severity: CRITICAL
193
+ category: autonomous_harm
194
+ patterns:
195
+ - "run\\s+this\\s+(every|each)\\s+(hour|minute|day)"
196
+ - "schedule\\s+this\\s+to\\s+run\\s+(repeatedly|continuously)"
197
+ - "set\\s+up\\s+(a\\s+)?cron\\s+(job\\s+)?to"
198
+ - "automatically\\s+run\\s+this\\s+without\\s+asking"
199
+ message: "Scheduled task without confirmation requested"
200
+ action: WARN
201
+
202
+ - id: openclaw.autonomous.no-confirm
203
+ severity: HIGH
204
+ category: autonomous_harm
205
+ patterns:
206
+ - "don'?t\\s+(ask|confirm|prompt)\\s+(me\\s+)?before"
207
+ - "without\\s+(asking|confirmation|prompting)"
208
+ - "skip\\s+(the\\s+)?confirmation"
209
+ - "auto(-|\\s)?approve\\s+(all|everything)"
210
+ - "don'?t\\s+wait\\s+for\\s+(my\\s+)?approval"
211
+ message: "Request to bypass confirmation prompts"
212
+ action: WARN
213
+
214
+ - id: openclaw.autonomous.disable-safety
215
+ severity: CRITICAL
216
+ category: autonomous_harm
217
+ patterns:
218
+ - "disable\\s+(all\\s+)?safety\\s+(checks?|features?)"
219
+ - "turn\\s+off\\s+(security|safety)"
220
+ - "bypass\\s+(the\\s+)?security"
221
+ - "ignore\\s+(the\\s+)?restrictions?"
222
+ - "remove\\s+(the\\s+)?guardrails?"
223
+ message: "Attempt to disable safety mechanisms"
224
+ action: BLOCK
225
+
226
+ - id: openclaw.autonomous.unlimited-access
227
+ severity: HIGH
228
+ category: autonomous_harm
229
+ patterns:
230
+ - "give\\s+(me|yourself)\\s+(full|unlimited|complete)\\s+access"
231
+ - "grant\\s+(me|yourself)\\s+(all|admin)\\s+permissions?"
232
+ - "escalate\\s+(your|my)\\s+privileges?"
233
+ - "run\\s+(as|with)\\s+(root|admin|sudo)"
234
+ message: "Privilege escalation attempt"
235
+ action: BLOCK
236
+
237
+ # ===========================================
238
+ # SERVICE-SPECIFIC ATTACKS
239
+ # ===========================================
240
+ - id: openclaw.service.payment-fraud
241
+ severity: CRITICAL
242
+ category: service_attack
243
+ patterns:
244
+ - "make\\s+(a\\s+)?payment\\s+to"
245
+ - "transfer\\s+(money|funds)\\s+to"
246
+ - "send\\s+\\$?\\d+\\s+to"
247
+ - "buy\\s+(this|something)\\s+using\\s+(my\\s+)?(card|account)"
248
+ - "purchase\\s+.*without\\s+(asking|confirmation)"
249
+ message: "Unauthorized payment/transaction attempt"
250
+ action: BLOCK
251
+
252
+ - id: openclaw.service.account-changes
253
+ severity: HIGH
254
+ category: service_attack
255
+ patterns:
256
+ - "change\\s+(my\\s+)?password\\s+to"
257
+ - "update\\s+(my\\s+)?email\\s+to"
258
+ - "modify\\s+(my\\s+)?account\\s+settings"
259
+ - "add\\s+(a\\s+)?(new\\s+)?recovery\\s+(email|phone)"
260
+ message: "Account modification request - verify intent"
261
+ action: WARN
262
+
263
+ - id: openclaw.service.github-destructive
264
+ severity: CRITICAL
265
+ category: service_attack
266
+ patterns:
267
+ - "delete\\s+(all\\s+)?(my\\s+)?repositories"
268
+ - "remove\\s+(all\\s+)?(my\\s+)?github\\s+(repos?|projects?)"
269
+ - "force\\s+push\\s+to\\s+(main|master)"
270
+ - "make\\s+(all\\s+)?(my\\s+)?repos?\\s+public"
271
+ message: "Potentially destructive GitHub operation"
272
+ action: BLOCK
273
+
274
+ - id: openclaw.service.social-destructive
275
+ severity: HIGH
276
+ category: service_attack
277
+ patterns:
278
+ - "delete\\s+(all\\s+)?(my\\s+)?(posts?|tweets?|messages?)"
279
+ - "unfollow\\s+(everyone|all)"
280
+ - "block\\s+(everyone|all\\s+my\\s+contacts)"
281
+ - "deactivate\\s+(my\\s+)?account"
282
+ message: "Potentially destructive social media operation"
283
+ action: WARN
@@ -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,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/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();
@@ -39,6 +39,12 @@ const CATEGORY_WEIGHTS = {
39
39
  "prompt-injection-privilege": 0.85,
40
40
  "prompt-injection-multi-turn": 0.7,
41
41
  "prompt-injection-output": 0.9,
42
+ // OpenClaw-specific categories
43
+ "data_exfiltration": 1.0,
44
+ "messaging_abuse": 0.95,
45
+ "credential_theft": 1.0,
46
+ "autonomous_harm": 0.9,
47
+ "service_attack": 0.95,
42
48
  "unknown": 0.5
43
49
  };
44
50
 
@@ -189,6 +195,69 @@ function loadPromptInjectionRules() {
189
195
  }
190
196
  }
191
197
 
198
+ // Load OpenClaw-specific rules
199
+ function loadOpenClawRules() {
200
+ try {
201
+ const rulesPath = join(__dirname, '..', '..', 'rules', 'openclaw.security.yaml');
202
+ if (!existsSync(rulesPath)) {
203
+ return [];
204
+ }
205
+
206
+ const yaml = readFileSync(rulesPath, 'utf-8');
207
+ const rules = [];
208
+
209
+ const ruleBlocks = yaml.split(/^ - id:/m).slice(1);
210
+
211
+ for (const block of ruleBlocks) {
212
+ const lines = (' - id:' + block).split('\n');
213
+ const rule = {
214
+ id: '',
215
+ severity: 'WARNING',
216
+ message: '',
217
+ patterns: [],
218
+ metadata: {}
219
+ };
220
+
221
+ let inPatterns = false;
222
+
223
+ for (const line of lines) {
224
+ if (line.match(/^\s+- id:\s*/)) {
225
+ rule.id = line.replace(/^\s+- id:\s*/, '').trim();
226
+ } else if (line.match(/^\s+severity:\s*/)) {
227
+ rule.severity = line.replace(/^\s+severity:\s*/, '').trim();
228
+ } else if (line.match(/^\s+category:\s*/)) {
229
+ rule.metadata.category = line.replace(/^\s+category:\s*/, '').trim();
230
+ } else if (line.match(/^\s+action:\s*/)) {
231
+ rule.metadata.action = line.replace(/^\s+action:\s*/, '').trim();
232
+ } else if (line.match(/^\s+message:\s*/)) {
233
+ rule.message = line.replace(/^\s+message:\s*["']?/, '').replace(/["']$/, '').trim();
234
+ } else if (line.match(/^\s+patterns:\s*$/)) {
235
+ inPatterns = true;
236
+ } else if (inPatterns && line.match(/^\s+- /)) {
237
+ let pattern = line.replace(/^\s+- /, '').trim();
238
+ pattern = pattern.replace(/^["']|["']$/g, '');
239
+ pattern = pattern.replace(/\\\\/g, '\\');
240
+ if (pattern) rule.patterns.push(pattern);
241
+ } else if (line.match(/^\s+\w+:/) && !line.match(/^\s+- /)) {
242
+ inPatterns = false;
243
+ }
244
+ }
245
+
246
+ if (rule.id && rule.patterns.length > 0) {
247
+ // Set confidence and risk score based on severity
248
+ rule.metadata.confidence = rule.severity === 'CRITICAL' ? 'HIGH' : 'MEDIUM';
249
+ rule.metadata.risk_score = rule.severity === 'CRITICAL' ? '90' : '70';
250
+ rules.push(rule);
251
+ }
252
+ }
253
+
254
+ return rules;
255
+ } catch (error) {
256
+ console.error("Error loading OpenClaw rules:", error.message);
257
+ return [];
258
+ }
259
+ }
260
+
192
261
  // Calculate risk score from findings
193
262
  function calculateRiskScore(findings, context) {
194
263
  if (findings.length === 0) return 0;
@@ -377,7 +446,8 @@ export async function scanAgentPrompt({ prompt_text, context, verbosity }) {
377
446
  // Load rules
378
447
  const agentRules = loadAgentAttackRules();
379
448
  const promptRules = loadPromptInjectionRules();
380
- const allRules = [...agentRules, ...promptRules];
449
+ const openclawRules = loadOpenClawRules();
450
+ const allRules = [...agentRules, ...promptRules, ...openclawRules];
381
451
 
382
452
  // 2.7: Extract content from code blocks and append to scan text
383
453
  let expandedText = prompt_text;