framework-mcp 1.1.0 → 1.1.2
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 +155 -9
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +459 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +581 -11
package/dist/index.js
CHANGED
|
@@ -2,6 +2,34 @@
|
|
|
2
2
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
3
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
4
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
+
// Domain-specific validation mapping
|
|
6
|
+
const SAFEGUARD_DOMAIN_REQUIREMENTS = {
|
|
7
|
+
"1.1": {
|
|
8
|
+
domain: "Asset Inventory",
|
|
9
|
+
required_tool_types: ["inventory", "asset_management", "cmdb", "discovery"],
|
|
10
|
+
description: "Only asset inventory and discovery tools can provide FULL/PARTIAL coverage"
|
|
11
|
+
},
|
|
12
|
+
"1.2": {
|
|
13
|
+
domain: "Asset Management",
|
|
14
|
+
required_tool_types: ["inventory", "asset_management", "network_security", "nac"],
|
|
15
|
+
description: "Asset management or network access control tools required for FULL/PARTIAL"
|
|
16
|
+
},
|
|
17
|
+
"5.1": {
|
|
18
|
+
domain: "Account Management",
|
|
19
|
+
required_tool_types: ["identity_management", "iam", "directory", "account_management"],
|
|
20
|
+
description: "Identity and account management tools required for FULL/PARTIAL"
|
|
21
|
+
},
|
|
22
|
+
"6.3": {
|
|
23
|
+
domain: "Authentication",
|
|
24
|
+
required_tool_types: ["mfa", "authentication", "identity_management", "iam"],
|
|
25
|
+
description: "Multi-factor authentication and identity tools required for FULL/PARTIAL"
|
|
26
|
+
},
|
|
27
|
+
"7.1": {
|
|
28
|
+
domain: "Vulnerability Management",
|
|
29
|
+
required_tool_types: ["vulnerability_management", "vulnerability_scanner", "patch_management"],
|
|
30
|
+
description: "Vulnerability management and scanning tools required for FULL/PARTIAL"
|
|
31
|
+
}
|
|
32
|
+
};
|
|
5
33
|
// Enhanced CIS Controls Framework Data with color-coded categorization
|
|
6
34
|
const CIS_SAFEGUARDS = {
|
|
7
35
|
"1.1": {
|
|
@@ -5537,6 +5565,35 @@ export class GRCAnalysisServer {
|
|
|
5537
5565
|
}
|
|
5538
5566
|
}
|
|
5539
5567
|
}
|
|
5568
|
+
},
|
|
5569
|
+
{
|
|
5570
|
+
name: 'validate_vendor_mapping',
|
|
5571
|
+
description: 'Validate whether a vendor\'s stated capability mapping (Full/Partial/Facilitates/Governance/Validates) is actually supported by their explanatory text for a specific CIS safeguard',
|
|
5572
|
+
inputSchema: {
|
|
5573
|
+
type: 'object',
|
|
5574
|
+
properties: {
|
|
5575
|
+
vendor_name: {
|
|
5576
|
+
type: 'string',
|
|
5577
|
+
description: 'Name of the vendor (optional)',
|
|
5578
|
+
default: 'Unknown Vendor'
|
|
5579
|
+
},
|
|
5580
|
+
safeguard_id: {
|
|
5581
|
+
type: 'string',
|
|
5582
|
+
description: 'CIS Control safeguard ID (e.g., "5.1", "1.1", "6.3")',
|
|
5583
|
+
pattern: '^[0-9]+\\.[0-9]+$'
|
|
5584
|
+
},
|
|
5585
|
+
claimed_capability: {
|
|
5586
|
+
type: 'string',
|
|
5587
|
+
enum: ['full', 'partial', 'facilitates', 'governance', 'validates'],
|
|
5588
|
+
description: 'Vendor\'s claimed capability mapping for this safeguard'
|
|
5589
|
+
},
|
|
5590
|
+
supporting_text: {
|
|
5591
|
+
type: 'string',
|
|
5592
|
+
description: 'Vendor\'s supporting text blob explaining how they meet the claimed capability'
|
|
5593
|
+
}
|
|
5594
|
+
},
|
|
5595
|
+
required: ['safeguard_id', 'claimed_capability', 'supporting_text']
|
|
5596
|
+
}
|
|
5540
5597
|
}
|
|
5541
5598
|
],
|
|
5542
5599
|
}));
|
|
@@ -5552,6 +5609,8 @@ export class GRCAnalysisServer {
|
|
|
5552
5609
|
return await this.validateCoverageClaim(args);
|
|
5553
5610
|
case 'list_available_safeguards':
|
|
5554
5611
|
return await this.listAvailableSafeguards(args);
|
|
5612
|
+
case 'validate_vendor_mapping':
|
|
5613
|
+
return await this.validateVendorMapping(args);
|
|
5555
5614
|
default:
|
|
5556
5615
|
throw new Error(`Unknown tool: ${name}`);
|
|
5557
5616
|
}
|
|
@@ -5698,6 +5757,11 @@ export class GRCAnalysisServer {
|
|
|
5698
5757
|
'improve', 'enhance', 'optimize', 'faster', 'better', 'stronger', 'automate',
|
|
5699
5758
|
'streamline', 'efficiency', 'facilitate', 'support', 'enable', 'accelerate',
|
|
5700
5759
|
'api', 'integration', 'data', 'export', 'import', 'sync', 'feed',
|
|
5760
|
+
// Data provision and enrichment
|
|
5761
|
+
'provides data', 'data source', 'data feeds', 'enrichment', 'data enrichment',
|
|
5762
|
+
'supplemental data', 'additional data', 'contextual data', 'threat data',
|
|
5763
|
+
'intelligence feeds', 'data aggregation', 'data collection', 'data gathering',
|
|
5764
|
+
'feeds data', 'populates', 'informs', 'enriches', 'supplements',
|
|
5701
5765
|
// Governance/process facilitation (new keywords for tools like Upolicy)
|
|
5702
5766
|
'enables compliance', 'facilitates implementation', 'supports compliance',
|
|
5703
5767
|
'creates framework', 'enables organizations', 'infrastructure', 'foundation',
|
|
@@ -5707,9 +5771,9 @@ export class GRCAnalysisServer {
|
|
|
5707
5771
|
];
|
|
5708
5772
|
const validatesKeywords = [
|
|
5709
5773
|
'audit', 'report', 'evidence', 'verify', 'validate', 'check', 'monitor',
|
|
5710
|
-
'compliance report', 'assessment', 'logging', 'tracking', 'review', 'attest',
|
|
5774
|
+
'compliance', 'compliance report', 'assessment', 'logging', 'tracking', 'review', 'attest',
|
|
5711
5775
|
'dashboard', 'metrics', 'analytics', 'visibility', 'alert', 'attestation',
|
|
5712
|
-
'compliance tracking', 'audit trail', 'reporting capabilities'
|
|
5776
|
+
'compliance tracking', 'audit trail', 'reporting capabilities', 'audit capabilities'
|
|
5713
5777
|
];
|
|
5714
5778
|
// Analyze element coverage (binary: covered or not)
|
|
5715
5779
|
const coreCoverage = this.analyzeBinaryElementCoverage(text, safeguard.coreRequirements);
|
|
@@ -5739,18 +5803,22 @@ export class GRCAnalysisServer {
|
|
|
5739
5803
|
'rather than direct', 'instead of direct'
|
|
5740
5804
|
];
|
|
5741
5805
|
const hasNonImplementationLanguage = nonImplementationPatterns.some(pattern => text.includes(pattern));
|
|
5742
|
-
// Determine if full or partial coverage (based on core + sub-taxonomical elements)
|
|
5743
|
-
|
|
5744
|
-
|
|
5806
|
+
// Determine if full or partial coverage (based on core + sub-taxonomical elements WITHIN SCOPE)
|
|
5807
|
+
// Full = addresses majority of core requirements + substantial sub-elements within their stated scope
|
|
5808
|
+
// Partial = addresses some core requirements with clear scope boundaries
|
|
5809
|
+
const corePercentage = safeguard.coreRequirements.length > 0 ?
|
|
5810
|
+
(coreCoverage.coveredElements.length / safeguard.coreRequirements.length) * 100 : 0;
|
|
5811
|
+
const subElementPercentage = safeguard.subTaxonomicalElements.length > 0 ?
|
|
5812
|
+
(subElementCoverage.coveredElements.length / safeguard.subTaxonomicalElements.length) * 100 : 0;
|
|
5745
5813
|
let fullCapability = false;
|
|
5746
5814
|
let partialCapability = false;
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5815
|
+
// Full capability: High coverage of core requirements + reasonable sub-element coverage
|
|
5816
|
+
if (corePercentage >= 70 && subElementPercentage >= 50) {
|
|
5817
|
+
fullCapability = true;
|
|
5818
|
+
}
|
|
5819
|
+
// Partial capability: Moderate core coverage OR clear scope-limited implementation
|
|
5820
|
+
else if (corePercentage >= 30 || (coreCoverage.coveredElements.length > 0 && subElementPercentage >= 20)) {
|
|
5821
|
+
partialCapability = true;
|
|
5754
5822
|
}
|
|
5755
5823
|
// Enhanced primary capability logic
|
|
5756
5824
|
let primaryCapability = 'none';
|
|
@@ -5788,6 +5856,8 @@ export class GRCAnalysisServer {
|
|
|
5788
5856
|
const evidence = this.extractEnhancedEvidence(responseText, safeguard);
|
|
5789
5857
|
// Calculate confidence based on evidence strength and keyword matches
|
|
5790
5858
|
const keywordConfidence = (governanceScore + facilitatesScore + validatesScore) / 3;
|
|
5859
|
+
const totalCoreAndSubElements = safeguard.coreRequirements.length + safeguard.subTaxonomicalElements.length;
|
|
5860
|
+
const coveredCoreAndSubElements = coreCoverage.coveredElements.length + subElementCoverage.coveredElements.length;
|
|
5791
5861
|
const coverageConfidence = totalCoreAndSubElements > 0 ?
|
|
5792
5862
|
coveredCoreAndSubElements / totalCoreAndSubElements : 0;
|
|
5793
5863
|
const confidence = Math.min((keywordConfidence * 0.4 + coverageConfidence * 0.6) * 100, 100);
|
|
@@ -6074,6 +6144,383 @@ export class GRCAnalysisServer {
|
|
|
6074
6144
|
}
|
|
6075
6145
|
return validation;
|
|
6076
6146
|
}
|
|
6147
|
+
async validateVendorMapping(args) {
|
|
6148
|
+
const { vendor_name = 'Unknown Vendor', safeguard_id, claimed_capability, supporting_text } = args;
|
|
6149
|
+
const safeguard = CIS_SAFEGUARDS[safeguard_id];
|
|
6150
|
+
if (!safeguard) {
|
|
6151
|
+
throw new Error(`Safeguard ${safeguard_id} not found. Available safeguards: ${Object.keys(CIS_SAFEGUARDS).join(', ')}`);
|
|
6152
|
+
}
|
|
6153
|
+
const validation = this.validateCapabilityClaim(vendor_name, safeguard, claimed_capability, supporting_text);
|
|
6154
|
+
return {
|
|
6155
|
+
content: [
|
|
6156
|
+
{
|
|
6157
|
+
type: 'text',
|
|
6158
|
+
text: JSON.stringify(validation, null, 2),
|
|
6159
|
+
},
|
|
6160
|
+
],
|
|
6161
|
+
};
|
|
6162
|
+
}
|
|
6163
|
+
validateCapabilityClaim(vendorName, safeguard, claimedCapability, supportingText) {
|
|
6164
|
+
const text = supportingText.toLowerCase();
|
|
6165
|
+
// Detect tool type and validate domain match
|
|
6166
|
+
const detectedToolType = this.detectToolType(supportingText);
|
|
6167
|
+
const domainValidation = this.validateDomainMatch(safeguard.id, claimedCapability, detectedToolType);
|
|
6168
|
+
// Adjust capability if domain mismatch detected
|
|
6169
|
+
let effectiveCapability = claimedCapability;
|
|
6170
|
+
let originalClaim;
|
|
6171
|
+
if (domainValidation.should_adjust_capability) {
|
|
6172
|
+
originalClaim = claimedCapability;
|
|
6173
|
+
effectiveCapability = domainValidation.adjusted_capability;
|
|
6174
|
+
}
|
|
6175
|
+
// Perform actual analysis of the supporting text
|
|
6176
|
+
const actualAnalysis = this.performEnhancedSafeguardAnalysis(vendorName, safeguard, supportingText);
|
|
6177
|
+
// Calculate coverage percentages
|
|
6178
|
+
const coreCoverage = this.analyzeBinaryElementCoverage(text, safeguard.coreRequirements);
|
|
6179
|
+
const subElementCoverage = this.analyzeBinaryElementCoverage(text, safeguard.subTaxonomicalElements);
|
|
6180
|
+
const governanceCoverage = this.analyzeBinaryElementCoverage(text, safeguard.governanceElements);
|
|
6181
|
+
const corePercentage = safeguard.coreRequirements.length > 0 ?
|
|
6182
|
+
(coreCoverage.coveredElements.length / safeguard.coreRequirements.length) * 100 : 0;
|
|
6183
|
+
const subElementPercentage = safeguard.subTaxonomicalElements.length > 0 ?
|
|
6184
|
+
(subElementCoverage.coveredElements.length / safeguard.subTaxonomicalElements.length) * 100 : 0;
|
|
6185
|
+
const governancePercentage = safeguard.governanceElements.length > 0 ?
|
|
6186
|
+
(governanceCoverage.coveredElements.length / safeguard.governanceElements.length) * 100 : 0;
|
|
6187
|
+
// Validate claim against criteria (using effective capability after domain adjustment)
|
|
6188
|
+
const validation = this.assessClaimAlignment(effectiveCapability, actualAnalysis, corePercentage, subElementPercentage, governancePercentage, text);
|
|
6189
|
+
// Add domain validation gaps if capability was adjusted
|
|
6190
|
+
if (domainValidation.should_adjust_capability) {
|
|
6191
|
+
validation.gaps.unshift(`Domain mismatch: ${domainValidation.reasoning}`);
|
|
6192
|
+
validation.recommendations.unshift(`Correct capability mapping should be '${effectiveCapability.toUpperCase()}' for ${detectedToolType} tools`);
|
|
6193
|
+
// Reduce confidence for domain mismatches
|
|
6194
|
+
validation.confidence = Math.max(validation.confidence - 20, 0);
|
|
6195
|
+
}
|
|
6196
|
+
return {
|
|
6197
|
+
vendor: vendorName,
|
|
6198
|
+
safeguard_id: safeguard.id,
|
|
6199
|
+
safeguard_title: safeguard.title,
|
|
6200
|
+
claimed_capability: claimedCapability,
|
|
6201
|
+
validation_status: validation.status,
|
|
6202
|
+
confidence_score: validation.confidence,
|
|
6203
|
+
evidence_analysis: {
|
|
6204
|
+
core_requirements_coverage: Math.round(corePercentage),
|
|
6205
|
+
sub_elements_coverage: Math.round(subElementPercentage),
|
|
6206
|
+
governance_alignment: Math.round(governancePercentage),
|
|
6207
|
+
language_consistency: validation.languageConsistency
|
|
6208
|
+
},
|
|
6209
|
+
domain_validation: {
|
|
6210
|
+
required_tool_type: domainValidation.required_tool_types.join('/'),
|
|
6211
|
+
detected_tool_type: detectedToolType,
|
|
6212
|
+
domain_match: domainValidation.domain_match,
|
|
6213
|
+
capability_adjusted: domainValidation.should_adjust_capability,
|
|
6214
|
+
original_claim: originalClaim
|
|
6215
|
+
},
|
|
6216
|
+
gaps_identified: validation.gaps,
|
|
6217
|
+
strengths_identified: validation.strengths,
|
|
6218
|
+
recommendations: validation.recommendations,
|
|
6219
|
+
detailed_feedback: validation.feedback
|
|
6220
|
+
};
|
|
6221
|
+
}
|
|
6222
|
+
assessClaimAlignment(claimedCapability, actualAnalysis, corePercentage, subElementPercentage, governancePercentage, text) {
|
|
6223
|
+
const gaps = [];
|
|
6224
|
+
const strengths = [];
|
|
6225
|
+
const recommendations = [];
|
|
6226
|
+
let languageConsistency = 0;
|
|
6227
|
+
let alignmentScore = 0;
|
|
6228
|
+
switch (claimedCapability.toLowerCase()) {
|
|
6229
|
+
case 'full':
|
|
6230
|
+
// Validate FULL claim
|
|
6231
|
+
if (corePercentage >= 70 && subElementPercentage >= 40) {
|
|
6232
|
+
alignmentScore = 85;
|
|
6233
|
+
strengths.push('High coverage of core requirements and sub-elements');
|
|
6234
|
+
}
|
|
6235
|
+
else if (corePercentage >= 80 && subElementPercentage >= 30) {
|
|
6236
|
+
// Alternative path: very high core with moderate sub-elements
|
|
6237
|
+
alignmentScore = 80;
|
|
6238
|
+
strengths.push('Very high core requirements coverage with adequate sub-element coverage');
|
|
6239
|
+
}
|
|
6240
|
+
else {
|
|
6241
|
+
alignmentScore = Math.max(0, (corePercentage + subElementPercentage) / 2 - 15);
|
|
6242
|
+
if (corePercentage < 70)
|
|
6243
|
+
gaps.push(`Core requirements coverage (${Math.round(corePercentage)}%) below FULL threshold (70%)`);
|
|
6244
|
+
if (subElementPercentage < 40)
|
|
6245
|
+
gaps.push(`Sub-element coverage (${Math.round(subElementPercentage)}%) below FULL threshold (40%)`);
|
|
6246
|
+
}
|
|
6247
|
+
// Check for conflicting facilitation language
|
|
6248
|
+
if (this.hasFacilitationLanguage(text)) {
|
|
6249
|
+
alignmentScore -= 30;
|
|
6250
|
+
gaps.push('Contains facilitation language inconsistent with FULL implementation claim');
|
|
6251
|
+
}
|
|
6252
|
+
languageConsistency = this.assessImplementationLanguage(text);
|
|
6253
|
+
break;
|
|
6254
|
+
case 'partial':
|
|
6255
|
+
// Validate PARTIAL claim
|
|
6256
|
+
if (corePercentage >= 30 || (corePercentage > 0 && subElementPercentage >= 20)) {
|
|
6257
|
+
alignmentScore = 75;
|
|
6258
|
+
strengths.push('Appropriate coverage level for PARTIAL implementation');
|
|
6259
|
+
}
|
|
6260
|
+
else {
|
|
6261
|
+
alignmentScore = Math.max(0, corePercentage + subElementPercentage - 10);
|
|
6262
|
+
gaps.push(`Coverage too low even for PARTIAL claim: ${Math.round(corePercentage)}% core, ${Math.round(subElementPercentage)}% sub-elements`);
|
|
6263
|
+
}
|
|
6264
|
+
// Check for scope boundary definition
|
|
6265
|
+
if (this.hasScopeBoundaries(text)) {
|
|
6266
|
+
strengths.push('Clearly defines scope boundaries and limitations');
|
|
6267
|
+
alignmentScore += 10;
|
|
6268
|
+
}
|
|
6269
|
+
else {
|
|
6270
|
+
gaps.push('Should clearly define scope boundaries for PARTIAL implementation');
|
|
6271
|
+
recommendations.push('Specify exactly which elements are covered and which are not');
|
|
6272
|
+
}
|
|
6273
|
+
languageConsistency = this.assessImplementationLanguage(text);
|
|
6274
|
+
break;
|
|
6275
|
+
case 'facilitates':
|
|
6276
|
+
// Validate FACILITATES claim
|
|
6277
|
+
if (this.hasFacilitationLanguage(text) || actualAnalysis.capabilities.facilitates) {
|
|
6278
|
+
alignmentScore = 80;
|
|
6279
|
+
strengths.push('Contains appropriate facilitation and enablement language');
|
|
6280
|
+
}
|
|
6281
|
+
else {
|
|
6282
|
+
alignmentScore = 40;
|
|
6283
|
+
gaps.push('Lacks clear facilitation language (enables, supports, provides framework)');
|
|
6284
|
+
}
|
|
6285
|
+
// Check that it doesn't claim direct implementation
|
|
6286
|
+
if (this.hasDirectImplementationLanguage(text)) {
|
|
6287
|
+
// Special handling: If it lacks facilitation language AND claims implementation, stay QUESTIONABLE
|
|
6288
|
+
if (alignmentScore <= 40) {
|
|
6289
|
+
alignmentScore = 45; // Keep it in QUESTIONABLE range
|
|
6290
|
+
}
|
|
6291
|
+
else {
|
|
6292
|
+
alignmentScore -= 15;
|
|
6293
|
+
}
|
|
6294
|
+
gaps.push('Claims direct implementation, inconsistent with FACILITATES capability');
|
|
6295
|
+
}
|
|
6296
|
+
languageConsistency = this.assessFacilitationLanguage(text);
|
|
6297
|
+
break;
|
|
6298
|
+
case 'governance':
|
|
6299
|
+
// Validate GOVERNANCE claim
|
|
6300
|
+
if (governancePercentage >= 60 || actualAnalysis.capabilities.governance) {
|
|
6301
|
+
alignmentScore = 85;
|
|
6302
|
+
strengths.push('Strong governance element coverage and policy management language');
|
|
6303
|
+
}
|
|
6304
|
+
else {
|
|
6305
|
+
alignmentScore = Math.max(30, governancePercentage);
|
|
6306
|
+
gaps.push(`Governance element coverage (${Math.round(governancePercentage)}%) below expected threshold (60%)`);
|
|
6307
|
+
}
|
|
6308
|
+
languageConsistency = this.assessGovernanceLanguage(text);
|
|
6309
|
+
break;
|
|
6310
|
+
case 'validates':
|
|
6311
|
+
// Validate VALIDATES claim
|
|
6312
|
+
if (actualAnalysis.capabilities.validates) {
|
|
6313
|
+
alignmentScore = 85;
|
|
6314
|
+
strengths.push('Contains evidence collection and reporting capabilities');
|
|
6315
|
+
}
|
|
6316
|
+
else {
|
|
6317
|
+
alignmentScore = 30;
|
|
6318
|
+
gaps.push('Lacks validation language (audit, report, evidence, verify, monitor)');
|
|
6319
|
+
}
|
|
6320
|
+
languageConsistency = this.assessValidationLanguage(text);
|
|
6321
|
+
break;
|
|
6322
|
+
default:
|
|
6323
|
+
alignmentScore = 0;
|
|
6324
|
+
gaps.push(`Unknown capability type: ${claimedCapability}`);
|
|
6325
|
+
languageConsistency = 0;
|
|
6326
|
+
}
|
|
6327
|
+
// Determine overall status
|
|
6328
|
+
let status;
|
|
6329
|
+
if (alignmentScore >= 70) {
|
|
6330
|
+
status = 'SUPPORTED';
|
|
6331
|
+
}
|
|
6332
|
+
else if (alignmentScore >= 40) {
|
|
6333
|
+
status = 'QUESTIONABLE';
|
|
6334
|
+
}
|
|
6335
|
+
else {
|
|
6336
|
+
status = 'UNSUPPORTED';
|
|
6337
|
+
}
|
|
6338
|
+
// Generate recommendations
|
|
6339
|
+
if (gaps.length > 0) {
|
|
6340
|
+
recommendations.push('Address identified gaps to strengthen capability claim');
|
|
6341
|
+
}
|
|
6342
|
+
if (status === 'QUESTIONABLE') {
|
|
6343
|
+
recommendations.push('Provide additional evidence or clarify scope to support claim');
|
|
6344
|
+
}
|
|
6345
|
+
const feedback = this.generateValidationFeedback(claimedCapability, status, gaps, strengths, alignmentScore);
|
|
6346
|
+
return {
|
|
6347
|
+
status,
|
|
6348
|
+
confidence: Math.round(alignmentScore),
|
|
6349
|
+
languageConsistency: Math.round(languageConsistency),
|
|
6350
|
+
gaps,
|
|
6351
|
+
strengths,
|
|
6352
|
+
recommendations,
|
|
6353
|
+
feedback
|
|
6354
|
+
};
|
|
6355
|
+
}
|
|
6356
|
+
hasFacilitationLanguage(text) {
|
|
6357
|
+
const facilitationPatterns = [
|
|
6358
|
+
'enables', 'facilitates', 'supports', 'helps', 'provides framework',
|
|
6359
|
+
'creates infrastructure', 'enables organizations', 'supports compliance',
|
|
6360
|
+
'provides data', 'enriches', 'supplements', 'feeds data'
|
|
6361
|
+
];
|
|
6362
|
+
return facilitationPatterns.some(pattern => text.includes(pattern));
|
|
6363
|
+
}
|
|
6364
|
+
hasScopeBoundaries(text) {
|
|
6365
|
+
const boundaryPatterns = [
|
|
6366
|
+
'covers', 'but not', 'limited to', 'specifically', 'only', 'excludes',
|
|
6367
|
+
'scope includes', 'scope excludes', 'within', 'applies to'
|
|
6368
|
+
];
|
|
6369
|
+
return boundaryPatterns.some(pattern => text.includes(pattern));
|
|
6370
|
+
}
|
|
6371
|
+
hasDirectImplementationLanguage(text) {
|
|
6372
|
+
const implementationPatterns = [
|
|
6373
|
+
'directly implements', 'performs', 'executes', 'scans', 'catalogs',
|
|
6374
|
+
'inventories', 'manages assets', 'controls access', 'blocks threats'
|
|
6375
|
+
];
|
|
6376
|
+
return implementationPatterns.some(pattern => text.includes(pattern));
|
|
6377
|
+
}
|
|
6378
|
+
assessImplementationLanguage(text) {
|
|
6379
|
+
const implementationKeywords = [
|
|
6380
|
+
'implements', 'performs', 'executes', 'manages', 'controls', 'maintains',
|
|
6381
|
+
'establishes', 'configures', 'monitors', 'tracks', 'inventories'
|
|
6382
|
+
];
|
|
6383
|
+
return this.calculateKeywordScore(text, implementationKeywords) * 100;
|
|
6384
|
+
}
|
|
6385
|
+
assessFacilitationLanguage(text) {
|
|
6386
|
+
const facilitationKeywords = [
|
|
6387
|
+
'enables', 'facilitates', 'supports', 'helps', 'enhances', 'improves',
|
|
6388
|
+
'streamlines', 'automates', 'optimizes', 'provides framework'
|
|
6389
|
+
];
|
|
6390
|
+
return this.calculateKeywordScore(text, facilitationKeywords) * 100;
|
|
6391
|
+
}
|
|
6392
|
+
assessGovernanceLanguage(text) {
|
|
6393
|
+
const governanceKeywords = [
|
|
6394
|
+
'policy', 'governance', 'compliance', 'oversight', 'management',
|
|
6395
|
+
'framework', 'procedures', 'processes', 'controls', 'standards'
|
|
6396
|
+
];
|
|
6397
|
+
return this.calculateKeywordScore(text, governanceKeywords) * 100;
|
|
6398
|
+
}
|
|
6399
|
+
assessValidationLanguage(text) {
|
|
6400
|
+
const validationKeywords = [
|
|
6401
|
+
'audit', 'validate', 'verify', 'report', 'evidence', 'monitor',
|
|
6402
|
+
'assess', 'check', 'review', 'attest', 'compliance', 'compliance tracking',
|
|
6403
|
+
'compliance reports', 'audit capabilities', 'audit trail', 'reporting capabilities'
|
|
6404
|
+
];
|
|
6405
|
+
return this.calculateKeywordScore(text, validationKeywords) * 100;
|
|
6406
|
+
}
|
|
6407
|
+
detectToolType(text) {
|
|
6408
|
+
const lowerText = text.toLowerCase();
|
|
6409
|
+
// Inventory/Asset Management tools
|
|
6410
|
+
const inventoryKeywords = [
|
|
6411
|
+
'asset management', 'inventory', 'cmdb', 'discovery', 'asset discovery',
|
|
6412
|
+
'hardware inventory', 'software inventory', 'device inventory', 'asset tracking',
|
|
6413
|
+
'configuration management database', 'it asset management', 'endpoint discovery'
|
|
6414
|
+
];
|
|
6415
|
+
// Identity/Authentication tools
|
|
6416
|
+
const identityKeywords = [
|
|
6417
|
+
'identity management', 'iam', 'active directory', 'ldap', 'sso', 'single sign-on',
|
|
6418
|
+
'mfa', 'multi-factor', 'authentication', 'identity provider', 'access management',
|
|
6419
|
+
'user management', 'account management', 'directory service'
|
|
6420
|
+
];
|
|
6421
|
+
// Vulnerability Management tools
|
|
6422
|
+
const vulnerabilityKeywords = [
|
|
6423
|
+
'vulnerability scanner', 'vulnerability management', 'patch management',
|
|
6424
|
+
'security scanner', 'vuln scan', 'penetration test', 'security assessment',
|
|
6425
|
+
'scanning capabilities', 'vulnerability scanning', 'network discovery'
|
|
6426
|
+
];
|
|
6427
|
+
// Network Security tools
|
|
6428
|
+
const networkSecurityKeywords = [
|
|
6429
|
+
'firewall', 'network access control', 'nac', 'network security', 'intrusion detection',
|
|
6430
|
+
'network monitoring', 'traffic analysis', 'network segmentation'
|
|
6431
|
+
];
|
|
6432
|
+
// Threat Intelligence/Data Enrichment tools
|
|
6433
|
+
const threatIntelKeywords = [
|
|
6434
|
+
'threat intelligence', 'threat intel', 'threat feed', 'security intelligence',
|
|
6435
|
+
'enrichment', 'data feed', 'contextual data', 'risk intelligence',
|
|
6436
|
+
'cyber threat intelligence', 'ioc feed', 'threat data'
|
|
6437
|
+
];
|
|
6438
|
+
// GRC/Governance tools
|
|
6439
|
+
const governanceKeywords = [
|
|
6440
|
+
'grc', 'governance', 'compliance management', 'policy management',
|
|
6441
|
+
'risk management', 'audit management', 'compliance platform'
|
|
6442
|
+
];
|
|
6443
|
+
// Security Analytics/SIEM tools
|
|
6444
|
+
const analyticsKeywords = [
|
|
6445
|
+
'siem', 'security analytics', 'log management', 'security monitoring',
|
|
6446
|
+
'event correlation', 'security orchestration', 'soar'
|
|
6447
|
+
];
|
|
6448
|
+
// Check for tool type patterns - order by specificity (most specific first)
|
|
6449
|
+
if (threatIntelKeywords.some(keyword => lowerText.includes(keyword))) {
|
|
6450
|
+
return 'threat_intelligence';
|
|
6451
|
+
}
|
|
6452
|
+
else if (vulnerabilityKeywords.some(keyword => lowerText.includes(keyword))) {
|
|
6453
|
+
return 'vulnerability_management';
|
|
6454
|
+
}
|
|
6455
|
+
else if (identityKeywords.some(keyword => lowerText.includes(keyword))) {
|
|
6456
|
+
return 'identity_management';
|
|
6457
|
+
}
|
|
6458
|
+
else if (networkSecurityKeywords.some(keyword => lowerText.includes(keyword))) {
|
|
6459
|
+
return 'network_security';
|
|
6460
|
+
}
|
|
6461
|
+
else if (governanceKeywords.some(keyword => lowerText.includes(keyword))) {
|
|
6462
|
+
return 'governance';
|
|
6463
|
+
}
|
|
6464
|
+
else if (analyticsKeywords.some(keyword => lowerText.includes(keyword))) {
|
|
6465
|
+
return 'security_analytics';
|
|
6466
|
+
}
|
|
6467
|
+
else if (inventoryKeywords.some(keyword => lowerText.includes(keyword))) {
|
|
6468
|
+
return 'inventory';
|
|
6469
|
+
}
|
|
6470
|
+
return 'unknown';
|
|
6471
|
+
}
|
|
6472
|
+
validateDomainMatch(safeguardId, claimedCapability, detectedToolType) {
|
|
6473
|
+
const domainReq = SAFEGUARD_DOMAIN_REQUIREMENTS[safeguardId];
|
|
6474
|
+
if (!domainReq) {
|
|
6475
|
+
return {
|
|
6476
|
+
domain_match: true,
|
|
6477
|
+
required_tool_types: [],
|
|
6478
|
+
should_adjust_capability: false,
|
|
6479
|
+
reasoning: 'No domain restrictions defined for this safeguard'
|
|
6480
|
+
};
|
|
6481
|
+
}
|
|
6482
|
+
const isFullOrPartial = ['full', 'partial'].includes(claimedCapability.toLowerCase());
|
|
6483
|
+
const toolTypeMatches = domainReq.required_tool_types.includes(detectedToolType);
|
|
6484
|
+
if (isFullOrPartial && !toolTypeMatches) {
|
|
6485
|
+
return {
|
|
6486
|
+
domain_match: false,
|
|
6487
|
+
required_tool_types: domainReq.required_tool_types,
|
|
6488
|
+
should_adjust_capability: true,
|
|
6489
|
+
adjusted_capability: 'facilitates',
|
|
6490
|
+
reasoning: `${domainReq.domain} safeguard requires ${domainReq.required_tool_types.join('/')} tool types for FULL/PARTIAL coverage. Detected tool type '${detectedToolType}' can only facilitate implementation.`
|
|
6491
|
+
};
|
|
6492
|
+
}
|
|
6493
|
+
return {
|
|
6494
|
+
domain_match: true,
|
|
6495
|
+
required_tool_types: domainReq.required_tool_types,
|
|
6496
|
+
should_adjust_capability: false,
|
|
6497
|
+
reasoning: toolTypeMatches ?
|
|
6498
|
+
`Tool type '${detectedToolType}' is appropriate for ${domainReq.domain} safeguard` :
|
|
6499
|
+
'No domain validation required for this capability type'
|
|
6500
|
+
};
|
|
6501
|
+
}
|
|
6502
|
+
generateValidationFeedback(claimedCapability, status, gaps, strengths, score) {
|
|
6503
|
+
let feedback = `Validation of ${claimedCapability.toUpperCase()} capability claim: ${status} (${Math.round(score)}% alignment)\n\n`;
|
|
6504
|
+
if (strengths.length > 0) {
|
|
6505
|
+
feedback += `STRENGTHS:\n${strengths.map(s => `• ${s}`).join('\n')}\n\n`;
|
|
6506
|
+
}
|
|
6507
|
+
if (gaps.length > 0) {
|
|
6508
|
+
feedback += `GAPS IDENTIFIED:\n${gaps.map(g => `• ${g}`).join('\n')}\n\n`;
|
|
6509
|
+
}
|
|
6510
|
+
feedback += `ASSESSMENT: `;
|
|
6511
|
+
switch (status) {
|
|
6512
|
+
case 'SUPPORTED':
|
|
6513
|
+
feedback += 'The vendor\'s supporting evidence strongly aligns with their claimed capability.';
|
|
6514
|
+
break;
|
|
6515
|
+
case 'QUESTIONABLE':
|
|
6516
|
+
feedback += 'The vendor\'s evidence partially supports their claim but has notable gaps or inconsistencies.';
|
|
6517
|
+
break;
|
|
6518
|
+
case 'UNSUPPORTED':
|
|
6519
|
+
feedback += 'The vendor\'s evidence does not adequately support their claimed capability.';
|
|
6520
|
+
break;
|
|
6521
|
+
}
|
|
6522
|
+
return feedback;
|
|
6523
|
+
}
|
|
6077
6524
|
async run() {
|
|
6078
6525
|
const transport = new StdioServerTransport();
|
|
6079
6526
|
await this.server.connect(transport);
|