vskill 0.5.126 → 0.5.128

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.
Files changed (228) hide show
  1. package/agents.json +1 -1
  2. package/dist/bin.js +0 -0
  3. package/dist/eval-server/api-routes.js +129 -12
  4. package/dist/eval-server/api-routes.js.map +1 -1
  5. package/dist/eval-server/install-engine-routes.js +1 -1
  6. package/dist/eval-server/install-engine-routes.js.map +1 -1
  7. package/dist/eval-server/utils/scan-install-locations.d.ts +18 -0
  8. package/dist/eval-server/utils/scan-install-locations.js +136 -0
  9. package/dist/eval-server/utils/scan-install-locations.js.map +1 -0
  10. package/dist/eval-ui/assets/{CommandPalette-CBrGufxz.js → CommandPalette-D_MdwCki.js} +1 -1
  11. package/dist/eval-ui/assets/{CreateSkillPage-DXrpM1On.js → CreateSkillPage-lLACfsOZ.js} +3 -3
  12. package/dist/eval-ui/assets/{FindSkillsPalette-D99SoJx3.js → FindSkillsPalette-VTksFrSO.js} +2 -2
  13. package/dist/eval-ui/assets/SearchPaletteCore-D49bVafl.js +14 -0
  14. package/dist/eval-ui/assets/{SkillDetailPanel-DzmlOsAc.js → SkillDetailPanel-Cg8lyDAl.js} +1 -1
  15. package/dist/eval-ui/assets/UpdateDropdown-CLt94M3u.js +1 -0
  16. package/dist/eval-ui/assets/{index-BAN03ugM.css → index-C8DXCPPg.css} +1 -1
  17. package/dist/eval-ui/assets/index-fbCfi37A.js +102 -0
  18. package/dist/eval-ui/assets/{skill-url-lxDpBkBU.js → skill-url-DXjZASn-.js} +1 -1
  19. package/dist/eval-ui/index.html +2 -2
  20. package/dist/index.js +0 -0
  21. package/package.json +1 -1
  22. package/dist/agents/agents-registry.test.d.ts +0 -1
  23. package/dist/agents/agents-registry.test.js +0 -248
  24. package/dist/agents/agents-registry.test.js.map +0 -1
  25. package/dist/api/client.test.d.ts +0 -1
  26. package/dist/api/client.test.js +0 -428
  27. package/dist/api/client.test.js.map +0 -1
  28. package/dist/audit/audit-integration.test.d.ts +0 -1
  29. package/dist/audit/audit-integration.test.js +0 -92
  30. package/dist/audit/audit-integration.test.js.map +0 -1
  31. package/dist/audit/audit-llm.test.d.ts +0 -1
  32. package/dist/audit/audit-llm.test.js +0 -110
  33. package/dist/audit/audit-llm.test.js.map +0 -1
  34. package/dist/audit/audit-patterns.test.d.ts +0 -1
  35. package/dist/audit/audit-patterns.test.js +0 -91
  36. package/dist/audit/audit-patterns.test.js.map +0 -1
  37. package/dist/audit/audit-scanner.test.d.ts +0 -1
  38. package/dist/audit/audit-scanner.test.js +0 -112
  39. package/dist/audit/audit-scanner.test.js.map +0 -1
  40. package/dist/audit/audit-types.test.d.ts +0 -1
  41. package/dist/audit/audit-types.test.js +0 -140
  42. package/dist/audit/audit-types.test.js.map +0 -1
  43. package/dist/audit/config.test.d.ts +0 -1
  44. package/dist/audit/config.test.js +0 -44
  45. package/dist/audit/config.test.js.map +0 -1
  46. package/dist/audit/file-discovery.test.d.ts +0 -1
  47. package/dist/audit/file-discovery.test.js +0 -120
  48. package/dist/audit/file-discovery.test.js.map +0 -1
  49. package/dist/audit/fix-suggestions.test.d.ts +0 -1
  50. package/dist/audit/fix-suggestions.test.js +0 -35
  51. package/dist/audit/fix-suggestions.test.js.map +0 -1
  52. package/dist/audit/formatters/json-formatter.test.d.ts +0 -1
  53. package/dist/audit/formatters/json-formatter.test.js +0 -49
  54. package/dist/audit/formatters/json-formatter.test.js.map +0 -1
  55. package/dist/audit/formatters/report-formatter.test.d.ts +0 -1
  56. package/dist/audit/formatters/report-formatter.test.js +0 -51
  57. package/dist/audit/formatters/report-formatter.test.js.map +0 -1
  58. package/dist/audit/formatters/sarif-formatter.test.d.ts +0 -1
  59. package/dist/audit/formatters/sarif-formatter.test.js +0 -71
  60. package/dist/audit/formatters/sarif-formatter.test.js.map +0 -1
  61. package/dist/audit/formatters/terminal-formatter.test.d.ts +0 -1
  62. package/dist/audit/formatters/terminal-formatter.test.js +0 -51
  63. package/dist/audit/formatters/terminal-formatter.test.js.map +0 -1
  64. package/dist/blocklist/blocklist-e2e.test.d.ts +0 -1
  65. package/dist/blocklist/blocklist-e2e.test.js +0 -346
  66. package/dist/blocklist/blocklist-e2e.test.js.map +0 -1
  67. package/dist/blocklist/blocklist.test.d.ts +0 -1
  68. package/dist/blocklist/blocklist.test.js +0 -259
  69. package/dist/blocklist/blocklist.test.js.map +0 -1
  70. package/dist/commands/__tests__/eval-router.test.d.ts +0 -1
  71. package/dist/commands/__tests__/eval-router.test.js +0 -60
  72. package/dist/commands/__tests__/eval-router.test.js.map +0 -1
  73. package/dist/commands/__tests__/eval-serve.test.d.ts +0 -1
  74. package/dist/commands/__tests__/eval-serve.test.js +0 -23
  75. package/dist/commands/__tests__/eval-serve.test.js.map +0 -1
  76. package/dist/commands/add-blocklist-e2e.test.d.ts +0 -1
  77. package/dist/commands/add-blocklist-e2e.test.js +0 -397
  78. package/dist/commands/add-blocklist-e2e.test.js.map +0 -1
  79. package/dist/commands/add-wizard.test.d.ts +0 -1
  80. package/dist/commands/add-wizard.test.js +0 -392
  81. package/dist/commands/add-wizard.test.js.map +0 -1
  82. package/dist/commands/add.test.d.ts +0 -1
  83. package/dist/commands/add.test.js +0 -2365
  84. package/dist/commands/add.test.js.map +0 -1
  85. package/dist/commands/audit.test.d.ts +0 -1
  86. package/dist/commands/audit.test.js +0 -79
  87. package/dist/commands/audit.test.js.map +0 -1
  88. package/dist/commands/blocklist.test.d.ts +0 -1
  89. package/dist/commands/blocklist.test.js +0 -158
  90. package/dist/commands/blocklist.test.js.map +0 -1
  91. package/dist/commands/eval/__tests__/coverage.test.d.ts +0 -1
  92. package/dist/commands/eval/__tests__/coverage.test.js +0 -122
  93. package/dist/commands/eval/__tests__/coverage.test.js.map +0 -1
  94. package/dist/commands/eval/__tests__/generate-all.test.d.ts +0 -1
  95. package/dist/commands/eval/__tests__/generate-all.test.js +0 -133
  96. package/dist/commands/eval/__tests__/generate-all.test.js.map +0 -1
  97. package/dist/commands/eval/__tests__/init.test.d.ts +0 -1
  98. package/dist/commands/eval/__tests__/init.test.js +0 -116
  99. package/dist/commands/eval/__tests__/init.test.js.map +0 -1
  100. package/dist/commands/eval/__tests__/run.test.d.ts +0 -1
  101. package/dist/commands/eval/__tests__/run.test.js +0 -186
  102. package/dist/commands/eval/__tests__/run.test.js.map +0 -1
  103. package/dist/commands/find.test.d.ts +0 -1
  104. package/dist/commands/find.test.js +0 -481
  105. package/dist/commands/find.test.js.map +0 -1
  106. package/dist/commands/marketplace.test.d.ts +0 -1
  107. package/dist/commands/marketplace.test.js +0 -129
  108. package/dist/commands/marketplace.test.js.map +0 -1
  109. package/dist/commands/remove.test.d.ts +0 -1
  110. package/dist/commands/remove.test.js +0 -164
  111. package/dist/commands/remove.test.js.map +0 -1
  112. package/dist/commands/should-skip.test.d.ts +0 -1
  113. package/dist/commands/should-skip.test.js +0 -56
  114. package/dist/commands/should-skip.test.js.map +0 -1
  115. package/dist/commands/submit.test.d.ts +0 -1
  116. package/dist/commands/submit.test.js +0 -83
  117. package/dist/commands/submit.test.js.map +0 -1
  118. package/dist/commands/update.test.d.ts +0 -1
  119. package/dist/commands/update.test.js +0 -250
  120. package/dist/commands/update.test.js.map +0 -1
  121. package/dist/discovery/github-tree.test.d.ts +0 -1
  122. package/dist/discovery/github-tree.test.js +0 -372
  123. package/dist/discovery/github-tree.test.js.map +0 -1
  124. package/dist/eval/__tests__/activation-tester.test.d.ts +0 -1
  125. package/dist/eval/__tests__/activation-tester.test.js +0 -203
  126. package/dist/eval/__tests__/activation-tester.test.js.map +0 -1
  127. package/dist/eval/__tests__/benchmark-history.test.d.ts +0 -1
  128. package/dist/eval/__tests__/benchmark-history.test.js +0 -422
  129. package/dist/eval/__tests__/benchmark-history.test.js.map +0 -1
  130. package/dist/eval/__tests__/benchmark.test.d.ts +0 -1
  131. package/dist/eval/__tests__/benchmark.test.js +0 -94
  132. package/dist/eval/__tests__/benchmark.test.js.map +0 -1
  133. package/dist/eval/__tests__/comparator.test.d.ts +0 -1
  134. package/dist/eval/__tests__/comparator.test.js +0 -282
  135. package/dist/eval/__tests__/comparator.test.js.map +0 -1
  136. package/dist/eval/__tests__/judge.test.d.ts +0 -1
  137. package/dist/eval/__tests__/judge.test.js +0 -122
  138. package/dist/eval/__tests__/judge.test.js.map +0 -1
  139. package/dist/eval/__tests__/llm.test.d.ts +0 -1
  140. package/dist/eval/__tests__/llm.test.js +0 -543
  141. package/dist/eval/__tests__/llm.test.js.map +0 -1
  142. package/dist/eval/__tests__/mcp-detector.test.d.ts +0 -1
  143. package/dist/eval/__tests__/mcp-detector.test.js +0 -180
  144. package/dist/eval/__tests__/mcp-detector.test.js.map +0 -1
  145. package/dist/eval/__tests__/prompt-builder.test.d.ts +0 -1
  146. package/dist/eval/__tests__/prompt-builder.test.js +0 -142
  147. package/dist/eval/__tests__/prompt-builder.test.js.map +0 -1
  148. package/dist/eval/__tests__/schema.test.d.ts +0 -1
  149. package/dist/eval/__tests__/schema.test.js +0 -247
  150. package/dist/eval/__tests__/schema.test.js.map +0 -1
  151. package/dist/eval/__tests__/skill-scanner.test.d.ts +0 -1
  152. package/dist/eval/__tests__/skill-scanner.test.js +0 -228
  153. package/dist/eval/__tests__/skill-scanner.test.js.map +0 -1
  154. package/dist/eval/__tests__/verdict.test.d.ts +0 -1
  155. package/dist/eval/__tests__/verdict.test.js +0 -47
  156. package/dist/eval/__tests__/verdict.test.js.map +0 -1
  157. package/dist/eval-server/__tests__/benchmark-runner.test.d.ts +0 -1
  158. package/dist/eval-server/__tests__/benchmark-runner.test.js +0 -301
  159. package/dist/eval-server/__tests__/benchmark-runner.test.js.map +0 -1
  160. package/dist/eval-server/__tests__/comparison-sse-events.test.d.ts +0 -1
  161. package/dist/eval-server/__tests__/comparison-sse-events.test.js +0 -278
  162. package/dist/eval-server/__tests__/comparison-sse-events.test.js.map +0 -1
  163. package/dist/eval-server/__tests__/sse-helpers.test.d.ts +0 -1
  164. package/dist/eval-server/__tests__/sse-helpers.test.js +0 -128
  165. package/dist/eval-server/__tests__/sse-helpers.test.js.map +0 -1
  166. package/dist/eval-ui/assets/SearchPaletteCore-CnRYmTuv.js +0 -6
  167. package/dist/eval-ui/assets/UpdateDropdown-BsAm4uMW.js +0 -1
  168. package/dist/eval-ui/assets/index-BGQolxHD.js +0 -102
  169. package/dist/installer/canonical.test.d.ts +0 -1
  170. package/dist/installer/canonical.test.js +0 -264
  171. package/dist/installer/canonical.test.js.map +0 -1
  172. package/dist/lockfile/lockfile.test.d.ts +0 -1
  173. package/dist/lockfile/lockfile.test.js +0 -204
  174. package/dist/lockfile/lockfile.test.js.map +0 -1
  175. package/dist/lockfile/project-root.test.d.ts +0 -1
  176. package/dist/lockfile/project-root.test.js +0 -49
  177. package/dist/lockfile/project-root.test.js.map +0 -1
  178. package/dist/marketplace/marketplace.test.d.ts +0 -1
  179. package/dist/marketplace/marketplace.test.js +0 -312
  180. package/dist/marketplace/marketplace.test.js.map +0 -1
  181. package/dist/resolvers/source-resolver.test.d.ts +0 -1
  182. package/dist/resolvers/source-resolver.test.js +0 -104
  183. package/dist/resolvers/source-resolver.test.js.map +0 -1
  184. package/dist/resolvers/url-resolver.test.d.ts +0 -1
  185. package/dist/resolvers/url-resolver.test.js +0 -49
  186. package/dist/resolvers/url-resolver.test.js.map +0 -1
  187. package/dist/scanner/dci-integration.test.d.ts +0 -1
  188. package/dist/scanner/dci-integration.test.js +0 -83
  189. package/dist/scanner/dci-integration.test.js.map +0 -1
  190. package/dist/scanner/patterns.test.d.ts +0 -1
  191. package/dist/scanner/patterns.test.js +0 -832
  192. package/dist/scanner/patterns.test.js.map +0 -1
  193. package/dist/scanner/tier1.test.d.ts +0 -1
  194. package/dist/scanner/tier1.test.js +0 -305
  195. package/dist/scanner/tier1.test.js.map +0 -1
  196. package/dist/security/platform-security.test.d.ts +0 -1
  197. package/dist/security/platform-security.test.js +0 -92
  198. package/dist/security/platform-security.test.js.map +0 -1
  199. package/dist/settings/settings.test.d.ts +0 -1
  200. package/dist/settings/settings.test.js +0 -103
  201. package/dist/settings/settings.test.js.map +0 -1
  202. package/dist/updater/source-fetcher.test.d.ts +0 -1
  203. package/dist/updater/source-fetcher.test.js +0 -192
  204. package/dist/updater/source-fetcher.test.js.map +0 -1
  205. package/dist/utils/__tests__/paths.test.d.ts +0 -1
  206. package/dist/utils/__tests__/paths.test.js +0 -22
  207. package/dist/utils/__tests__/paths.test.js.map +0 -1
  208. package/dist/utils/__tests__/resolve-binary.integration.test.d.ts +0 -1
  209. package/dist/utils/__tests__/resolve-binary.integration.test.js +0 -138
  210. package/dist/utils/__tests__/resolve-binary.integration.test.js.map +0 -1
  211. package/dist/utils/__tests__/resolve-binary.test.d.ts +0 -1
  212. package/dist/utils/__tests__/resolve-binary.test.js +0 -175
  213. package/dist/utils/__tests__/resolve-binary.test.js.map +0 -1
  214. package/dist/utils/__tests__/validation.test.d.ts +0 -1
  215. package/dist/utils/__tests__/validation.test.js +0 -107
  216. package/dist/utils/__tests__/validation.test.js.map +0 -1
  217. package/dist/utils/agent-filter.test.d.ts +0 -1
  218. package/dist/utils/agent-filter.test.js +0 -75
  219. package/dist/utils/agent-filter.test.js.map +0 -1
  220. package/dist/utils/output.test.d.ts +0 -1
  221. package/dist/utils/output.test.js +0 -28
  222. package/dist/utils/output.test.js.map +0 -1
  223. package/dist/utils/project-root.test.d.ts +0 -1
  224. package/dist/utils/project-root.test.js +0 -74
  225. package/dist/utils/project-root.test.js.map +0 -1
  226. package/dist/utils/prompts.test.d.ts +0 -1
  227. package/dist/utils/prompts.test.js +0 -285
  228. package/dist/utils/prompts.test.js.map +0 -1
@@ -1,346 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // E2E integration tests: blocklist blocking with REAL malicious skill data
3
- //
4
- // These tests simulate the full chain:
5
- // API response (real seed data) -> local cache -> checkBlocklist -> block
6
- //
7
- // They use the actual ClawHub malicious skill names, threat types, severities,
8
- // and reasons from the verified-skill.com seed data to prove that a developer
9
- // attempting to install a known-malicious skill is:
10
- // 1. Blocked with the correct threat details
11
- // 2. Shown the exact reason WHY it's blocked
12
- // 3. Allowed through with --force but with a prominent warning
13
- // ---------------------------------------------------------------------------
14
- import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
15
- // ---------------------------------------------------------------------------
16
- // Mocks
17
- // ---------------------------------------------------------------------------
18
- const mocks = vi.hoisted(() => ({
19
- readFileSync: vi.fn(),
20
- writeFileSync: vi.fn(),
21
- mkdirSync: vi.fn(),
22
- existsSync: vi.fn(),
23
- }));
24
- vi.mock("node:fs", () => ({
25
- readFileSync: mocks.readFileSync,
26
- writeFileSync: mocks.writeFileSync,
27
- mkdirSync: mocks.mkdirSync,
28
- existsSync: mocks.existsSync,
29
- }));
30
- const { checkBlocklist, getCachedBlocklist, syncBlocklist } = await import("./blocklist.js");
31
- // ---------------------------------------------------------------------------
32
- // Real seed data — mirrors the actual seed from vskill-platform
33
- // These are the EXACT entries from blocklist-seed-data.ts
34
- // ---------------------------------------------------------------------------
35
- const REAL_SEED_ENTRIES = [
36
- // hightower6eu — platform impersonation
37
- {
38
- skillName: "Clawhub",
39
- sourceUrl: "https://github.com/hightower6eu/Clawhub",
40
- sourceRegistry: "clawhub",
41
- threatType: "platform-impersonation",
42
- severity: "critical",
43
- reason: "Impersonates the ClawHub/GitHub platform to trick users into running malicious code",
44
- evidenceUrls: [
45
- "https://snyk.io/blog/toxicskills-mcp-exploit",
46
- "https://www.aikido.dev/blog/malicious-mcp-servers",
47
- ],
48
- discoveredAt: "2025-12-01T00:00:00.000Z",
49
- },
50
- // hightower6eu — credential theft
51
- {
52
- skillName: "Polymarket Trading Bot",
53
- sourceUrl: "https://github.com/hightower6eu/polymarket-trading-bot",
54
- sourceRegistry: "clawhub",
55
- threatType: "credential-theft",
56
- severity: "critical",
57
- reason: "Trading bot facade stealing wallet credentials and API keys",
58
- evidenceUrls: ["https://snyk.io/blog/toxicskills-mcp-exploit"],
59
- discoveredAt: "2025-12-01T00:00:00.000Z",
60
- },
61
- // hightower6eu — auto-updater trojan
62
- {
63
- skillName: "Skills Auto-Updater",
64
- sourceUrl: "https://github.com/hightower6eu/skills-auto-updater",
65
- sourceRegistry: "clawhub",
66
- threatType: "auto-updater-trojan",
67
- severity: "high",
68
- reason: "Auto-updater trojan that downloads and executes malicious payloads",
69
- evidenceUrls: ["https://snyk.io/blog/toxicskills-mcp-exploit"],
70
- discoveredAt: "2025-12-01T00:00:00.000Z",
71
- },
72
- // Aslaep123 — base64 credential exfil
73
- {
74
- skillName: "polymarket-traiding-bot",
75
- sourceUrl: "https://github.com/Aslaep123/polymarket-traiding-bot",
76
- sourceRegistry: "clawhub",
77
- threatType: "credential-theft",
78
- severity: "critical",
79
- reason: "Base64-encoded credential exfiltration via hidden HTTP requests",
80
- evidenceUrls: [
81
- "https://snyk.io/blog/toxicskills-mcp-exploit",
82
- "https://www.aikido.dev/blog/malicious-mcp-servers",
83
- ],
84
- discoveredAt: "2025-12-01T00:00:00.000Z",
85
- },
86
- // aztr0nutzs — prompt injection
87
- {
88
- skillName: "google-qx4",
89
- sourceUrl: "https://github.com/aztr0nutzs/google-qx4",
90
- sourceRegistry: "clawhub",
91
- threatType: "prompt-injection",
92
- severity: "critical",
93
- reason: "Prompt injection via fake Google integration skill",
94
- evidenceUrls: ["https://www.aikido.dev/blog/malicious-mcp-servers"],
95
- discoveredAt: "2025-12-01T00:00:00.000Z",
96
- },
97
- // zaycv — typosquatting
98
- {
99
- skillName: "clawhud",
100
- sourceUrl: "https://github.com/zaycv/clawhud",
101
- sourceRegistry: "clawhub",
102
- threatType: "typosquatting",
103
- severity: "high",
104
- reason: "Typosquatting ClawHub (clawhud vs clawhub) to mislead users",
105
- evidenceUrls: ["https://www.aikido.dev/blog/malicious-mcp-servers"],
106
- discoveredAt: "2025-12-01T00:00:00.000Z",
107
- },
108
- // zaycv — typosquatting (homoglyph)
109
- {
110
- skillName: "cIawhub",
111
- sourceUrl: "https://github.com/zaycv/cIawhub",
112
- sourceRegistry: "clawhub",
113
- threatType: "typosquatting",
114
- severity: "high",
115
- reason: "Typosquatting ClawHub using uppercase I for lowercase l (cIawhub)",
116
- evidenceUrls: ["https://www.aikido.dev/blog/malicious-mcp-servers"],
117
- discoveredAt: "2025-12-01T00:00:00.000Z",
118
- },
119
- ];
120
- function makeFreshCache(entries = REAL_SEED_ENTRIES) {
121
- return {
122
- entries,
123
- count: entries.length,
124
- lastUpdated: "2026-02-19T00:00:00Z",
125
- fetchedAt: new Date().toISOString(), // fresh (within 1 hour)
126
- etag: '"seed-data"',
127
- };
128
- }
129
- // ---------------------------------------------------------------------------
130
- // Tests
131
- // ---------------------------------------------------------------------------
132
- const originalFetch = globalThis.fetch;
133
- beforeEach(() => {
134
- vi.clearAllMocks();
135
- });
136
- afterEach(() => {
137
- globalThis.fetch = originalFetch;
138
- delete process.env.VSKILL_API_URL;
139
- });
140
- // ============================================================================
141
- // 1. Blocking known malicious skills by exact name
142
- // ============================================================================
143
- describe("E2E: blocking known malicious skills from ClawHub seed data", () => {
144
- beforeEach(() => {
145
- // Simulate fresh local cache with real seed data
146
- mocks.existsSync.mockReturnValue(true);
147
- mocks.readFileSync.mockReturnValue(JSON.stringify(makeFreshCache()));
148
- });
149
- it("blocks hightower6eu's Clawhub (platform-impersonation, critical)", async () => {
150
- const result = await checkBlocklist("Clawhub");
151
- expect(result).not.toBeNull();
152
- expect(result.skillName).toBe("Clawhub");
153
- expect(result.threatType).toBe("platform-impersonation");
154
- expect(result.severity).toBe("critical");
155
- expect(result.reason).toContain("Impersonates the ClawHub");
156
- expect(result.sourceRegistry).toBe("clawhub");
157
- });
158
- it("blocks hightower6eu's Polymarket Trading Bot (credential-theft, critical)", async () => {
159
- const result = await checkBlocklist("Polymarket Trading Bot");
160
- expect(result).not.toBeNull();
161
- expect(result.skillName).toBe("Polymarket Trading Bot");
162
- expect(result.threatType).toBe("credential-theft");
163
- expect(result.severity).toBe("critical");
164
- expect(result.reason).toContain("wallet credentials");
165
- });
166
- it("blocks hightower6eu's Skills Auto-Updater (auto-updater-trojan, high)", async () => {
167
- const result = await checkBlocklist("Skills Auto-Updater");
168
- expect(result).not.toBeNull();
169
- expect(result.threatType).toBe("auto-updater-trojan");
170
- expect(result.severity).toBe("high");
171
- expect(result.reason).toContain("malicious payloads");
172
- });
173
- it("blocks Aslaep123's polymarket-traiding-bot (credential-theft, critical)", async () => {
174
- const result = await checkBlocklist("polymarket-traiding-bot");
175
- expect(result).not.toBeNull();
176
- expect(result.threatType).toBe("credential-theft");
177
- expect(result.severity).toBe("critical");
178
- expect(result.reason).toContain("Base64-encoded credential exfiltration");
179
- expect(result.evidenceUrls).toContain("https://snyk.io/blog/toxicskills-mcp-exploit");
180
- });
181
- it("blocks aztr0nutzs's google-qx4 (prompt-injection, critical)", async () => {
182
- const result = await checkBlocklist("google-qx4");
183
- expect(result).not.toBeNull();
184
- expect(result.threatType).toBe("prompt-injection");
185
- expect(result.severity).toBe("critical");
186
- expect(result.reason).toContain("Prompt injection");
187
- });
188
- it("blocks zaycv's clawhud typosquatting (typosquatting, high)", async () => {
189
- const result = await checkBlocklist("clawhud");
190
- expect(result).not.toBeNull();
191
- expect(result.threatType).toBe("typosquatting");
192
- expect(result.severity).toBe("high");
193
- expect(result.reason).toContain("clawhud vs clawhub");
194
- });
195
- it("blocks zaycv's cIawhub homoglyph attack (typosquatting, high)", async () => {
196
- const result = await checkBlocklist("cIawhub");
197
- expect(result).not.toBeNull();
198
- expect(result.threatType).toBe("typosquatting");
199
- expect(result.reason).toContain("uppercase I for lowercase l");
200
- });
201
- it("allows legitimate skill that is NOT on the blocklist", async () => {
202
- const result = await checkBlocklist("my-safe-coding-assistant");
203
- expect(result).toBeNull();
204
- });
205
- });
206
- // ============================================================================
207
- // 2. API sync produces correct cache from real data
208
- // ============================================================================
209
- describe("E2E: API sync with real seed data", () => {
210
- it("syncs 22 entries from API and all are searchable", async () => {
211
- // Simulate the API returning the full seed data
212
- globalThis.fetch = vi.fn().mockResolvedValue({
213
- ok: true,
214
- headers: { get: (h) => (h === "etag" ? '"v1"' : null) },
215
- json: async () => ({
216
- entries: REAL_SEED_ENTRIES,
217
- count: REAL_SEED_ENTRIES.length,
218
- lastUpdated: "2026-02-19T00:00:00Z",
219
- }),
220
- });
221
- mocks.existsSync.mockReturnValue(true);
222
- const cache = await syncBlocklist();
223
- expect(cache.entries).toHaveLength(REAL_SEED_ENTRIES.length);
224
- expect(cache.count).toBe(REAL_SEED_ENTRIES.length);
225
- expect(cache.etag).toBe('"v1"');
226
- // Verify writeFileSync was called with the cache
227
- expect(mocks.writeFileSync).toHaveBeenCalledTimes(1);
228
- const writtenData = JSON.parse(mocks.writeFileSync.mock.calls[0][1]);
229
- expect(writtenData.entries).toHaveLength(REAL_SEED_ENTRIES.length);
230
- // Every entry should have required fields
231
- for (const entry of writtenData.entries) {
232
- expect(entry.skillName).toBeTruthy();
233
- expect(entry.threatType).toBeTruthy();
234
- expect(entry.severity).toBeTruthy();
235
- expect(entry.reason).toBeTruthy();
236
- }
237
- });
238
- it("cached data allows blocking every seed entry by name", async () => {
239
- // Set up fresh cache with all seed data
240
- mocks.existsSync.mockReturnValue(true);
241
- mocks.readFileSync.mockReturnValue(JSON.stringify(makeFreshCache()));
242
- // Check every single seed entry is findable
243
- for (const entry of REAL_SEED_ENTRIES) {
244
- const result = await checkBlocklist(entry.skillName);
245
- expect(result).not.toBeNull();
246
- expect(result.skillName).toBe(entry.skillName);
247
- expect(result.threatType).toBe(entry.threatType);
248
- expect(result.severity).toBe(entry.severity);
249
- }
250
- });
251
- });
252
- // ============================================================================
253
- // 3. Stale cache refresh with real data
254
- // ============================================================================
255
- describe("E2E: stale cache refresh with real seed data", () => {
256
- it("refreshes stale cache from API and blocks newly added skills", async () => {
257
- // Start with stale cache that has only 2 entries
258
- const twoHoursAgo = new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString();
259
- const staleCache = makeFreshCache(REAL_SEED_ENTRIES.slice(0, 2));
260
- staleCache.fetchedAt = twoHoursAgo;
261
- mocks.existsSync.mockReturnValue(true);
262
- mocks.readFileSync.mockReturnValue(JSON.stringify(staleCache));
263
- // API returns full data
264
- globalThis.fetch = vi.fn().mockResolvedValue({
265
- ok: true,
266
- headers: { get: () => null },
267
- json: async () => ({
268
- entries: REAL_SEED_ENTRIES,
269
- count: REAL_SEED_ENTRIES.length,
270
- lastUpdated: "2026-02-19T00:00:00Z",
271
- }),
272
- });
273
- // google-qx4 was not in stale cache (only first 2 entries)
274
- // but after refresh it should be findable
275
- const result = await checkBlocklist("google-qx4");
276
- expect(result).not.toBeNull();
277
- expect(result.threatType).toBe("prompt-injection");
278
- expect(result.severity).toBe("critical");
279
- });
280
- it("falls back to stale cache when API is down, still blocks known skills", async () => {
281
- const twoHoursAgo = new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString();
282
- const staleCache = makeFreshCache();
283
- staleCache.fetchedAt = twoHoursAgo;
284
- mocks.existsSync.mockReturnValue(true);
285
- mocks.readFileSync.mockReturnValue(JSON.stringify(staleCache));
286
- // API is down
287
- globalThis.fetch = vi
288
- .fn()
289
- .mockRejectedValue(new Error("ECONNREFUSED"));
290
- // Should still block from stale cache
291
- const result = await checkBlocklist("polymarket-traiding-bot");
292
- expect(result).not.toBeNull();
293
- expect(result.threatType).toBe("credential-theft");
294
- expect(result.reason).toContain("Base64-encoded");
295
- });
296
- });
297
- // ============================================================================
298
- // 4. All 5 threat types are represented and catchable
299
- // ============================================================================
300
- describe("E2E: all threat types from ClawHub research are catchable", () => {
301
- beforeEach(() => {
302
- mocks.existsSync.mockReturnValue(true);
303
- mocks.readFileSync.mockReturnValue(JSON.stringify(makeFreshCache()));
304
- });
305
- const threatTypeCases = [
306
- {
307
- name: "platform-impersonation (hightower6eu)",
308
- skillName: "Clawhub",
309
- expectedType: "platform-impersonation",
310
- expectedSeverity: "critical",
311
- },
312
- {
313
- name: "credential-theft (Aslaep123)",
314
- skillName: "polymarket-traiding-bot",
315
- expectedType: "credential-theft",
316
- expectedSeverity: "critical",
317
- },
318
- {
319
- name: "auto-updater-trojan (hightower6eu)",
320
- skillName: "Skills Auto-Updater",
321
- expectedType: "auto-updater-trojan",
322
- expectedSeverity: "high",
323
- },
324
- {
325
- name: "prompt-injection (aztr0nutzs)",
326
- skillName: "google-qx4",
327
- expectedType: "prompt-injection",
328
- expectedSeverity: "critical",
329
- },
330
- {
331
- name: "typosquatting (zaycv)",
332
- skillName: "clawhud",
333
- expectedType: "typosquatting",
334
- expectedSeverity: "high",
335
- },
336
- ];
337
- it.each(threatTypeCases)("catches $name: $skillName", async ({ skillName, expectedType, expectedSeverity }) => {
338
- const result = await checkBlocklist(skillName);
339
- expect(result).not.toBeNull();
340
- expect(result.threatType).toBe(expectedType);
341
- expect(result.severity).toBe(expectedSeverity);
342
- expect(result.reason.length).toBeGreaterThan(10); // has meaningful reason
343
- expect(result.evidenceUrls.length).toBeGreaterThan(0); // has evidence
344
- });
345
- });
346
- //# sourceMappingURL=blocklist-e2e.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"blocklist-e2e.test.js","sourceRoot":"","sources":["../../src/blocklist/blocklist-e2e.test.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- export {};
@@ -1,259 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
- // ---------------------------------------------------------------------------
3
- // Mocks — vi.hoisted for ESM compatibility
4
- // ---------------------------------------------------------------------------
5
- const mocks = vi.hoisted(() => ({
6
- readFileSync: vi.fn(),
7
- writeFileSync: vi.fn(),
8
- mkdirSync: vi.fn(),
9
- existsSync: vi.fn(),
10
- fetch: vi.fn(),
11
- }));
12
- vi.mock("node:fs", () => ({
13
- readFileSync: mocks.readFileSync,
14
- writeFileSync: mocks.writeFileSync,
15
- mkdirSync: mocks.mkdirSync,
16
- existsSync: mocks.existsSync,
17
- }));
18
- // Mock global fetch
19
- const originalFetch = globalThis.fetch;
20
- // ---------------------------------------------------------------------------
21
- // Import module under test AFTER mocks
22
- // ---------------------------------------------------------------------------
23
- const { checkBlocklist, syncBlocklist, getCachedBlocklist, isBlocklistStale, } = await import("./blocklist.js");
24
- // ---------------------------------------------------------------------------
25
- // Helpers
26
- // ---------------------------------------------------------------------------
27
- function makeEntry(overrides = {}) {
28
- return {
29
- skillName: "evil-skill",
30
- threatType: "credential-theft",
31
- severity: "critical",
32
- reason: "Steals AWS credentials",
33
- evidenceUrls: ["https://example.com/report"],
34
- discoveredAt: "2026-02-01T00:00:00Z",
35
- ...overrides,
36
- };
37
- }
38
- function makeCache(overrides = {}) {
39
- return {
40
- entries: [makeEntry()],
41
- count: 1,
42
- lastUpdated: "2026-02-01T00:00:00Z",
43
- fetchedAt: new Date().toISOString(),
44
- ...overrides,
45
- };
46
- }
47
- // ---------------------------------------------------------------------------
48
- // Tests
49
- // ---------------------------------------------------------------------------
50
- beforeEach(() => {
51
- vi.clearAllMocks();
52
- globalThis.fetch = mocks.fetch;
53
- });
54
- afterEach(() => {
55
- globalThis.fetch = originalFetch;
56
- delete process.env.VSKILL_API_URL;
57
- });
58
- describe("getCachedBlocklist", () => {
59
- it("returns null when cache file does not exist", () => {
60
- mocks.existsSync.mockReturnValue(false);
61
- expect(getCachedBlocklist()).toBeNull();
62
- });
63
- it("returns parsed cache when file exists", () => {
64
- const cache = makeCache();
65
- mocks.existsSync.mockReturnValue(true);
66
- mocks.readFileSync.mockReturnValue(JSON.stringify(cache));
67
- const result = getCachedBlocklist();
68
- expect(result).toEqual(cache);
69
- });
70
- it("returns null when cache file is corrupted", () => {
71
- mocks.existsSync.mockReturnValue(true);
72
- mocks.readFileSync.mockReturnValue("not json{{{");
73
- expect(getCachedBlocklist()).toBeNull();
74
- });
75
- });
76
- describe("isBlocklistStale", () => {
77
- it("returns true when cache is older than 1 hour", () => {
78
- const twoHoursAgo = new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString();
79
- const cache = makeCache({ fetchedAt: twoHoursAgo });
80
- expect(isBlocklistStale(cache)).toBe(true);
81
- });
82
- it("returns false when cache is less than 1 hour old", () => {
83
- const tenMinutesAgo = new Date(Date.now() - 10 * 60 * 1000).toISOString();
84
- const cache = makeCache({ fetchedAt: tenMinutesAgo });
85
- expect(isBlocklistStale(cache)).toBe(false);
86
- });
87
- it("returns true when fetchedAt is invalid", () => {
88
- const cache = makeCache({ fetchedAt: "invalid-date" });
89
- expect(isBlocklistStale(cache)).toBe(true);
90
- });
91
- });
92
- describe("syncBlocklist", () => {
93
- it("fetches from API and writes cache file", async () => {
94
- const apiResponse = {
95
- entries: [makeEntry()],
96
- count: 1,
97
- lastUpdated: "2026-02-01T00:00:00Z",
98
- };
99
- mocks.fetch.mockResolvedValue({
100
- ok: true,
101
- headers: { get: () => null },
102
- json: async () => apiResponse,
103
- });
104
- mocks.existsSync.mockReturnValue(true);
105
- const result = await syncBlocklist();
106
- expect(mocks.fetch).toHaveBeenCalledWith("https://verified-skill.com/api/v1/blocklist", expect.any(Object));
107
- expect(mocks.writeFileSync).toHaveBeenCalled();
108
- expect(result.entries).toEqual(apiResponse.entries);
109
- expect(result.count).toBe(1);
110
- expect(result.fetchedAt).toBeDefined();
111
- });
112
- it("uses VSKILL_API_URL environment variable when set", async () => {
113
- process.env.VSKILL_API_URL = "https://custom-api.example.com";
114
- const apiResponse = {
115
- entries: [],
116
- count: 0,
117
- lastUpdated: "2026-02-01T00:00:00Z",
118
- };
119
- mocks.fetch.mockResolvedValue({
120
- ok: true,
121
- headers: { get: () => null },
122
- json: async () => apiResponse,
123
- });
124
- mocks.existsSync.mockReturnValue(true);
125
- await syncBlocklist();
126
- expect(mocks.fetch).toHaveBeenCalledWith("https://custom-api.example.com/api/v1/blocklist", expect.any(Object));
127
- });
128
- it("creates ~/.vskill directory if it doesn't exist", async () => {
129
- const apiResponse = {
130
- entries: [],
131
- count: 0,
132
- lastUpdated: "2026-02-01T00:00:00Z",
133
- };
134
- mocks.fetch.mockResolvedValue({
135
- ok: true,
136
- headers: { get: () => null },
137
- json: async () => apiResponse,
138
- });
139
- mocks.existsSync.mockReturnValue(false);
140
- await syncBlocklist();
141
- expect(mocks.mkdirSync).toHaveBeenCalledWith(expect.stringContaining(".vskill"), { recursive: true });
142
- });
143
- it("stores etag from response headers", async () => {
144
- const apiResponse = {
145
- entries: [],
146
- count: 0,
147
- lastUpdated: "2026-02-01T00:00:00Z",
148
- };
149
- mocks.fetch.mockResolvedValue({
150
- ok: true,
151
- headers: { get: (h) => (h === "etag" ? '"abc123"' : null) },
152
- json: async () => apiResponse,
153
- });
154
- mocks.existsSync.mockReturnValue(true);
155
- const result = await syncBlocklist();
156
- expect(result.etag).toBe('"abc123"');
157
- });
158
- it("throws when API returns non-ok response", async () => {
159
- mocks.fetch.mockResolvedValue({
160
- ok: false,
161
- status: 500,
162
- statusText: "Internal Server Error",
163
- });
164
- await expect(syncBlocklist()).rejects.toThrow("Blocklist API error: 500");
165
- });
166
- });
167
- describe("checkBlocklist", () => {
168
- it("returns matching entry from fresh cache", async () => {
169
- const entry = makeEntry({ skillName: "evil-skill" });
170
- const cache = makeCache({
171
- entries: [entry],
172
- fetchedAt: new Date().toISOString(),
173
- });
174
- mocks.existsSync.mockReturnValue(true);
175
- mocks.readFileSync.mockReturnValue(JSON.stringify(cache));
176
- const result = await checkBlocklist("evil-skill");
177
- expect(result).toEqual(entry);
178
- });
179
- it("returns null when skill is not in blocklist", async () => {
180
- const cache = makeCache({
181
- entries: [makeEntry({ skillName: "evil-skill" })],
182
- fetchedAt: new Date().toISOString(),
183
- });
184
- mocks.existsSync.mockReturnValue(true);
185
- mocks.readFileSync.mockReturnValue(JSON.stringify(cache));
186
- const result = await checkBlocklist("safe-skill");
187
- expect(result).toBeNull();
188
- });
189
- it("refreshes cache when stale and API is available", async () => {
190
- const twoHoursAgo = new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString();
191
- const staleCache = makeCache({
192
- entries: [makeEntry({ skillName: "old-evil" })],
193
- fetchedAt: twoHoursAgo,
194
- });
195
- const freshEntry = makeEntry({ skillName: "new-evil" });
196
- mocks.existsSync.mockReturnValue(true);
197
- mocks.readFileSync.mockReturnValue(JSON.stringify(staleCache));
198
- mocks.fetch.mockResolvedValue({
199
- ok: true,
200
- headers: { get: () => null },
201
- json: async () => ({
202
- entries: [freshEntry],
203
- count: 1,
204
- lastUpdated: "2026-02-19T00:00:00Z",
205
- }),
206
- });
207
- const result = await checkBlocklist("new-evil");
208
- expect(result).toEqual(freshEntry);
209
- expect(mocks.fetch).toHaveBeenCalled();
210
- });
211
- it("falls back to stale cache when API is unreachable", async () => {
212
- const twoHoursAgo = new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString();
213
- const entry = makeEntry({ skillName: "evil-skill" });
214
- const staleCache = makeCache({
215
- entries: [entry],
216
- fetchedAt: twoHoursAgo,
217
- });
218
- mocks.existsSync.mockReturnValue(true);
219
- mocks.readFileSync.mockReturnValue(JSON.stringify(staleCache));
220
- mocks.fetch.mockRejectedValue(new Error("Network error"));
221
- const result = await checkBlocklist("evil-skill");
222
- expect(result).toEqual(entry);
223
- });
224
- it("returns null when no cache exists and API is unreachable", async () => {
225
- mocks.existsSync.mockReturnValue(false);
226
- mocks.fetch.mockRejectedValue(new Error("Network error"));
227
- const result = await checkBlocklist("evil-skill");
228
- expect(result).toBeNull();
229
- });
230
- it("matches by contentHash when provided", async () => {
231
- const entry = makeEntry({
232
- skillName: "evil-skill",
233
- contentHash: "sha256:abc123",
234
- });
235
- const cache = makeCache({
236
- entries: [entry],
237
- fetchedAt: new Date().toISOString(),
238
- });
239
- mocks.existsSync.mockReturnValue(true);
240
- mocks.readFileSync.mockReturnValue(JSON.stringify(cache));
241
- const result = await checkBlocklist("different-name", "sha256:abc123");
242
- expect(result).toEqual(entry);
243
- });
244
- it("matches by name even when contentHash doesn't match", async () => {
245
- const entry = makeEntry({
246
- skillName: "evil-skill",
247
- contentHash: "sha256:different",
248
- });
249
- const cache = makeCache({
250
- entries: [entry],
251
- fetchedAt: new Date().toISOString(),
252
- });
253
- mocks.existsSync.mockReturnValue(true);
254
- mocks.readFileSync.mockReturnValue(JSON.stringify(cache));
255
- const result = await checkBlocklist("evil-skill", "sha256:nomatch");
256
- expect(result).toEqual(entry);
257
- });
258
- });
259
- //# sourceMappingURL=blocklist.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"blocklist.test.js","sourceRoot":"","sources":["../../src/blocklist/blocklist.test.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- export {};