agent-security-scanner-mcp 3.7.0 → 3.9.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 +156 -10
- package/analyzer.py +22 -5
- package/cross_file_analyzer.py +216 -0
- package/daemon.py +179 -0
- package/index.js +279 -3
- package/package.json +19 -5
- package/packages/npm-bloom.json +1 -0
- package/pattern_matcher.py +1 -0
- package/regex_fallback.py +199 -1
- package/requirements.txt +1 -0
- package/rules/prompt-injection.security.yaml +273 -41
- package/scripts/postinstall.js +60 -0
- package/skills/openclaw/SKILL.md +102 -0
- package/skills/security-review.md +139 -0
- package/skills/security-scan-batch.md +107 -0
- package/skills/security-scanner.md +76 -0
- package/src/cli/doctor.js +29 -1
- package/src/cli/init.js +93 -0
- package/src/cli/report.js +444 -0
- package/src/config.js +247 -0
- package/src/context.js +289 -0
- package/src/daemon-client.js +233 -0
- package/src/dedup.js +129 -0
- package/src/fix-patterns.js +76 -19
- package/src/history.js +159 -0
- package/src/tools/check-package.js +36 -12
- package/src/tools/fix-security.js +32 -5
- package/src/tools/import-resolver.js +249 -0
- package/src/tools/project-context.js +365 -0
- package/src/tools/scan-action.js +489 -0
- package/src/tools/scan-mcp.js +922 -0
- package/src/tools/scan-project.js +16 -4
- package/src/tools/scan-prompt.js +292 -527
- package/src/tools/scan-security.js +37 -6
- package/src/typosquat.js +210 -0
- package/src/utils.js +215 -8
- package/templates/gitlab-ci-security.yml +225 -0
- package/templates/pre-commit-hook.sh +233 -0
- package/src/tools/garak-bridge.js +0 -209
|
@@ -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
|
-
|
|
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();
|