framework-mcp 1.1.2 → 1.2.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/.do/app.yaml +78 -0
- package/CAPABILITY_TRANSFORMATION_SUMMARY.md +158 -0
- package/DAYS_5_6_COMPLETION_SUMMARY.md +178 -0
- package/DEPLOYMENT_GUIDE.md +335 -0
- package/DEPLOYMENT_SUMMARY_v1.1.3.md +211 -0
- package/README.md +34 -35
- package/RELEASE_NOTES_v1.1.3.md +321 -0
- package/RELEASE_NOTES_v1.2.0.md +396 -0
- package/dist/core/capability-analyzer.d.ts +29 -0
- package/dist/core/capability-analyzer.d.ts.map +1 -0
- package/dist/core/capability-analyzer.js +568 -0
- package/dist/core/capability-analyzer.js.map +1 -0
- package/dist/core/safeguard-manager.d.ts +15 -0
- package/dist/core/safeguard-manager.d.ts.map +1 -0
- package/dist/core/safeguard-manager.js +315 -0
- package/dist/core/safeguard-manager.js.map +1 -0
- package/dist/index.d.ts +29 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +609 -403
- package/dist/index.js.map +1 -1
- package/dist/interfaces/http/http-server.d.ts +17 -0
- package/dist/interfaces/http/http-server.d.ts.map +1 -0
- package/dist/interfaces/http/http-server.js +285 -0
- package/dist/interfaces/http/http-server.js.map +1 -0
- package/dist/interfaces/mcp/mcp-server.d.ts +18 -0
- package/dist/interfaces/mcp/mcp-server.d.ts.map +1 -0
- package/dist/interfaces/mcp/mcp-server.js +299 -0
- package/dist/interfaces/mcp/mcp-server.js.map +1 -0
- package/dist/shared/types.d.ts +89 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +3 -0
- package/dist/shared/types.js.map +1 -0
- package/package.json +17 -6
- package/src/core/capability-analyzer.ts +708 -0
- package/src/core/safeguard-manager.ts +339 -0
- package/src/index.ts +722 -461
- package/src/interfaces/http/http-server.ts +360 -0
- package/src/interfaces/mcp/mcp-server.ts +367 -0
- package/src/shared/types.ts +104 -0
- package/test_capability_integration.js +73 -0
- package/test_comprehensive_scenarios.js +192 -0
- package/test_enhanced_detection.js +74 -0
- package/test_integrated_validation.js +112 -0
- package/test_language_update.js +101 -0
- package/test_live_validation.json +12 -0
- package/test_performance_monitoring.js +124 -0
- package/test_runner_automated.js +156 -0
- package/test_suite_comprehensive.js +218 -0
package/dist/index.js
CHANGED
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
// Re-export the MCP server for backward compatibility
|
|
3
|
+
import { FrameworkMcpServer } from './interfaces/mcp/mcp-server.js';
|
|
4
|
+
// Start MCP server if this file is run directly
|
|
5
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
6
|
+
const server = new FrameworkMcpServer();
|
|
7
|
+
server.run().catch(console.error);
|
|
8
|
+
}
|
|
9
|
+
export { FrameworkMcpServer } from './interfaces/mcp/mcp-server.js';
|
|
10
|
+
export { FrameworkHttpServer } from './interfaces/http/http-server.js';
|
|
11
|
+
export { CapabilityAnalyzer } from './core/capability-analyzer.js';
|
|
12
|
+
export { SafeguardManager } from './core/safeguard-manager.js';
|
|
13
|
+
// Legacy compatibility - keep the original massive implementation for reference
|
|
14
|
+
// This will be removed in a future version once migration is complete
|
|
2
15
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
16
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
17
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
@@ -7,27 +20,27 @@ const SAFEGUARD_DOMAIN_REQUIREMENTS = {
|
|
|
7
20
|
"1.1": {
|
|
8
21
|
domain: "Asset Inventory",
|
|
9
22
|
required_tool_types: ["inventory", "asset_management", "cmdb", "discovery"],
|
|
10
|
-
description: "Only asset inventory and discovery tools can provide FULL/PARTIAL
|
|
23
|
+
description: "Only asset inventory and discovery tools can provide FULL/PARTIAL implementation capability"
|
|
11
24
|
},
|
|
12
25
|
"1.2": {
|
|
13
26
|
domain: "Asset Management",
|
|
14
27
|
required_tool_types: ["inventory", "asset_management", "network_security", "nac"],
|
|
15
|
-
description: "Asset management or network access control tools required for FULL/PARTIAL"
|
|
28
|
+
description: "Asset management or network access control tools required for FULL/PARTIAL implementation capability"
|
|
16
29
|
},
|
|
17
30
|
"5.1": {
|
|
18
31
|
domain: "Account Management",
|
|
19
32
|
required_tool_types: ["identity_management", "iam", "directory", "account_management"],
|
|
20
|
-
description: "Identity and account management tools required for FULL/PARTIAL"
|
|
33
|
+
description: "Identity and account management tools required for FULL/PARTIAL implementation capability"
|
|
21
34
|
},
|
|
22
35
|
"6.3": {
|
|
23
36
|
domain: "Authentication",
|
|
24
37
|
required_tool_types: ["mfa", "authentication", "identity_management", "iam"],
|
|
25
|
-
description: "Multi-factor authentication and identity tools required for FULL/PARTIAL"
|
|
38
|
+
description: "Multi-factor authentication and identity tools required for FULL/PARTIAL implementation capability"
|
|
26
39
|
},
|
|
27
40
|
"7.1": {
|
|
28
41
|
domain: "Vulnerability Management",
|
|
29
42
|
required_tool_types: ["vulnerability_management", "vulnerability_scanner", "patch_management"],
|
|
30
|
-
description: "Vulnerability management and scanning tools required for FULL/PARTIAL"
|
|
43
|
+
description: "Vulnerability management and scanning tools required for FULL/PARTIAL implementation capability"
|
|
31
44
|
}
|
|
32
45
|
};
|
|
33
46
|
// Enhanced CIS Controls Framework Data with color-coded categorization
|
|
@@ -5462,6 +5475,19 @@ const CIS_SAFEGUARDS = {
|
|
|
5462
5475
|
};
|
|
5463
5476
|
export class GRCAnalysisServer {
|
|
5464
5477
|
constructor() {
|
|
5478
|
+
// Performance monitoring and caching
|
|
5479
|
+
this.performanceMetrics = {
|
|
5480
|
+
toolExecutionTimes: new Map(),
|
|
5481
|
+
startTime: Date.now(),
|
|
5482
|
+
totalRequests: 0,
|
|
5483
|
+
errorCount: 0
|
|
5484
|
+
};
|
|
5485
|
+
// Simple cache for safeguard details (most commonly requested data)
|
|
5486
|
+
this.cache = {
|
|
5487
|
+
safeguardDetails: new Map(),
|
|
5488
|
+
safeguardList: null,
|
|
5489
|
+
lastCacheCleanup: Date.now()
|
|
5490
|
+
};
|
|
5465
5491
|
this.server = new Server({
|
|
5466
5492
|
name: 'framework-mcp',
|
|
5467
5493
|
version: '1.0.0',
|
|
@@ -5473,7 +5499,7 @@ export class GRCAnalysisServer {
|
|
|
5473
5499
|
tools: [
|
|
5474
5500
|
{
|
|
5475
5501
|
name: 'analyze_vendor_response',
|
|
5476
|
-
description: 'Analyze a vendor response
|
|
5502
|
+
description: 'Analyze a vendor response to determine their tool capability role (Full Implementation, Partial Implementation, Facilitates, Governance, or Validates) for a specific CIS Control safeguard',
|
|
5477
5503
|
inputSchema: {
|
|
5478
5504
|
type: 'object',
|
|
5479
5505
|
properties: {
|
|
@@ -5488,7 +5514,7 @@ export class GRCAnalysisServer {
|
|
|
5488
5514
|
},
|
|
5489
5515
|
response_text: {
|
|
5490
5516
|
type: 'string',
|
|
5491
|
-
description: 'Vendor response text
|
|
5517
|
+
description: 'Vendor response text describing their tool capabilities for the safeguard'
|
|
5492
5518
|
}
|
|
5493
5519
|
},
|
|
5494
5520
|
required: ['vendor_name', 'safeguard_id', 'response_text']
|
|
@@ -5516,7 +5542,7 @@ export class GRCAnalysisServer {
|
|
|
5516
5542
|
},
|
|
5517
5543
|
{
|
|
5518
5544
|
name: 'validate_coverage_claim',
|
|
5519
|
-
description: 'Validate a vendor\'s
|
|
5545
|
+
description: 'Validate a vendor\'s implementation capability claim (FULL/PARTIAL) against specific safeguard requirements and evidence quality',
|
|
5520
5546
|
inputSchema: {
|
|
5521
5547
|
type: 'object',
|
|
5522
5548
|
properties: {
|
|
@@ -5532,16 +5558,16 @@ export class GRCAnalysisServer {
|
|
|
5532
5558
|
coverage_claim: {
|
|
5533
5559
|
type: 'string',
|
|
5534
5560
|
enum: ['FULL', 'PARTIAL'],
|
|
5535
|
-
description: 'Vendor\'s
|
|
5561
|
+
description: 'Vendor\'s implementation capability claim (FULL = complete implementation, PARTIAL = limited scope implementation)'
|
|
5536
5562
|
},
|
|
5537
5563
|
response_text: {
|
|
5538
5564
|
type: 'string',
|
|
5539
|
-
description: 'Vendor response explaining their
|
|
5565
|
+
description: 'Vendor response explaining their implementation capabilities'
|
|
5540
5566
|
},
|
|
5541
5567
|
capabilities: {
|
|
5542
5568
|
type: 'array',
|
|
5543
5569
|
items: { type: 'string' },
|
|
5544
|
-
description: 'List of vendor
|
|
5570
|
+
description: 'List of additional vendor capability types (Governance, Facilitates, Validates)'
|
|
5545
5571
|
}
|
|
5546
5572
|
},
|
|
5547
5573
|
required: ['vendor_name', 'safeguard_id', 'coverage_claim', 'response_text', 'capabilities']
|
|
@@ -5568,7 +5594,7 @@ export class GRCAnalysisServer {
|
|
|
5568
5594
|
},
|
|
5569
5595
|
{
|
|
5570
5596
|
name: 'validate_vendor_mapping',
|
|
5571
|
-
description: 'Validate whether a vendor\'s
|
|
5597
|
+
description: 'Validate whether a vendor\'s claimed capability role (Full Implementation/Partial Implementation/Facilitates/Governance/Validates) is actually supported by their supporting evidence for a specific CIS safeguard',
|
|
5572
5598
|
inputSchema: {
|
|
5573
5599
|
type: 'object',
|
|
5574
5600
|
properties: {
|
|
@@ -5585,11 +5611,11 @@ export class GRCAnalysisServer {
|
|
|
5585
5611
|
claimed_capability: {
|
|
5586
5612
|
type: 'string',
|
|
5587
5613
|
enum: ['full', 'partial', 'facilitates', 'governance', 'validates'],
|
|
5588
|
-
description: 'Vendor\'s claimed capability
|
|
5614
|
+
description: 'Vendor\'s claimed capability role: full (complete implementation), partial (limited implementation), facilitates (enables/enhances), governance (policies/processes), validates (evidence/reporting)'
|
|
5589
5615
|
},
|
|
5590
5616
|
supporting_text: {
|
|
5591
5617
|
type: 'string',
|
|
5592
|
-
description: 'Vendor\'s supporting
|
|
5618
|
+
description: 'Vendor\'s supporting evidence explaining how their tool fulfills the claimed capability role'
|
|
5593
5619
|
}
|
|
5594
5620
|
},
|
|
5595
5621
|
required: ['safeguard_id', 'claimed_capability', 'supporting_text']
|
|
@@ -5599,28 +5625,45 @@ export class GRCAnalysisServer {
|
|
|
5599
5625
|
}));
|
|
5600
5626
|
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
5601
5627
|
const { name, arguments: args } = request.params;
|
|
5628
|
+
const startTime = Date.now();
|
|
5602
5629
|
try {
|
|
5630
|
+
let result;
|
|
5603
5631
|
switch (name) {
|
|
5604
5632
|
case 'analyze_vendor_response':
|
|
5605
|
-
|
|
5633
|
+
result = await this.analyzeVendorResponse(args);
|
|
5634
|
+
break;
|
|
5606
5635
|
case 'get_safeguard_details':
|
|
5607
|
-
|
|
5636
|
+
result = await this.getSafeguardDetails(args);
|
|
5637
|
+
break;
|
|
5608
5638
|
case 'validate_coverage_claim':
|
|
5609
|
-
|
|
5639
|
+
result = await this.validateCoverageClaim(args);
|
|
5640
|
+
break;
|
|
5610
5641
|
case 'list_available_safeguards':
|
|
5611
|
-
|
|
5642
|
+
result = await this.listAvailableSafeguards(args);
|
|
5643
|
+
break;
|
|
5612
5644
|
case 'validate_vendor_mapping':
|
|
5613
|
-
|
|
5645
|
+
result = await this.validateVendorMapping(args);
|
|
5646
|
+
break;
|
|
5614
5647
|
default:
|
|
5615
5648
|
throw new Error(`Unknown tool: ${name}`);
|
|
5616
5649
|
}
|
|
5650
|
+
// Record successful execution time
|
|
5651
|
+
const executionTime = Date.now() - startTime;
|
|
5652
|
+
this.recordToolExecution(name, executionTime);
|
|
5653
|
+
return result;
|
|
5617
5654
|
}
|
|
5618
5655
|
catch (error) {
|
|
5656
|
+
// Record error and performance metrics
|
|
5657
|
+
this.performanceMetrics.errorCount++;
|
|
5658
|
+
const executionTime = Date.now() - startTime;
|
|
5659
|
+
this.recordToolExecution(`${name}_error`, executionTime);
|
|
5660
|
+
const errorMessage = this.formatErrorMessage(error, name);
|
|
5661
|
+
console.error(`[FrameworkMCP] Tool execution error: ${name}`, error);
|
|
5619
5662
|
return {
|
|
5620
5663
|
content: [
|
|
5621
5664
|
{
|
|
5622
5665
|
type: 'text',
|
|
5623
|
-
text:
|
|
5666
|
+
text: errorMessage,
|
|
5624
5667
|
},
|
|
5625
5668
|
],
|
|
5626
5669
|
};
|
|
@@ -5629,10 +5672,14 @@ export class GRCAnalysisServer {
|
|
|
5629
5672
|
}
|
|
5630
5673
|
async getSafeguardDetails(args) {
|
|
5631
5674
|
const { safeguard_id, include_examples = true } = args;
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5675
|
+
// Input validation
|
|
5676
|
+
this.validateSafeguardId(safeguard_id);
|
|
5677
|
+
// Check cache first
|
|
5678
|
+
const cached = this.getCachedSafeguardDetails(safeguard_id, include_examples);
|
|
5679
|
+
if (cached) {
|
|
5680
|
+
return cached;
|
|
5635
5681
|
}
|
|
5682
|
+
const safeguard = CIS_SAFEGUARDS[safeguard_id];
|
|
5636
5683
|
const result = {
|
|
5637
5684
|
...safeguard,
|
|
5638
5685
|
elementBreakdown: {
|
|
@@ -5660,7 +5707,7 @@ export class GRCAnalysisServer {
|
|
|
5660
5707
|
})
|
|
5661
5708
|
}
|
|
5662
5709
|
};
|
|
5663
|
-
|
|
5710
|
+
const response = {
|
|
5664
5711
|
content: [
|
|
5665
5712
|
{
|
|
5666
5713
|
type: 'text',
|
|
@@ -5668,9 +5715,19 @@ export class GRCAnalysisServer {
|
|
|
5668
5715
|
},
|
|
5669
5716
|
],
|
|
5670
5717
|
};
|
|
5718
|
+
// Cache the result for future requests
|
|
5719
|
+
this.setCachedSafeguardDetails(safeguard_id, include_examples, response);
|
|
5720
|
+
return response;
|
|
5671
5721
|
}
|
|
5672
5722
|
async listAvailableSafeguards(args) {
|
|
5673
5723
|
const { implementation_group, security_function } = args;
|
|
5724
|
+
// Check cache for complete safeguard list (only if no filters applied)
|
|
5725
|
+
if (!implementation_group && !security_function && this.cache.safeguardList) {
|
|
5726
|
+
const cacheAge = Date.now() - this.cache.safeguardList.timestamp;
|
|
5727
|
+
if (cacheAge < 10 * 60 * 1000) { // 10 minute cache for safeguard list
|
|
5728
|
+
return this.cache.safeguardList.data;
|
|
5729
|
+
}
|
|
5730
|
+
}
|
|
5674
5731
|
let safeguards = Object.values(CIS_SAFEGUARDS);
|
|
5675
5732
|
if (implementation_group) {
|
|
5676
5733
|
safeguards = safeguards.filter(s => s.implementationGroup === implementation_group);
|
|
@@ -5693,7 +5750,7 @@ export class GRCAnalysisServer {
|
|
|
5693
5750
|
securityFunction: s.securityFunction
|
|
5694
5751
|
}))
|
|
5695
5752
|
};
|
|
5696
|
-
|
|
5753
|
+
const response = {
|
|
5697
5754
|
content: [
|
|
5698
5755
|
{
|
|
5699
5756
|
type: 'text',
|
|
@@ -5701,14 +5758,25 @@ export class GRCAnalysisServer {
|
|
|
5701
5758
|
},
|
|
5702
5759
|
],
|
|
5703
5760
|
};
|
|
5761
|
+
// Cache the complete list if no filters were applied
|
|
5762
|
+
if (!implementation_group && !security_function) {
|
|
5763
|
+
this.cache.safeguardList = {
|
|
5764
|
+
data: response,
|
|
5765
|
+
timestamp: Date.now()
|
|
5766
|
+
};
|
|
5767
|
+
}
|
|
5768
|
+
return response;
|
|
5704
5769
|
}
|
|
5705
5770
|
async analyzeVendorResponse(args) {
|
|
5706
5771
|
const { vendor_name, safeguard_id, response_text } = args;
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5772
|
+
// Input validation
|
|
5773
|
+
this.validateSafeguardId(safeguard_id);
|
|
5774
|
+
this.validateTextInput(response_text, 'Response text');
|
|
5775
|
+
if (!vendor_name || typeof vendor_name !== 'string' || vendor_name.trim().length === 0) {
|
|
5776
|
+
throw new Error('Vendor name is required');
|
|
5710
5777
|
}
|
|
5711
|
-
const
|
|
5778
|
+
const safeguard = CIS_SAFEGUARDS[safeguard_id];
|
|
5779
|
+
const analysis = this.performCapabilityAnalysis(vendor_name, safeguard, response_text);
|
|
5712
5780
|
return {
|
|
5713
5781
|
content: [
|
|
5714
5782
|
{
|
|
@@ -5724,7 +5792,7 @@ export class GRCAnalysisServer {
|
|
|
5724
5792
|
if (!safeguard) {
|
|
5725
5793
|
throw new Error(`Safeguard ${safeguard_id} not found`);
|
|
5726
5794
|
}
|
|
5727
|
-
const analysis = this.
|
|
5795
|
+
const analysis = this.performCapabilityAnalysis(vendor_name, safeguard, response_text);
|
|
5728
5796
|
// Validate the coverage claim
|
|
5729
5797
|
const validation = this.validateClaim(coverage_claim, analysis, capabilities, safeguard);
|
|
5730
5798
|
return {
|
|
@@ -5743,163 +5811,242 @@ export class GRCAnalysisServer {
|
|
|
5743
5811
|
],
|
|
5744
5812
|
};
|
|
5745
5813
|
}
|
|
5746
|
-
|
|
5814
|
+
performCapabilityAnalysis(vendorName, safeguard, responseText) {
|
|
5747
5815
|
const text = responseText.toLowerCase();
|
|
5748
|
-
//
|
|
5749
|
-
const
|
|
5816
|
+
// Step 1: Determine what type of capability this tool is claiming
|
|
5817
|
+
const claimedCapability = this.determineClaimedCapability(text, safeguard);
|
|
5818
|
+
// Step 2: Assess how well the tool executes that specific capability type
|
|
5819
|
+
const qualityAssessment = this.assessCapabilityQuality(text, safeguard, claimedCapability);
|
|
5820
|
+
// Step 3: Generate capability-focused analysis
|
|
5821
|
+
return this.generateCapabilityAnalysis(vendorName, safeguard, responseText, claimedCapability, qualityAssessment);
|
|
5822
|
+
}
|
|
5823
|
+
determineClaimedCapability(text, safeguard) {
|
|
5824
|
+
// Capability detection keywords - focused on what the tool DOES, not what elements it covers
|
|
5825
|
+
const governanceIndicators = [
|
|
5750
5826
|
'policy', 'policies', 'manage', 'process', 'workflow', 'governance', 'grc',
|
|
5751
5827
|
'compliance management', 'documented', 'establish', 'maintain', 'procedure',
|
|
5752
5828
|
'control', 'controls', 'framework', 'standard', 'enterprise risk management',
|
|
5753
5829
|
'centralized management', 'oversight'
|
|
5754
5830
|
];
|
|
5755
|
-
const
|
|
5756
|
-
// Technical facilitation (original keywords)
|
|
5831
|
+
const facilitatesIndicators = [
|
|
5757
5832
|
'improve', 'enhance', 'optimize', 'faster', 'better', 'stronger', 'automate',
|
|
5758
5833
|
'streamline', 'efficiency', 'facilitate', 'support', 'enable', 'accelerate',
|
|
5759
5834
|
'api', 'integration', 'data', 'export', 'import', 'sync', 'feed',
|
|
5760
|
-
// Data provision and enrichment
|
|
5761
5835
|
'provides data', 'data source', 'data feeds', 'enrichment', 'data enrichment',
|
|
5762
5836
|
'supplemental data', 'additional data', 'contextual data', 'threat data',
|
|
5763
5837
|
'intelligence feeds', 'data aggregation', 'data collection', 'data gathering',
|
|
5764
5838
|
'feeds data', 'populates', 'informs', 'enriches', 'supplements',
|
|
5765
|
-
// Governance/process facilitation (new keywords for tools like Upolicy)
|
|
5766
5839
|
'enables compliance', 'facilitates implementation', 'supports compliance',
|
|
5767
5840
|
'creates framework', 'enables organizations', 'infrastructure', 'foundation',
|
|
5768
|
-
'compliance infrastructure', 'audit infrastructure', 'policy framework',
|
|
5769
|
-
'enables effective', 'working together', 'comprehensive coverage',
|
|
5770
5841
|
'template', 'templates', 'workflow automation', 'orchestration'
|
|
5771
5842
|
];
|
|
5772
|
-
const
|
|
5843
|
+
const validatesIndicators = [
|
|
5773
5844
|
'audit', 'report', 'evidence', 'verify', 'validate', 'check', 'monitor',
|
|
5774
5845
|
'compliance', 'compliance report', 'assessment', 'logging', 'tracking', 'review', 'attest',
|
|
5775
5846
|
'dashboard', 'metrics', 'analytics', 'visibility', 'alert', 'attestation',
|
|
5776
5847
|
'compliance tracking', 'audit trail', 'reporting capabilities', 'audit capabilities'
|
|
5777
5848
|
];
|
|
5778
|
-
//
|
|
5779
|
-
const
|
|
5780
|
-
|
|
5781
|
-
const
|
|
5782
|
-
const
|
|
5783
|
-
|
|
5784
|
-
const
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
const validatesCapability = validatesScore > 0.3;
|
|
5790
|
-
// Check for specific facilitation patterns (tools that enable/support compliance)
|
|
5791
|
-
const facilitationPatterns = [
|
|
5792
|
-
'enables compliance', 'facilitates implementation', 'creates framework',
|
|
5793
|
-
'policy framework', 'compliance infrastructure', 'audit infrastructure',
|
|
5794
|
-
'enables organizations', 'enables effective', 'working together',
|
|
5795
|
-
'creates the policy framework', 'enables organizations to implement',
|
|
5796
|
-
'facilitates implementation of', 'compliance infrastructure facilitates'
|
|
5797
|
-
];
|
|
5798
|
-
const hasFacilitationPattern = facilitationPatterns.some(pattern => text.includes(pattern));
|
|
5799
|
-
// Check for explicit non-implementation language
|
|
5800
|
-
const nonImplementationPatterns = [
|
|
5801
|
-
'don\'t scan', 'don\'t catalog', 'doesn\'t scan', 'doesn\'t catalog',
|
|
5802
|
-
'not scan', 'not catalog', 'even though we don\'t', 'we don\'t directly',
|
|
5803
|
-
'rather than direct', 'instead of direct'
|
|
5804
|
-
];
|
|
5805
|
-
const hasNonImplementationLanguage = nonImplementationPatterns.some(pattern => text.includes(pattern));
|
|
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;
|
|
5813
|
-
let fullCapability = false;
|
|
5814
|
-
let partialCapability = false;
|
|
5815
|
-
// Full capability: High coverage of core requirements + reasonable sub-element coverage
|
|
5816
|
-
if (corePercentage >= 70 && subElementPercentage >= 50) {
|
|
5817
|
-
fullCapability = true;
|
|
5849
|
+
// Direct implementation indicators (tools that actually perform the safeguard)
|
|
5850
|
+
const implementationIndicators = this.getImplementationIndicators(safeguard.id);
|
|
5851
|
+
// Calculate keyword presence scores
|
|
5852
|
+
const governanceScore = this.calculateKeywordScore(text, governanceIndicators);
|
|
5853
|
+
const facilitatesScore = this.calculateKeywordScore(text, facilitatesIndicators);
|
|
5854
|
+
const validatesScore = this.calculateKeywordScore(text, validatesIndicators);
|
|
5855
|
+
const implementationScore = this.calculateKeywordScore(text, implementationIndicators);
|
|
5856
|
+
// Determine claimed capability based on strongest indicators and patterns
|
|
5857
|
+
if (implementationScore > 0.2 && implementationScore >= Math.max(facilitatesScore, governanceScore, validatesScore)) {
|
|
5858
|
+
// Tool claims to directly implement the safeguard
|
|
5859
|
+
return implementationScore > 0.5 ? 'full' : 'partial';
|
|
5818
5860
|
}
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
partialCapability = true;
|
|
5861
|
+
else if (governanceScore > 0.2 && governanceScore >= Math.max(facilitatesScore, validatesScore)) {
|
|
5862
|
+
return 'governance';
|
|
5822
5863
|
}
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
if (fullCapability) {
|
|
5826
|
-
primaryCapability = 'full';
|
|
5864
|
+
else if (validatesScore > 0.2 && validatesScore >= facilitatesScore) {
|
|
5865
|
+
return 'validates';
|
|
5827
5866
|
}
|
|
5828
|
-
else
|
|
5829
|
-
|
|
5830
|
-
// Prioritize facilitation when:
|
|
5831
|
-
// 1. Clear facilitation language patterns detected, OR
|
|
5832
|
-
// 2. Explicit non-implementation language (tool doesn't directly implement), OR
|
|
5833
|
-
// 3. Facilitates score is substantial AND significantly higher than governance
|
|
5834
|
-
primaryCapability = 'facilitates';
|
|
5867
|
+
else {
|
|
5868
|
+
return 'facilitates';
|
|
5835
5869
|
}
|
|
5836
|
-
|
|
5837
|
-
|
|
5870
|
+
}
|
|
5871
|
+
getImplementationIndicators(safeguardId) {
|
|
5872
|
+
// Return specific indicators for what constitutes direct implementation for each safeguard
|
|
5873
|
+
const implementationMap = {
|
|
5874
|
+
"1.1": ['inventory', 'discovery', 'asset management', 'catalog', 'enumerate', 'scan devices', 'device database'],
|
|
5875
|
+
"1.2": ['unauthorized', 'rogue', 'detect', 'identify unauthorized', 'quarantine', 'block unauthorized'],
|
|
5876
|
+
"5.1": ['account inventory', 'user management', 'identity management', 'account lifecycle', 'user provisioning'],
|
|
5877
|
+
"6.3": ['multi-factor', 'mfa', '2fa', 'authentication', 'two-factor', 'multi-factor authentication'],
|
|
5878
|
+
"7.1": ['vulnerability', 'vuln', 'scanning', 'vulnerability management', 'security testing', 'penetration testing']
|
|
5879
|
+
};
|
|
5880
|
+
return implementationMap[safeguardId] || [];
|
|
5881
|
+
}
|
|
5882
|
+
assessCapabilityQuality(text, safeguard, claimedCapability) {
|
|
5883
|
+
// Assess how well the tool executes the claimed capability type
|
|
5884
|
+
const evidence = [];
|
|
5885
|
+
const gaps = [];
|
|
5886
|
+
// Quality assessment based on capability type
|
|
5887
|
+
let qualityScore = 0;
|
|
5888
|
+
switch (claimedCapability) {
|
|
5889
|
+
case 'full':
|
|
5890
|
+
case 'partial':
|
|
5891
|
+
qualityScore = this.assessImplementationQuality(text, safeguard, evidence, gaps);
|
|
5892
|
+
break;
|
|
5893
|
+
case 'governance':
|
|
5894
|
+
qualityScore = this.assessGovernanceQuality(text, safeguard, evidence, gaps);
|
|
5895
|
+
break;
|
|
5896
|
+
case 'facilitates':
|
|
5897
|
+
qualityScore = this.assessFacilitationQuality(text, safeguard, evidence, gaps);
|
|
5898
|
+
break;
|
|
5899
|
+
case 'validates':
|
|
5900
|
+
qualityScore = this.assessValidationQuality(text, safeguard, evidence, gaps);
|
|
5901
|
+
break;
|
|
5838
5902
|
}
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5903
|
+
// Convert score to quality rating
|
|
5904
|
+
let quality;
|
|
5905
|
+
if (qualityScore >= 0.8)
|
|
5906
|
+
quality = 'excellent';
|
|
5907
|
+
else if (qualityScore >= 0.6)
|
|
5908
|
+
quality = 'good';
|
|
5909
|
+
else if (qualityScore >= 0.4)
|
|
5910
|
+
quality = 'fair';
|
|
5911
|
+
else
|
|
5912
|
+
quality = 'poor';
|
|
5913
|
+
return {
|
|
5914
|
+
quality,
|
|
5915
|
+
confidence: Math.round(qualityScore * 100),
|
|
5916
|
+
evidence: evidence.slice(0, 5), // Top 5 pieces of evidence
|
|
5917
|
+
gaps: gaps.slice(0, 3) // Top 3 gaps identified
|
|
5918
|
+
};
|
|
5919
|
+
}
|
|
5920
|
+
assessImplementationQuality(text, safeguard, evidence, gaps) {
|
|
5921
|
+
// Assess quality of direct implementation capability
|
|
5922
|
+
const implementationIndicators = this.getImplementationIndicators(safeguard.id);
|
|
5923
|
+
let score = 0;
|
|
5924
|
+
// Check for strong implementation language
|
|
5925
|
+
const strongIndicators = implementationIndicators.filter(indicator => text.includes(indicator.toLowerCase()));
|
|
5926
|
+
if (strongIndicators.length > 0) {
|
|
5927
|
+
score += 0.4;
|
|
5928
|
+
evidence.push(`Strong implementation indicators: ${strongIndicators.join(', ')}`);
|
|
5929
|
+
}
|
|
5930
|
+
// Check for comprehensive functionality description
|
|
5931
|
+
if (text.includes('comprehensive') || text.includes('complete') || text.includes('full')) {
|
|
5932
|
+
score += 0.2;
|
|
5933
|
+
evidence.push('Claims comprehensive functionality');
|
|
5934
|
+
}
|
|
5935
|
+
// Check for automated vs manual implementation
|
|
5936
|
+
if (text.includes('automat') || text.includes('real-time') || text.includes('continuous')) {
|
|
5937
|
+
score += 0.2;
|
|
5938
|
+
evidence.push('Automated implementation capability');
|
|
5842
5939
|
}
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5940
|
+
// Identify potential gaps
|
|
5941
|
+
if (strongIndicators.length === 0) {
|
|
5942
|
+
gaps.push('No clear implementation indicators found');
|
|
5846
5943
|
}
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5944
|
+
return Math.min(score, 1.0);
|
|
5945
|
+
}
|
|
5946
|
+
assessGovernanceQuality(text, safeguard, evidence, gaps) {
|
|
5947
|
+
const governanceIndicators = ['policy', 'process', 'governance', 'compliance', 'documentation', 'oversight'];
|
|
5948
|
+
let score = 0;
|
|
5949
|
+
const foundIndicators = governanceIndicators.filter(indicator => text.includes(indicator));
|
|
5950
|
+
if (foundIndicators.length >= 3) {
|
|
5951
|
+
score += 0.5;
|
|
5952
|
+
evidence.push(`Strong governance capability: ${foundIndicators.join(', ')}`);
|
|
5953
|
+
}
|
|
5954
|
+
if (text.includes('documented') && text.includes('process')) {
|
|
5955
|
+
score += 0.3;
|
|
5956
|
+
evidence.push('Documented process management');
|
|
5957
|
+
}
|
|
5958
|
+
return Math.min(score, 1.0);
|
|
5959
|
+
}
|
|
5960
|
+
assessFacilitationQuality(text, safeguard, evidence, gaps) {
|
|
5961
|
+
const facilitationIndicators = ['enhance', 'enable', 'support', 'facilitate', 'improve', 'optimize'];
|
|
5962
|
+
let score = 0;
|
|
5963
|
+
const foundIndicators = facilitationIndicators.filter(indicator => text.includes(indicator));
|
|
5964
|
+
if (foundIndicators.length >= 2) {
|
|
5965
|
+
score += 0.4;
|
|
5966
|
+
evidence.push(`Clear facilitation capability: ${foundIndicators.join(', ')}`);
|
|
5850
5967
|
}
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5968
|
+
return Math.min(score, 1.0);
|
|
5969
|
+
}
|
|
5970
|
+
assessValidationQuality(text, safeguard, evidence, gaps) {
|
|
5971
|
+
const validationIndicators = ['audit', 'report', 'monitor', 'track', 'verify', 'validate'];
|
|
5972
|
+
let score = 0;
|
|
5973
|
+
const foundIndicators = validationIndicators.filter(indicator => text.includes(indicator));
|
|
5974
|
+
if (foundIndicators.length >= 2) {
|
|
5975
|
+
score += 0.4;
|
|
5976
|
+
evidence.push(`Strong validation capability: ${foundIndicators.join(', ')}`);
|
|
5854
5977
|
}
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
const totalCoreAndSubElements = safeguard.coreRequirements.length + safeguard.subTaxonomicalElements.length;
|
|
5860
|
-
const coveredCoreAndSubElements = coreCoverage.coveredElements.length + subElementCoverage.coveredElements.length;
|
|
5861
|
-
const coverageConfidence = totalCoreAndSubElements > 0 ?
|
|
5862
|
-
coveredCoreAndSubElements / totalCoreAndSubElements : 0;
|
|
5863
|
-
const confidence = Math.min((keywordConfidence * 0.4 + coverageConfidence * 0.6) * 100, 100);
|
|
5978
|
+
return Math.min(score, 1.0);
|
|
5979
|
+
}
|
|
5980
|
+
generateCapabilityAnalysis(vendorName, safeguard, responseText, claimedCapability, qualityAssessment) {
|
|
5981
|
+
// Generate the new capability-focused analysis result
|
|
5864
5982
|
return {
|
|
5865
5983
|
vendor: vendorName,
|
|
5866
5984
|
safeguardId: safeguard.id,
|
|
5867
5985
|
safeguardTitle: safeguard.title,
|
|
5868
|
-
capability:
|
|
5986
|
+
capability: claimedCapability,
|
|
5869
5987
|
capabilities: {
|
|
5870
|
-
full:
|
|
5871
|
-
partial:
|
|
5872
|
-
facilitates:
|
|
5873
|
-
governance:
|
|
5874
|
-
validates:
|
|
5875
|
-
},
|
|
5876
|
-
confidence: Math.round(confidence),
|
|
5877
|
-
reasoning: this.generateCapabilityReasoning(primaryCapability, fullCapability, partialCapability, governanceCapability, facilitatesCapability, validatesCapability, coreCoverage, subElementCoverage, safeguard, hasFacilitationPattern, hasNonImplementationLanguage),
|
|
5878
|
-
evidence,
|
|
5879
|
-
elementsCovered: {
|
|
5880
|
-
coreRequirements: coreCoverage.coveredElements,
|
|
5881
|
-
subTaxonomicalElements: subElementCoverage.coveredElements,
|
|
5882
|
-
governanceElements: governanceCoverage.coveredElements,
|
|
5883
|
-
implementationMethods: implementationCoverage.coveredElements
|
|
5988
|
+
full: claimedCapability === 'full',
|
|
5989
|
+
partial: claimedCapability === 'partial',
|
|
5990
|
+
facilitates: claimedCapability === 'facilitates',
|
|
5991
|
+
governance: claimedCapability === 'governance',
|
|
5992
|
+
validates: claimedCapability === 'validates'
|
|
5884
5993
|
},
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5994
|
+
confidence: qualityAssessment.confidence,
|
|
5995
|
+
reasoning: this.generateCapabilityReasoning(claimedCapability, qualityAssessment, safeguard),
|
|
5996
|
+
evidence: qualityAssessment.evidence,
|
|
5997
|
+
// Note: elementsCovered is now less relevant in capability-focused analysis
|
|
5998
|
+
// We focus on tool capability rather than element coverage
|
|
5999
|
+
toolCapabilityDescription: this.generateToolCapabilityDescription(claimedCapability, qualityAssessment),
|
|
6000
|
+
recommendedUse: this.generateRecommendedUse(claimedCapability, safeguard)
|
|
6001
|
+
};
|
|
6002
|
+
}
|
|
6003
|
+
generateCapabilityReasoning(claimedCapability, qualityAssessment, safeguard) {
|
|
6004
|
+
const capabilityDescriptions = {
|
|
6005
|
+
full: "directly implements the core functionality of this safeguard",
|
|
6006
|
+
partial: "implements limited aspects of this safeguard with clear scope boundaries",
|
|
6007
|
+
facilitates: "enhances or enables the implementation of this safeguard by others",
|
|
6008
|
+
governance: "provides governance, policy, and oversight capabilities for this safeguard",
|
|
6009
|
+
validates: "provides evidence, audit, and compliance validation for this safeguard"
|
|
6010
|
+
};
|
|
6011
|
+
const qualityDescriptor = qualityAssessment.quality;
|
|
6012
|
+
const description = capabilityDescriptions[claimedCapability];
|
|
6013
|
+
return `This tool ${description} with ${qualityDescriptor} capability quality. ${qualityAssessment.evidence.length > 0 ? 'Evidence: ' + qualityAssessment.evidence.join('; ') : ''}`;
|
|
6014
|
+
}
|
|
6015
|
+
generateToolCapabilityDescription(claimedCapability, qualityAssessment) {
|
|
6016
|
+
const roleDescriptions = {
|
|
6017
|
+
full: "Core Implementation Tool - Directly performs the safeguard functionality",
|
|
6018
|
+
partial: "Focused Implementation Tool - Performs specific aspects of the safeguard",
|
|
6019
|
+
facilitates: "Enablement Tool - Helps organizations implement the safeguard more effectively",
|
|
6020
|
+
governance: "Governance Tool - Manages policies, processes, and oversight for the safeguard",
|
|
6021
|
+
validates: "Compliance Tool - Provides audit, evidence, and validation capabilities"
|
|
6022
|
+
};
|
|
6023
|
+
return roleDescriptions[claimedCapability] || "Support Tool";
|
|
6024
|
+
}
|
|
6025
|
+
generateRecommendedUse(claimedCapability, safeguard) {
|
|
6026
|
+
const recommendations = {
|
|
6027
|
+
full: `Use as primary implementation tool for ${safeguard.title}. Ensure proper configuration and integration.`,
|
|
6028
|
+
partial: `Use as part of a multi-tool strategy for ${safeguard.title}. Supplement with additional capabilities as needed.`,
|
|
6029
|
+
facilitates: `Use to enhance existing safeguard implementation. Combine with direct implementation tools.`,
|
|
6030
|
+
governance: `Use for policy management and governance oversight. Pair with implementation and validation tools.`,
|
|
6031
|
+
validates: `Use for compliance monitoring and evidence collection. Combine with implementation tools for complete coverage.`
|
|
5889
6032
|
};
|
|
6033
|
+
return recommendations[claimedCapability] || "Evaluate specific use case alignment.";
|
|
5890
6034
|
}
|
|
5891
6035
|
calculateKeywordScore(text, keywords) {
|
|
5892
|
-
let
|
|
5893
|
-
let
|
|
6036
|
+
let matchedKeywords = 0;
|
|
6037
|
+
let totalMatches = 0;
|
|
5894
6038
|
keywords.forEach(keyword => {
|
|
5895
6039
|
const regex = new RegExp(keyword.replace(/\s+/g, '\\s+'), 'gi');
|
|
5896
6040
|
const keywordMatches = (text.match(regex) || []).length;
|
|
5897
6041
|
if (keywordMatches > 0) {
|
|
5898
|
-
|
|
5899
|
-
|
|
6042
|
+
matchedKeywords++;
|
|
6043
|
+
totalMatches += keywordMatches;
|
|
5900
6044
|
}
|
|
5901
6045
|
});
|
|
5902
|
-
|
|
6046
|
+
// Return percentage of keywords that were found, with bonus for multiple matches
|
|
6047
|
+
const baseScore = matchedKeywords / keywords.length;
|
|
6048
|
+
const matchBonus = Math.min(totalMatches * 0.1, 0.5); // Up to 50% bonus for multiple matches
|
|
6049
|
+
return Math.min(baseScore + matchBonus, 1.0);
|
|
5903
6050
|
}
|
|
5904
6051
|
analyzeElementCoverage(text, elements) {
|
|
5905
6052
|
const coveredElements = [];
|
|
@@ -6009,63 +6156,6 @@ export class GRCAnalysisServer {
|
|
|
6009
6156
|
}
|
|
6010
6157
|
return reasons.join('. ');
|
|
6011
6158
|
}
|
|
6012
|
-
generateCapabilityReasoning(primaryCapability, full, partial, governance, facilitates, validates, coreCoverage, subElementCoverage, safeguard, hasFacilitationPattern = false, hasNonImplementationLanguage = false) {
|
|
6013
|
-
const reasons = [];
|
|
6014
|
-
// Primary capability explanation
|
|
6015
|
-
switch (primaryCapability) {
|
|
6016
|
-
case 'full':
|
|
6017
|
-
reasons.push(`Provides FULL coverage of ${safeguard.title} - directly implements all core and sub-taxonomical elements`);
|
|
6018
|
-
break;
|
|
6019
|
-
case 'partial':
|
|
6020
|
-
reasons.push(`Provides PARTIAL coverage of ${safeguard.title} - directly implements some but not all core and sub-taxonomical elements`);
|
|
6021
|
-
break;
|
|
6022
|
-
case 'facilitates':
|
|
6023
|
-
if (hasFacilitationPattern || hasNonImplementationLanguage || governance) {
|
|
6024
|
-
reasons.push(`FACILITATES ${safeguard.title} by creating governance frameworks, policy infrastructure, and compliance processes that enable organizations to implement the control effectively`);
|
|
6025
|
-
}
|
|
6026
|
-
else {
|
|
6027
|
-
reasons.push(`FACILITATES ${safeguard.title} through data integration, automation, or technical capabilities that support implementation`);
|
|
6028
|
-
}
|
|
6029
|
-
break;
|
|
6030
|
-
case 'governance':
|
|
6031
|
-
reasons.push(`Provides GOVERNANCE capabilities for ${safeguard.title} through centralized policy management, process controls, and compliance oversight`);
|
|
6032
|
-
break;
|
|
6033
|
-
case 'validates':
|
|
6034
|
-
reasons.push(`VALIDATES ${safeguard.title} implementation through evidence collection, compliance reporting, and audit capabilities`);
|
|
6035
|
-
break;
|
|
6036
|
-
default:
|
|
6037
|
-
reasons.push(`No clear capability identified for ${safeguard.title}`);
|
|
6038
|
-
}
|
|
6039
|
-
// Coverage details
|
|
6040
|
-
if (coreCoverage.coveredElements.length > 0) {
|
|
6041
|
-
reasons.push(`Core elements addressed: ${coreCoverage.coveredElements.length}/${safeguard.coreRequirements.length}`);
|
|
6042
|
-
}
|
|
6043
|
-
if (subElementCoverage.coveredElements.length > 0) {
|
|
6044
|
-
reasons.push(`Sub-taxonomical elements addressed: ${subElementCoverage.coveredElements.length}/${safeguard.subTaxonomicalElements.length}`);
|
|
6045
|
-
}
|
|
6046
|
-
// Additional context for facilitation tools
|
|
6047
|
-
if (primaryCapability === 'facilitates') {
|
|
6048
|
-
if (hasFacilitationPattern || hasNonImplementationLanguage || governance) {
|
|
6049
|
-
reasons.push(`Note: This type of facilitation tool works alongside technical implementation solutions (asset scanners, MDM tools, etc.) to provide comprehensive control coverage`);
|
|
6050
|
-
}
|
|
6051
|
-
if (hasNonImplementationLanguage) {
|
|
6052
|
-
reasons.push(`Tool explicitly enables compliance through governance/process rather than direct technical implementation`);
|
|
6053
|
-
}
|
|
6054
|
-
}
|
|
6055
|
-
// Multi-capability products
|
|
6056
|
-
const capabilityFlags = [governance, facilitates, validates].filter(Boolean);
|
|
6057
|
-
if (capabilityFlags.length > 1) {
|
|
6058
|
-
const capabilities = [];
|
|
6059
|
-
if (governance)
|
|
6060
|
-
capabilities.push('governance');
|
|
6061
|
-
if (facilitates)
|
|
6062
|
-
capabilities.push('facilitates');
|
|
6063
|
-
if (validates)
|
|
6064
|
-
capabilities.push('validates');
|
|
6065
|
-
reasons.push(`Multi-capability product with: ${capabilities.join(', ')}`);
|
|
6066
|
-
}
|
|
6067
|
-
return reasons.join('. ');
|
|
6068
|
-
}
|
|
6069
6159
|
validateClaim(claim, analysis, capabilities, safeguard) {
|
|
6070
6160
|
const validation = {
|
|
6071
6161
|
coverageClaimValid: false,
|
|
@@ -6078,16 +6168,14 @@ export class GRCAnalysisServer {
|
|
|
6078
6168
|
const meetsFullCriteria = analysis.capabilities.full;
|
|
6079
6169
|
validation.coverageClaimValid = meetsFullCriteria;
|
|
6080
6170
|
if (!meetsFullCriteria) {
|
|
6081
|
-
|
|
6082
|
-
const coveredElements = analysis.elementsCovered.coreRequirements.length + analysis.elementsCovered.subTaxonomicalElements.length;
|
|
6083
|
-
validation.gaps.push(`FULL coverage claim not supported: Only ${coveredElements}/${totalElements} core and sub-taxonomical elements covered`);
|
|
6171
|
+
validation.gaps.push(`FULL implementation capability claim not supported: Tool does not demonstrate direct implementation of core safeguard functionality`);
|
|
6084
6172
|
}
|
|
6085
6173
|
}
|
|
6086
6174
|
else if (claim === 'PARTIAL') {
|
|
6087
6175
|
const meetsPartialCriteria = analysis.capabilities.partial || analysis.capabilities.full;
|
|
6088
6176
|
validation.coverageClaimValid = meetsPartialCriteria;
|
|
6089
6177
|
if (!meetsPartialCriteria) {
|
|
6090
|
-
validation.gaps.push(`PARTIAL
|
|
6178
|
+
validation.gaps.push(`PARTIAL implementation capability claim questionable: No core or sub-taxonomical elements clearly addressed`);
|
|
6091
6179
|
}
|
|
6092
6180
|
}
|
|
6093
6181
|
// Validate capability claims
|
|
@@ -6131,12 +6219,18 @@ export class GRCAnalysisServer {
|
|
|
6131
6219
|
}
|
|
6132
6220
|
else {
|
|
6133
6221
|
validation.recommendations.push(`Consider requesting additional information about: ${validation.gaps.join(', ')}`);
|
|
6134
|
-
//
|
|
6135
|
-
if (analysis.
|
|
6136
|
-
validation.recommendations.push(
|
|
6222
|
+
// Capability-based recommendations
|
|
6223
|
+
if (analysis.capability === 'facilitates') {
|
|
6224
|
+
validation.recommendations.push('Consider pairing with direct implementation tools for complete safeguard coverage');
|
|
6225
|
+
}
|
|
6226
|
+
else if (analysis.capability === 'partial') {
|
|
6227
|
+
validation.recommendations.push('Evaluate scope limitations and identify complementary tools for full coverage');
|
|
6137
6228
|
}
|
|
6138
|
-
if (analysis.
|
|
6139
|
-
validation.recommendations.push(
|
|
6229
|
+
else if (analysis.capability === 'governance') {
|
|
6230
|
+
validation.recommendations.push('Combine with technical implementation tools for complete safeguard execution');
|
|
6231
|
+
}
|
|
6232
|
+
else if (analysis.capability === 'validates') {
|
|
6233
|
+
validation.recommendations.push('Pair with implementation tools to ensure both execution and validation coverage');
|
|
6140
6234
|
}
|
|
6141
6235
|
if (!analysis.capabilities.validates && capabilities.includes('Validates')) {
|
|
6142
6236
|
validation.recommendations.push(`Request examples of audit trails, reporting capabilities, and compliance evidence`);
|
|
@@ -6146,10 +6240,11 @@ export class GRCAnalysisServer {
|
|
|
6146
6240
|
}
|
|
6147
6241
|
async validateVendorMapping(args) {
|
|
6148
6242
|
const { vendor_name = 'Unknown Vendor', safeguard_id, claimed_capability, supporting_text } = args;
|
|
6243
|
+
// Input validation
|
|
6244
|
+
this.validateSafeguardId(safeguard_id);
|
|
6245
|
+
this.validateTextInput(supporting_text, 'Supporting text');
|
|
6246
|
+
this.validateCapability(claimed_capability);
|
|
6149
6247
|
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
6248
|
const validation = this.validateCapabilityClaim(vendor_name, safeguard, claimed_capability, supporting_text);
|
|
6154
6249
|
return {
|
|
6155
6250
|
content: [
|
|
@@ -6163,7 +6258,7 @@ export class GRCAnalysisServer {
|
|
|
6163
6258
|
validateCapabilityClaim(vendorName, safeguard, claimedCapability, supportingText) {
|
|
6164
6259
|
const text = supportingText.toLowerCase();
|
|
6165
6260
|
// Detect tool type and validate domain match
|
|
6166
|
-
const detectedToolType = this.detectToolType(supportingText);
|
|
6261
|
+
const detectedToolType = this.detectToolType(supportingText, safeguard.id);
|
|
6167
6262
|
const domainValidation = this.validateDomainMatch(safeguard.id, claimedCapability, detectedToolType);
|
|
6168
6263
|
// Adjust capability if domain mismatch detected
|
|
6169
6264
|
let effectiveCapability = claimedCapability;
|
|
@@ -6172,20 +6267,10 @@ export class GRCAnalysisServer {
|
|
|
6172
6267
|
originalClaim = claimedCapability;
|
|
6173
6268
|
effectiveCapability = domainValidation.adjusted_capability;
|
|
6174
6269
|
}
|
|
6175
|
-
// Perform
|
|
6176
|
-
const actualAnalysis = this.
|
|
6177
|
-
//
|
|
6178
|
-
const
|
|
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);
|
|
6270
|
+
// Perform capability-focused analysis of the supporting text
|
|
6271
|
+
const actualAnalysis = this.performCapabilityAnalysis(vendorName, safeguard, supportingText);
|
|
6272
|
+
// Validate claimed capability against actual capability analysis and domain requirements
|
|
6273
|
+
const validation = this.assessCapabilityClaimAlignment(claimedCapability, effectiveCapability, actualAnalysis, domainValidation, text);
|
|
6189
6274
|
// Add domain validation gaps if capability was adjusted
|
|
6190
6275
|
if (domainValidation.should_adjust_capability) {
|
|
6191
6276
|
validation.gaps.unshift(`Domain mismatch: ${domainValidation.reasoning}`);
|
|
@@ -6200,12 +6285,10 @@ export class GRCAnalysisServer {
|
|
|
6200
6285
|
claimed_capability: claimedCapability,
|
|
6201
6286
|
validation_status: validation.status,
|
|
6202
6287
|
confidence_score: validation.confidence,
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
language_consistency: validation.languageConsistency
|
|
6208
|
-
},
|
|
6288
|
+
actual_capability_detected: actualAnalysis.capability,
|
|
6289
|
+
capability_confidence: actualAnalysis.confidence,
|
|
6290
|
+
tool_capability_description: actualAnalysis.toolCapabilityDescription,
|
|
6291
|
+
recommended_use: actualAnalysis.recommendedUse,
|
|
6209
6292
|
domain_validation: {
|
|
6210
6293
|
required_tool_type: domainValidation.required_tool_types.join('/'),
|
|
6211
6294
|
detected_tool_type: detectedToolType,
|
|
@@ -6219,112 +6302,42 @@ export class GRCAnalysisServer {
|
|
|
6219
6302
|
detailed_feedback: validation.feedback
|
|
6220
6303
|
};
|
|
6221
6304
|
}
|
|
6222
|
-
|
|
6305
|
+
assessCapabilityClaimAlignment(claimedCapability, effectiveCapability, actualAnalysis, domainValidation, text) {
|
|
6223
6306
|
const gaps = [];
|
|
6224
6307
|
const strengths = [];
|
|
6225
6308
|
const recommendations = [];
|
|
6226
|
-
|
|
6309
|
+
// Compare claimed capability with what we actually detected
|
|
6310
|
+
const claimedLower = claimedCapability.toLowerCase();
|
|
6311
|
+
const effectiveLower = effectiveCapability.toLowerCase();
|
|
6312
|
+
const actualCapability = actualAnalysis.capability;
|
|
6227
6313
|
let alignmentScore = 0;
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
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;
|
|
6314
|
+
// Check if claim aligns with actual analysis
|
|
6315
|
+
if (claimedLower === actualCapability) {
|
|
6316
|
+
alignmentScore = actualAnalysis.confidence;
|
|
6317
|
+
strengths.push(`Claimed capability '${claimedCapability}' aligns with detected capability`);
|
|
6318
|
+
strengths.push(`Tool demonstrates appropriate ${actualAnalysis.toolCapabilityDescription.toLowerCase()}`);
|
|
6319
|
+
}
|
|
6320
|
+
else if (effectiveLower === actualCapability) {
|
|
6321
|
+
// Domain validation adjusted the capability and it matches the analysis
|
|
6322
|
+
alignmentScore = Math.max(actualAnalysis.confidence - 20, 30);
|
|
6323
|
+
gaps.push(`Original claim '${claimedCapability}' doesn't match tool type, adjusted to '${effectiveCapability}'`);
|
|
6324
|
+
strengths.push(`Adjusted capability '${effectiveCapability}' aligns with tool analysis`);
|
|
6325
|
+
}
|
|
6326
|
+
else {
|
|
6327
|
+
// Neither claimed nor effective capability matches the analysis
|
|
6328
|
+
alignmentScore = Math.max(actualAnalysis.confidence - 40, 10);
|
|
6329
|
+
gaps.push(`Claimed capability '${claimedCapability}' doesn't align with detected capability '${actualCapability}'`);
|
|
6330
|
+
gaps.push(`Tool appears to be: ${actualAnalysis.toolCapabilityDescription}`);
|
|
6331
|
+
}
|
|
6332
|
+
// Add evidence from the capability analysis
|
|
6333
|
+
if (actualAnalysis.evidence && actualAnalysis.evidence.length > 0) {
|
|
6334
|
+
strengths.push(`Supporting evidence: ${actualAnalysis.evidence.slice(0, 2).join('; ')}`);
|
|
6326
6335
|
}
|
|
6327
|
-
//
|
|
6336
|
+
// Domain validation feedback
|
|
6337
|
+
if (!domainValidation.domain_match) {
|
|
6338
|
+
gaps.push(`Tool type '${domainValidation.detected_tool_type}' not appropriate for this safeguard domain`);
|
|
6339
|
+
}
|
|
6340
|
+
// Determine overall status based on alignment score
|
|
6328
6341
|
let status;
|
|
6329
6342
|
if (alignmentScore >= 70) {
|
|
6330
6343
|
status = 'SUPPORTED';
|
|
@@ -6335,18 +6348,18 @@ export class GRCAnalysisServer {
|
|
|
6335
6348
|
else {
|
|
6336
6349
|
status = 'UNSUPPORTED';
|
|
6337
6350
|
}
|
|
6338
|
-
// Generate recommendations
|
|
6339
|
-
|
|
6340
|
-
recommendations.push('Address identified gaps to strengthen capability claim');
|
|
6341
|
-
}
|
|
6351
|
+
// Generate capability-focused recommendations
|
|
6352
|
+
recommendations.push(actualAnalysis.recommendedUse);
|
|
6342
6353
|
if (status === 'QUESTIONABLE') {
|
|
6343
|
-
recommendations.push('
|
|
6354
|
+
recommendations.push('Consider clarifying tool capabilities or adjusting capability claim');
|
|
6355
|
+
}
|
|
6356
|
+
if (!domainValidation.domain_match) {
|
|
6357
|
+
recommendations.push(`For ${actualCapability.toUpperCase()} capability, focus on how the tool ${actualCapability === 'facilitates' ? 'enables and enhances' : actualCapability === 'governance' ? 'manages policies and processes for' : actualCapability === 'validates' ? 'provides evidence and reporting on' : 'directly implements'} this safeguard`);
|
|
6344
6358
|
}
|
|
6345
|
-
const feedback = this.
|
|
6359
|
+
const feedback = this.generateCapabilityValidationFeedback(claimedCapability, effectiveCapability, actualCapability, status, alignmentScore, domainValidation);
|
|
6346
6360
|
return {
|
|
6347
6361
|
status,
|
|
6348
6362
|
confidence: Math.round(alignmentScore),
|
|
6349
|
-
languageConsistency: Math.round(languageConsistency),
|
|
6350
6363
|
gaps,
|
|
6351
6364
|
strengths,
|
|
6352
6365
|
recommendations,
|
|
@@ -6404,70 +6417,139 @@ export class GRCAnalysisServer {
|
|
|
6404
6417
|
];
|
|
6405
6418
|
return this.calculateKeywordScore(text, validationKeywords) * 100;
|
|
6406
6419
|
}
|
|
6407
|
-
detectToolType(text) {
|
|
6420
|
+
detectToolType(text, safeguardId) {
|
|
6408
6421
|
const lowerText = text.toLowerCase();
|
|
6409
|
-
//
|
|
6410
|
-
const
|
|
6411
|
-
'
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
'
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
'
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
'
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
|
|
6462
|
-
|
|
6422
|
+
// Enhanced keyword definitions with scoring weights and context
|
|
6423
|
+
const toolTypePatterns = {
|
|
6424
|
+
'inventory': {
|
|
6425
|
+
primary: [
|
|
6426
|
+
'asset management', 'inventory management', 'cmdb', 'configuration management database',
|
|
6427
|
+
'asset discovery', 'hardware inventory', 'software inventory', 'device inventory',
|
|
6428
|
+
'asset tracking', 'it asset management', 'endpoint discovery', 'asset lifecycle'
|
|
6429
|
+
],
|
|
6430
|
+
secondary: [
|
|
6431
|
+
'inventory', 'discovery', 'device management', 'endpoint management',
|
|
6432
|
+
'configuration management', 'asset database', 'equipment tracking'
|
|
6433
|
+
],
|
|
6434
|
+
weight: { primary: 3, secondary: 1 }
|
|
6435
|
+
},
|
|
6436
|
+
'identity_management': {
|
|
6437
|
+
primary: [
|
|
6438
|
+
'identity management', 'iam', 'active directory', 'identity provider',
|
|
6439
|
+
'single sign-on', 'sso', 'multi-factor authentication', 'mfa',
|
|
6440
|
+
'user management', 'account management', 'directory service'
|
|
6441
|
+
],
|
|
6442
|
+
secondary: [
|
|
6443
|
+
'ldap', 'authentication', 'access management', 'identity access management',
|
|
6444
|
+
'user directory', 'account lifecycle', 'privileged access'
|
|
6445
|
+
],
|
|
6446
|
+
weight: { primary: 3, secondary: 1 }
|
|
6447
|
+
},
|
|
6448
|
+
'vulnerability_management': {
|
|
6449
|
+
primary: [
|
|
6450
|
+
'vulnerability management', 'vulnerability scanner', 'patch management',
|
|
6451
|
+
'security scanning', 'vulnerability assessment', 'penetration testing'
|
|
6452
|
+
],
|
|
6453
|
+
secondary: [
|
|
6454
|
+
'vuln scan', 'security scanner', 'network scanner', 'scanning capabilities',
|
|
6455
|
+
'security assessment', 'vulnerability scanning', 'patch deployment'
|
|
6456
|
+
],
|
|
6457
|
+
weight: { primary: 3, secondary: 1 }
|
|
6458
|
+
},
|
|
6459
|
+
'threat_intelligence': {
|
|
6460
|
+
primary: [
|
|
6461
|
+
'threat intelligence', 'cyber threat intelligence', 'threat intel',
|
|
6462
|
+
'threat feed', 'ioc feed', 'security intelligence', 'threat data'
|
|
6463
|
+
],
|
|
6464
|
+
secondary: [
|
|
6465
|
+
'enrichment', 'data feed', 'contextual data', 'risk intelligence',
|
|
6466
|
+
'threat indicators', 'intelligence platform', 'threat correlation'
|
|
6467
|
+
],
|
|
6468
|
+
weight: { primary: 3, secondary: 1 }
|
|
6469
|
+
},
|
|
6470
|
+
'network_security': {
|
|
6471
|
+
primary: [
|
|
6472
|
+
'firewall', 'network access control', 'nac', 'intrusion detection',
|
|
6473
|
+
'network security', 'network segmentation'
|
|
6474
|
+
],
|
|
6475
|
+
secondary: [
|
|
6476
|
+
'network monitoring', 'traffic analysis', 'perimeter security',
|
|
6477
|
+
'network protection', 'network filtering'
|
|
6478
|
+
],
|
|
6479
|
+
weight: { primary: 3, secondary: 1 }
|
|
6480
|
+
},
|
|
6481
|
+
'governance': {
|
|
6482
|
+
primary: [
|
|
6483
|
+
'grc', 'governance risk compliance', 'compliance management',
|
|
6484
|
+
'policy management', 'risk management', 'audit management'
|
|
6485
|
+
],
|
|
6486
|
+
secondary: [
|
|
6487
|
+
'governance', 'compliance platform', 'policy enforcement',
|
|
6488
|
+
'regulatory compliance', 'framework management'
|
|
6489
|
+
],
|
|
6490
|
+
weight: { primary: 3, secondary: 1 }
|
|
6491
|
+
},
|
|
6492
|
+
'security_analytics': {
|
|
6493
|
+
primary: [
|
|
6494
|
+
'siem', 'security information event management', 'security analytics',
|
|
6495
|
+
'soar', 'security orchestration', 'log management'
|
|
6496
|
+
],
|
|
6497
|
+
secondary: [
|
|
6498
|
+
'security monitoring', 'event correlation', 'log analysis',
|
|
6499
|
+
'security intelligence', 'incident response platform'
|
|
6500
|
+
],
|
|
6501
|
+
weight: { primary: 3, secondary: 1 }
|
|
6502
|
+
}
|
|
6503
|
+
};
|
|
6504
|
+
// Calculate scores for each tool type
|
|
6505
|
+
const toolScores = {};
|
|
6506
|
+
for (const [toolType, patterns] of Object.entries(toolTypePatterns)) {
|
|
6507
|
+
let score = 0;
|
|
6508
|
+
// Check primary keywords
|
|
6509
|
+
for (const keyword of patterns.primary) {
|
|
6510
|
+
if (lowerText.includes(keyword)) {
|
|
6511
|
+
score += patterns.weight.primary;
|
|
6512
|
+
}
|
|
6513
|
+
}
|
|
6514
|
+
// Check secondary keywords
|
|
6515
|
+
for (const keyword of patterns.secondary) {
|
|
6516
|
+
if (lowerText.includes(keyword)) {
|
|
6517
|
+
score += patterns.weight.secondary;
|
|
6518
|
+
}
|
|
6519
|
+
}
|
|
6520
|
+
toolScores[toolType] = score;
|
|
6463
6521
|
}
|
|
6464
|
-
|
|
6465
|
-
|
|
6522
|
+
// Apply safeguard-specific context weighting if provided
|
|
6523
|
+
if (safeguardId && toolScores) {
|
|
6524
|
+
const contextBonus = 1; // Small bonus for domain alignment
|
|
6525
|
+
// Asset inventory safeguards (1.1, 1.2) favor inventory tools
|
|
6526
|
+
if (['1.1', '1.2'].includes(safeguardId) && toolScores['inventory'] > 0) {
|
|
6527
|
+
toolScores['inventory'] += contextBonus;
|
|
6528
|
+
}
|
|
6529
|
+
// Account inventory safeguards (5.1, 5.2, 5.3) favor identity tools
|
|
6530
|
+
if (['5.1', '5.2', '5.3'].includes(safeguardId) && toolScores['identity_management'] > 0) {
|
|
6531
|
+
toolScores['identity_management'] += contextBonus;
|
|
6532
|
+
}
|
|
6533
|
+
// Authentication safeguards (6.1, 6.2, 6.3) favor identity tools
|
|
6534
|
+
if (['6.1', '6.2', '6.3'].includes(safeguardId) && toolScores['identity_management'] > 0) {
|
|
6535
|
+
toolScores['identity_management'] += contextBonus;
|
|
6536
|
+
}
|
|
6537
|
+
// Vulnerability safeguards (7.1-7.7) favor vulnerability management tools
|
|
6538
|
+
if (['7.1', '7.2', '7.3', '7.4', '7.5', '7.6', '7.7'].includes(safeguardId) && toolScores['vulnerability_management'] > 0) {
|
|
6539
|
+
toolScores['vulnerability_management'] += contextBonus;
|
|
6540
|
+
}
|
|
6466
6541
|
}
|
|
6467
|
-
|
|
6468
|
-
|
|
6542
|
+
// Find the tool type with highest score
|
|
6543
|
+
let maxScore = 0;
|
|
6544
|
+
let detectedType = 'unknown';
|
|
6545
|
+
for (const [toolType, score] of Object.entries(toolScores)) {
|
|
6546
|
+
if (score > maxScore) {
|
|
6547
|
+
maxScore = score;
|
|
6548
|
+
detectedType = toolType;
|
|
6549
|
+
}
|
|
6469
6550
|
}
|
|
6470
|
-
|
|
6551
|
+
// Require minimum score threshold to avoid false positives
|
|
6552
|
+
return maxScore >= 2 ? detectedType : 'unknown';
|
|
6471
6553
|
}
|
|
6472
6554
|
validateDomainMatch(safeguardId, claimedCapability, detectedToolType) {
|
|
6473
6555
|
const domainReq = SAFEGUARD_DOMAIN_REQUIREMENTS[safeguardId];
|
|
@@ -6487,7 +6569,7 @@ export class GRCAnalysisServer {
|
|
|
6487
6569
|
required_tool_types: domainReq.required_tool_types,
|
|
6488
6570
|
should_adjust_capability: true,
|
|
6489
6571
|
adjusted_capability: 'facilitates',
|
|
6490
|
-
reasoning: `${domainReq.domain} safeguard requires ${domainReq.required_tool_types.join('/')} tool types for FULL/PARTIAL
|
|
6572
|
+
reasoning: `${domainReq.domain} safeguard requires ${domainReq.required_tool_types.join('/')} tool types for FULL/PARTIAL implementation capability. Detected tool type '${detectedToolType}' can only facilitate implementation.`
|
|
6491
6573
|
};
|
|
6492
6574
|
}
|
|
6493
6575
|
return {
|
|
@@ -6499,8 +6581,31 @@ export class GRCAnalysisServer {
|
|
|
6499
6581
|
'No domain validation required for this capability type'
|
|
6500
6582
|
};
|
|
6501
6583
|
}
|
|
6584
|
+
generateCapabilityValidationFeedback(claimedCapability, effectiveCapability, actualCapability, status, score, domainValidation) {
|
|
6585
|
+
let feedback = `Capability Validation: ${claimedCapability.toUpperCase()} claim is ${status} (${Math.round(score)}% confidence)\n\n`;
|
|
6586
|
+
// Analysis summary
|
|
6587
|
+
feedback += `ANALYSIS:\n`;
|
|
6588
|
+
feedback += `• Claimed: ${claimedCapability.toUpperCase()}\n`;
|
|
6589
|
+
if (effectiveCapability !== claimedCapability) {
|
|
6590
|
+
feedback += `• Domain Adjusted: ${effectiveCapability.toUpperCase()} (${domainValidation.reasoning})\n`;
|
|
6591
|
+
}
|
|
6592
|
+
feedback += `• Detected: ${actualCapability.toUpperCase()}\n`;
|
|
6593
|
+
feedback += `• Tool Type: ${domainValidation.detected_tool_type}\n\n`;
|
|
6594
|
+
// Assessment
|
|
6595
|
+
feedback += `ASSESSMENT: `;
|
|
6596
|
+
if (claimedCapability.toLowerCase() === actualCapability) {
|
|
6597
|
+
feedback += 'Claimed capability aligns perfectly with tool analysis.';
|
|
6598
|
+
}
|
|
6599
|
+
else if (effectiveCapability.toLowerCase() === actualCapability) {
|
|
6600
|
+
feedback += 'After domain validation adjustment, capability aligns with tool analysis.';
|
|
6601
|
+
}
|
|
6602
|
+
else {
|
|
6603
|
+
feedback += `Capability mismatch detected. Tool functions as ${actualCapability.toUpperCase()} rather than claimed ${claimedCapability.toUpperCase()}.`;
|
|
6604
|
+
}
|
|
6605
|
+
return feedback;
|
|
6606
|
+
}
|
|
6502
6607
|
generateValidationFeedback(claimedCapability, status, gaps, strengths, score) {
|
|
6503
|
-
let feedback = `Validation of ${claimedCapability.toUpperCase()} capability claim: ${status} (${Math.round(score)}% alignment)\n\n`;
|
|
6608
|
+
let feedback = `Validation of ${claimedCapability.toUpperCase()} capability role claim: ${status} (${Math.round(score)}% alignment)\n\n`;
|
|
6504
6609
|
if (strengths.length > 0) {
|
|
6505
6610
|
feedback += `STRENGTHS:\n${strengths.map(s => `• ${s}`).join('\n')}\n\n`;
|
|
6506
6611
|
}
|
|
@@ -6510,21 +6615,122 @@ export class GRCAnalysisServer {
|
|
|
6510
6615
|
feedback += `ASSESSMENT: `;
|
|
6511
6616
|
switch (status) {
|
|
6512
6617
|
case 'SUPPORTED':
|
|
6513
|
-
feedback += 'The vendor\'s supporting evidence strongly aligns with their claimed capability.';
|
|
6618
|
+
feedback += 'The vendor\'s supporting evidence strongly aligns with their claimed capability role.';
|
|
6514
6619
|
break;
|
|
6515
6620
|
case 'QUESTIONABLE':
|
|
6516
6621
|
feedback += 'The vendor\'s evidence partially supports their claim but has notable gaps or inconsistencies.';
|
|
6517
6622
|
break;
|
|
6518
6623
|
case 'UNSUPPORTED':
|
|
6519
|
-
feedback += 'The vendor\'s evidence does not adequately support their claimed capability.';
|
|
6624
|
+
feedback += 'The vendor\'s evidence does not adequately support their claimed capability role.';
|
|
6520
6625
|
break;
|
|
6521
6626
|
}
|
|
6522
6627
|
return feedback;
|
|
6523
6628
|
}
|
|
6629
|
+
// Enhanced error handling and formatting
|
|
6630
|
+
formatErrorMessage(error, toolName) {
|
|
6631
|
+
if (error instanceof Error) {
|
|
6632
|
+
// Production-friendly error messages
|
|
6633
|
+
switch (error.message) {
|
|
6634
|
+
case /^Safeguard .+ not found/.test(error.message) ? error.message : '':
|
|
6635
|
+
return `❌ Invalid safeguard ID. Use 'list_available_safeguards' to see available CIS Control safeguards.`;
|
|
6636
|
+
case /^Unknown tool/.test(error.message) ? error.message : '':
|
|
6637
|
+
return `❌ Tool '${toolName}' is not available. Available tools: analyze_vendor_response, validate_vendor_mapping, validate_coverage_claim, get_safeguard_details, list_available_safeguards.`;
|
|
6638
|
+
default:
|
|
6639
|
+
return `❌ Error in ${toolName}: ${error.message}`;
|
|
6640
|
+
}
|
|
6641
|
+
}
|
|
6642
|
+
return `❌ Unexpected error in ${toolName}: ${String(error)}`;
|
|
6643
|
+
}
|
|
6644
|
+
getCachedSafeguardDetails(safeguardId, includeExamples) {
|
|
6645
|
+
const cacheKey = `${safeguardId}_${includeExamples}`;
|
|
6646
|
+
const cached = this.cache.safeguardDetails.get(cacheKey);
|
|
6647
|
+
if (cached && (Date.now() - cached.timestamp < 5 * 60 * 1000)) { // 5 minute cache
|
|
6648
|
+
return cached.data;
|
|
6649
|
+
}
|
|
6650
|
+
return null;
|
|
6651
|
+
}
|
|
6652
|
+
setCachedSafeguardDetails(safeguardId, includeExamples, data) {
|
|
6653
|
+
const cacheKey = `${safeguardId}_${includeExamples}`;
|
|
6654
|
+
this.cache.safeguardDetails.set(cacheKey, {
|
|
6655
|
+
data,
|
|
6656
|
+
timestamp: Date.now()
|
|
6657
|
+
});
|
|
6658
|
+
// Periodic cache cleanup to prevent memory leaks
|
|
6659
|
+
if (Date.now() - this.cache.lastCacheCleanup > 10 * 60 * 1000) { // 10 minutes
|
|
6660
|
+
this.cleanupCache();
|
|
6661
|
+
}
|
|
6662
|
+
}
|
|
6663
|
+
cleanupCache() {
|
|
6664
|
+
const now = Date.now();
|
|
6665
|
+
const maxAge = 10 * 60 * 1000; // 10 minutes
|
|
6666
|
+
// Clean up safeguard details cache
|
|
6667
|
+
for (const [key, value] of this.cache.safeguardDetails.entries()) {
|
|
6668
|
+
if (now - value.timestamp > maxAge) {
|
|
6669
|
+
this.cache.safeguardDetails.delete(key);
|
|
6670
|
+
}
|
|
6671
|
+
}
|
|
6672
|
+
this.cache.lastCacheCleanup = now;
|
|
6673
|
+
}
|
|
6674
|
+
recordToolExecution(toolName, executionTime) {
|
|
6675
|
+
this.performanceMetrics.totalRequests++;
|
|
6676
|
+
if (!this.performanceMetrics.toolExecutionTimes.has(toolName)) {
|
|
6677
|
+
this.performanceMetrics.toolExecutionTimes.set(toolName, []);
|
|
6678
|
+
}
|
|
6679
|
+
const times = this.performanceMetrics.toolExecutionTimes.get(toolName);
|
|
6680
|
+
times.push(executionTime);
|
|
6681
|
+
// Keep only last 100 measurements for memory efficiency
|
|
6682
|
+
if (times.length > 100) {
|
|
6683
|
+
times.shift();
|
|
6684
|
+
}
|
|
6685
|
+
}
|
|
6686
|
+
getPerformanceStats() {
|
|
6687
|
+
const uptime = Date.now() - this.performanceMetrics.startTime;
|
|
6688
|
+
const avgTimes = Array.from(this.performanceMetrics.toolExecutionTimes.entries())
|
|
6689
|
+
.map(([tool, times]) => {
|
|
6690
|
+
const avg = times.reduce((a, b) => a + b, 0) / times.length;
|
|
6691
|
+
return `${tool}: ${avg.toFixed(2)}ms`;
|
|
6692
|
+
});
|
|
6693
|
+
return `Performance Stats (Uptime: ${(uptime / 1000).toFixed(1)}s, Requests: ${this.performanceMetrics.totalRequests}, Errors: ${this.performanceMetrics.errorCount})\n${avgTimes.join(', ')}`;
|
|
6694
|
+
}
|
|
6695
|
+
// Input validation and sanitization
|
|
6696
|
+
validateSafeguardId(safeguardId) {
|
|
6697
|
+
if (!safeguardId || typeof safeguardId !== 'string') {
|
|
6698
|
+
throw new Error('Safeguard ID is required and must be a string');
|
|
6699
|
+
}
|
|
6700
|
+
if (!/^[0-9]+\.[0-9]+$/.test(safeguardId)) {
|
|
6701
|
+
throw new Error('Safeguard ID must be in format "X.Y" (e.g., "1.1", "5.1")');
|
|
6702
|
+
}
|
|
6703
|
+
if (!CIS_SAFEGUARDS[safeguardId]) {
|
|
6704
|
+
throw new Error(`Safeguard ${safeguardId} not found`);
|
|
6705
|
+
}
|
|
6706
|
+
}
|
|
6707
|
+
validateTextInput(text, fieldName) {
|
|
6708
|
+
if (!text || typeof text !== 'string') {
|
|
6709
|
+
throw new Error(`${fieldName} is required and must be a string`);
|
|
6710
|
+
}
|
|
6711
|
+
if (text.length > 10000) {
|
|
6712
|
+
throw new Error(`${fieldName} must be less than 10,000 characters`);
|
|
6713
|
+
}
|
|
6714
|
+
if (text.trim().length < 10) {
|
|
6715
|
+
throw new Error(`${fieldName} must contain at least 10 meaningful characters`);
|
|
6716
|
+
}
|
|
6717
|
+
}
|
|
6718
|
+
validateCapability(capability) {
|
|
6719
|
+
const validCapabilities = ['full', 'partial', 'facilitates', 'governance', 'validates'];
|
|
6720
|
+
if (!validCapabilities.includes(capability.toLowerCase())) {
|
|
6721
|
+
throw new Error(`Invalid capability. Must be one of: ${validCapabilities.join(', ')}`);
|
|
6722
|
+
}
|
|
6723
|
+
}
|
|
6524
6724
|
async run() {
|
|
6525
6725
|
const transport = new StdioServerTransport();
|
|
6526
6726
|
await this.server.connect(transport);
|
|
6527
6727
|
console.error('FrameworkMCP server running on stdio');
|
|
6728
|
+
// Log performance stats every 5 minutes in production
|
|
6729
|
+
if (process.env.NODE_ENV === 'production') {
|
|
6730
|
+
setInterval(() => {
|
|
6731
|
+
console.error(`[FrameworkMCP] ${this.getPerformanceStats()}`);
|
|
6732
|
+
}, 5 * 60 * 1000);
|
|
6733
|
+
}
|
|
6528
6734
|
}
|
|
6529
6735
|
}
|
|
6530
6736
|
const server = new GRCAnalysisServer();
|