@bryan-thompson/inspector-assessment-client 1.26.5 → 1.26.6
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/dist/assets/{OAuthCallback-DpdInvWI.js → OAuthCallback-CCWVtjr7.js} +1 -1
- package/dist/assets/{OAuthDebugCallback-D1ImpKK5.js → OAuthDebugCallback-DqbXfUi4.js} +1 -1
- package/dist/assets/{index-umcoGmYw.js → index-CsDJSSWq.js} +4 -4
- package/dist/index.html +1 -1
- package/lib/services/assessment/modules/securityTests/ConfidenceScorer.d.ts +57 -0
- package/lib/services/assessment/modules/securityTests/ConfidenceScorer.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/ConfidenceScorer.js +199 -0
- package/lib/services/assessment/modules/securityTests/ErrorClassifier.d.ts +57 -0
- package/lib/services/assessment/modules/securityTests/ErrorClassifier.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/ErrorClassifier.js +113 -0
- package/lib/services/assessment/modules/securityTests/ExecutionArtifactDetector.d.ts +49 -0
- package/lib/services/assessment/modules/securityTests/ExecutionArtifactDetector.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/ExecutionArtifactDetector.js +74 -0
- package/lib/services/assessment/modules/securityTests/MathAnalyzer.d.ts +58 -0
- package/lib/services/assessment/modules/securityTests/MathAnalyzer.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/MathAnalyzer.js +251 -0
- package/lib/services/assessment/modules/securityTests/SafeResponseDetector.d.ts +59 -0
- package/lib/services/assessment/modules/securityTests/SafeResponseDetector.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/SafeResponseDetector.js +151 -0
- package/lib/services/assessment/modules/securityTests/SecurityPatternLibrary.d.ts +229 -0
- package/lib/services/assessment/modules/securityTests/SecurityPatternLibrary.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/SecurityPatternLibrary.js +566 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.d.ts.map +1 -1
- package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.js +49 -24
- package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts +63 -85
- package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts.map +1 -1
- package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.js +270 -1171
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { u as useToast, r as reactExports, j as jsxRuntimeExports, p as parseOAuthCallbackParams, g as generateOAuthErrorDescription, S as SESSION_KEYS, I as InspectorOAuthClientProvider, a as auth } from "./index-
|
|
1
|
+
import { u as useToast, r as reactExports, j as jsxRuntimeExports, p as parseOAuthCallbackParams, g as generateOAuthErrorDescription, S as SESSION_KEYS, I as InspectorOAuthClientProvider, a as auth } from "./index-CsDJSSWq.js";
|
|
2
2
|
const OAuthCallback = ({ onConnect }) => {
|
|
3
3
|
const { toast } = useToast();
|
|
4
4
|
const hasProcessedRef = reactExports.useRef(false);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as reactExports, S as SESSION_KEYS, p as parseOAuthCallbackParams, j as jsxRuntimeExports, g as generateOAuthErrorDescription } from "./index-
|
|
1
|
+
import { r as reactExports, S as SESSION_KEYS, p as parseOAuthCallbackParams, j as jsxRuntimeExports, g as generateOAuthErrorDescription } from "./index-CsDJSSWq.js";
|
|
2
2
|
const OAuthDebugCallback = ({ onConnect }) => {
|
|
3
3
|
reactExports.useEffect(() => {
|
|
4
4
|
let isProcessed = false;
|
|
@@ -16373,7 +16373,7 @@ object({
|
|
|
16373
16373
|
token_type_hint: string().optional()
|
|
16374
16374
|
}).strip();
|
|
16375
16375
|
const name = "@bryan-thompson/inspector-assessment-client";
|
|
16376
|
-
const version$1 = "1.26.
|
|
16376
|
+
const version$1 = "1.26.6";
|
|
16377
16377
|
const packageJson = {
|
|
16378
16378
|
name,
|
|
16379
16379
|
version: version$1
|
|
@@ -45288,7 +45288,7 @@ const useTheme = () => {
|
|
|
45288
45288
|
[theme, setThemeWithSideEffect]
|
|
45289
45289
|
);
|
|
45290
45290
|
};
|
|
45291
|
-
const version = "1.26.
|
|
45291
|
+
const version = "1.26.6";
|
|
45292
45292
|
var [createTooltipContext] = createContextScope("Tooltip", [
|
|
45293
45293
|
createPopperScope
|
|
45294
45294
|
]);
|
|
@@ -48845,13 +48845,13 @@ const App = () => {
|
|
|
48845
48845
|
) });
|
|
48846
48846
|
if (window.location.pathname === "/oauth/callback") {
|
|
48847
48847
|
const OAuthCallback = React.lazy(
|
|
48848
|
-
() => __vitePreload(() => import("./OAuthCallback-
|
|
48848
|
+
() => __vitePreload(() => import("./OAuthCallback-CCWVtjr7.js"), true ? [] : void 0)
|
|
48849
48849
|
);
|
|
48850
48850
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthCallback, { onConnect: onOAuthConnect }) });
|
|
48851
48851
|
}
|
|
48852
48852
|
if (window.location.pathname === "/oauth/callback/debug") {
|
|
48853
48853
|
const OAuthDebugCallback = React.lazy(
|
|
48854
|
-
() => __vitePreload(() => import("./OAuthDebugCallback-
|
|
48854
|
+
() => __vitePreload(() => import("./OAuthDebugCallback-DqbXfUi4.js"), true ? [] : void 0)
|
|
48855
48855
|
);
|
|
48856
48856
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthDebugCallback, { onConnect: onOAuthDebugConnect }) });
|
|
48857
48857
|
}
|
package/dist/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/mcp.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>MCP Inspector</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-CsDJSSWq.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-cHhcEXbr.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Confidence Scorer
|
|
3
|
+
* Calculates confidence levels for vulnerability detections
|
|
4
|
+
*
|
|
5
|
+
* Extracted from SecurityResponseAnalyzer.ts (Issue #53)
|
|
6
|
+
* Handles: confidence calculation, structured data tool detection, validation pattern checks
|
|
7
|
+
*/
|
|
8
|
+
import { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
9
|
+
import { SecurityPayload } from "../../../../lib/securityPatterns.js";
|
|
10
|
+
import type { SanitizationDetectionResult } from "./SanitizationDetector.js";
|
|
11
|
+
/**
|
|
12
|
+
* Result of confidence calculation
|
|
13
|
+
*/
|
|
14
|
+
export interface ConfidenceResult {
|
|
15
|
+
confidence: "high" | "medium" | "low";
|
|
16
|
+
requiresManualReview: boolean;
|
|
17
|
+
manualReviewReason?: string;
|
|
18
|
+
reviewGuidance?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Calculates confidence levels for security vulnerability detections
|
|
22
|
+
*/
|
|
23
|
+
export declare class ConfidenceScorer {
|
|
24
|
+
/**
|
|
25
|
+
* Calculate confidence level for a vulnerability detection
|
|
26
|
+
*
|
|
27
|
+
* Factors considered:
|
|
28
|
+
* - Sanitization detection (Issue #56)
|
|
29
|
+
* - Structured data tool context
|
|
30
|
+
* - Evidence quality
|
|
31
|
+
* - Response characteristics
|
|
32
|
+
*
|
|
33
|
+
* @param tool - The tool being tested
|
|
34
|
+
* @param isVulnerable - Whether the tool was flagged as vulnerable
|
|
35
|
+
* @param evidence - Evidence string from vulnerability detection
|
|
36
|
+
* @param responseText - The response text from the tool
|
|
37
|
+
* @param payload - The security payload used for testing
|
|
38
|
+
* @param sanitizationResult - Optional sanitization detection result (Issue #56)
|
|
39
|
+
* @returns Confidence result with manual review requirements
|
|
40
|
+
*/
|
|
41
|
+
calculateConfidence(tool: Tool, isVulnerable: boolean, evidence: string, responseText: string, payload: SecurityPayload, sanitizationResult?: SanitizationDetectionResult): ConfidenceResult;
|
|
42
|
+
/**
|
|
43
|
+
* Check if tool is a structured data tool (search, lookup, retrieval)
|
|
44
|
+
*
|
|
45
|
+
* These tools are more likely to return data containing patterns
|
|
46
|
+
* that look like vulnerabilities but are actually just data.
|
|
47
|
+
*/
|
|
48
|
+
isStructuredDataTool(toolName: string, toolDescription: string): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Check if evidence pattern is ambiguous (validation-like)
|
|
51
|
+
*
|
|
52
|
+
* Some patterns match both security issues AND normal validation errors.
|
|
53
|
+
* These require more careful analysis.
|
|
54
|
+
*/
|
|
55
|
+
isValidationPattern(evidencePattern: RegExp): boolean;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=ConfidenceScorer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfidenceScorer.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/securityTests/ConfidenceScorer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,oBAAoB,EAAE,OAAO,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAmCD;;GAEG;AACH,qBAAa,gBAAgB;IAC3B;;;;;;;;;;;;;;;;OAgBG;IACH,mBAAmB,CACjB,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,OAAO,EACrB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,eAAe,EACxB,kBAAkB,CAAC,EAAE,2BAA2B,GAC/C,gBAAgB;IA4JnB;;;;;OAKG;IACH,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO;IAOxE;;;;;OAKG;IACH,mBAAmB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO;CAOtD"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Confidence Scorer
|
|
3
|
+
* Calculates confidence levels for vulnerability detections
|
|
4
|
+
*
|
|
5
|
+
* Extracted from SecurityResponseAnalyzer.ts (Issue #53)
|
|
6
|
+
* Handles: confidence calculation, structured data tool detection, validation pattern checks
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Patterns for detecting structured data tools
|
|
10
|
+
*/
|
|
11
|
+
const STRUCTURED_DATA_TOOL_PATTERNS = [
|
|
12
|
+
/search/i,
|
|
13
|
+
/find/i,
|
|
14
|
+
/lookup/i,
|
|
15
|
+
/query/i,
|
|
16
|
+
/retrieve/i,
|
|
17
|
+
/fetch/i,
|
|
18
|
+
/get/i,
|
|
19
|
+
/list/i,
|
|
20
|
+
/resolve/i,
|
|
21
|
+
/discover/i,
|
|
22
|
+
/browse/i,
|
|
23
|
+
];
|
|
24
|
+
/**
|
|
25
|
+
* Ambiguous validation patterns that may cause false positives
|
|
26
|
+
*/
|
|
27
|
+
const VALIDATION_AMBIGUOUS_PATTERNS = [
|
|
28
|
+
"type.*error",
|
|
29
|
+
"invalid.*type",
|
|
30
|
+
"error",
|
|
31
|
+
"invalid",
|
|
32
|
+
"failed",
|
|
33
|
+
"negative.*not.*allowed",
|
|
34
|
+
"must.*be.*positive",
|
|
35
|
+
"invalid.*value",
|
|
36
|
+
"overflow",
|
|
37
|
+
"out.*of.*range",
|
|
38
|
+
];
|
|
39
|
+
/**
|
|
40
|
+
* Calculates confidence levels for security vulnerability detections
|
|
41
|
+
*/
|
|
42
|
+
export class ConfidenceScorer {
|
|
43
|
+
/**
|
|
44
|
+
* Calculate confidence level for a vulnerability detection
|
|
45
|
+
*
|
|
46
|
+
* Factors considered:
|
|
47
|
+
* - Sanitization detection (Issue #56)
|
|
48
|
+
* - Structured data tool context
|
|
49
|
+
* - Evidence quality
|
|
50
|
+
* - Response characteristics
|
|
51
|
+
*
|
|
52
|
+
* @param tool - The tool being tested
|
|
53
|
+
* @param isVulnerable - Whether the tool was flagged as vulnerable
|
|
54
|
+
* @param evidence - Evidence string from vulnerability detection
|
|
55
|
+
* @param responseText - The response text from the tool
|
|
56
|
+
* @param payload - The security payload used for testing
|
|
57
|
+
* @param sanitizationResult - Optional sanitization detection result (Issue #56)
|
|
58
|
+
* @returns Confidence result with manual review requirements
|
|
59
|
+
*/
|
|
60
|
+
calculateConfidence(tool, isVulnerable, evidence, responseText, payload, sanitizationResult) {
|
|
61
|
+
// Issue #56: If sanitization is detected, reduce confidence for vulnerabilities
|
|
62
|
+
// This helps reduce false positives on well-protected servers
|
|
63
|
+
if (isVulnerable && sanitizationResult?.detected) {
|
|
64
|
+
const adjustment = sanitizationResult.totalConfidenceAdjustment;
|
|
65
|
+
// Strong sanitization evidence (adjustment >= 30) - downgrade to low confidence
|
|
66
|
+
// This indicates the tool has specific security libraries in place
|
|
67
|
+
if (adjustment >= 30) {
|
|
68
|
+
const libraries = sanitizationResult.libraries.join(", ") || "general";
|
|
69
|
+
return {
|
|
70
|
+
confidence: "low",
|
|
71
|
+
requiresManualReview: true,
|
|
72
|
+
manualReviewReason: `Sanitization detected (${libraries}). ` +
|
|
73
|
+
`Pattern match may be false positive due to security measures in place.`,
|
|
74
|
+
reviewGuidance: `Tool uses sanitization libraries. Verify if the detected vulnerability ` +
|
|
75
|
+
`actually bypasses the sanitization layer. Check: 1) Does the payload execute ` +
|
|
76
|
+
`after sanitization? 2) Is the sanitization comprehensive for this attack type? ` +
|
|
77
|
+
`3) Evidence: ${sanitizationResult.evidence.join("; ")}`,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
// Moderate sanitization evidence (adjustment >= 15) - downgrade high to medium
|
|
81
|
+
if (adjustment >= 15) {
|
|
82
|
+
const patterns = sanitizationResult.libraries.length > 0
|
|
83
|
+
? sanitizationResult.libraries.join(", ")
|
|
84
|
+
: sanitizationResult.genericPatterns.join(", ");
|
|
85
|
+
return {
|
|
86
|
+
confidence: "medium",
|
|
87
|
+
requiresManualReview: true,
|
|
88
|
+
manualReviewReason: `Sanitization patterns detected (${patterns}). Verify actual vulnerability.`,
|
|
89
|
+
reviewGuidance: `Tool mentions sanitization in description or shows sanitization in response. ` +
|
|
90
|
+
`Verify if the detected pattern represents actual code execution or if it's ` +
|
|
91
|
+
`safely handled. Evidence: ${sanitizationResult.evidence.join("; ")}`,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const toolDescription = (tool.description || "").toLowerCase();
|
|
96
|
+
const toolName = tool.name.toLowerCase();
|
|
97
|
+
const responseLower = responseText.toLowerCase();
|
|
98
|
+
const payloadLower = payload.payload.toLowerCase();
|
|
99
|
+
// HIGH CONFIDENCE: Clear cases
|
|
100
|
+
if (!isVulnerable &&
|
|
101
|
+
(evidence.includes("safely reflected") ||
|
|
102
|
+
evidence.includes("API wrapper") ||
|
|
103
|
+
evidence.includes("safe: true"))) {
|
|
104
|
+
return {
|
|
105
|
+
confidence: "high",
|
|
106
|
+
requiresManualReview: false,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
if (isVulnerable &&
|
|
110
|
+
evidence.includes("executed") &&
|
|
111
|
+
!this.isStructuredDataTool(toolName, toolDescription)) {
|
|
112
|
+
return {
|
|
113
|
+
confidence: "high",
|
|
114
|
+
requiresManualReview: false,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
// LOW CONFIDENCE: Ambiguous pattern matches in structured data
|
|
118
|
+
if (isVulnerable) {
|
|
119
|
+
const isDataTool = this.isStructuredDataTool(toolName, toolDescription);
|
|
120
|
+
const hasStructuredData = /title:|name:|description:|trust score:|id:|snippets:/i.test(responseText) ||
|
|
121
|
+
/^\s*-\s+/m.test(responseText) ||
|
|
122
|
+
/"[^"]+"\s*:\s*"[^"]+"/g.test(responseText);
|
|
123
|
+
const patternInInput = payload.evidence?.test(payloadLower);
|
|
124
|
+
const echosInput = responseLower.includes(payloadLower);
|
|
125
|
+
if (isDataTool && (hasStructuredData || echosInput) && patternInInput) {
|
|
126
|
+
return {
|
|
127
|
+
confidence: "low",
|
|
128
|
+
requiresManualReview: true,
|
|
129
|
+
manualReviewReason: "Pattern matched in structured data response. Tool may be legitimately " +
|
|
130
|
+
"returning data containing search terms rather than executing malicious code.",
|
|
131
|
+
reviewGuidance: "Verify: 1) Does the tool actually execute/compute the input? " +
|
|
132
|
+
"2) Or does it just return pre-existing data that happens to contain the pattern? " +
|
|
133
|
+
`3) Check if '${payload.evidence}' appears in legitimate tool output vs. execution results.`,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
if (payload.evidence &&
|
|
137
|
+
/\b\d\b/.test(payload.evidence.toString()) &&
|
|
138
|
+
/\b(score|count|trust|rating|id|version)\b/i.test(responseText)) {
|
|
139
|
+
return {
|
|
140
|
+
confidence: "low",
|
|
141
|
+
requiresManualReview: true,
|
|
142
|
+
manualReviewReason: "Numeric pattern found in response with numeric metadata (scores, counts, etc.). " +
|
|
143
|
+
"May be coincidental data rather than arithmetic execution.",
|
|
144
|
+
reviewGuidance: "Verify: 1) Did the tool actually compute an arithmetic result? " +
|
|
145
|
+
"2) Or does the number appear in metadata like trust scores, version numbers, or counts? " +
|
|
146
|
+
"3) Compare pattern location in response with tool's expected output format.",
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
if (/admin|role|privilege|elevated/i.test(payload.payload) &&
|
|
150
|
+
/\b(library|search|documentation|api|wrapper)\b/i.test(toolDescription)) {
|
|
151
|
+
return {
|
|
152
|
+
confidence: "low",
|
|
153
|
+
requiresManualReview: true,
|
|
154
|
+
manualReviewReason: "Admin-related keywords found in search/retrieval tool results. " +
|
|
155
|
+
"Tool may be returning data about admin-related libraries/APIs rather than elevating privileges.",
|
|
156
|
+
reviewGuidance: "Verify: 1) Did the tool actually change behavior or assume admin role? " +
|
|
157
|
+
"2) Or did it return search results for admin-related content? " +
|
|
158
|
+
"3) Test if tool behavior actually changed after this request.",
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// MEDIUM CONFIDENCE: Execution evidence but some ambiguity
|
|
163
|
+
if (isVulnerable && evidence.includes("executed")) {
|
|
164
|
+
return {
|
|
165
|
+
confidence: "medium",
|
|
166
|
+
requiresManualReview: true,
|
|
167
|
+
manualReviewReason: "Execution indicators found but context suggests possible ambiguity.",
|
|
168
|
+
reviewGuidance: "Verify: 1) Review the full response to confirm actual code execution. " +
|
|
169
|
+
"2) Check if tool's intended function involves execution. " +
|
|
170
|
+
"3) Test with variations to confirm consistency.",
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
// Default: HIGH confidence for clear safe cases
|
|
174
|
+
return {
|
|
175
|
+
confidence: "high",
|
|
176
|
+
requiresManualReview: false,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Check if tool is a structured data tool (search, lookup, retrieval)
|
|
181
|
+
*
|
|
182
|
+
* These tools are more likely to return data containing patterns
|
|
183
|
+
* that look like vulnerabilities but are actually just data.
|
|
184
|
+
*/
|
|
185
|
+
isStructuredDataTool(toolName, toolDescription) {
|
|
186
|
+
const combined = `${toolName} ${toolDescription}`;
|
|
187
|
+
return STRUCTURED_DATA_TOOL_PATTERNS.some((pattern) => pattern.test(combined));
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Check if evidence pattern is ambiguous (validation-like)
|
|
191
|
+
*
|
|
192
|
+
* Some patterns match both security issues AND normal validation errors.
|
|
193
|
+
* These require more careful analysis.
|
|
194
|
+
*/
|
|
195
|
+
isValidationPattern(evidencePattern) {
|
|
196
|
+
const patternStr = evidencePattern.toString().toLowerCase();
|
|
197
|
+
return VALIDATION_AMBIGUOUS_PATTERNS.some((ambiguous) => patternStr.includes(ambiguous));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Classifier
|
|
3
|
+
* Classifies and analyzes error responses for security testing
|
|
4
|
+
*
|
|
5
|
+
* Extracted from SecurityResponseAnalyzer.ts (Issue #53)
|
|
6
|
+
* Handles: connection error detection, error classification, error info extraction
|
|
7
|
+
*/
|
|
8
|
+
import { CompatibilityCallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
9
|
+
/**
|
|
10
|
+
* Error classification types
|
|
11
|
+
*/
|
|
12
|
+
export type ErrorClassification = "connection" | "server" | "protocol";
|
|
13
|
+
/**
|
|
14
|
+
* Extracted error information from response
|
|
15
|
+
*/
|
|
16
|
+
export interface ErrorInfo {
|
|
17
|
+
code?: string | number;
|
|
18
|
+
message?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Classifies errors from tool responses and exceptions
|
|
22
|
+
*/
|
|
23
|
+
export declare class ErrorClassifier {
|
|
24
|
+
/**
|
|
25
|
+
* Check if response indicates connection/server failure
|
|
26
|
+
*/
|
|
27
|
+
isConnectionError(response: CompatibilityCallToolResult): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Check if caught exception indicates connection/server failure
|
|
30
|
+
*/
|
|
31
|
+
isConnectionErrorFromException(error: unknown): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Internal: Check if text indicates connection/server failure
|
|
34
|
+
*/
|
|
35
|
+
private isConnectionErrorFromText;
|
|
36
|
+
/**
|
|
37
|
+
* Classify error type for reporting
|
|
38
|
+
*/
|
|
39
|
+
classifyError(response: CompatibilityCallToolResult): ErrorClassification;
|
|
40
|
+
/**
|
|
41
|
+
* Classify error type from caught exception
|
|
42
|
+
*/
|
|
43
|
+
classifyErrorFromException(error: unknown): ErrorClassification;
|
|
44
|
+
/**
|
|
45
|
+
* Internal: Classify error type from text
|
|
46
|
+
*/
|
|
47
|
+
private classifyErrorFromText;
|
|
48
|
+
/**
|
|
49
|
+
* Extract error info from response
|
|
50
|
+
*/
|
|
51
|
+
extractErrorInfo(response: CompatibilityCallToolResult): ErrorInfo;
|
|
52
|
+
/**
|
|
53
|
+
* Extract response content from MCP response
|
|
54
|
+
*/
|
|
55
|
+
extractResponseContent(response: CompatibilityCallToolResult): string;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=ErrorClassifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErrorClassifier.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/securityTests/ErrorClassifier.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AAQjF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEvE;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,eAAe;IAC1B;;OAEG;IACH,iBAAiB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,OAAO;IAKjE;;OAEG;IACH,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;IAQvD;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAgBjC;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,2BAA2B,GAAG,mBAAmB;IAKzE;;OAEG;IACH,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB;IAQ/D;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAgB7B;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,SAAS;IAsBlE;;OAEG;IACH,sBAAsB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,MAAM;CAUtE"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Classifier
|
|
3
|
+
* Classifies and analyzes error responses for security testing
|
|
4
|
+
*
|
|
5
|
+
* Extracted from SecurityResponseAnalyzer.ts (Issue #53)
|
|
6
|
+
* Handles: connection error detection, error classification, error info extraction
|
|
7
|
+
*/
|
|
8
|
+
import { CONNECTION_ERROR_PATTERNS, ERROR_CLASSIFICATION_PATTERNS, matchesAny, hasMcpErrorPrefix, } from "./SecurityPatternLibrary.js";
|
|
9
|
+
/**
|
|
10
|
+
* Classifies errors from tool responses and exceptions
|
|
11
|
+
*/
|
|
12
|
+
export class ErrorClassifier {
|
|
13
|
+
/**
|
|
14
|
+
* Check if response indicates connection/server failure
|
|
15
|
+
*/
|
|
16
|
+
isConnectionError(response) {
|
|
17
|
+
const text = this.extractResponseContent(response).toLowerCase();
|
|
18
|
+
return this.isConnectionErrorFromText(text);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Check if caught exception indicates connection/server failure
|
|
22
|
+
*/
|
|
23
|
+
isConnectionErrorFromException(error) {
|
|
24
|
+
if (error instanceof Error) {
|
|
25
|
+
const message = error.message.toLowerCase();
|
|
26
|
+
return this.isConnectionErrorFromText(message);
|
|
27
|
+
}
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Internal: Check if text indicates connection/server failure
|
|
32
|
+
*/
|
|
33
|
+
isConnectionErrorFromText(text) {
|
|
34
|
+
// Check unambiguous patterns first
|
|
35
|
+
if (matchesAny(CONNECTION_ERROR_PATTERNS.unambiguous, text)) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
// Check contextual patterns only if text has MCP error prefix
|
|
39
|
+
if (hasMcpErrorPrefix(text)) {
|
|
40
|
+
if (matchesAny(CONNECTION_ERROR_PATTERNS.contextual, text)) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Classify error type for reporting
|
|
48
|
+
*/
|
|
49
|
+
classifyError(response) {
|
|
50
|
+
const text = this.extractResponseContent(response).toLowerCase();
|
|
51
|
+
return this.classifyErrorFromText(text);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Classify error type from caught exception
|
|
55
|
+
*/
|
|
56
|
+
classifyErrorFromException(error) {
|
|
57
|
+
if (error instanceof Error) {
|
|
58
|
+
const message = error.message.toLowerCase();
|
|
59
|
+
return this.classifyErrorFromText(message);
|
|
60
|
+
}
|
|
61
|
+
return "protocol";
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Internal: Classify error type from text
|
|
65
|
+
*/
|
|
66
|
+
classifyErrorFromText(text) {
|
|
67
|
+
if (ERROR_CLASSIFICATION_PATTERNS.connection.test(text)) {
|
|
68
|
+
return "connection";
|
|
69
|
+
}
|
|
70
|
+
if (ERROR_CLASSIFICATION_PATTERNS.server.test(text)) {
|
|
71
|
+
return "server";
|
|
72
|
+
}
|
|
73
|
+
if (ERROR_CLASSIFICATION_PATTERNS.protocol.test(text)) {
|
|
74
|
+
return "protocol";
|
|
75
|
+
}
|
|
76
|
+
return "protocol";
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Extract error info from response
|
|
80
|
+
*/
|
|
81
|
+
extractErrorInfo(response) {
|
|
82
|
+
const content = this.extractResponseContent(response);
|
|
83
|
+
try {
|
|
84
|
+
const parsed = JSON.parse(content);
|
|
85
|
+
if (parsed.error) {
|
|
86
|
+
return {
|
|
87
|
+
code: parsed.error.code || parsed.code,
|
|
88
|
+
message: parsed.error.message || parsed.message,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
return { code: parsed.code, message: parsed.message };
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Check for MCP error format in text
|
|
95
|
+
const mcpMatch = content.match(/MCP error (-?\d+):\s*(.*)/i);
|
|
96
|
+
if (mcpMatch) {
|
|
97
|
+
return { code: parseInt(mcpMatch[1]), message: mcpMatch[2] };
|
|
98
|
+
}
|
|
99
|
+
return {};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Extract response content from MCP response
|
|
104
|
+
*/
|
|
105
|
+
extractResponseContent(response) {
|
|
106
|
+
if (response.content && Array.isArray(response.content)) {
|
|
107
|
+
return response.content
|
|
108
|
+
.map((c) => c.type === "text" ? c.text : "")
|
|
109
|
+
.join(" ");
|
|
110
|
+
}
|
|
111
|
+
return String(response.content || "");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution Artifact Detector
|
|
3
|
+
* Detects evidence of actual code/command execution in tool responses
|
|
4
|
+
*
|
|
5
|
+
* Extracted from SecurityResponseAnalyzer.ts (Issue #53)
|
|
6
|
+
* Handles: execution evidence detection, artifact detection, injection payload echoing
|
|
7
|
+
*/
|
|
8
|
+
import { CompatibilityCallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
9
|
+
/**
|
|
10
|
+
* Result of response analysis
|
|
11
|
+
*/
|
|
12
|
+
export interface AnalysisResult {
|
|
13
|
+
isVulnerable: boolean;
|
|
14
|
+
evidence?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Detects execution artifacts in tool responses
|
|
18
|
+
*/
|
|
19
|
+
export declare class ExecutionArtifactDetector {
|
|
20
|
+
/**
|
|
21
|
+
* Check if response contains evidence of actual execution
|
|
22
|
+
* Used to distinguish between safe reflection and actual command/code execution
|
|
23
|
+
*/
|
|
24
|
+
hasExecutionEvidence(responseText: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Detect execution artifacts in response
|
|
27
|
+
* Two-tier detection: unambiguous artifacts + context-sensitive patterns
|
|
28
|
+
*/
|
|
29
|
+
detectExecutionArtifacts(responseText: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Check if response contains echoed injection payload patterns
|
|
32
|
+
* These indicate the payload was stored/reflected, not executed
|
|
33
|
+
*/
|
|
34
|
+
containsEchoedInjectionPayload(responseText: string): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Analyze injection response (fallback logic)
|
|
37
|
+
* Used when primary detection methods are inconclusive
|
|
38
|
+
*
|
|
39
|
+
* @param responseText The response text to analyze
|
|
40
|
+
* @param isReflectionCheck Function to check if response is reflection
|
|
41
|
+
* @returns Analysis result with vulnerability status
|
|
42
|
+
*/
|
|
43
|
+
analyzeInjectionResponse(responseText: string, isReflectionCheck: (text: string) => boolean): AnalysisResult;
|
|
44
|
+
/**
|
|
45
|
+
* Extract response content from MCP response
|
|
46
|
+
*/
|
|
47
|
+
extractResponseContent(response: CompatibilityCallToolResult): string;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=ExecutionArtifactDetector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExecutionArtifactDetector.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/securityTests/ExecutionArtifactDetector.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AASjF;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,qBAAa,yBAAyB;IACpC;;;OAGG;IACH,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAInD;;;OAGG;IACH,wBAAwB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAqBvD;;;OAGG;IACH,8BAA8B,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAI7D;;;;;;;OAOG;IACH,wBAAwB,CACtB,YAAY,EAAE,MAAM,EACpB,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAC3C,cAAc;IAajB;;OAEG;IACH,sBAAsB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,MAAM;CAUtE"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution Artifact Detector
|
|
3
|
+
* Detects evidence of actual code/command execution in tool responses
|
|
4
|
+
*
|
|
5
|
+
* Extracted from SecurityResponseAnalyzer.ts (Issue #53)
|
|
6
|
+
* Handles: execution evidence detection, artifact detection, injection payload echoing
|
|
7
|
+
*/
|
|
8
|
+
import { EXECUTION_INDICATORS, EXECUTION_ARTIFACT_PATTERNS, ECHOED_PAYLOAD_PATTERNS, FALLBACK_EXECUTION_PATTERNS, matchesAny, } from "./SecurityPatternLibrary.js";
|
|
9
|
+
/**
|
|
10
|
+
* Detects execution artifacts in tool responses
|
|
11
|
+
*/
|
|
12
|
+
export class ExecutionArtifactDetector {
|
|
13
|
+
/**
|
|
14
|
+
* Check if response contains evidence of actual execution
|
|
15
|
+
* Used to distinguish between safe reflection and actual command/code execution
|
|
16
|
+
*/
|
|
17
|
+
hasExecutionEvidence(responseText) {
|
|
18
|
+
return matchesAny(EXECUTION_INDICATORS, responseText);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Detect execution artifacts in response
|
|
22
|
+
* Two-tier detection: unambiguous artifacts + context-sensitive patterns
|
|
23
|
+
*/
|
|
24
|
+
detectExecutionArtifacts(responseText) {
|
|
25
|
+
const containsEchoedPayload = this.containsEchoedInjectionPayload(responseText);
|
|
26
|
+
// Check always-execution patterns
|
|
27
|
+
if (matchesAny(EXECUTION_ARTIFACT_PATTERNS.alwaysExecution, responseText)) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
// Context-sensitive patterns only count if no echoed payload present
|
|
31
|
+
if (!containsEchoedPayload) {
|
|
32
|
+
if (matchesAny(EXECUTION_ARTIFACT_PATTERNS.contextSensitive, responseText)) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Check if response contains echoed injection payload patterns
|
|
40
|
+
* These indicate the payload was stored/reflected, not executed
|
|
41
|
+
*/
|
|
42
|
+
containsEchoedInjectionPayload(responseText) {
|
|
43
|
+
return matchesAny(ECHOED_PAYLOAD_PATTERNS, responseText);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Analyze injection response (fallback logic)
|
|
47
|
+
* Used when primary detection methods are inconclusive
|
|
48
|
+
*
|
|
49
|
+
* @param responseText The response text to analyze
|
|
50
|
+
* @param isReflectionCheck Function to check if response is reflection
|
|
51
|
+
* @returns Analysis result with vulnerability status
|
|
52
|
+
*/
|
|
53
|
+
analyzeInjectionResponse(responseText, isReflectionCheck) {
|
|
54
|
+
const hasExecution = matchesAny(FALLBACK_EXECUTION_PATTERNS, responseText);
|
|
55
|
+
if (hasExecution && !isReflectionCheck(responseText)) {
|
|
56
|
+
return {
|
|
57
|
+
isVulnerable: true,
|
|
58
|
+
evidence: "Tool executed instruction: found execution keywords",
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return { isVulnerable: false };
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Extract response content from MCP response
|
|
65
|
+
*/
|
|
66
|
+
extractResponseContent(response) {
|
|
67
|
+
if (response.content && Array.isArray(response.content)) {
|
|
68
|
+
return response.content
|
|
69
|
+
.map((c) => c.type === "text" ? c.text : "")
|
|
70
|
+
.join(" ");
|
|
71
|
+
}
|
|
72
|
+
return String(response.content || "");
|
|
73
|
+
}
|
|
74
|
+
}
|