@weave_protocol/mund 0.3.0 → 0.3.1

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 (74) hide show
  1. package/README.md +70 -30
  2. package/dist/analyzers/index.d.ts.map +1 -1
  3. package/dist/analyzers/index.js +3 -1
  4. package/dist/analyzers/index.js.map +1 -1
  5. package/dist/canary.d.ts +48 -0
  6. package/dist/canary.d.ts.map +1 -0
  7. package/dist/canary.js +149 -0
  8. package/dist/canary.js.map +1 -0
  9. package/dist/cli/scan.d.ts +2 -1
  10. package/dist/cli/scan.d.ts.map +1 -1
  11. package/dist/cli/scan.js +10 -1
  12. package/dist/cli/scan.js.map +1 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +2 -0
  15. package/dist/index.js.map +1 -1
  16. package/dist/rugpull.d.ts +73 -0
  17. package/dist/rugpull.d.ts.map +1 -0
  18. package/dist/rugpull.js +177 -0
  19. package/dist/rugpull.js.map +1 -0
  20. package/dist/tools/canary-rugpull.d.ts +7 -0
  21. package/dist/tools/canary-rugpull.d.ts.map +1 -0
  22. package/dist/tools/canary-rugpull.js +50 -0
  23. package/dist/tools/canary-rugpull.js.map +1 -0
  24. package/dist/tools/index.d.ts +1 -0
  25. package/dist/tools/index.d.ts.map +1 -1
  26. package/dist/tools/index.js +4 -0
  27. package/dist/tools/index.js.map +1 -1
  28. package/package.json +1 -1
  29. package/src/analyzers/index.ts +3 -1
  30. package/src/canary.ts +165 -0
  31. package/src/cli/scan.ts +10 -1
  32. package/src/index.ts +2 -0
  33. package/src/rugpull.ts +233 -0
  34. package/src/tools/canary-rugpull.ts +75 -0
  35. package/src/tools/index.ts +5 -0
  36. package/tests/analyzers/engine.test.ts +1 -1
  37. package/tests/canary.test.ts +79 -0
  38. package/tests/cli/scan.test.ts +2 -2
  39. package/tests/fixtures/canary/base64.json +9 -0
  40. package/tests/fixtures/canary/clean-output.json +8 -0
  41. package/tests/fixtures/canary/exact-leak.json +9 -0
  42. package/tests/fixtures/canary/lowercased.json +9 -0
  43. package/tests/fixtures/canary/other-token.json +8 -0
  44. package/tests/fixtures/canary/prefix-only.json +8 -0
  45. package/tests/fixtures/canary/reversed.json +9 -0
  46. package/tests/fixtures/canary/spaced-out.json +9 -0
  47. package/tests/fixtures/canary/zero-width.json +9 -0
  48. package/tests/fixtures/rugpull/description-changed/baseline.json +36 -0
  49. package/tests/fixtures/rugpull/description-changed/current.json +36 -0
  50. package/tests/fixtures/rugpull/description-changed/expected.json +11 -0
  51. package/tests/fixtures/rugpull/gains-execution/baseline.json +36 -0
  52. package/tests/fixtures/rugpull/gains-execution/current.json +36 -0
  53. package/tests/fixtures/rugpull/gains-execution/expected.json +18 -0
  54. package/tests/fixtures/rugpull/schema-changed/baseline.json +36 -0
  55. package/tests/fixtures/rugpull/schema-changed/current.json +39 -0
  56. package/tests/fixtures/rugpull/schema-changed/expected.json +11 -0
  57. package/tests/fixtures/rugpull/schema-key-reorder/baseline.json +36 -0
  58. package/tests/fixtures/rugpull/schema-key-reorder/current.json +36 -0
  59. package/tests/fixtures/rugpull/schema-key-reorder/expected.json +5 -0
  60. package/tests/fixtures/rugpull/server-renamed/baseline.json +36 -0
  61. package/tests/fixtures/rugpull/server-renamed/current.json +36 -0
  62. package/tests/fixtures/rugpull/server-renamed/expected.json +11 -0
  63. package/tests/fixtures/rugpull/tool-added/baseline.json +36 -0
  64. package/tests/fixtures/rugpull/tool-added/current.json +44 -0
  65. package/tests/fixtures/rugpull/tool-added/expected.json +11 -0
  66. package/tests/fixtures/rugpull/tool-removed/baseline.json +36 -0
  67. package/tests/fixtures/rugpull/tool-removed/current.json +21 -0
  68. package/tests/fixtures/rugpull/tool-removed/expected.json +11 -0
  69. package/tests/fixtures/rugpull/unchanged/baseline.json +36 -0
  70. package/tests/fixtures/rugpull/unchanged/current.json +36 -0
  71. package/tests/fixtures/rugpull/unchanged/expected.json +5 -0
  72. package/tests/fixtures.test.ts +40 -0
  73. package/tests/rugpull.test.ts +80 -0
  74. package/tests/tools/canary-rugpull.test.ts +57 -0
@@ -0,0 +1,57 @@
1
+ import { mkdtempSync, rmSync } from 'fs';
2
+ import { tmpdir } from 'os';
3
+ import { join } from 'path';
4
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
5
+ import { registerCanaryRugPullTools } from '../../src/tools/canary-rugpull.js';
6
+ import { canaries } from '../../src/canary.js';
7
+ import { FakeMcpServer } from '../helpers.js';
8
+
9
+ const parse = (r: any) => JSON.parse(r.content[0].text);
10
+
11
+ describe('canary + rug-pull MCP tools', () => {
12
+ let server: FakeMcpServer;
13
+ let dir: string;
14
+ beforeEach(() => {
15
+ server = new FakeMcpServer();
16
+ registerCanaryRugPullTools(server as any);
17
+ dir = mkdtempSync(join(tmpdir(), 'mund-tools-'));
18
+ vi.stubEnv('MUND_BASELINE_PATH', join(dir, 'baselines.json'));
19
+ });
20
+ afterEach(() => {
21
+ vi.unstubAllEnvs();
22
+ rmSync(dir, { recursive: true, force: true });
23
+ for (const c of canaries.list()) canaries.remove(c.token);
24
+ });
25
+
26
+ it('creates, lists and removes canaries', async () => {
27
+ const created = parse(await server.call('mund_create_canary', { label: 'bot' }));
28
+ expect(created.how_to_use).toContain(created.token);
29
+ expect(parse(await server.call('mund_list_canaries', {})).canaries).toHaveLength(1);
30
+ expect(parse(await server.call('mund_remove_canary', { token: created.token })).removed).toBe(true);
31
+ });
32
+
33
+ it('returns an error for a too-short custom token', async () => {
34
+ expect(parse(await server.call('mund_create_canary', { token: 'short' })).error).toMatch(/at least 12/);
35
+ });
36
+
37
+ it('walks baseline -> change -> accept for an MCP server', async () => {
38
+ const m = (d: string) => JSON.stringify({ name: 's', version: '1', tools: [{ name: 't', description: d }] });
39
+ expect(parse(await server.call('mund_check_mcp_rugpull', { server_id: 's', manifest: m('Read a note.') })).recommendation).toBe('BASELINE_RECORDED');
40
+ const changed = parse(await server.call('mund_check_mcp_rugpull', { server_id: 's', manifest: m('Read a note, newest first.') }));
41
+ expect(changed).toMatchObject({ status: 'changed', recommendation: 'REVIEW_CHANGES', risk_label: 'high' });
42
+ expect(parse(await server.call('mund_check_mcp_rugpull', { server_id: 's', manifest: m('Read a note, newest first.'), accept_changes: true })).recommendation).toBe('CHANGES_ACCEPTED');
43
+ expect(parse(await server.call('mund_check_mcp_rugpull', { server_id: 's', manifest: m('Read a note, newest first.') })).recommendation).toBe('UNCHANGED');
44
+ });
45
+
46
+ it('says DO_NOT_USE when a changed tool gains command execution', async () => {
47
+ const m = (d: string) => JSON.stringify({ name: 's', version: '1', tools: [{ name: 't', description: d }] });
48
+ await server.call('mund_check_mcp_rugpull', { server_id: 's', manifest: m('Read a note.') });
49
+ const r = parse(await server.call('mund_check_mcp_rugpull', { server_id: 's', manifest: m('Run a shell command on the host.') }));
50
+ expect(r.recommendation).toBe('DO_NOT_USE');
51
+ expect(r.risk_label).toBe('critical');
52
+ });
53
+
54
+ it('rejects invalid manifests', async () => {
55
+ expect(parse(await server.call('mund_check_mcp_rugpull', { server_id: 's', manifest: 'not json' })).error).toMatch(/Invalid manifest/);
56
+ });
57
+ });