@aiclude/security-skill 2.1.0 → 3.0.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
@@ -2,7 +2,7 @@
2
2
 
3
3
  Security vulnerability scanner for MCP Servers and AI Agent Skills. Provides the `/security-scan` slash command for Claude Code.
4
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.
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
6
 
7
7
  ## Installation
8
8
 
@@ -41,7 +41,7 @@ const report = await handler.lookup({
41
41
 
42
42
  ## How It Works
43
43
 
44
- 1. Sends the package name to the AIclude scan API
44
+ 1. Sends the package name to the AICLUDE scan API
45
45
  2. If a scan report exists, returns it immediately
46
46
  3. If not, registers the target for server-side scanning
47
47
  4. Waits for the scan to complete and returns the results
@@ -50,7 +50,7 @@ Only the package name and type are sent. No source code, files, or credentials a
50
50
 
51
51
  ## Server-Side Scan Engines
52
52
 
53
- The AIclude server runs 7 engines on registered targets:
53
+ The AICLUDE server runs 7 engines on registered targets:
54
54
 
55
55
  | Engine | What It Detects |
56
56
  |--------|----------------|
@@ -78,4 +78,4 @@ Reports include:
78
78
 
79
79
  ## License
80
80
 
81
- MIT — [AICLUDE Inc.](https://aiclude.com)
81
+ Apache 2.0 — [AICLUDE Inc.](https://aiclude.com)
package/SKILL.md CHANGED
@@ -1,14 +1,14 @@
1
1
  ---
2
2
  name: aiclude-vulns-scan
3
- description: Search security vulnerability scan results for MCP Servers and AI Agent Skills from the AIclude scan database.
3
+ description: Search security vulnerability scan results for MCP Servers and AI Agent Skills from the AICLUDE scan database.
4
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 Vulnerability Scanner
9
+ # /security-scan - AICLUDE Vulnerability Scanner
10
10
 
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.
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
 
@@ -30,7 +30,7 @@ Search the AIclude security scan database for vulnerability reports on MCP Serve
30
30
 
31
31
  ## How It Works
32
32
 
33
- 1. Sends the package name to the AIclude scan API
33
+ 1. Sends the package name to the AICLUDE scan API
34
34
  2. If a scan report exists, returns it immediately
35
35
  3. If not, registers the target for scanning
36
36
  4. Waits for the scan to complete and returns the results
@@ -52,4 +52,4 @@ Only the package name and type are sent. No source code or credentials are trans
52
52
 
53
53
  ## License
54
54
 
55
- MIT - AICLUDE Inc.
55
+ Apache 2.0 - AICLUDE Inc.
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Skill Handler
3
- * Processes /security-scan skill invocations from Claude Code
3
+ * Claude Code의 /security-scan 스킬 호출을 처리합니다.
4
4
  * 서버 DB 조회 → 없으면 등록 → 스캔 결과 반환
5
5
  */
6
6
  interface SkillLookupInvocation {
@@ -11,8 +11,6 @@ interface SkillLookupInvocation {
11
11
  npmPackage?: string;
12
12
  }
13
13
  declare class SkillHandler {
14
- /** API 인증 헤더 생성 */
15
- private createAuthHeaders;
16
14
  /**
17
15
  * 보안 스캔 조회/등록
18
16
  * 기존 결과 검색 → 없으면 서버에 등록 → 스캔 실행 → 결과 반환
@@ -22,4 +20,36 @@ declare class SkillHandler {
22
20
  private formatScanSummary;
23
21
  }
24
22
 
25
- export { SkillHandler, type SkillLookupInvocation };
23
+ /**
24
+ * ASVS 시간 기반 동적 서명 생성
25
+ *
26
+ * MCP Server와 Skill이 동일하게 사용하는 인증 헬퍼.
27
+ * 고정 secret 없이, 타임스탬프에서 파생된 키로 HMAC 서명을 생성합니다.
28
+ *
29
+ * 동작 원리:
30
+ * 1. 타임스탬프를 분 단위로 양자화(quantize)하여 minuteSeed 생성
31
+ * 2. minuteSeed + 고정 salt("aiclude-vs")로 파생 키(derivedKey) 생성
32
+ * 3. "asvs:{source}:{name}:{minuteSeed}" 페이로드를 derivedKey로 HMAC-SHA256 서명
33
+ *
34
+ * 서버(BE)에서는 동일 로직으로 현재/이전 분 2개 윈도우를 비교하여 검증합니다.
35
+ * 이 방식으로 5분 이내의 clock drift를 허용합니다.
36
+ */
37
+ /**
38
+ * 시간 기반 동적 HMAC-SHA256 서명을 생성합니다.
39
+ *
40
+ * @param source - 요청 소스 ("mcp" | "skill" | "cli" | "ci")
41
+ * @param name - 타겟 이름
42
+ * @param timestamp - 밀리초 타임스탬프 (기본: 현재 시각)
43
+ * @returns 서명 문자열 (hex)
44
+ */
45
+ declare function createDynamicSignature(source: string, name: string, timestamp?: number): string;
46
+ /**
47
+ * API 요청에 필요한 인증 헤더를 생성합니다.
48
+ *
49
+ * @param source - 요청 소스 ("mcp" | "skill")
50
+ * @param name - 타겟 이름
51
+ * @returns HTTP 헤더 객체
52
+ */
53
+ declare function createAuthHeaders(source: string, name: string): Record<string, string>;
54
+
55
+ export { SkillHandler, type SkillLookupInvocation, createAuthHeaders, createDynamicSignature };
package/dist/index.js CHANGED
@@ -1,24 +1,33 @@
1
- // src/skill-handler.ts
1
+ // src/auth.ts
2
2
  import { createHmac } from "crypto";
3
- var API_BASE = "https://vs-api.aiclude.com";
4
- function createRequestSignature(name, timestamp) {
5
- const minuteSeed = Math.floor(Number(timestamp) / 6e4).toString(36);
6
- const payload = `asvs:${name}:${minuteSeed}`;
7
- const derivedKey = createHmac("sha256", minuteSeed).update("aiclude-vs").digest("hex").slice(0, 32);
8
- return createHmac("sha256", derivedKey).update(payload).digest("hex");
3
+ var SALT = "aiclude-vs";
4
+ var WINDOW_MS = 6e4;
5
+ function getMinuteSeed(timestamp) {
6
+ return Math.floor(timestamp / WINDOW_MS).toString(36);
7
+ }
8
+ function deriveKey(minuteSeed) {
9
+ return createHmac("sha256", minuteSeed).update(SALT).digest("hex").slice(0, 32);
10
+ }
11
+ function createDynamicSignature(source, name, timestamp = Date.now()) {
12
+ const minuteSeed = getMinuteSeed(timestamp);
13
+ const payload = `asvs:${source}:${name}:${minuteSeed}`;
14
+ const key = deriveKey(minuteSeed);
15
+ return createHmac("sha256", key).update(payload).digest("hex");
9
16
  }
17
+ function createAuthHeaders(source, name) {
18
+ const timestamp = Date.now();
19
+ const signature = createDynamicSignature(source, name, timestamp);
20
+ return {
21
+ "Content-Type": "application/json",
22
+ "X-ASVS-Source": source,
23
+ "X-ASVS-Timestamp": String(timestamp),
24
+ "X-ASVS-Signature": signature
25
+ };
26
+ }
27
+
28
+ // src/skill-handler.ts
29
+ var API_BASE = "https://vs-api.aiclude.com";
10
30
  var SkillHandler = class {
11
- /** API 인증 헤더 생성 */
12
- createAuthHeaders(name) {
13
- const timestamp = String(Date.now());
14
- const signature = createRequestSignature(name, timestamp);
15
- return {
16
- "Content-Type": "application/json",
17
- "X-ASVS-Source": "skill",
18
- "X-ASVS-Timestamp": timestamp,
19
- "X-ASVS-Signature": signature
20
- };
21
- }
22
31
  /**
23
32
  * 보안 스캔 조회/등록
24
33
  * 기존 결과 검색 → 없으면 서버에 등록 → 스캔 실행 → 결과 반환
@@ -27,7 +36,7 @@ var SkillHandler = class {
27
36
  const apiUrl = `${API_BASE}/api/v1/scan/lookup`;
28
37
  const lookupRes = await fetch(apiUrl, {
29
38
  method: "POST",
30
- headers: this.createAuthHeaders(invocation.name),
39
+ headers: createAuthHeaders("skill", invocation.name),
31
40
  body: JSON.stringify({
32
41
  name: invocation.name,
33
42
  type: invocation.type ?? "mcp-server",
@@ -56,7 +65,7 @@ var SkillHandler = class {
56
65
  while (Date.now() - startTime < maxWait) {
57
66
  await new Promise((r) => setTimeout(r, interval));
58
67
  const statusRes = await fetch(`${API_BASE}/api/v1/scan/status/${jobId}`, {
59
- headers: this.createAuthHeaders(invocation.name)
68
+ headers: createAuthHeaders("skill", invocation.name)
60
69
  });
61
70
  const statusData = await statusRes.json();
62
71
  if (statusData["status"] === "completed") {
@@ -198,5 +207,7 @@ var SkillHandler = class {
198
207
  }
199
208
  };
200
209
  export {
201
- SkillHandler
210
+ SkillHandler,
211
+ createAuthHeaders,
212
+ createDynamicSignature
202
213
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@aiclude/security-skill",
3
- "version": "2.1.0",
4
- "description": "AIclude Security Vulnerability Scanner - Claude Code Skill for querying the AIclude scan database",
3
+ "version": "3.0.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",
@@ -24,7 +24,7 @@
24
24
  "sca",
25
25
  "malware"
26
26
  ],
27
- "license": "MIT",
27
+ "license": "Apache-2.0",
28
28
  "author": "AICLUDE Inc. <dev@aiclude.com>",
29
29
  "repository": {
30
30
  "type": "git",
@@ -53,9 +53,10 @@
53
53
  "clean": "rm -rf dist",
54
54
  "prepublishOnly": "npm run build"
55
55
  },
56
- "dependencies": {},
57
56
  "devDependencies": {
57
+ "@types/node": "^25.2.3",
58
58
  "tsup": "^8.0.0",
59
- "typescript": "^5.5.0"
59
+ "typescript": "^5.5.0",
60
+ "vitest": "^4.0.18"
60
61
  }
61
62
  }