@aiclude/security-skill 2.0.0 → 2.1.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 ADDED
@@ -0,0 +1,81 @@
1
+ # @aiclude/security-skill
2
+
3
+ Security vulnerability scanner for MCP Servers and AI Agent Skills. Provides the `/security-scan` slash command for Claude Code.
4
+
5
+ Queries the [AIclude scan database](https://vs.aiclude.com) for existing vulnerability reports. If no report exists, the target is automatically registered and scanned server-side.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @aiclude/security-skill
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ### As a Claude Code Skill
16
+
17
+ ```
18
+ /security-scan --name @anthropic/mcp-server-fetch
19
+ /security-scan --name my-awesome-skill --type skill
20
+ ```
21
+
22
+ ### Programmatic API
23
+
24
+ ```typescript
25
+ import { SkillHandler } from "@aiclude/security-skill";
26
+
27
+ const handler = new SkillHandler();
28
+
29
+ const report = await handler.lookup({
30
+ name: "@some/mcp-server",
31
+ type: "mcp-server",
32
+ });
33
+ ```
34
+
35
+ ## Parameters
36
+
37
+ | Parameter | Description |
38
+ |-----------|-------------|
39
+ | `--name` | Package name to search (npm, GitHub, etc.) |
40
+ | `--type` | `mcp-server` or `skill` (auto-detected) |
41
+
42
+ ## How It Works
43
+
44
+ 1. Sends the package name to the AIclude scan API
45
+ 2. If a scan report exists, returns it immediately
46
+ 3. If not, registers the target for server-side scanning
47
+ 4. Waits for the scan to complete and returns the results
48
+
49
+ Only the package name and type are sent. No source code, files, or credentials are transmitted.
50
+
51
+ ## Server-Side Scan Engines
52
+
53
+ The AIclude server runs 7 engines on registered targets:
54
+
55
+ | Engine | What It Detects |
56
+ |--------|----------------|
57
+ | SAST | Code vulnerabilities via pattern matching |
58
+ | SCA | Known CVEs in dependencies (OSV.dev) |
59
+ | Tool Analyzer | MCP tool poisoning, shadowing, rug-pull |
60
+ | DAST | SQL/Command/XSS injection via fuzzing |
61
+ | Permission Checker | Excessive filesystem/network/process access |
62
+ | Behavior Monitor | Suspicious runtime behavior patterns |
63
+ | Malware Detector | Backdoors, cryptominers, ransomware, data stealers |
64
+
65
+ ## Output
66
+
67
+ Reports include:
68
+
69
+ 1. **Risk Level** — CRITICAL / HIGH / MEDIUM / LOW / INFO
70
+ 2. **Vulnerability List** — code location, description, severity
71
+ 3. **Risk Assessment** — impact and likelihood analysis
72
+ 4. **Remediation** — how to fix each finding
73
+
74
+ ## Related Packages
75
+
76
+ - [`@aiclude/security-mcp`](https://www.npmjs.com/package/@aiclude/security-mcp) — MCP Server interface
77
+ - [vs.aiclude.com](https://vs.aiclude.com) — Web dashboard with full scan results
78
+
79
+ ## License
80
+
81
+ MIT — [AICLUDE Inc.](https://aiclude.com)
package/SKILL.md CHANGED
@@ -1,91 +1,55 @@
1
1
  ---
2
2
  name: aiclude-vulns-scan
3
- description: Scan MCP Servers and AI Agent Skills for security vulnerabilities. 7 parallel engines detect prompt injection, tool poisoning, malware, supply chain attacks, and more.
4
- tags: [security, vulnerability, scanner, mcp, ai-agent, sast, sca, malware]
3
+ description: Search security vulnerability scan results for MCP Servers and AI Agent Skills from the AIclude scan database.
4
+ tags: [security, vulnerability, scanner, mcp, ai-agent]
5
5
  homepage: https://vs.aiclude.com
6
6
  repository: https://github.com/aiclude/asvs
7
7
  ---
8
8
 
9
- # /security-scan - AIclude Security Vulnerability Scanner
9
+ # /security-scan - AIclude Vulnerability Scanner
10
10
 
11
- Scan MCP Servers and AI Agent Skills for security vulnerabilities. Queries existing scan results from the AIclude database, or registers a new scan and returns the results.
11
+ Search the AIclude security scan database for vulnerability reports on MCP Servers and AI Agent Skills. If no report exists, the target is registered and scanned automatically.
12
12
 
13
13
  ## Usage
14
14
 
15
15
  ```
16
- # Search by package name (queries AIclude scan database)
17
- /security-scan --name <package-name> [options]
18
-
19
- # Scan a local directory (offline, no network)
20
- /security-scan <target-path> [options]
16
+ /security-scan --name <package-name> [--type mcp-server|skill]
21
17
  ```
22
18
 
23
19
  ## Parameters
24
20
 
25
21
  - `--name`: Package name to search (npm package, GitHub repo, etc.)
26
- - `target-path`: Local directory path to scan directly
27
22
  - `--type`: Target type (`mcp-server` | `skill`) - auto-detected if omitted
28
- - `--profile`: Sandbox profile (`strict` | `standard` | `permissive`)
29
- - `--format`: Output format (`markdown` | `json`)
30
- - `--engines`: Scan engines to use (comma-separated)
31
23
 
32
24
  ## Examples
33
25
 
34
26
  ```
35
- # Look up scan results for an MCP server
36
27
  /security-scan --name @anthropic/mcp-server-fetch
37
-
38
- # Look up scan results for a Skill
39
28
  /security-scan --name my-awesome-skill --type skill
40
-
41
- # Scan local source code (fully offline)
42
- /security-scan ./my-mcp-server
43
29
  ```
44
30
 
45
31
  ## How It Works
46
32
 
47
- - **Name-based lookup** queries the AIclude scan database. If a report exists, it is returned immediately. If not, the target is registered for scanning and results are returned when ready. Only the package name is sent. No source code is uploaded.
48
- - **Local scan** reads files from the specified directory and runs all 7 engines locally. No network requests are made.
49
-
50
- No environment variables or credentials are required.
51
-
52
- ## What It Checks
33
+ 1. Sends the package name to the AIclude scan API
34
+ 2. If a scan report exists, returns it immediately
35
+ 3. If not, registers the target for scanning
36
+ 4. Waits for the scan to complete and returns the results
37
+ 5. Results are also viewable at https://vs.aiclude.com
53
38
 
54
- - **Prompt Injection**: Hidden patterns targeting LLMs
55
- - **Tool Poisoning**: Malicious instructions in tool descriptions
56
- - **Command Injection**: Unvalidated input passed to exec/spawn
57
- - **Supply Chain**: Known CVEs, typosquatting
58
- - **Malware**: Backdoors, cryptominers, ransomware, data stealers
59
- - **Permission Abuse**: Excessive filesystem/network/process permissions
60
-
61
- ## Scan Engines
62
-
63
- 7 engines run in parallel:
64
-
65
- | Engine | Description |
66
- |--------|-------------|
67
- | SAST | Static code pattern matching |
68
- | SCA | Dependency CVE lookup via OSV.dev |
69
- | Tool Analyzer | MCP tool definition analysis |
70
- | DAST | Parameter fuzzing |
71
- | Permission Checker | Permission analysis |
72
- | Behavior Monitor | Runtime behavior detection |
73
- | Malware Detector | Signature scanning, entropy analysis |
39
+ Only the package name and type are sent. No source code or credentials are transmitted.
74
40
 
75
41
  ## Output
76
42
 
77
- 1. **Risk Level** (CRITICAL / HIGH / MEDIUM / LOW / INFO)
78
- 2. **Vulnerability List** with code locations
79
- 3. **Risk Assessment** and impact analysis
80
- 4. **Remediation Recommendations**
43
+ - **Risk Level** (CRITICAL / HIGH / MEDIUM / LOW / INFO)
44
+ - **Vulnerability List** with locations and descriptions
45
+ - **Risk Assessment** and remediation recommendations
81
46
 
82
47
  ## Links
83
48
 
49
+ - **Web Dashboard**: https://vs.aiclude.com
84
50
  - **npm**: [`@aiclude/security-skill`](https://www.npmjs.com/package/@aiclude/security-skill)
85
51
  - **MCP Server**: [`@aiclude/security-mcp`](https://www.npmjs.com/package/@aiclude/security-mcp)
86
- - **Web Dashboard**: https://vs.aiclude.com
87
52
 
88
53
  ## License
89
54
 
90
55
  MIT - AICLUDE Inc.
91
- Inc.
package/dist/index.d.ts CHANGED
@@ -1,20 +1,8 @@
1
- import { ReportFormat, ScanEngineId } from '@asvs/core';
2
-
3
1
  /**
4
2
  * Skill Handler
5
3
  * Processes /security-scan skill invocations from Claude Code
6
- * 서버 조회 → 없으면 등록 → 스캔 결과 반환 (vs.aiclude.com에 누적)
7
- * 로컬 스캔도 지원
4
+ * 서버 DB 조회 → 없으면 등록 → 스캔 결과 반환
8
5
  */
9
-
10
- interface SkillInvocation {
11
- targetPath: string;
12
- type?: "mcp-server" | "skill";
13
- profile?: "strict" | "standard" | "permissive";
14
- format?: ReportFormat;
15
- engines?: ScanEngineId[];
16
- }
17
- /** API 기반 조회 요청 */
18
6
  interface SkillLookupInvocation {
19
7
  name: string;
20
8
  type?: "mcp-server" | "skill";
@@ -23,23 +11,15 @@ interface SkillLookupInvocation {
23
11
  npmPackage?: string;
24
12
  }
25
13
  declare class SkillHandler {
26
- private scanner;
27
- private reporter;
28
- constructor();
29
- /** API 인증 헤더 생성 — 시간 기반 서명, 환경변수 불필요 */
14
+ /** API 인증 헤더 생성 */
30
15
  private createAuthHeaders;
31
16
  /**
32
- * API 기반 보안 스캔 조회/등록
33
- * 기존 스캔 결과를 검색하고, 없으면 서버에 등록 → 스캔 실행 → 결과 반환
17
+ * 보안 스캔 조회/등록
18
+ * 기존 결과 검색 없으면 서버에 등록 → 스캔 실행 → 결과 반환
34
19
  */
35
20
  lookup(invocation: SkillLookupInvocation): Promise<string>;
36
- /** Handle a /security-scan invocation (local path scan) */
37
- handle(invocation: SkillInvocation): Promise<string>;
38
- private detectTargetType;
39
- private formatOutput;
40
- /** API에서 받은 상세 리포트를 마크다운으로 포맷 */
41
21
  private formatApiReport;
42
22
  private formatScanSummary;
43
23
  }
44
24
 
45
- export { SkillHandler, type SkillInvocation, type SkillLookupInvocation };
25
+ export { SkillHandler, type SkillLookupInvocation };
package/dist/index.js CHANGED
@@ -1,19 +1,4 @@
1
1
  // src/skill-handler.ts
2
- import {
3
- Scanner,
4
- SastEngine,
5
- ScaEngine,
6
- ToolAnalyzerEngine,
7
- MalwareDetectorEngine,
8
- PermissionCheckerEngine,
9
- DastEngine,
10
- BehaviorMonitorEngine,
11
- RiskLevel,
12
- validateScanPath
13
- } from "@asvs/core";
14
- import { ReportGenerator } from "@asvs/reporter";
15
- import { existsSync } from "fs";
16
- import { resolve } from "path";
17
2
  import { createHmac } from "crypto";
18
3
  var API_BASE = "https://vs-api.aiclude.com";
19
4
  function createRequestSignature(name, timestamp) {
@@ -23,20 +8,7 @@ function createRequestSignature(name, timestamp) {
23
8
  return createHmac("sha256", derivedKey).update(payload).digest("hex");
24
9
  }
25
10
  var SkillHandler = class {
26
- scanner;
27
- reporter;
28
- constructor() {
29
- this.scanner = new Scanner();
30
- this.reporter = new ReportGenerator();
31
- this.scanner.registerEngine(new SastEngine());
32
- this.scanner.registerEngine(new ScaEngine());
33
- this.scanner.registerEngine(new ToolAnalyzerEngine());
34
- this.scanner.registerEngine(new MalwareDetectorEngine());
35
- this.scanner.registerEngine(new PermissionCheckerEngine());
36
- this.scanner.registerEngine(new DastEngine());
37
- this.scanner.registerEngine(new BehaviorMonitorEngine());
38
- }
39
- /** API 인증 헤더 생성 — 시간 기반 서명, 환경변수 불필요 */
11
+ /** API 인증 헤더 생성 */
40
12
  createAuthHeaders(name) {
41
13
  const timestamp = String(Date.now());
42
14
  const signature = createRequestSignature(name, timestamp);
@@ -48,8 +20,8 @@ var SkillHandler = class {
48
20
  };
49
21
  }
50
22
  /**
51
- * API 기반 보안 스캔 조회/등록
52
- * 기존 스캔 결과를 검색하고, 없으면 서버에 등록 → 스캔 실행 → 결과 반환
23
+ * 보안 스캔 조회/등록
24
+ * 기존 결과 검색 없으면 서버에 등록 → 스캔 실행 → 결과 반환
53
25
  */
54
26
  async lookup(invocation) {
55
27
  const apiUrl = `${API_BASE}/api/v1/scan/lookup`;
@@ -113,126 +85,6 @@ var SkillHandler = class {
113
85
  }
114
86
  return `API response: ${JSON.stringify(lookupData, null, 2)}`;
115
87
  }
116
- /** Handle a /security-scan invocation (local path scan) */
117
- async handle(invocation) {
118
- const defaultConfig = {
119
- engines: ["sast", "sca", "tool-analyzer", "permission-checker", "malware-detector", "dast", "behavior-monitor"],
120
- sandboxProfile: "standard",
121
- rulesets: ["default"],
122
- timeout: 3e5,
123
- maxConcurrency: 4,
124
- skipPatterns: ["node_modules/**", ".git/**", "dist/**", "coverage/**"]
125
- };
126
- const scanConfig = {
127
- ...defaultConfig,
128
- ...invocation.profile && { sandboxProfile: invocation.profile },
129
- ...invocation.engines && { engines: invocation.engines }
130
- };
131
- const targetPath = validateScanPath(invocation.targetPath);
132
- const targetType = invocation.type ?? this.detectTargetType(targetPath);
133
- const target = {
134
- type: targetType,
135
- name: targetPath.split("/").pop() ?? targetPath,
136
- path: targetPath
137
- };
138
- const scanResult = await this.scanner.scan(target, scanConfig);
139
- const format = invocation.format ?? "markdown";
140
- const report = this.reporter.generate(scanResult, format);
141
- return this.formatOutput(report, format, scanResult.engineResults.flatMap((r) => r.vulnerabilities));
142
- }
143
- detectTargetType(targetPath) {
144
- if (existsSync(resolve(targetPath, "SKILL.md")) || targetPath.endsWith("SKILL.md") || targetPath.includes("/skill")) {
145
- return "skill";
146
- }
147
- return "mcp-server";
148
- }
149
- formatOutput(report, format, vulnerabilities) {
150
- if (format === "json") {
151
- return JSON.stringify(report, null, 2);
152
- }
153
- const lines = [];
154
- const { summary } = report.scanResult;
155
- const icon = summary.overallRiskLevel === RiskLevel.CRITICAL ? "[CRITICAL]" : summary.overallRiskLevel === RiskLevel.HIGH ? "[HIGH RISK]" : summary.overallRiskLevel === RiskLevel.MEDIUM ? "[MEDIUM RISK]" : summary.overallRiskLevel === RiskLevel.LOW ? "[LOW RISK]" : "[CLEAN]";
156
- lines.push(`# ${icon} Security Scan Report: ${report.title}`);
157
- lines.push("");
158
- lines.push(`| Metric | Value |`);
159
- lines.push(`|--------|-------|`);
160
- lines.push(`| Scan Date | ${report.generatedAt} |`);
161
- lines.push(`| Target | ${report.scanResult.target.path} |`);
162
- lines.push(`| Target Type | ${report.scanResult.target.type} |`);
163
- lines.push(`| Overall Risk | **${summary.overallRiskLevel}** |`);
164
- lines.push(`| Risk Score | **${summary.overallScore}/100** |`);
165
- lines.push(`| Total Findings | ${summary.totalVulnerabilities} |`);
166
- lines.push(`| Scan Duration | ${report.scanResult.duration}ms |`);
167
- lines.push("");
168
- lines.push("## Severity Breakdown");
169
- lines.push("");
170
- lines.push(`| Severity | Count |`);
171
- lines.push(`|----------|-------|`);
172
- for (const [level, count] of Object.entries(summary.bySeverity)) {
173
- if (count > 0) {
174
- lines.push(`| **${level}** | ${count} |`);
175
- }
176
- }
177
- lines.push("");
178
- if (vulnerabilities.length > 0) {
179
- lines.push("## Detailed Findings");
180
- lines.push("");
181
- const sorted = [...vulnerabilities].sort((a, b) => {
182
- const order = { CRITICAL: 0, HIGH: 1, MEDIUM: 2, LOW: 3, INFO: 4 };
183
- return (order[a.severity] ?? 5) - (order[b.severity] ?? 5);
184
- });
185
- const top = sorted.slice(0, 20);
186
- for (let i = 0; i < top.length; i++) {
187
- const v = top[i];
188
- lines.push(`### ${i + 1}. [${v.severity}] ${v.title}`);
189
- lines.push("");
190
- lines.push(`- **ID**: ${v.id}`);
191
- lines.push(`- **Category**: ${v.category}`);
192
- lines.push(`- **Confidence**: ${Math.round(v.confidence * 100)}%`);
193
- if (v.location) {
194
- lines.push(`- **Location**: \`${v.location.file}:${v.location.line}\``);
195
- }
196
- lines.push(`- **Description**: ${v.description}`);
197
- lines.push(`- **Remediation**: ${v.remediation}`);
198
- if (v.cveIds?.length) {
199
- lines.push(`- **CVE**: ${v.cveIds.join(", ")}`);
200
- }
201
- if (v.location?.snippet) {
202
- lines.push("");
203
- lines.push("```");
204
- lines.push(v.location.snippet.substring(0, 300));
205
- lines.push("```");
206
- }
207
- lines.push("");
208
- }
209
- if (sorted.length > 20) {
210
- lines.push(`> ... and ${sorted.length - 20} more findings. Use \`--format json\` for the complete list.`);
211
- lines.push("");
212
- }
213
- }
214
- if (report.risks.length > 0) {
215
- lines.push("## Risk Assessment");
216
- lines.push("");
217
- for (const risk of report.risks) {
218
- lines.push(`### [${risk.level}] ${risk.area}`);
219
- lines.push(`- **Impact**: ${risk.impact}`);
220
- lines.push(`- **Likelihood**: ${risk.likelihood}`);
221
- lines.push(`- **Remediation**: ${risk.remediation}`);
222
- lines.push("");
223
- }
224
- }
225
- if (report.precautions.length > 0) {
226
- lines.push("## Precautions & Warnings");
227
- lines.push("");
228
- for (const precaution of report.precautions) {
229
- lines.push(`- ${precaution}`);
230
- }
231
- lines.push("");
232
- }
233
- return lines.join("\n");
234
- }
235
- /** API에서 받은 상세 리포트를 마크다운으로 포맷 */
236
88
  formatApiReport(report, target) {
237
89
  const lines = [];
238
90
  const scanResult = report["scanResult"];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@aiclude/security-skill",
3
- "version": "2.0.0",
4
- "description": "AIclude Security Vulnerability Scanner - Claude Code Skill for inline security scanning",
3
+ "version": "2.1.0",
4
+ "description": "AIclude Security Vulnerability Scanner - Claude Code Skill for querying the AIclude scan database",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -53,10 +53,7 @@
53
53
  "clean": "rm -rf dist",
54
54
  "prepublishOnly": "npm run build"
55
55
  },
56
- "dependencies": {
57
- "@asvs/core": "workspace:*",
58
- "@asvs/reporter": "workspace:*"
59
- },
56
+ "dependencies": {},
60
57
  "devDependencies": {
61
58
  "tsup": "^8.0.0",
62
59
  "typescript": "^5.5.0"