@cognium-ai/mcp-server 0.2.0 → 0.3.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 +110 -5
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +14 -1
- package/dist/server.js.map +1 -1
- package/dist/tools/check-license-compliance.d.ts +11 -0
- package/dist/tools/check-license-compliance.d.ts.map +1 -0
- package/dist/tools/check-license-compliance.js +125 -0
- package/dist/tools/check-license-compliance.js.map +1 -0
- package/dist/tools/find-excessive-permissions.d.ts +16 -0
- package/dist/tools/find-excessive-permissions.d.ts.map +1 -0
- package/dist/tools/find-excessive-permissions.js +127 -0
- package/dist/tools/find-excessive-permissions.js.map +1 -0
- package/dist/tools/find-install-script-risk.d.ts +11 -0
- package/dist/tools/find-install-script-risk.d.ts.map +1 -0
- package/dist/tools/find-install-script-risk.js +115 -0
- package/dist/tools/find-install-script-risk.js.map +1 -0
- package/dist/tools/find-stale-dependencies.d.ts +11 -0
- package/dist/tools/find-stale-dependencies.d.ts.map +1 -0
- package/dist/tools/find-stale-dependencies.js +122 -0
- package/dist/tools/find-stale-dependencies.js.map +1 -0
- package/dist/tools/find-typosquats.d.ts +11 -0
- package/dist/tools/find-typosquats.d.ts.map +1 -0
- package/dist/tools/find-typosquats.js +110 -0
- package/dist/tools/find-typosquats.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
# @cognium-ai/mcp-server
|
|
2
2
|
|
|
3
|
-
An [MCP](https://modelcontextprotocol.io) server exposing Cognium's
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
An [MCP](https://modelcontextprotocol.io) server exposing Cognium's security
|
|
4
|
+
scanning and spec-conformance tools over **stdio**. Backed by the
|
|
5
|
+
[`circle-ir-ai`](https://www.npmjs.com/package/circle-ir-ai) engine.
|
|
6
|
+
|
|
7
|
+
## Tools Overview
|
|
8
|
+
|
|
9
|
+
| Tool | Category | Description |
|
|
10
|
+
|------|----------|-------------|
|
|
11
|
+
| `find_credential_exposure` | Pillar I | Detect hardcoded secrets (AWS, GitHub, OpenAI, etc.) |
|
|
12
|
+
| `check_license_compliance` | Pillar I | Flag copyleft licenses in dependencies |
|
|
13
|
+
| `find_stale_dependencies` | Pillar I | Check npm registry for outdated packages |
|
|
14
|
+
| `find_install_script_risk` | Pillar I | Detect malicious install script patterns |
|
|
15
|
+
| `find_typosquats` | Pillar I | Detect typosquat package names |
|
|
16
|
+
| `find_excessive_permissions` | Pillar I | Audit MCP config permissions |
|
|
17
|
+
| `verify_spec_conformance` | Spec | Analyze code-to-spec alignment |
|
|
18
|
+
| `find_spec_drift` | Spec | Report spec/code drift |
|
|
19
|
+
| `find_pattern` | Utility | Regex search over code |
|
|
7
20
|
|
|
8
21
|
## Install & run
|
|
9
22
|
|
|
@@ -31,7 +44,99 @@ Inspect it interactively:
|
|
|
31
44
|
npx @modelcontextprotocol/inspector cognium-mcp
|
|
32
45
|
```
|
|
33
46
|
|
|
34
|
-
## Tools
|
|
47
|
+
## Pillar I Security Tools
|
|
48
|
+
|
|
49
|
+
All Pillar I tools return a common envelope:
|
|
50
|
+
|
|
51
|
+
```jsonc
|
|
52
|
+
{
|
|
53
|
+
"findings": [{ "kind": "...", "severity": "...", "location": {...}, "evidence": {...}, "suggested_action": "..." }],
|
|
54
|
+
"summary": { "total": N, "by_severity": {...}, "truncated": false }
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
- `location.span` is **1-indexed line numbers** `[start_line, end_line]`
|
|
59
|
+
- All tools accept `severity_floor` to filter results
|
|
60
|
+
|
|
61
|
+
### `find_credential_exposure`
|
|
62
|
+
|
|
63
|
+
Detect hardcoded secrets using SAST pattern matching.
|
|
64
|
+
|
|
65
|
+
| Input | Type | Description |
|
|
66
|
+
|-------|------|-------------|
|
|
67
|
+
| `code_root` | string | Absolute path to scan |
|
|
68
|
+
| `include_git_history` | boolean | Scan git history (default: false) |
|
|
69
|
+
| `severity_floor` | enum | Minimum severity: info/low/medium/high/critical |
|
|
70
|
+
|
|
71
|
+
**Evidence:** `rule_id`, `match_snippet` (redacted), `confidence`
|
|
72
|
+
|
|
73
|
+
### `check_license_compliance`
|
|
74
|
+
|
|
75
|
+
Flag copyleft licenses in npm/Cargo dependencies.
|
|
76
|
+
|
|
77
|
+
| Input | Type | Description |
|
|
78
|
+
|-------|------|-------------|
|
|
79
|
+
| `code_root` | string | Absolute path to scan |
|
|
80
|
+
| `include_dev_deps` | boolean | Include devDependencies (default: false) |
|
|
81
|
+
| `severity_floor` | enum | Minimum severity |
|
|
82
|
+
|
|
83
|
+
**Severity:** AGPL/SSPL=critical, GPL=high, LGPL/MPL=medium, EUPL/CPAL=low
|
|
84
|
+
|
|
85
|
+
### `find_stale_dependencies`
|
|
86
|
+
|
|
87
|
+
Check npm registry for outdated packages.
|
|
88
|
+
|
|
89
|
+
| Input | Type | Description |
|
|
90
|
+
|-------|------|-------------|
|
|
91
|
+
| `code_root` | string | Absolute path to scan |
|
|
92
|
+
| `include_dev_deps` | boolean | Include devDependencies (default: false) |
|
|
93
|
+
| `severity_floor` | enum | Minimum severity |
|
|
94
|
+
|
|
95
|
+
**Severity:** >3 years=high, >2 years=medium, >1 year=low
|
|
96
|
+
|
|
97
|
+
**Evidence:** `dependency`, `current_version`, `latest_version`, `days_since_publish`, `last_publish_date`
|
|
98
|
+
|
|
99
|
+
### `find_install_script_risk`
|
|
100
|
+
|
|
101
|
+
Detect malicious patterns in npm lifecycle scripts (preinstall, postinstall, etc.).
|
|
102
|
+
|
|
103
|
+
| Input | Type | Description |
|
|
104
|
+
|-------|------|-------------|
|
|
105
|
+
| `code_root` | string | Absolute path to scan |
|
|
106
|
+
| `severity_floor` | enum | Minimum severity |
|
|
107
|
+
|
|
108
|
+
**Rules:** piped downloads (critical), eval/exec (critical), base64 decode (high), env exfiltration (high), network downloads (medium), hidden file writes (medium)
|
|
109
|
+
|
|
110
|
+
### `find_typosquats`
|
|
111
|
+
|
|
112
|
+
Detect typosquat package names using Levenshtein distance.
|
|
113
|
+
|
|
114
|
+
| Input | Type | Description |
|
|
115
|
+
|-------|------|-------------|
|
|
116
|
+
| `code_root` | string | Absolute path to scan |
|
|
117
|
+
| `include_dev_deps` | boolean | Include devDependencies (default: false) |
|
|
118
|
+
| `severity_floor` | enum | Minimum severity |
|
|
119
|
+
|
|
120
|
+
**Severity:** distance=1 is high, distance=2 is medium
|
|
121
|
+
|
|
122
|
+
**Evidence:** `dependency`, `similar_to`, `distance`
|
|
123
|
+
|
|
124
|
+
### `find_excessive_permissions`
|
|
125
|
+
|
|
126
|
+
Audit MCP server configurations for overly broad permissions.
|
|
127
|
+
|
|
128
|
+
| Input | Type | Description |
|
|
129
|
+
|-------|------|-------------|
|
|
130
|
+
| `code_root` | string | Absolute path to scan |
|
|
131
|
+
| `severity_floor` | enum | Minimum severity |
|
|
132
|
+
|
|
133
|
+
**Config formats:** skill bundle (mcp.json), Claude Desktop, Cursor
|
|
134
|
+
|
|
135
|
+
**Rules:** broad filesystem paths, secret env vars, unrestricted network, dangerous commands
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Spec Tools
|
|
35
140
|
|
|
36
141
|
### `verify_spec_conformance`
|
|
37
142
|
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAWpE,wBAAgB,WAAW,IAAI,SAAS,CAsBvC"}
|
package/dist/server.js
CHANGED
|
@@ -6,15 +6,28 @@ import { registerVerifySpecConformance } from './tools/verify-spec-conformance.j
|
|
|
6
6
|
import { registerFindSpecDrift } from './tools/find-spec-drift.js';
|
|
7
7
|
import { registerFindPattern } from './tools/find-pattern.js';
|
|
8
8
|
import { registerFindCredentialExposure } from './tools/find-credential-exposure.js';
|
|
9
|
+
import { registerCheckLicenseCompliance } from './tools/check-license-compliance.js';
|
|
10
|
+
import { registerFindStaleDependencies } from './tools/find-stale-dependencies.js';
|
|
11
|
+
import { registerFindInstallScriptRisk } from './tools/find-install-script-risk.js';
|
|
12
|
+
import { registerFindTyposquats } from './tools/find-typosquats.js';
|
|
13
|
+
import { registerFindExcessivePermissions } from './tools/find-excessive-permissions.js';
|
|
9
14
|
export function buildServer() {
|
|
10
15
|
const server = new McpServer({
|
|
11
16
|
name: 'cognium-mcp',
|
|
12
|
-
version: '0.
|
|
17
|
+
version: '0.3.0',
|
|
13
18
|
});
|
|
19
|
+
// Spec tools (legacy)
|
|
14
20
|
registerVerifySpecConformance(server);
|
|
15
21
|
registerFindSpecDrift(server);
|
|
16
22
|
registerFindPattern(server);
|
|
23
|
+
// Pillar I Batch 1
|
|
17
24
|
registerFindCredentialExposure(server);
|
|
25
|
+
registerCheckLicenseCompliance(server);
|
|
26
|
+
// Pillar I Batch 2
|
|
27
|
+
registerFindStaleDependencies(server);
|
|
28
|
+
registerFindInstallScriptRisk(server);
|
|
29
|
+
registerFindTyposquats(server);
|
|
30
|
+
registerFindExcessivePermissions(server);
|
|
18
31
|
return server;
|
|
19
32
|
}
|
|
20
33
|
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AACrF,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AACrF,OAAO,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAC;AACnF,OAAO,EAAE,6BAA6B,EAAE,MAAM,qCAAqC,CAAC;AACpF,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,gCAAgC,EAAE,MAAM,uCAAuC,CAAC;AAEzF,MAAM,UAAU,WAAW;IACzB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,sBAAsB;IACtB,6BAA6B,CAAC,MAAM,CAAC,CAAC;IACtC,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAE5B,mBAAmB;IACnB,8BAA8B,CAAC,MAAM,CAAC,CAAC;IACvC,8BAA8B,CAAC,MAAM,CAAC,CAAC;IAEvC,mBAAmB;IACnB,6BAA6B,CAAC,MAAM,CAAC,CAAC;IACtC,6BAA6B,CAAC,MAAM,CAAC,CAAC;IACtC,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/B,gCAAgC,CAAC,MAAM,CAAC,CAAC;IAEzC,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* check_license_compliance MCP tool (Pillar I, Workflow #2).
|
|
3
|
+
*
|
|
4
|
+
* Scans a code root for copyleft/restrictive license issues in dependencies.
|
|
5
|
+
* Supports Node.js (package.json) and Rust (Cargo.toml) ecosystems.
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/cogniumhq/cognium-ai/issues/79
|
|
8
|
+
*/
|
|
9
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
10
|
+
export declare function registerCheckLicenseCompliance(server: McpServer): void;
|
|
11
|
+
//# sourceMappingURL=check-license-compliance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-license-compliance.d.ts","sourceRoot":"","sources":["../../src/tools/check-license-compliance.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA0HzE,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsDtE"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* check_license_compliance MCP tool (Pillar I, Workflow #2).
|
|
3
|
+
*
|
|
4
|
+
* Scans a code root for copyleft/restrictive license issues in dependencies.
|
|
5
|
+
* Supports Node.js (package.json) and Rust (Cargo.toml) ecosystems.
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/cogniumhq/cognium-ai/issues/79
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { scanLicenseCompliance, COPYLEFT_SEVERITY, } from 'circle-ir-ai';
|
|
11
|
+
const MAX_FINDINGS = 500;
|
|
12
|
+
const inputSchema = {
|
|
13
|
+
code_root: z.string().describe('Absolute path to the code root to scan'),
|
|
14
|
+
include_dev_deps: z.boolean().optional().default(false).describe('Include devDependencies (default: false)'),
|
|
15
|
+
severity_floor: z.enum(['info', 'low', 'medium', 'high', 'critical']).optional().default('low').describe('Minimum severity to report (default: low)'),
|
|
16
|
+
};
|
|
17
|
+
const findingSchema = z.object({
|
|
18
|
+
kind: z.literal('LICENSE_VIOLATION'),
|
|
19
|
+
severity: z.enum(['low', 'medium', 'high', 'critical']),
|
|
20
|
+
location: z.object({
|
|
21
|
+
file: z.string(),
|
|
22
|
+
span: z.tuple([z.number(), z.number()]),
|
|
23
|
+
}),
|
|
24
|
+
evidence: z.object({
|
|
25
|
+
rule_id: z.string(),
|
|
26
|
+
dependency: z.string(),
|
|
27
|
+
license: z.string(),
|
|
28
|
+
confidence: z.number(),
|
|
29
|
+
}),
|
|
30
|
+
suggested_action: z.string(),
|
|
31
|
+
});
|
|
32
|
+
const outputSchema = {
|
|
33
|
+
findings: z.array(findingSchema),
|
|
34
|
+
summary: z.object({
|
|
35
|
+
total: z.number(),
|
|
36
|
+
by_severity: z.object({
|
|
37
|
+
critical: z.number(),
|
|
38
|
+
high: z.number(),
|
|
39
|
+
medium: z.number(),
|
|
40
|
+
low: z.number(),
|
|
41
|
+
}),
|
|
42
|
+
by_ecosystem: z.object({
|
|
43
|
+
nodejs: z.number(),
|
|
44
|
+
rust: z.number(),
|
|
45
|
+
}),
|
|
46
|
+
truncated: z.boolean(),
|
|
47
|
+
}),
|
|
48
|
+
copyleft_reference: z.record(z.string(), z.string()).describe('Reference table: license to severity'),
|
|
49
|
+
};
|
|
50
|
+
const SEVERITY_ORDER = {
|
|
51
|
+
info: 0,
|
|
52
|
+
low: 1,
|
|
53
|
+
medium: 2,
|
|
54
|
+
high: 3,
|
|
55
|
+
critical: 4,
|
|
56
|
+
};
|
|
57
|
+
function licenseToFinding(finding) {
|
|
58
|
+
return {
|
|
59
|
+
kind: 'LICENSE_VIOLATION',
|
|
60
|
+
severity: finding.severity === 'info' ? 'low' : finding.severity,
|
|
61
|
+
location: {
|
|
62
|
+
file: finding.file,
|
|
63
|
+
span: [finding.line ?? 1, finding.line ?? 1],
|
|
64
|
+
},
|
|
65
|
+
evidence: {
|
|
66
|
+
rule_id: finding.ruleId,
|
|
67
|
+
dependency: finding.dependency,
|
|
68
|
+
license: finding.license,
|
|
69
|
+
confidence: finding.confidence,
|
|
70
|
+
},
|
|
71
|
+
suggested_action: finding.suggestedAction,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function buildCopyleftReference() {
|
|
75
|
+
const ref = {};
|
|
76
|
+
for (const [license, severity] of Object.entries(COPYLEFT_SEVERITY)) {
|
|
77
|
+
ref[license] = severity;
|
|
78
|
+
}
|
|
79
|
+
return ref;
|
|
80
|
+
}
|
|
81
|
+
export function registerCheckLicenseCompliance(server) {
|
|
82
|
+
server.registerTool('check_license_compliance', {
|
|
83
|
+
title: 'Check License Compliance',
|
|
84
|
+
description: 'Scan a code root for copyleft/restrictive license issues in dependencies. ' +
|
|
85
|
+
'Supports Node.js (package.json) and Rust (Cargo.toml). ' +
|
|
86
|
+
'Flags AGPL, GPL, LGPL, MPL, and other copyleft licenses with severity classification. ' +
|
|
87
|
+
'Returns findings with dependency info, license SPDX, and remediation guidance.',
|
|
88
|
+
inputSchema,
|
|
89
|
+
outputSchema,
|
|
90
|
+
}, async ({ code_root, include_dev_deps, severity_floor }) => {
|
|
91
|
+
const scanResult = await scanLicenseCompliance(code_root, {
|
|
92
|
+
includeDevDeps: include_dev_deps,
|
|
93
|
+
minSeverity: severity_floor,
|
|
94
|
+
});
|
|
95
|
+
const floorValue = SEVERITY_ORDER[severity_floor ?? 'low'];
|
|
96
|
+
const filteredFindings = scanResult.findings.filter((f) => SEVERITY_ORDER[f.severity] >= floorValue);
|
|
97
|
+
const truncated = filteredFindings.length > MAX_FINDINGS;
|
|
98
|
+
const findings = filteredFindings
|
|
99
|
+
.slice(0, MAX_FINDINGS)
|
|
100
|
+
.map(licenseToFinding);
|
|
101
|
+
const result = {
|
|
102
|
+
findings,
|
|
103
|
+
summary: {
|
|
104
|
+
total: filteredFindings.length,
|
|
105
|
+
by_severity: {
|
|
106
|
+
critical: filteredFindings.filter((f) => f.severity === 'critical').length,
|
|
107
|
+
high: filteredFindings.filter((f) => f.severity === 'high').length,
|
|
108
|
+
medium: filteredFindings.filter((f) => f.severity === 'medium').length,
|
|
109
|
+
low: filteredFindings.filter((f) => f.severity === 'low').length,
|
|
110
|
+
},
|
|
111
|
+
by_ecosystem: {
|
|
112
|
+
nodejs: filteredFindings.filter((f) => f.ecosystem === 'nodejs').length,
|
|
113
|
+
rust: filteredFindings.filter((f) => f.ecosystem === 'rust').length,
|
|
114
|
+
},
|
|
115
|
+
truncated,
|
|
116
|
+
},
|
|
117
|
+
copyleft_reference: buildCopyleftReference(),
|
|
118
|
+
};
|
|
119
|
+
return {
|
|
120
|
+
content: [{ type: 'text', text: JSON.stringify(result) }],
|
|
121
|
+
structuredContent: result,
|
|
122
|
+
};
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=check-license-compliance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-license-compliance.js","sourceRoot":"","sources":["../../src/tools/check-license-compliance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* find_excessive_permissions MCP tool (Pillar I, Batch 2).
|
|
3
|
+
*
|
|
4
|
+
* Analyzes MCP server configurations for overly broad or dangerous permissions.
|
|
5
|
+
* Supports: skill bundle (mcp.json), Claude Desktop, Cursor configs.
|
|
6
|
+
*
|
|
7
|
+
* Auto-detection heuristic:
|
|
8
|
+
* - Files named mcp.json, .mcp.json, mcp-config.json → skill bundle format
|
|
9
|
+
* - claude_desktop_config.json → Claude Desktop format
|
|
10
|
+
* - .cursor/mcp.json → Cursor format
|
|
11
|
+
*
|
|
12
|
+
* @see https://github.com/cogniumhq/cognium-ai/issues/80
|
|
13
|
+
*/
|
|
14
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
15
|
+
export declare function registerFindExcessivePermissions(server: McpServer): void;
|
|
16
|
+
//# sourceMappingURL=find-excessive-permissions.d.ts.map
|
|
@@ -0,0 +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;AA6FzE,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsDxE"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* find_excessive_permissions MCP tool (Pillar I, Batch 2).
|
|
3
|
+
*
|
|
4
|
+
* Analyzes MCP server configurations for overly broad or dangerous permissions.
|
|
5
|
+
* Supports: skill bundle (mcp.json), Claude Desktop, Cursor configs.
|
|
6
|
+
*
|
|
7
|
+
* Auto-detection heuristic:
|
|
8
|
+
* - Files named mcp.json, .mcp.json, mcp-config.json → skill bundle format
|
|
9
|
+
* - claude_desktop_config.json → Claude Desktop format
|
|
10
|
+
* - .cursor/mcp.json → Cursor format
|
|
11
|
+
*
|
|
12
|
+
* @see https://github.com/cogniumhq/cognium-ai/issues/80
|
|
13
|
+
*/
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
import { excessivePermissionsPass } from 'circle-ir-ai';
|
|
16
|
+
const MAX_FINDINGS = 500;
|
|
17
|
+
const SEVERITY_ORDER = {
|
|
18
|
+
info: 0,
|
|
19
|
+
low: 1,
|
|
20
|
+
medium: 2,
|
|
21
|
+
high: 3,
|
|
22
|
+
critical: 4,
|
|
23
|
+
};
|
|
24
|
+
const inputSchema = {
|
|
25
|
+
code_root: z.string().describe('Absolute path to the code root to scan'),
|
|
26
|
+
severity_floor: z.enum(['info', 'low', 'medium', 'high', 'critical']).optional().default('low').describe('Minimum severity to report (default: low)'),
|
|
27
|
+
};
|
|
28
|
+
const outputSchema = {
|
|
29
|
+
findings: z.array(z.object({
|
|
30
|
+
kind: z.literal('EXCESSIVE_PERMISSION'),
|
|
31
|
+
severity: z.enum(['low', 'medium', 'high', 'critical']),
|
|
32
|
+
location: z.object({
|
|
33
|
+
file: z.string(),
|
|
34
|
+
span: z.tuple([z.number(), z.number()]),
|
|
35
|
+
}),
|
|
36
|
+
evidence: z.object({
|
|
37
|
+
rule_id: z.string(),
|
|
38
|
+
config_file: z.string(),
|
|
39
|
+
permission_type: z.string(),
|
|
40
|
+
value: z.string(),
|
|
41
|
+
}),
|
|
42
|
+
suggested_action: z.string(),
|
|
43
|
+
})),
|
|
44
|
+
summary: z.object({
|
|
45
|
+
total: z.number(),
|
|
46
|
+
by_severity: z.object({
|
|
47
|
+
critical: z.number(),
|
|
48
|
+
high: z.number(),
|
|
49
|
+
medium: z.number(),
|
|
50
|
+
low: z.number(),
|
|
51
|
+
}),
|
|
52
|
+
truncated: z.boolean(),
|
|
53
|
+
}),
|
|
54
|
+
detection_info: z.object({
|
|
55
|
+
config_files_checked: z.array(z.string()),
|
|
56
|
+
auto_detection_heuristic: z.string(),
|
|
57
|
+
}),
|
|
58
|
+
};
|
|
59
|
+
const SUGGESTED_ACTIONS = {
|
|
60
|
+
'perm-broad-filesystem': 'Restrict filesystem access to specific directories needed by the tool. Avoid /home, /Users, or ~ wildcards.',
|
|
61
|
+
'perm-secret-env-exposure': 'Remove sensitive environment variables from MCP config. Use secrets management instead.',
|
|
62
|
+
'perm-unrestricted-network': 'Restrict network access to specific hosts/ports needed by the tool.',
|
|
63
|
+
'perm-dangerous-command': 'Review and restrict allowed commands. Avoid shell interpreters and system utilities.',
|
|
64
|
+
'perm-write-sensitive-path': 'Restrict write access to user-specific directories. Avoid system paths.',
|
|
65
|
+
};
|
|
66
|
+
function trustFindingToMcp(f) {
|
|
67
|
+
const meta = f.meta;
|
|
68
|
+
return {
|
|
69
|
+
kind: 'EXCESSIVE_PERMISSION',
|
|
70
|
+
severity: f.severity === 'info' ? 'low' : f.severity,
|
|
71
|
+
location: {
|
|
72
|
+
file: f.location?.file ?? 'mcp.json',
|
|
73
|
+
span: [f.location?.line ?? 1, f.location?.line ?? 1],
|
|
74
|
+
},
|
|
75
|
+
evidence: {
|
|
76
|
+
rule_id: f.ruleId,
|
|
77
|
+
config_file: f.location?.file ?? 'mcp.json',
|
|
78
|
+
permission_type: meta.permissionType ?? 'unknown',
|
|
79
|
+
value: meta.value ?? '',
|
|
80
|
+
},
|
|
81
|
+
suggested_action: SUGGESTED_ACTIONS[f.ruleId] ?? 'Review this permission for security risks and apply least-privilege principle.',
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
export function registerFindExcessivePermissions(server) {
|
|
85
|
+
server.registerTool('find_excessive_permissions', {
|
|
86
|
+
title: 'Find Excessive Permissions',
|
|
87
|
+
description: 'Analyze MCP server configurations for overly broad permissions. ' +
|
|
88
|
+
'Detects: broad filesystem paths (/home, /Users, ~), secret env var exposure, ' +
|
|
89
|
+
'unrestricted network access, dangerous command allowlisting. ' +
|
|
90
|
+
'Auto-detects config format (skill bundle, Claude Desktop, Cursor).',
|
|
91
|
+
inputSchema,
|
|
92
|
+
outputSchema,
|
|
93
|
+
}, async ({ code_root, severity_floor }) => {
|
|
94
|
+
const result = await excessivePermissionsPass(code_root, {});
|
|
95
|
+
const floorValue = SEVERITY_ORDER[severity_floor ?? 'low'];
|
|
96
|
+
const filtered = result.findings.filter((f) => SEVERITY_ORDER[f.severity] >= floorValue);
|
|
97
|
+
const truncated = filtered.length > MAX_FINDINGS;
|
|
98
|
+
const findings = filtered.slice(0, MAX_FINDINGS).map(trustFindingToMcp);
|
|
99
|
+
const output = {
|
|
100
|
+
findings,
|
|
101
|
+
summary: {
|
|
102
|
+
total: filtered.length,
|
|
103
|
+
by_severity: {
|
|
104
|
+
critical: filtered.filter((f) => f.severity === 'critical').length,
|
|
105
|
+
high: filtered.filter((f) => f.severity === 'high').length,
|
|
106
|
+
medium: filtered.filter((f) => f.severity === 'medium').length,
|
|
107
|
+
low: filtered.filter((f) => f.severity === 'low').length,
|
|
108
|
+
},
|
|
109
|
+
truncated,
|
|
110
|
+
},
|
|
111
|
+
detection_info: {
|
|
112
|
+
config_files_checked: [
|
|
113
|
+
'mcp.json', '.mcp.json', 'mcp-config.json',
|
|
114
|
+
'claude_desktop_config.json', '.cursor/mcp.json',
|
|
115
|
+
],
|
|
116
|
+
auto_detection_heuristic: 'Files named mcp.json/.mcp.json/mcp-config.json use skill bundle format. ' +
|
|
117
|
+
'claude_desktop_config.json uses Claude Desktop format. ' +
|
|
118
|
+
'.cursor/mcp.json uses Cursor format.',
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
return {
|
|
122
|
+
content: [{ type: 'text', text: JSON.stringify(output) }],
|
|
123
|
+
structuredContent: output,
|
|
124
|
+
};
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=find-excessive-permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-excessive-permissions.js","sourceRoot":"","sources":["../../src/tools/find-excessive-permissions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* find_install_script_risk MCP tool (Pillar I, Batch 2).
|
|
3
|
+
*
|
|
4
|
+
* Analyzes npm package.json lifecycle scripts for suspicious patterns.
|
|
5
|
+
* Scope: npm lifecycle scripts only (preinstall, install, postinstall, prepare, etc.)
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/cogniumhq/cognium-ai/issues/80
|
|
8
|
+
*/
|
|
9
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
10
|
+
export declare function registerFindInstallScriptRisk(server: McpServer): void;
|
|
11
|
+
//# sourceMappingURL=find-install-script-risk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-install-script-risk.d.ts","sourceRoot":"","sources":["../../src/tools/find-install-script-risk.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAgGzE,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2CrE"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* find_install_script_risk MCP tool (Pillar I, Batch 2).
|
|
3
|
+
*
|
|
4
|
+
* Analyzes npm package.json lifecycle scripts for suspicious patterns.
|
|
5
|
+
* Scope: npm lifecycle scripts only (preinstall, install, postinstall, prepare, etc.)
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/cogniumhq/cognium-ai/issues/80
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { maliciousInstallScriptPass } from 'circle-ir-ai';
|
|
11
|
+
const MAX_FINDINGS = 500;
|
|
12
|
+
const MAX_SNIPPET_LENGTH = 200;
|
|
13
|
+
const SEVERITY_ORDER = {
|
|
14
|
+
info: 0,
|
|
15
|
+
low: 1,
|
|
16
|
+
medium: 2,
|
|
17
|
+
high: 3,
|
|
18
|
+
critical: 4,
|
|
19
|
+
};
|
|
20
|
+
const inputSchema = {
|
|
21
|
+
code_root: z.string().describe('Absolute path to the code root to scan'),
|
|
22
|
+
severity_floor: z.enum(['info', 'low', 'medium', 'high', 'critical']).optional().default('low').describe('Minimum severity to report (default: low)'),
|
|
23
|
+
};
|
|
24
|
+
const outputSchema = {
|
|
25
|
+
findings: z.array(z.object({
|
|
26
|
+
kind: z.literal('MALICIOUS_INSTALL_SCRIPT'),
|
|
27
|
+
severity: z.enum(['low', 'medium', 'high', 'critical']),
|
|
28
|
+
location: z.object({
|
|
29
|
+
file: z.string(),
|
|
30
|
+
span: z.tuple([z.number(), z.number()]),
|
|
31
|
+
}),
|
|
32
|
+
evidence: z.object({
|
|
33
|
+
rule_id: z.string(),
|
|
34
|
+
script_name: z.string(),
|
|
35
|
+
script_content: z.string(),
|
|
36
|
+
pattern_matched: z.string(),
|
|
37
|
+
}),
|
|
38
|
+
suggested_action: z.string(),
|
|
39
|
+
})),
|
|
40
|
+
summary: z.object({
|
|
41
|
+
total: z.number(),
|
|
42
|
+
by_severity: z.object({
|
|
43
|
+
critical: z.number(),
|
|
44
|
+
high: z.number(),
|
|
45
|
+
medium: z.number(),
|
|
46
|
+
low: z.number(),
|
|
47
|
+
}),
|
|
48
|
+
truncated: z.boolean(),
|
|
49
|
+
}),
|
|
50
|
+
};
|
|
51
|
+
const SUGGESTED_ACTIONS = {
|
|
52
|
+
'install-script-piped-download': 'Remove piped download execution. If external resources are needed, download explicitly and verify checksums.',
|
|
53
|
+
'install-script-eval-exec': 'Remove dynamic code execution. Use static scripts instead of eval/exec patterns.',
|
|
54
|
+
'install-script-base64-decode': 'Remove base64 obfuscation. Install scripts should be readable and auditable.',
|
|
55
|
+
'install-script-env-exfil': 'Remove environment variable access that could leak secrets. Document required env vars instead.',
|
|
56
|
+
'install-script-network-download': 'Avoid network downloads in install scripts. Bundle dependencies or use npm dependencies.',
|
|
57
|
+
'install-script-hidden-file-write': 'Avoid writing to hidden files/directories. Use explicit, documented paths.',
|
|
58
|
+
};
|
|
59
|
+
function truncate(str, max) {
|
|
60
|
+
if (str.length <= max)
|
|
61
|
+
return str;
|
|
62
|
+
return str.slice(0, max - 3) + '...';
|
|
63
|
+
}
|
|
64
|
+
function trustFindingToMcp(f) {
|
|
65
|
+
const meta = f.meta;
|
|
66
|
+
return {
|
|
67
|
+
kind: 'MALICIOUS_INSTALL_SCRIPT',
|
|
68
|
+
severity: f.severity === 'info' ? 'low' : f.severity,
|
|
69
|
+
location: {
|
|
70
|
+
file: f.location?.file ?? 'package.json',
|
|
71
|
+
span: [f.location?.line ?? 1, f.location?.line ?? 1],
|
|
72
|
+
},
|
|
73
|
+
evidence: {
|
|
74
|
+
rule_id: f.ruleId,
|
|
75
|
+
script_name: meta.scriptName ?? 'unknown',
|
|
76
|
+
script_content: truncate(meta.scriptContent ?? '', MAX_SNIPPET_LENGTH),
|
|
77
|
+
pattern_matched: f.ruleId,
|
|
78
|
+
},
|
|
79
|
+
suggested_action: SUGGESTED_ACTIONS[f.ruleId] ?? 'Review this install script for security risks.',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
export function registerFindInstallScriptRisk(server) {
|
|
83
|
+
server.registerTool('find_install_script_risk', {
|
|
84
|
+
title: 'Find Install Script Risk',
|
|
85
|
+
description: 'Analyze npm package.json lifecycle scripts (preinstall, install, postinstall, prepare) ' +
|
|
86
|
+
'for suspicious patterns: piped downloads, eval/exec, base64 decoding, env exfiltration, ' +
|
|
87
|
+
'network downloads, hidden file writes. npm lifecycle scripts only.',
|
|
88
|
+
inputSchema,
|
|
89
|
+
outputSchema,
|
|
90
|
+
}, async ({ code_root, severity_floor }) => {
|
|
91
|
+
const result = await maliciousInstallScriptPass(code_root, {});
|
|
92
|
+
const floorValue = SEVERITY_ORDER[severity_floor ?? 'low'];
|
|
93
|
+
const filtered = result.findings.filter((f) => SEVERITY_ORDER[f.severity] >= floorValue);
|
|
94
|
+
const truncated = filtered.length > MAX_FINDINGS;
|
|
95
|
+
const findings = filtered.slice(0, MAX_FINDINGS).map(trustFindingToMcp);
|
|
96
|
+
const output = {
|
|
97
|
+
findings,
|
|
98
|
+
summary: {
|
|
99
|
+
total: filtered.length,
|
|
100
|
+
by_severity: {
|
|
101
|
+
critical: filtered.filter((f) => f.severity === 'critical').length,
|
|
102
|
+
high: filtered.filter((f) => f.severity === 'high').length,
|
|
103
|
+
medium: filtered.filter((f) => f.severity === 'medium').length,
|
|
104
|
+
low: filtered.filter((f) => f.severity === 'low').length,
|
|
105
|
+
},
|
|
106
|
+
truncated,
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
return {
|
|
110
|
+
content: [{ type: 'text', text: JSON.stringify(output) }],
|
|
111
|
+
structuredContent: output,
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=find-install-script-risk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-install-script-risk.js","sourceRoot":"","sources":["../../src/tools/find-install-script-risk.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* find_stale_dependencies MCP tool (Pillar I, Batch 2).
|
|
3
|
+
*
|
|
4
|
+
* Checks npm registry for dependency publish dates and flags stale packages.
|
|
5
|
+
* npm package.json only (pypi/cargo/go deferred).
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/cogniumhq/cognium-ai/issues/80
|
|
8
|
+
*/
|
|
9
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
10
|
+
export declare function registerFindStaleDependencies(server: McpServer): void;
|
|
11
|
+
//# sourceMappingURL=find-stale-dependencies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-stale-dependencies.d.ts","sourceRoot":"","sources":["../../src/tools/find-stale-dependencies.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsGzE,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6CrE"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* find_stale_dependencies MCP tool (Pillar I, Batch 2).
|
|
3
|
+
*
|
|
4
|
+
* Checks npm registry for dependency publish dates and flags stale packages.
|
|
5
|
+
* npm package.json only (pypi/cargo/go deferred).
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/cogniumhq/cognium-ai/issues/80
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { dependencyStalenessPass } from 'circle-ir-ai';
|
|
11
|
+
const MAX_FINDINGS = 500;
|
|
12
|
+
const SEVERITY_ORDER = {
|
|
13
|
+
info: 0,
|
|
14
|
+
low: 1,
|
|
15
|
+
medium: 2,
|
|
16
|
+
high: 3,
|
|
17
|
+
critical: 4,
|
|
18
|
+
};
|
|
19
|
+
const inputSchema = {
|
|
20
|
+
code_root: z.string().describe('Absolute path to the code root to scan'),
|
|
21
|
+
include_dev_deps: z.boolean().optional().default(false).describe('Include devDependencies (default: false)'),
|
|
22
|
+
severity_floor: z.enum(['info', 'low', 'medium', 'high', 'critical']).optional().default('low').describe('Minimum severity to report (default: low)'),
|
|
23
|
+
};
|
|
24
|
+
const outputSchema = {
|
|
25
|
+
findings: z.array(z.object({
|
|
26
|
+
kind: z.literal('STALE_DEPENDENCY'),
|
|
27
|
+
severity: z.enum(['low', 'medium', 'high', 'critical']),
|
|
28
|
+
location: z.object({
|
|
29
|
+
file: z.string(),
|
|
30
|
+
span: z.tuple([z.number(), z.number()]),
|
|
31
|
+
}),
|
|
32
|
+
evidence: z.object({
|
|
33
|
+
rule_id: z.string(),
|
|
34
|
+
dependency: z.string(),
|
|
35
|
+
current_version: z.string(),
|
|
36
|
+
latest_version: z.string().nullable(),
|
|
37
|
+
days_since_publish: z.number(),
|
|
38
|
+
last_publish_date: z.string(),
|
|
39
|
+
}),
|
|
40
|
+
suggested_action: z.string(),
|
|
41
|
+
})),
|
|
42
|
+
summary: z.object({
|
|
43
|
+
total: z.number(),
|
|
44
|
+
by_severity: z.object({
|
|
45
|
+
critical: z.number(),
|
|
46
|
+
high: z.number(),
|
|
47
|
+
medium: z.number(),
|
|
48
|
+
low: z.number(),
|
|
49
|
+
}),
|
|
50
|
+
truncated: z.boolean(),
|
|
51
|
+
}),
|
|
52
|
+
};
|
|
53
|
+
function trustFindingToMcp(f) {
|
|
54
|
+
const meta = f.meta;
|
|
55
|
+
const days = meta.daysSincePublish ?? 0;
|
|
56
|
+
let action = 'Consider updating to the latest version.';
|
|
57
|
+
if (days > 1095) {
|
|
58
|
+
action = 'This package has not been updated in over 3 years. Evaluate if it is still maintained or find an alternative.';
|
|
59
|
+
}
|
|
60
|
+
else if (days > 730) {
|
|
61
|
+
action = 'This package has not been updated in over 2 years. Check for security advisories and consider alternatives.';
|
|
62
|
+
}
|
|
63
|
+
else if (days > 365) {
|
|
64
|
+
action = 'This package has not been updated in over 1 year. Monitor for updates.';
|
|
65
|
+
}
|
|
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
|
+
return {
|
|
70
|
+
kind: 'STALE_DEPENDENCY',
|
|
71
|
+
severity: f.severity === 'info' ? 'low' : f.severity,
|
|
72
|
+
location: {
|
|
73
|
+
file: f.location?.file ?? 'package.json',
|
|
74
|
+
span: [f.location?.line ?? 1, f.location?.line ?? 1],
|
|
75
|
+
},
|
|
76
|
+
evidence: {
|
|
77
|
+
rule_id: f.ruleId,
|
|
78
|
+
dependency: meta.dependency ?? 'unknown',
|
|
79
|
+
current_version: meta.currentVersion ?? 'unknown',
|
|
80
|
+
latest_version: meta.latestVersion ?? null,
|
|
81
|
+
days_since_publish: meta.daysSincePublish ?? 0,
|
|
82
|
+
last_publish_date: meta.lastPublishDate ?? '',
|
|
83
|
+
},
|
|
84
|
+
suggested_action: action,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
export function registerFindStaleDependencies(server) {
|
|
88
|
+
server.registerTool('find_stale_dependencies', {
|
|
89
|
+
title: 'Find Stale Dependencies',
|
|
90
|
+
description: 'Check npm dependencies for staleness by querying the registry for last publish date. ' +
|
|
91
|
+
'Flags packages not updated in >1 year (low), >2 years (medium), >3 years (high). ' +
|
|
92
|
+
'Also flags packages with zero maintainers. npm package.json only.',
|
|
93
|
+
inputSchema,
|
|
94
|
+
outputSchema,
|
|
95
|
+
}, async ({ code_root, include_dev_deps, severity_floor }) => {
|
|
96
|
+
const result = await dependencyStalenessPass(code_root, {
|
|
97
|
+
includeDevDeps: include_dev_deps,
|
|
98
|
+
});
|
|
99
|
+
const floorValue = SEVERITY_ORDER[severity_floor ?? 'low'];
|
|
100
|
+
const filtered = result.findings.filter((f) => SEVERITY_ORDER[f.severity] >= floorValue);
|
|
101
|
+
const truncated = filtered.length > MAX_FINDINGS;
|
|
102
|
+
const findings = filtered.slice(0, MAX_FINDINGS).map(trustFindingToMcp);
|
|
103
|
+
const output = {
|
|
104
|
+
findings,
|
|
105
|
+
summary: {
|
|
106
|
+
total: filtered.length,
|
|
107
|
+
by_severity: {
|
|
108
|
+
critical: filtered.filter((f) => f.severity === 'critical').length,
|
|
109
|
+
high: filtered.filter((f) => f.severity === 'high').length,
|
|
110
|
+
medium: filtered.filter((f) => f.severity === 'medium').length,
|
|
111
|
+
low: filtered.filter((f) => f.severity === 'low').length,
|
|
112
|
+
},
|
|
113
|
+
truncated,
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
return {
|
|
117
|
+
content: [{ type: 'text', text: JSON.stringify(output) }],
|
|
118
|
+
structuredContent: output,
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=find-stale-dependencies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-stale-dependencies.js","sourceRoot":"","sources":["../../src/tools/find-stale-dependencies.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* find_typosquats MCP tool (Pillar I, Batch 2).
|
|
3
|
+
*
|
|
4
|
+
* Detects potential typosquat packages by comparing dependency names
|
|
5
|
+
* against popular npm packages using Levenshtein distance.
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/cogniumhq/cognium-ai/issues/80
|
|
8
|
+
*/
|
|
9
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
10
|
+
export declare function registerFindTyposquats(server: McpServer): void;
|
|
11
|
+
//# sourceMappingURL=find-typosquats.d.ts.map
|
|
@@ -0,0 +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;AAyFzE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6C9D"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* find_typosquats MCP tool (Pillar I, Batch 2).
|
|
3
|
+
*
|
|
4
|
+
* Detects potential typosquat packages by comparing dependency names
|
|
5
|
+
* against popular npm packages using Levenshtein distance.
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/cogniumhq/cognium-ai/issues/80
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { typosquatDetectionPass } from 'circle-ir-ai';
|
|
11
|
+
const MAX_FINDINGS = 500;
|
|
12
|
+
const SEVERITY_ORDER = {
|
|
13
|
+
info: 0,
|
|
14
|
+
low: 1,
|
|
15
|
+
medium: 2,
|
|
16
|
+
high: 3,
|
|
17
|
+
critical: 4,
|
|
18
|
+
};
|
|
19
|
+
const inputSchema = {
|
|
20
|
+
code_root: z.string().describe('Absolute path to the code root to scan'),
|
|
21
|
+
include_dev_deps: z.boolean().optional().default(false).describe('Include devDependencies (default: false)'),
|
|
22
|
+
severity_floor: z.enum(['info', 'low', 'medium', 'high', 'critical']).optional().default('low').describe('Minimum severity to report (default: low)'),
|
|
23
|
+
};
|
|
24
|
+
const outputSchema = {
|
|
25
|
+
findings: z.array(z.object({
|
|
26
|
+
kind: z.literal('TYPOSQUAT_RISK'),
|
|
27
|
+
severity: z.enum(['medium', 'high']),
|
|
28
|
+
location: z.object({
|
|
29
|
+
file: z.string(),
|
|
30
|
+
span: z.tuple([z.number(), z.number()]),
|
|
31
|
+
}),
|
|
32
|
+
evidence: z.object({
|
|
33
|
+
rule_id: z.string(),
|
|
34
|
+
dependency: z.string(),
|
|
35
|
+
similar_to: z.string(),
|
|
36
|
+
distance: z.number(),
|
|
37
|
+
}),
|
|
38
|
+
suggested_action: z.string(),
|
|
39
|
+
})),
|
|
40
|
+
summary: z.object({
|
|
41
|
+
total: z.number(),
|
|
42
|
+
by_severity: z.object({
|
|
43
|
+
critical: z.number(),
|
|
44
|
+
high: z.number(),
|
|
45
|
+
medium: z.number(),
|
|
46
|
+
low: z.number(),
|
|
47
|
+
}),
|
|
48
|
+
truncated: z.boolean(),
|
|
49
|
+
}),
|
|
50
|
+
};
|
|
51
|
+
function trustFindingToMcp(f) {
|
|
52
|
+
const meta = f.meta;
|
|
53
|
+
const distance = meta.distance ?? 0;
|
|
54
|
+
const similarTo = meta.similarTo ?? 'unknown';
|
|
55
|
+
const dependency = meta.dependency ?? 'unknown';
|
|
56
|
+
const action = distance === 1
|
|
57
|
+
? `"${dependency}" is 1 character away from "${similarTo}". Verify this is intentional and not a typosquat attack.`
|
|
58
|
+
: `"${dependency}" is similar to "${similarTo}". Verify this is the intended package.`;
|
|
59
|
+
return {
|
|
60
|
+
kind: 'TYPOSQUAT_RISK',
|
|
61
|
+
severity: f.severity === 'high' ? 'high' : 'medium',
|
|
62
|
+
location: {
|
|
63
|
+
file: f.location?.file ?? 'package.json',
|
|
64
|
+
span: [f.location?.line ?? 1, f.location?.line ?? 1],
|
|
65
|
+
},
|
|
66
|
+
evidence: {
|
|
67
|
+
rule_id: f.ruleId,
|
|
68
|
+
dependency,
|
|
69
|
+
similar_to: similarTo,
|
|
70
|
+
distance,
|
|
71
|
+
},
|
|
72
|
+
suggested_action: action,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export function registerFindTyposquats(server) {
|
|
76
|
+
server.registerTool('find_typosquats', {
|
|
77
|
+
title: 'Find Typosquats',
|
|
78
|
+
description: 'Detect potential typosquat packages by comparing dependency names against popular npm packages. ' +
|
|
79
|
+
'Uses Levenshtein distance: distance=1 is high severity, distance=2 is medium. ' +
|
|
80
|
+
'Protects against attacks like "lodahs" instead of "lodash".',
|
|
81
|
+
inputSchema,
|
|
82
|
+
outputSchema,
|
|
83
|
+
}, async ({ code_root, include_dev_deps, severity_floor }) => {
|
|
84
|
+
const result = await typosquatDetectionPass(code_root, {
|
|
85
|
+
includeDevDeps: include_dev_deps,
|
|
86
|
+
});
|
|
87
|
+
const floorValue = SEVERITY_ORDER[severity_floor ?? 'low'];
|
|
88
|
+
const filtered = result.findings.filter((f) => SEVERITY_ORDER[f.severity] >= floorValue);
|
|
89
|
+
const truncated = filtered.length > MAX_FINDINGS;
|
|
90
|
+
const findings = filtered.slice(0, MAX_FINDINGS).map(trustFindingToMcp);
|
|
91
|
+
const output = {
|
|
92
|
+
findings,
|
|
93
|
+
summary: {
|
|
94
|
+
total: filtered.length,
|
|
95
|
+
by_severity: {
|
|
96
|
+
critical: filtered.filter((f) => f.severity === 'critical').length,
|
|
97
|
+
high: filtered.filter((f) => f.severity === 'high').length,
|
|
98
|
+
medium: filtered.filter((f) => f.severity === 'medium').length,
|
|
99
|
+
low: filtered.filter((f) => f.severity === 'low').length,
|
|
100
|
+
},
|
|
101
|
+
truncated,
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
return {
|
|
105
|
+
content: [{ type: 'text', text: JSON.stringify(output) }],
|
|
106
|
+
structuredContent: output,
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=find-typosquats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-typosquats.js","sourceRoot":"","sources":["../../src/tools/find-typosquats.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED