@cognium-ai/mcp-server 0.3.0 → 0.4.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 +19 -7
- package/dist/server.js +1 -1
- package/dist/tools/find-excessive-permissions.d.ts.map +1 -1
- package/dist/tools/find-excessive-permissions.js +19 -2
- package/dist/tools/find-excessive-permissions.js.map +1 -1
- package/dist/tools/find-stale-dependencies.d.ts +4 -1
- package/dist/tools/find-stale-dependencies.d.ts.map +1 -1
- package/dist/tools/find-stale-dependencies.js +69 -14
- package/dist/tools/find-stale-dependencies.js.map +1 -1
- package/dist/tools/find-typosquats.d.ts.map +1 -1
- package/dist/tools/find-typosquats.js +42 -11
- package/dist/tools/find-typosquats.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -84,17 +84,22 @@ Flag copyleft licenses in npm/Cargo dependencies.
|
|
|
84
84
|
|
|
85
85
|
### `find_stale_dependencies`
|
|
86
86
|
|
|
87
|
-
Check npm
|
|
87
|
+
Check npm dependencies for staleness and known vulnerabilities.
|
|
88
88
|
|
|
89
89
|
| Input | Type | Description |
|
|
90
90
|
|-------|------|-------------|
|
|
91
91
|
| `code_root` | string | Absolute path to scan |
|
|
92
92
|
| `include_dev_deps` | boolean | Include devDependencies (default: false) |
|
|
93
93
|
| `severity_floor` | enum | Minimum severity |
|
|
94
|
+
| `check_vulnerabilities` | boolean | Query OSV for CVEs (default: true) |
|
|
94
95
|
|
|
95
|
-
**
|
|
96
|
+
**Staleness severity:** >3 years=high, >2 years=medium, >1 year=low
|
|
96
97
|
|
|
97
|
-
**
|
|
98
|
+
**Vulnerability severity:** CVSS ≥9.0=critical, ≥7.0=high, ≥4.0=medium, <4.0=low
|
|
99
|
+
|
|
100
|
+
**Evidence:**
|
|
101
|
+
- Staleness: `dependency`, `current_version`, `latest_version`, `days_since_publish`, `last_publish_date`
|
|
102
|
+
- Vulnerability: `dependency`, `current_version`, `vuln_id`, `cve`, `cvss`, `summary`
|
|
98
103
|
|
|
99
104
|
### `find_install_script_risk`
|
|
100
105
|
|
|
@@ -109,17 +114,21 @@ Detect malicious patterns in npm lifecycle scripts (preinstall, postinstall, etc
|
|
|
109
114
|
|
|
110
115
|
### `find_typosquats`
|
|
111
116
|
|
|
112
|
-
Detect typosquat package names using Levenshtein distance.
|
|
117
|
+
Detect typosquat package names using Levenshtein distance and homoglyph detection.
|
|
113
118
|
|
|
114
119
|
| Input | Type | Description |
|
|
115
120
|
|-------|------|-------------|
|
|
116
121
|
| `code_root` | string | Absolute path to scan |
|
|
117
122
|
| `include_dev_deps` | boolean | Include devDependencies (default: false) |
|
|
118
123
|
| `severity_floor` | enum | Minimum severity |
|
|
124
|
+
| `check_homoglyphs` | boolean | Detect visual deception attacks (default: true) |
|
|
125
|
+
| `check_popularity` | boolean | Query npm for download counts (default: false) |
|
|
119
126
|
|
|
120
|
-
**
|
|
127
|
+
**Detection methods:**
|
|
128
|
+
- **Levenshtein:** distance=1 is high, distance=2 is medium
|
|
129
|
+
- **Homoglyph:** detects visual deception (`rn`→`m`, `1`→`l`, `0`→`o`, etc.) - always high severity
|
|
121
130
|
|
|
122
|
-
**Evidence:** `dependency`, `similar_to`, `distance`
|
|
131
|
+
**Evidence:** `dependency`, `similar_to`, `detection_method`, `distance`, `homoglyph`, `target_downloads`
|
|
123
132
|
|
|
124
133
|
### `find_excessive_permissions`
|
|
125
134
|
|
|
@@ -129,10 +138,13 @@ Audit MCP server configurations for overly broad permissions.
|
|
|
129
138
|
|-------|------|-------------|
|
|
130
139
|
| `code_root` | string | Absolute path to scan |
|
|
131
140
|
| `severity_floor` | enum | Minimum severity |
|
|
141
|
+
| `deep_analysis` | boolean | Run CircleIR to detect undisclosed capabilities (default: true) |
|
|
132
142
|
|
|
133
143
|
**Config formats:** skill bundle (mcp.json), Claude Desktop, Cursor
|
|
134
144
|
|
|
135
|
-
**
|
|
145
|
+
**Static rules:** broad filesystem paths, secret env vars, unrestricted network, dangerous commands
|
|
146
|
+
|
|
147
|
+
**Deep analysis:** Cross-references declared permissions against actual code behavior. Detects undisclosed network, filesystem, or process execution capabilities.
|
|
136
148
|
|
|
137
149
|
---
|
|
138
150
|
|
package/dist/server.js
CHANGED
|
@@ -14,7 +14,7 @@ import { registerFindExcessivePermissions } from './tools/find-excessive-permiss
|
|
|
14
14
|
export function buildServer() {
|
|
15
15
|
const server = new McpServer({
|
|
16
16
|
name: 'cognium-mcp',
|
|
17
|
-
version: '0.
|
|
17
|
+
version: '0.4.0',
|
|
18
18
|
});
|
|
19
19
|
// Spec tools (legacy)
|
|
20
20
|
registerVerifySpecConformance(server);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find-excessive-permissions.d.ts","sourceRoot":"","sources":["../../src/tools/find-excessive-permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"find-excessive-permissions.d.ts","sourceRoot":"","sources":["../../src/tools/find-excessive-permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAiGzE,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAmExE"}
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { z } from 'zod';
|
|
15
15
|
import { excessivePermissionsPass } from 'circle-ir-ai';
|
|
16
|
+
import { loadCircleIR } from '../analysis.js';
|
|
16
17
|
const MAX_FINDINGS = 500;
|
|
17
18
|
const SEVERITY_ORDER = {
|
|
18
19
|
info: 0,
|
|
@@ -24,6 +25,7 @@ const SEVERITY_ORDER = {
|
|
|
24
25
|
const inputSchema = {
|
|
25
26
|
code_root: z.string().describe('Absolute path to the code root to scan'),
|
|
26
27
|
severity_floor: z.enum(['info', 'low', 'medium', 'high', 'critical']).optional().default('low').describe('Minimum severity to report (default: low)'),
|
|
28
|
+
deep_analysis: z.boolean().optional().default(true).describe('Run CircleIR analysis to detect undisclosed capabilities (default: true)'),
|
|
27
29
|
};
|
|
28
30
|
const outputSchema = {
|
|
29
31
|
findings: z.array(z.object({
|
|
@@ -54,6 +56,8 @@ const outputSchema = {
|
|
|
54
56
|
detection_info: z.object({
|
|
55
57
|
config_files_checked: z.array(z.string()),
|
|
56
58
|
auto_detection_heuristic: z.string(),
|
|
59
|
+
deep_analysis_performed: z.boolean(),
|
|
60
|
+
files_analyzed: z.number().optional(),
|
|
57
61
|
}),
|
|
58
62
|
};
|
|
59
63
|
const SUGGESTED_ACTIONS = {
|
|
@@ -90,8 +94,19 @@ export function registerFindExcessivePermissions(server) {
|
|
|
90
94
|
'Auto-detects config format (skill bundle, Claude Desktop, Cursor).',
|
|
91
95
|
inputSchema,
|
|
92
96
|
outputSchema,
|
|
93
|
-
}, async ({ code_root, severity_floor }) => {
|
|
94
|
-
|
|
97
|
+
}, async ({ code_root, severity_floor, deep_analysis }) => {
|
|
98
|
+
// Run CircleIR analysis for deep capability detection
|
|
99
|
+
let circleIRResults;
|
|
100
|
+
if (deep_analysis !== false) {
|
|
101
|
+
try {
|
|
102
|
+
const { results } = await loadCircleIR(code_root);
|
|
103
|
+
circleIRResults = results;
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// CircleIR analysis failed, continue with static-only analysis
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const result = await excessivePermissionsPass(code_root, { circleIRResults });
|
|
95
110
|
const floorValue = SEVERITY_ORDER[severity_floor ?? 'low'];
|
|
96
111
|
const filtered = result.findings.filter((f) => SEVERITY_ORDER[f.severity] >= floorValue);
|
|
97
112
|
const truncated = filtered.length > MAX_FINDINGS;
|
|
@@ -116,6 +131,8 @@ export function registerFindExcessivePermissions(server) {
|
|
|
116
131
|
auto_detection_heuristic: 'Files named mcp.json/.mcp.json/mcp-config.json use skill bundle format. ' +
|
|
117
132
|
'claude_desktop_config.json uses Claude Desktop format. ' +
|
|
118
133
|
'.cursor/mcp.json uses Cursor format.',
|
|
134
|
+
deep_analysis_performed: !!circleIRResults,
|
|
135
|
+
files_analyzed: circleIRResults?.length,
|
|
119
136
|
},
|
|
120
137
|
};
|
|
121
138
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find-excessive-permissions.js","sourceRoot":"","sources":["../../src/tools/find-excessive-permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,wBAAwB,EAAyC,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"find-excessive-permissions.js","sourceRoot":"","sources":["../../src/tools/find-excessive-permissions.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* find_stale_dependencies MCP tool (Pillar I, Batch 2).
|
|
3
3
|
*
|
|
4
|
-
* Checks npm
|
|
4
|
+
* Checks npm dependencies for:
|
|
5
|
+
* 1. Staleness: last publish date via npm registry
|
|
6
|
+
* 2. Known vulnerabilities: via OSV (Open Source Vulnerabilities) API
|
|
7
|
+
*
|
|
5
8
|
* npm package.json only (pypi/cargo/go deferred).
|
|
6
9
|
*
|
|
7
10
|
* @see https://github.com/cogniumhq/cognium-ai/issues/80
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find-stale-dependencies.d.ts","sourceRoot":"","sources":["../../src/tools/find-stale-dependencies.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"find-stale-dependencies.d.ts","sourceRoot":"","sources":["../../src/tools/find-stale-dependencies.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAoJzE,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA+DrE"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* find_stale_dependencies MCP tool (Pillar I, Batch 2).
|
|
3
3
|
*
|
|
4
|
-
* Checks npm
|
|
4
|
+
* Checks npm dependencies for:
|
|
5
|
+
* 1. Staleness: last publish date via npm registry
|
|
6
|
+
* 2. Known vulnerabilities: via OSV (Open Source Vulnerabilities) API
|
|
7
|
+
*
|
|
5
8
|
* npm package.json only (pypi/cargo/go deferred).
|
|
6
9
|
*
|
|
7
10
|
* @see https://github.com/cogniumhq/cognium-ai/issues/80
|
|
@@ -20,10 +23,11 @@ const inputSchema = {
|
|
|
20
23
|
code_root: z.string().describe('Absolute path to the code root to scan'),
|
|
21
24
|
include_dev_deps: z.boolean().optional().default(false).describe('Include devDependencies (default: false)'),
|
|
22
25
|
severity_floor: z.enum(['info', 'low', 'medium', 'high', 'critical']).optional().default('low').describe('Minimum severity to report (default: low)'),
|
|
26
|
+
check_vulnerabilities: z.boolean().optional().default(true).describe('Check for known vulnerabilities via OSV database (default: true)'),
|
|
23
27
|
};
|
|
24
28
|
const outputSchema = {
|
|
25
29
|
findings: z.array(z.object({
|
|
26
|
-
kind: z.
|
|
30
|
+
kind: z.enum(['STALE_DEPENDENCY', 'VULNERABLE_DEPENDENCY']),
|
|
27
31
|
severity: z.enum(['low', 'medium', 'high', 'critical']),
|
|
28
32
|
location: z.object({
|
|
29
33
|
file: z.string(),
|
|
@@ -34,8 +38,15 @@ const outputSchema = {
|
|
|
34
38
|
dependency: z.string(),
|
|
35
39
|
current_version: z.string(),
|
|
36
40
|
latest_version: z.string().nullable(),
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
finding_type: z.enum(['staleness', 'maintainer', 'vulnerability']),
|
|
42
|
+
// Staleness fields
|
|
43
|
+
days_since_publish: z.number().optional(),
|
|
44
|
+
last_publish_date: z.string().optional(),
|
|
45
|
+
// Vulnerability fields
|
|
46
|
+
vuln_id: z.string().optional(),
|
|
47
|
+
cve: z.string().optional(),
|
|
48
|
+
cvss: z.number().optional(),
|
|
49
|
+
summary: z.string().optional(),
|
|
39
50
|
}),
|
|
40
51
|
suggested_action: z.string(),
|
|
41
52
|
})),
|
|
@@ -47,14 +58,39 @@ const outputSchema = {
|
|
|
47
58
|
medium: z.number(),
|
|
48
59
|
low: z.number(),
|
|
49
60
|
}),
|
|
61
|
+
by_finding_type: z.object({
|
|
62
|
+
staleness: z.number(),
|
|
63
|
+
maintainer: z.number(),
|
|
64
|
+
vulnerability: z.number(),
|
|
65
|
+
}),
|
|
50
66
|
truncated: z.boolean(),
|
|
51
67
|
}),
|
|
52
68
|
};
|
|
53
69
|
function trustFindingToMcp(f) {
|
|
54
70
|
const meta = f.meta;
|
|
71
|
+
const findingType = meta.findingType ?? 'staleness';
|
|
55
72
|
const days = meta.daysSincePublish ?? 0;
|
|
56
73
|
let action = 'Consider updating to the latest version.';
|
|
57
|
-
|
|
74
|
+
let kind = 'STALE_DEPENDENCY';
|
|
75
|
+
if (findingType === 'vulnerability') {
|
|
76
|
+
kind = 'VULNERABLE_DEPENDENCY';
|
|
77
|
+
const cve = meta.cve;
|
|
78
|
+
const vulnId = meta.vulnId;
|
|
79
|
+
const cvss = meta.cvss;
|
|
80
|
+
if (cvss && cvss >= 9.0) {
|
|
81
|
+
action = `CRITICAL vulnerability ${cve ?? vulnId}. Upgrade immediately or remove this dependency.`;
|
|
82
|
+
}
|
|
83
|
+
else if (cvss && cvss >= 7.0) {
|
|
84
|
+
action = `HIGH severity vulnerability ${cve ?? vulnId}. Upgrade to a patched version as soon as possible.`;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
action = `Known vulnerability ${cve ?? vulnId}. Upgrade to a patched version when available.`;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else if (findingType === 'maintainer') {
|
|
91
|
+
action = 'This package has zero maintainers on npm. High risk of abandonment - find an alternative.';
|
|
92
|
+
}
|
|
93
|
+
else if (days > 1095) {
|
|
58
94
|
action = 'This package has not been updated in over 3 years. Evaluate if it is still maintained or find an alternative.';
|
|
59
95
|
}
|
|
60
96
|
else if (days > 730) {
|
|
@@ -63,11 +99,8 @@ function trustFindingToMcp(f) {
|
|
|
63
99
|
else if (days > 365) {
|
|
64
100
|
action = 'This package has not been updated in over 1 year. Monitor for updates.';
|
|
65
101
|
}
|
|
66
|
-
if (f.ruleId === 'dep-no-maintainers') {
|
|
67
|
-
action = 'This package has zero maintainers on npm. High risk of abandonment - find an alternative.';
|
|
68
|
-
}
|
|
69
102
|
return {
|
|
70
|
-
kind
|
|
103
|
+
kind,
|
|
71
104
|
severity: f.severity === 'info' ? 'low' : f.severity,
|
|
72
105
|
location: {
|
|
73
106
|
file: f.location?.file ?? 'package.json',
|
|
@@ -78,8 +111,19 @@ function trustFindingToMcp(f) {
|
|
|
78
111
|
dependency: meta.dependency ?? 'unknown',
|
|
79
112
|
current_version: meta.currentVersion ?? 'unknown',
|
|
80
113
|
latest_version: meta.latestVersion ?? null,
|
|
81
|
-
|
|
82
|
-
|
|
114
|
+
finding_type: findingType,
|
|
115
|
+
// Staleness fields (only for staleness findings)
|
|
116
|
+
...(findingType === 'staleness' && {
|
|
117
|
+
days_since_publish: meta.daysSincePublish ?? 0,
|
|
118
|
+
last_publish_date: meta.lastPublishDate ?? '',
|
|
119
|
+
}),
|
|
120
|
+
// Vulnerability fields (only for vulnerability findings)
|
|
121
|
+
...(findingType === 'vulnerability' && {
|
|
122
|
+
vuln_id: meta.vulnId,
|
|
123
|
+
cve: meta.cve,
|
|
124
|
+
cvss: meta.cvss,
|
|
125
|
+
summary: meta.summary,
|
|
126
|
+
}),
|
|
83
127
|
},
|
|
84
128
|
suggested_action: action,
|
|
85
129
|
};
|
|
@@ -87,19 +131,25 @@ function trustFindingToMcp(f) {
|
|
|
87
131
|
export function registerFindStaleDependencies(server) {
|
|
88
132
|
server.registerTool('find_stale_dependencies', {
|
|
89
133
|
title: 'Find Stale Dependencies',
|
|
90
|
-
description: 'Check npm dependencies for staleness
|
|
91
|
-
'
|
|
134
|
+
description: 'Check npm dependencies for staleness and known vulnerabilities. ' +
|
|
135
|
+
'Staleness: flags packages not updated in >1 year (low), >2 years (medium), >3 years (high). ' +
|
|
136
|
+
'Vulnerabilities: queries OSV database for CVEs affecting your exact versions. ' +
|
|
92
137
|
'Also flags packages with zero maintainers. npm package.json only.',
|
|
93
138
|
inputSchema,
|
|
94
139
|
outputSchema,
|
|
95
|
-
}, async ({ code_root, include_dev_deps, severity_floor }) => {
|
|
140
|
+
}, async ({ code_root, include_dev_deps, severity_floor, check_vulnerabilities }) => {
|
|
96
141
|
const result = await dependencyStalenessPass(code_root, {
|
|
97
142
|
includeDevDeps: include_dev_deps,
|
|
143
|
+
checkVulnerabilities: check_vulnerabilities,
|
|
98
144
|
});
|
|
99
145
|
const floorValue = SEVERITY_ORDER[severity_floor ?? 'low'];
|
|
100
146
|
const filtered = result.findings.filter((f) => SEVERITY_ORDER[f.severity] >= floorValue);
|
|
101
147
|
const truncated = filtered.length > MAX_FINDINGS;
|
|
102
148
|
const findings = filtered.slice(0, MAX_FINDINGS).map(trustFindingToMcp);
|
|
149
|
+
// Count by finding type
|
|
150
|
+
const stalenessCount = filtered.filter((f) => f.meta?.findingType === 'staleness').length;
|
|
151
|
+
const maintainerCount = filtered.filter((f) => f.meta?.findingType === 'maintainer').length;
|
|
152
|
+
const vulnerabilityCount = filtered.filter((f) => f.meta?.findingType === 'vulnerability').length;
|
|
103
153
|
const output = {
|
|
104
154
|
findings,
|
|
105
155
|
summary: {
|
|
@@ -110,6 +160,11 @@ export function registerFindStaleDependencies(server) {
|
|
|
110
160
|
medium: filtered.filter((f) => f.severity === 'medium').length,
|
|
111
161
|
low: filtered.filter((f) => f.severity === 'low').length,
|
|
112
162
|
},
|
|
163
|
+
by_finding_type: {
|
|
164
|
+
staleness: stalenessCount,
|
|
165
|
+
maintainer: maintainerCount,
|
|
166
|
+
vulnerability: vulnerabilityCount,
|
|
167
|
+
},
|
|
113
168
|
truncated,
|
|
114
169
|
},
|
|
115
170
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find-stale-dependencies.js","sourceRoot":"","sources":["../../src/tools/find-stale-dependencies.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"find-stale-dependencies.js","sourceRoot":"","sources":["../../src/tools/find-stale-dependencies.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find-typosquats.d.ts","sourceRoot":"","sources":["../../src/tools/find-typosquats.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"find-typosquats.d.ts","sourceRoot":"","sources":["../../src/tools/find-typosquats.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAgHzE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2D9D"}
|
|
@@ -20,6 +20,8 @@ const inputSchema = {
|
|
|
20
20
|
code_root: z.string().describe('Absolute path to the code root to scan'),
|
|
21
21
|
include_dev_deps: z.boolean().optional().default(false).describe('Include devDependencies (default: false)'),
|
|
22
22
|
severity_floor: z.enum(['info', 'low', 'medium', 'high', 'critical']).optional().default('low').describe('Minimum severity to report (default: low)'),
|
|
23
|
+
check_homoglyphs: z.boolean().optional().default(true).describe('Detect homoglyph attacks like "rn" vs "m" (default: true)'),
|
|
24
|
+
check_popularity: z.boolean().optional().default(false).describe('Query npm for download counts (slower, default: false)'),
|
|
23
25
|
};
|
|
24
26
|
const outputSchema = {
|
|
25
27
|
findings: z.array(z.object({
|
|
@@ -33,7 +35,10 @@ const outputSchema = {
|
|
|
33
35
|
rule_id: z.string(),
|
|
34
36
|
dependency: z.string(),
|
|
35
37
|
similar_to: z.string(),
|
|
36
|
-
|
|
38
|
+
detection_method: z.enum(['levenshtein', 'homoglyph']),
|
|
39
|
+
distance: z.number().optional(),
|
|
40
|
+
homoglyph: z.string().optional(),
|
|
41
|
+
target_downloads: z.number().optional(),
|
|
37
42
|
}),
|
|
38
43
|
suggested_action: z.string(),
|
|
39
44
|
})),
|
|
@@ -45,17 +50,31 @@ const outputSchema = {
|
|
|
45
50
|
medium: z.number(),
|
|
46
51
|
low: z.number(),
|
|
47
52
|
}),
|
|
53
|
+
by_detection_method: z.object({
|
|
54
|
+
levenshtein: z.number(),
|
|
55
|
+
homoglyph: z.number(),
|
|
56
|
+
}),
|
|
48
57
|
truncated: z.boolean(),
|
|
49
58
|
}),
|
|
50
59
|
};
|
|
51
60
|
function trustFindingToMcp(f) {
|
|
52
61
|
const meta = f.meta;
|
|
53
|
-
const distance = meta.distance ?? 0;
|
|
54
|
-
const similarTo = meta.similarTo ?? 'unknown';
|
|
55
62
|
const dependency = meta.dependency ?? 'unknown';
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
63
|
+
const similarTo = meta.similarTo ?? 'unknown';
|
|
64
|
+
const detectionMethod = meta.detectionMethod ?? 'levenshtein';
|
|
65
|
+
const distance = meta.distance;
|
|
66
|
+
const homoglyph = meta.homoglyph;
|
|
67
|
+
const targetDownloads = meta.targetDownloads;
|
|
68
|
+
let action;
|
|
69
|
+
if (detectionMethod === 'homoglyph') {
|
|
70
|
+
action = `"${dependency}" uses visual deception (${homoglyph}) to mimic "${similarTo}". This is a high-confidence typosquat attack. Remove immediately.`;
|
|
71
|
+
}
|
|
72
|
+
else if (distance === 1) {
|
|
73
|
+
action = `"${dependency}" is 1 character away from "${similarTo}". Verify this is intentional and not a typosquat attack.`;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
action = `"${dependency}" is similar to "${similarTo}". Verify this is the intended package.`;
|
|
77
|
+
}
|
|
59
78
|
return {
|
|
60
79
|
kind: 'TYPOSQUAT_RISK',
|
|
61
80
|
severity: f.severity === 'high' ? 'high' : 'medium',
|
|
@@ -67,7 +86,10 @@ function trustFindingToMcp(f) {
|
|
|
67
86
|
rule_id: f.ruleId,
|
|
68
87
|
dependency,
|
|
69
88
|
similar_to: similarTo,
|
|
70
|
-
|
|
89
|
+
detection_method: detectionMethod,
|
|
90
|
+
...(distance !== undefined && { distance }),
|
|
91
|
+
...(homoglyph && { homoglyph }),
|
|
92
|
+
...(targetDownloads !== undefined && { target_downloads: targetDownloads }),
|
|
71
93
|
},
|
|
72
94
|
suggested_action: action,
|
|
73
95
|
};
|
|
@@ -75,19 +97,24 @@ function trustFindingToMcp(f) {
|
|
|
75
97
|
export function registerFindTyposquats(server) {
|
|
76
98
|
server.registerTool('find_typosquats', {
|
|
77
99
|
title: 'Find Typosquats',
|
|
78
|
-
description: 'Detect potential typosquat packages
|
|
79
|
-
'
|
|
80
|
-
'Protects against attacks like "lodahs"
|
|
100
|
+
description: 'Detect potential typosquat packages using Levenshtein distance and homoglyph detection. ' +
|
|
101
|
+
'Homoglyph attacks use visual deception (e.g., "rn" looks like "m", "1" looks like "l"). ' +
|
|
102
|
+
'Protects against attacks like "lodahs" (typo) or "rnaterial-ui" (homoglyph for "material-ui").',
|
|
81
103
|
inputSchema,
|
|
82
104
|
outputSchema,
|
|
83
|
-
}, async ({ code_root, include_dev_deps, severity_floor }) => {
|
|
105
|
+
}, async ({ code_root, include_dev_deps, severity_floor, check_homoglyphs, check_popularity }) => {
|
|
84
106
|
const result = await typosquatDetectionPass(code_root, {
|
|
85
107
|
includeDevDeps: include_dev_deps,
|
|
108
|
+
checkHomoglyphs: check_homoglyphs,
|
|
109
|
+
checkPopularity: check_popularity,
|
|
86
110
|
});
|
|
87
111
|
const floorValue = SEVERITY_ORDER[severity_floor ?? 'low'];
|
|
88
112
|
const filtered = result.findings.filter((f) => SEVERITY_ORDER[f.severity] >= floorValue);
|
|
89
113
|
const truncated = filtered.length > MAX_FINDINGS;
|
|
90
114
|
const findings = filtered.slice(0, MAX_FINDINGS).map(trustFindingToMcp);
|
|
115
|
+
// Count by detection method
|
|
116
|
+
const levenshteinCount = filtered.filter((f) => f.meta?.detectionMethod === 'levenshtein').length;
|
|
117
|
+
const homoglyphCount = filtered.filter((f) => f.meta?.detectionMethod === 'homoglyph').length;
|
|
91
118
|
const output = {
|
|
92
119
|
findings,
|
|
93
120
|
summary: {
|
|
@@ -98,6 +125,10 @@ export function registerFindTyposquats(server) {
|
|
|
98
125
|
medium: filtered.filter((f) => f.severity === 'medium').length,
|
|
99
126
|
low: filtered.filter((f) => f.severity === 'low').length,
|
|
100
127
|
},
|
|
128
|
+
by_detection_method: {
|
|
129
|
+
levenshtein: levenshteinCount,
|
|
130
|
+
homoglyph: homoglyphCount,
|
|
131
|
+
},
|
|
101
132
|
truncated,
|
|
102
133
|
},
|
|
103
134
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find-typosquats.js","sourceRoot":"","sources":["../../src/tools/find-typosquats.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,sBAAsB,EAAyC,MAAM,cAAc,CAAC;AAE7F,MAAM,YAAY,GAAG,GAAG,CAAC;AAIzB,MAAM,cAAc,GAAkC;IACpD,IAAI,EAAE,CAAC;IACP,GAAG,EAAE,CAAC;IACN,MAAM,EAAE,CAAC;IACT,IAAI,EAAE,CAAC;IACP,QAAQ,EAAE,CAAC;CACZ,CAAC;AAEF,MAAM,WAAW,GAAG;IAClB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;IACxE,gBAAgB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,0CAA0C,CAAC;IAC5G,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"find-typosquats.js","sourceRoot":"","sources":["../../src/tools/find-typosquats.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cognium-ai/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "MCP server exposing Cognium spec-conformance, spec-drift, and pattern-search tools over stdio",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
48
48
|
"circle-ir": "^3.23.3",
|
|
49
|
-
"circle-ir-ai": "^2.8.
|
|
49
|
+
"circle-ir-ai": "^2.8.3",
|
|
50
50
|
"minimatch": "^10.2.5",
|
|
51
51
|
"zod": "^3.25.0"
|
|
52
52
|
},
|