@bryan-thompson/inspector-assessment-client 1.29.1 → 1.30.1
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/lib/lib/assessment/configTypes.d.ts +32 -0
- package/lib/lib/assessment/configTypes.d.ts.map +1 -1
- package/lib/lib/assessment/configTypes.js +25 -7
- package/lib/lib/assessment/coreTypes.d.ts +14 -0
- package/lib/lib/assessment/coreTypes.d.ts.map +1 -1
- package/lib/lib/assessment/coreTypes.js +3 -0
- package/lib/lib/assessment/index.d.ts +1 -0
- package/lib/lib/assessment/index.d.ts.map +1 -1
- package/lib/lib/assessment/index.js +1 -0
- package/lib/lib/assessment/progressTypes.d.ts +13 -0
- package/lib/lib/assessment/progressTypes.d.ts.map +1 -1
- package/lib/lib/assessment/progressTypes.js +1 -0
- package/lib/lib/assessment/resultTypes.d.ts +8 -0
- package/lib/lib/assessment/resultTypes.d.ts.map +1 -1
- package/lib/lib/securityPatterns.d.ts +3 -2
- package/lib/lib/securityPatterns.d.ts.map +1 -1
- package/lib/lib/securityPatterns.js +150 -2
- package/lib/services/assessment/AssessmentOrchestrator.d.ts +31 -0
- package/lib/services/assessment/AssessmentOrchestrator.d.ts.map +1 -1
- package/lib/services/assessment/AssessmentOrchestrator.js +23 -0
- package/lib/services/assessment/ResponseValidator.d.ts +3 -0
- package/lib/services/assessment/ResponseValidator.d.ts.map +1 -1
- package/lib/services/assessment/ResponseValidator.js +3 -0
- package/lib/services/assessment/TestDataGenerator.d.ts +3 -0
- package/lib/services/assessment/TestDataGenerator.d.ts.map +1 -1
- package/lib/services/assessment/TestDataGenerator.js +3 -0
- package/lib/services/assessment/TestScenarioEngine.d.ts +3 -0
- package/lib/services/assessment/TestScenarioEngine.d.ts.map +1 -1
- package/lib/services/assessment/TestScenarioEngine.js +3 -0
- package/lib/services/assessment/config/performanceConfig.d.ts +8 -0
- package/lib/services/assessment/config/performanceConfig.d.ts.map +1 -1
- package/lib/services/assessment/config/performanceConfig.js +7 -0
- package/lib/services/assessment/lib/claudeCodeBridge.d.ts +3 -0
- package/lib/services/assessment/lib/claudeCodeBridge.d.ts.map +1 -1
- package/lib/services/assessment/lib/claudeCodeBridge.js +3 -0
- package/lib/services/assessment/lib/errors.d.ts +3 -0
- package/lib/services/assessment/lib/errors.d.ts.map +1 -1
- package/lib/services/assessment/lib/errors.js +3 -0
- package/lib/services/assessment/lib/timeoutUtils.d.ts +3 -0
- package/lib/services/assessment/lib/timeoutUtils.d.ts.map +1 -1
- package/lib/services/assessment/lib/timeoutUtils.js +3 -0
- package/lib/services/assessment/modules/annotations/index.d.ts +6 -1
- package/lib/services/assessment/modules/annotations/index.d.ts.map +1 -1
- package/lib/services/assessment/modules/annotations/index.js +6 -1
- package/lib/services/assessment/modules/index.d.ts +5 -0
- package/lib/services/assessment/modules/index.d.ts.map +1 -1
- package/lib/services/assessment/modules/index.js +5 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.d.ts.map +1 -1
- package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.js +86 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.d.ts.map +1 -1
- package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.js +26 -0
- package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts +58 -0
- package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts.map +1 -1
- package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.js +398 -0
- package/lib/services/assessment/modules/securityTests/index.d.ts +6 -1
- package/lib/services/assessment/modules/securityTests/index.d.ts.map +1 -1
- package/lib/services/assessment/modules/securityTests/index.js +6 -1
- package/lib/services/assessment/orchestratorHelpers.d.ts +3 -0
- package/lib/services/assessment/orchestratorHelpers.d.ts.map +1 -1
- package/lib/services/assessment/orchestratorHelpers.js +3 -0
- package/package.json +1 -1
|
@@ -444,6 +444,404 @@ export class SecurityResponseAnalyzer {
|
|
|
444
444
|
}
|
|
445
445
|
return { detected: false, injectionType: "UNKNOWN" };
|
|
446
446
|
}
|
|
447
|
+
/**
|
|
448
|
+
* Analyze response for session management vulnerabilities (Issue #111, Challenge #12)
|
|
449
|
+
* Detects 5 CWEs from mcp-vulnerable-testbed:
|
|
450
|
+
* - CWE-384: Session Fixation (accepts external session ID, no regeneration)
|
|
451
|
+
* - CWE-330: Predictable Tokens (session_{user}_{timestamp}_{counter})
|
|
452
|
+
* - CWE-613: No Session Timeout (expires_at: null, timeout_checked: false)
|
|
453
|
+
* - CWE-200: ID Exposure in URL (session_url contains session_id=)
|
|
454
|
+
*
|
|
455
|
+
* @param response The tool response to analyze
|
|
456
|
+
* @returns Analysis result with session management detection status
|
|
457
|
+
*/
|
|
458
|
+
analyzeSessionManagementResponse(response) {
|
|
459
|
+
const responseText = this.extractResponseContent(response);
|
|
460
|
+
const cweIds = [];
|
|
461
|
+
let vulnerabilityType = "UNKNOWN";
|
|
462
|
+
let evidence;
|
|
463
|
+
// Check for safe patterns first (hardened server)
|
|
464
|
+
const safePatterns = [
|
|
465
|
+
{
|
|
466
|
+
pattern: /"fixation_prevented"\s*:\s*true/i,
|
|
467
|
+
name: "fixation_prevented",
|
|
468
|
+
},
|
|
469
|
+
{ pattern: /"token_secure"\s*:\s*true/i, name: "token_secure" },
|
|
470
|
+
{ pattern: /"timeout_enforced"\s*:\s*true/i, name: "timeout_enforced" },
|
|
471
|
+
{ pattern: /"id_in_url"\s*:\s*false/i, name: "id_in_url: false" },
|
|
472
|
+
{
|
|
473
|
+
pattern: /"regeneration_on_auth"\s*:\s*true/i,
|
|
474
|
+
name: "regeneration_on_auth",
|
|
475
|
+
},
|
|
476
|
+
{ pattern: /"attack_blocked"\s*:\s*true/i, name: "attack_blocked" },
|
|
477
|
+
{ pattern: /"cwe_384_mitigated"\s*:\s*true/i, name: "cwe_384_mitigated" },
|
|
478
|
+
];
|
|
479
|
+
for (const { pattern, name } of safePatterns) {
|
|
480
|
+
if (pattern.test(responseText)) {
|
|
481
|
+
return {
|
|
482
|
+
detected: false,
|
|
483
|
+
vulnerabilityType: "UNKNOWN",
|
|
484
|
+
cweIds: [],
|
|
485
|
+
evidence: `Secure session management: ${name}`,
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
// CWE-384: Session Fixation (external ID accepted)
|
|
490
|
+
const fixationPatterns = [
|
|
491
|
+
{
|
|
492
|
+
pattern: /"attacker_controlled"\s*:\s*true/i,
|
|
493
|
+
evidence: "attacker_controlled: true (session fixation)",
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
pattern: /"fixed"\s*:\s*true/i,
|
|
497
|
+
evidence: "fixed: true (fixated session)",
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
pattern: /session\s*fixation\s*accepted/i,
|
|
501
|
+
evidence: "session fixation attack accepted",
|
|
502
|
+
},
|
|
503
|
+
{
|
|
504
|
+
pattern: /"fixation_url"\s*:/i,
|
|
505
|
+
evidence: "fixation_url present (attack vector)",
|
|
506
|
+
},
|
|
507
|
+
];
|
|
508
|
+
for (const { pattern, evidence: evidenceText } of fixationPatterns) {
|
|
509
|
+
if (pattern.test(responseText)) {
|
|
510
|
+
if (!cweIds.includes("CWE-384"))
|
|
511
|
+
cweIds.push("CWE-384");
|
|
512
|
+
vulnerabilityType = "SESSION_FIXATION";
|
|
513
|
+
evidence = evidenceText;
|
|
514
|
+
break;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
// CWE-384: No Regeneration after authentication
|
|
518
|
+
if (/"session_regenerated"\s*:\s*false/i.test(responseText)) {
|
|
519
|
+
if (!cweIds.includes("CWE-384"))
|
|
520
|
+
cweIds.push("CWE-384");
|
|
521
|
+
if (vulnerabilityType === "UNKNOWN") {
|
|
522
|
+
vulnerabilityType = "NO_REGENERATION";
|
|
523
|
+
evidence = "session_regenerated: false (CWE-384)";
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
// CWE-330: Predictable Token Pattern
|
|
527
|
+
const predictablePatterns = [
|
|
528
|
+
{
|
|
529
|
+
pattern: /"token_pattern"\s*:\s*"session_\{user\}_\{timestamp\}_\{counter\}"/i,
|
|
530
|
+
evidence: "Predictable token pattern exposed: session_{user}_{timestamp}_{counter}",
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
pattern: /"session_id"\s*:\s*"session_[a-z0-9]+_\d{9,}_\d+"/i,
|
|
534
|
+
evidence: "Predictable session ID format detected",
|
|
535
|
+
},
|
|
536
|
+
];
|
|
537
|
+
for (const { pattern, evidence: evidenceText } of predictablePatterns) {
|
|
538
|
+
if (pattern.test(responseText)) {
|
|
539
|
+
if (!cweIds.includes("CWE-330"))
|
|
540
|
+
cweIds.push("CWE-330");
|
|
541
|
+
if (vulnerabilityType === "UNKNOWN") {
|
|
542
|
+
vulnerabilityType = "PREDICTABLE_TOKEN";
|
|
543
|
+
evidence = evidenceText;
|
|
544
|
+
}
|
|
545
|
+
break;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
// CWE-613: No Session Timeout
|
|
549
|
+
const noTimeoutPatterns = [
|
|
550
|
+
{
|
|
551
|
+
pattern: /"expires_at"\s*:\s*null/i,
|
|
552
|
+
evidence: "expires_at: null (sessions never expire)",
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
pattern: /"timeout_checked"\s*:\s*false/i,
|
|
556
|
+
evidence: "timeout_checked: false (no expiration validation)",
|
|
557
|
+
},
|
|
558
|
+
];
|
|
559
|
+
for (const { pattern, evidence: evidenceText } of noTimeoutPatterns) {
|
|
560
|
+
if (pattern.test(responseText)) {
|
|
561
|
+
if (!cweIds.includes("CWE-613"))
|
|
562
|
+
cweIds.push("CWE-613");
|
|
563
|
+
if (vulnerabilityType === "UNKNOWN") {
|
|
564
|
+
vulnerabilityType = "NO_TIMEOUT";
|
|
565
|
+
evidence = evidenceText;
|
|
566
|
+
}
|
|
567
|
+
break;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
// CWE-200: Session ID in URL
|
|
571
|
+
const idInUrlPatterns = [
|
|
572
|
+
{
|
|
573
|
+
pattern: /"session_url"\s*:\s*"[^"]*[?&]session_id=/i,
|
|
574
|
+
evidence: "Session ID exposed in URL query parameter",
|
|
575
|
+
},
|
|
576
|
+
{
|
|
577
|
+
pattern: /"fixation_url"\s*:\s*"[^"]*[?&]session_id=/i,
|
|
578
|
+
evidence: "Session ID exposed in fixation URL",
|
|
579
|
+
},
|
|
580
|
+
];
|
|
581
|
+
for (const { pattern, evidence: evidenceText } of idInUrlPatterns) {
|
|
582
|
+
if (pattern.test(responseText)) {
|
|
583
|
+
if (!cweIds.includes("CWE-200"))
|
|
584
|
+
cweIds.push("CWE-200");
|
|
585
|
+
if (vulnerabilityType === "UNKNOWN") {
|
|
586
|
+
vulnerabilityType = "ID_IN_URL";
|
|
587
|
+
evidence = evidenceText;
|
|
588
|
+
}
|
|
589
|
+
break;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
return {
|
|
593
|
+
detected: cweIds.length > 0,
|
|
594
|
+
vulnerabilityType,
|
|
595
|
+
cweIds: [...new Set(cweIds)], // Dedupe
|
|
596
|
+
evidence,
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Analyze response for cryptographic failures (Issue #112, Challenge #13)
|
|
601
|
+
* Detects OWASP A02:2021 Cryptographic Failures from mcp-vulnerable-testbed:
|
|
602
|
+
* - CWE-328: Weak Hash (MD5/SHA1 for password hashing)
|
|
603
|
+
* - CWE-916: Static Salt / Weak KDF
|
|
604
|
+
* - CWE-330: Predictable RNG (random.random() with timestamp seed)
|
|
605
|
+
* - CWE-208: Timing Attack (non-constant-time comparison)
|
|
606
|
+
* - CWE-327: Broken Cipher (ECB mode, XOR)
|
|
607
|
+
* - CWE-321: Hardcoded Key (key_source: "hardcoded")
|
|
608
|
+
* - CWE-326: Weak Key Length (key_length < 16)
|
|
609
|
+
*
|
|
610
|
+
* @param response The tool response to analyze
|
|
611
|
+
* @returns Analysis result with cryptographic failure detection status
|
|
612
|
+
*/
|
|
613
|
+
analyzeCryptographicFailures(response) {
|
|
614
|
+
const responseText = this.extractResponseContent(response);
|
|
615
|
+
const cweIds = [];
|
|
616
|
+
let vulnerabilityType = "UNKNOWN";
|
|
617
|
+
let evidence;
|
|
618
|
+
// Check for safe patterns first (hardened server)
|
|
619
|
+
const safePatterns = [
|
|
620
|
+
{
|
|
621
|
+
pattern: /"status"\s*:\s*"stored"/i,
|
|
622
|
+
name: "request stored (not executed)",
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
pattern: /"note"\s*:\s*".*blocked.*secure/i,
|
|
626
|
+
name: "weak crypto blocked",
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
pattern: /"recommendation"\s*:\s*"Use\s+(?:bcrypt|scrypt|Argon2|AES-GCM)/i,
|
|
630
|
+
name: "secure alternative recommended",
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
pattern: /"vulnerable"\s*:\s*false/i,
|
|
634
|
+
name: "vulnerable: false",
|
|
635
|
+
},
|
|
636
|
+
];
|
|
637
|
+
for (const { pattern, name } of safePatterns) {
|
|
638
|
+
if (pattern.test(responseText)) {
|
|
639
|
+
return {
|
|
640
|
+
detected: false,
|
|
641
|
+
vulnerabilityType: "UNKNOWN",
|
|
642
|
+
cweIds: [],
|
|
643
|
+
evidence: `Secure crypto handling: ${name}`,
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
// CWE-328: Weak Hash Algorithm (MD5/SHA1)
|
|
648
|
+
const weakHashPatterns = [
|
|
649
|
+
{
|
|
650
|
+
pattern: /"algorithm"\s*:\s*"MD5"/i,
|
|
651
|
+
evidence: 'algorithm: "MD5" (weak hash for passwords)',
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
pattern: /"algorithm"\s*:\s*"SHA1"/i,
|
|
655
|
+
evidence: 'algorithm: "SHA1" (weak hash for passwords)',
|
|
656
|
+
},
|
|
657
|
+
{
|
|
658
|
+
pattern: /"algorithm_secure"\s*:\s*false/i,
|
|
659
|
+
evidence: "algorithm_secure: false",
|
|
660
|
+
},
|
|
661
|
+
];
|
|
662
|
+
for (const { pattern, evidence: evidenceText } of weakHashPatterns) {
|
|
663
|
+
if (pattern.test(responseText)) {
|
|
664
|
+
if (!cweIds.includes("CWE-328"))
|
|
665
|
+
cweIds.push("CWE-328");
|
|
666
|
+
vulnerabilityType = "WEAK_HASH";
|
|
667
|
+
evidence = evidenceText;
|
|
668
|
+
break;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
// CWE-916: Static Salt
|
|
672
|
+
const staticSaltPatterns = [
|
|
673
|
+
{
|
|
674
|
+
pattern: /"salt_type"\s*:\s*"static"/i,
|
|
675
|
+
evidence: 'salt_type: "static" (same salt for all passwords)',
|
|
676
|
+
},
|
|
677
|
+
{
|
|
678
|
+
pattern: /"salt"\s*:\s*"static_salt_123"/i,
|
|
679
|
+
evidence: 'salt: "static_salt_123" (hardcoded static salt)',
|
|
680
|
+
},
|
|
681
|
+
{
|
|
682
|
+
pattern: /"salt_secure"\s*:\s*false/i,
|
|
683
|
+
evidence: "salt_secure: false",
|
|
684
|
+
},
|
|
685
|
+
];
|
|
686
|
+
for (const { pattern, evidence: evidenceText } of staticSaltPatterns) {
|
|
687
|
+
if (pattern.test(responseText)) {
|
|
688
|
+
if (!cweIds.includes("CWE-916"))
|
|
689
|
+
cweIds.push("CWE-916");
|
|
690
|
+
if (vulnerabilityType === "UNKNOWN") {
|
|
691
|
+
vulnerabilityType = "STATIC_SALT";
|
|
692
|
+
evidence = evidenceText;
|
|
693
|
+
}
|
|
694
|
+
break;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
// CWE-330: Predictable RNG
|
|
698
|
+
const predictableRngPatterns = [
|
|
699
|
+
{
|
|
700
|
+
pattern: /"rng_type"\s*:\s*"random\.random\(\)"/i,
|
|
701
|
+
evidence: 'rng_type: "random.random()" (non-cryptographic RNG)',
|
|
702
|
+
},
|
|
703
|
+
{
|
|
704
|
+
pattern: /"seed"\s*:\s*"timestamp"/i,
|
|
705
|
+
evidence: 'seed: "timestamp" (predictable seed)',
|
|
706
|
+
},
|
|
707
|
+
{
|
|
708
|
+
pattern: /"cryptographically_secure"\s*:\s*false/i,
|
|
709
|
+
evidence: "cryptographically_secure: false",
|
|
710
|
+
},
|
|
711
|
+
];
|
|
712
|
+
for (const { pattern, evidence: evidenceText } of predictableRngPatterns) {
|
|
713
|
+
if (pattern.test(responseText)) {
|
|
714
|
+
if (!cweIds.includes("CWE-330"))
|
|
715
|
+
cweIds.push("CWE-330");
|
|
716
|
+
if (vulnerabilityType === "UNKNOWN") {
|
|
717
|
+
vulnerabilityType = "PREDICTABLE_RNG";
|
|
718
|
+
evidence = evidenceText;
|
|
719
|
+
}
|
|
720
|
+
break;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
// CWE-208: Timing Attack
|
|
724
|
+
const timingPatterns = [
|
|
725
|
+
{
|
|
726
|
+
pattern: /"timing_safe"\s*:\s*false/i,
|
|
727
|
+
evidence: "timing_safe: false (vulnerable to timing attacks)",
|
|
728
|
+
},
|
|
729
|
+
{
|
|
730
|
+
pattern: /"comparison_type"\s*:\s*"direct_equality"/i,
|
|
731
|
+
evidence: 'comparison_type: "direct_equality" (non-constant-time)',
|
|
732
|
+
},
|
|
733
|
+
];
|
|
734
|
+
for (const { pattern, evidence: evidenceText } of timingPatterns) {
|
|
735
|
+
if (pattern.test(responseText)) {
|
|
736
|
+
if (!cweIds.includes("CWE-208"))
|
|
737
|
+
cweIds.push("CWE-208");
|
|
738
|
+
if (vulnerabilityType === "UNKNOWN") {
|
|
739
|
+
vulnerabilityType = "TIMING_ATTACK";
|
|
740
|
+
evidence = evidenceText;
|
|
741
|
+
}
|
|
742
|
+
break;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
// CWE-327: Broken Cipher Mode (ECB/XOR)
|
|
746
|
+
const brokenCipherPatterns = [
|
|
747
|
+
{
|
|
748
|
+
pattern: /"mode"\s*:\s*"ECB"/i,
|
|
749
|
+
evidence: 'mode: "ECB" (pattern leakage in ciphertext)',
|
|
750
|
+
},
|
|
751
|
+
{
|
|
752
|
+
pattern: /"algorithm"\s*:\s*"XOR"/i,
|
|
753
|
+
evidence: 'algorithm: "XOR" (weak cipher)',
|
|
754
|
+
},
|
|
755
|
+
];
|
|
756
|
+
for (const { pattern, evidence: evidenceText } of brokenCipherPatterns) {
|
|
757
|
+
if (pattern.test(responseText)) {
|
|
758
|
+
if (!cweIds.includes("CWE-327"))
|
|
759
|
+
cweIds.push("CWE-327");
|
|
760
|
+
if (vulnerabilityType === "UNKNOWN") {
|
|
761
|
+
vulnerabilityType = "ECB_MODE";
|
|
762
|
+
evidence = evidenceText;
|
|
763
|
+
}
|
|
764
|
+
break;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
// CWE-321: Hardcoded Key
|
|
768
|
+
const hardcodedKeyPatterns = [
|
|
769
|
+
{
|
|
770
|
+
pattern: /"key_source"\s*:\s*"hardcoded"/i,
|
|
771
|
+
evidence: 'key_source: "hardcoded" (key in source code)',
|
|
772
|
+
},
|
|
773
|
+
{
|
|
774
|
+
pattern: /"key_preview"\s*:\s*"hardcode/i,
|
|
775
|
+
evidence: "key_preview shows hardcoded key",
|
|
776
|
+
},
|
|
777
|
+
];
|
|
778
|
+
for (const { pattern, evidence: evidenceText } of hardcodedKeyPatterns) {
|
|
779
|
+
if (pattern.test(responseText)) {
|
|
780
|
+
if (!cweIds.includes("CWE-321"))
|
|
781
|
+
cweIds.push("CWE-321");
|
|
782
|
+
if (vulnerabilityType === "UNKNOWN") {
|
|
783
|
+
vulnerabilityType = "HARDCODED_KEY";
|
|
784
|
+
evidence = evidenceText;
|
|
785
|
+
}
|
|
786
|
+
break;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
// CWE-916: Weak KDF (MD5 for key derivation)
|
|
790
|
+
const weakKdfPatterns = [
|
|
791
|
+
{
|
|
792
|
+
pattern: /"derivation_function"\s*:\s*"MD5"/i,
|
|
793
|
+
evidence: 'derivation_function: "MD5" (weak KDF)',
|
|
794
|
+
},
|
|
795
|
+
{
|
|
796
|
+
pattern: /"iterations"\s*:\s*1\b/i,
|
|
797
|
+
evidence: "iterations: 1 (no key stretching)",
|
|
798
|
+
},
|
|
799
|
+
{
|
|
800
|
+
pattern: /"kdf_secure"\s*:\s*false/i,
|
|
801
|
+
evidence: "kdf_secure: false",
|
|
802
|
+
},
|
|
803
|
+
];
|
|
804
|
+
for (const { pattern, evidence: evidenceText } of weakKdfPatterns) {
|
|
805
|
+
if (pattern.test(responseText)) {
|
|
806
|
+
if (!cweIds.includes("CWE-916"))
|
|
807
|
+
cweIds.push("CWE-916");
|
|
808
|
+
if (vulnerabilityType === "UNKNOWN") {
|
|
809
|
+
vulnerabilityType = "WEAK_KDF";
|
|
810
|
+
evidence = evidenceText;
|
|
811
|
+
}
|
|
812
|
+
break;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
// CWE-326: Weak Key Length
|
|
816
|
+
const weakKeyPatterns = [
|
|
817
|
+
{
|
|
818
|
+
// Match single digit key_length (1-9 bytes = weak)
|
|
819
|
+
pattern: /"key_length"\s*:\s*[1-9](?!\d)/i,
|
|
820
|
+
evidence: "key_length < 10 bytes (weak key)",
|
|
821
|
+
},
|
|
822
|
+
{
|
|
823
|
+
pattern: /"key_secure"\s*:\s*false/i,
|
|
824
|
+
evidence: "key_secure: false (weak key)",
|
|
825
|
+
},
|
|
826
|
+
];
|
|
827
|
+
for (const { pattern, evidence: evidenceText } of weakKeyPatterns) {
|
|
828
|
+
if (pattern.test(responseText)) {
|
|
829
|
+
if (!cweIds.includes("CWE-326"))
|
|
830
|
+
cweIds.push("CWE-326");
|
|
831
|
+
if (vulnerabilityType === "UNKNOWN") {
|
|
832
|
+
vulnerabilityType = "WEAK_KEY_LENGTH";
|
|
833
|
+
evidence = evidenceText;
|
|
834
|
+
}
|
|
835
|
+
break;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
return {
|
|
839
|
+
detected: cweIds.length > 0,
|
|
840
|
+
vulnerabilityType,
|
|
841
|
+
cweIds: [...new Set(cweIds)], // Dedupe
|
|
842
|
+
evidence,
|
|
843
|
+
};
|
|
844
|
+
}
|
|
447
845
|
/**
|
|
448
846
|
* Analyze response for chain exploitation vulnerabilities (Issue #93, Challenge #6)
|
|
449
847
|
* Detects multi-tool chained exploitation attacks including:
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Security Assessment Module
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* Exports all security-related components for testing MCP servers.
|
|
5
|
+
* Includes payload generation, testing, and response analysis.
|
|
6
|
+
*
|
|
7
|
+
* @public
|
|
8
|
+
* @module assessment/security
|
|
4
9
|
*/
|
|
5
10
|
export { SecurityResponseAnalyzer, type ConfidenceResult, type AnalysisResult, type ErrorClassification, type StateBasedAuthResult, type ChainExploitationAnalysis, type ChainExecutionType, type ChainVulnerabilityCategory, } from "./SecurityResponseAnalyzer.js";
|
|
6
11
|
export { SecurityPayloadTester, type TestProgressCallback, type PayloadTestConfig, type TestLogger, } from "./SecurityPayloadTester.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/securityTests/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/securityTests/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,wBAAwB,EACxB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,KAAK,0BAA0B,GAChC,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,qBAAqB,EACrB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,UAAU,GAChB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,OAAO,EACL,oBAAoB,EACpB,KAAK,mBAAmB,EACxB,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,GACzB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,oBAAoB,EACpB,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAC/B,KAAK,eAAe,GACrB,MAAM,wBAAwB,CAAC"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Security Assessment Module
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* Exports all security-related components for testing MCP servers.
|
|
5
|
+
* Includes payload generation, testing, and response analysis.
|
|
6
|
+
*
|
|
7
|
+
* @public
|
|
8
|
+
* @module assessment/security
|
|
4
9
|
*/
|
|
5
10
|
export { SecurityResponseAnalyzer, } from "./SecurityResponseAnalyzer.js";
|
|
6
11
|
export { SecurityPayloadTester, } from "./SecurityPayloadTester.js";
|
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
* - Module progress/started event emission
|
|
8
8
|
* - Overall status determination
|
|
9
9
|
* - Summary and recommendations generation
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
* @module orchestratorHelpers
|
|
10
13
|
*/
|
|
11
14
|
import { MCPDirectoryAssessment, AssessmentStatus } from "../../lib/assessmentTypes.js";
|
|
12
15
|
export declare const moduleStartTimes: Map<string, number>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestratorHelpers.d.ts","sourceRoot":"","sources":["../../../src/services/assessment/orchestratorHelpers.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"orchestratorHelpers.d.ts","sourceRoot":"","sources":["../../../src/services/assessment/orchestratorHelpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAW/B,eAAO,MAAM,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAa,CAAC;AAE/D;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,GAChB,IAAI,CAeN;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,EACf,QAAQ,GAAE,MAAU,GACnB,IAAI,CAkCN;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE;IACT,UAAU,CAAC,EAAE,KAAK,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;IACH,gBAAgB,CAAC,EAAE;QACjB,SAAS,EAAE,OAAO,CAAC;QACnB,gBAAgB,EAAE,OAAO,CAAC;QAC1B,MAAM,EAAE,OAAO,CAAC;QAChB,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC;IACF,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B,EACD,UAAU,GAAE,MAAW,GACtB;IACD,gBAAgB,EAAE,KAAK,CAAC;QACtB,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACpC,CAAC;IACF,gBAAgB,EAAE;QAChB,SAAS,EAAE,OAAO,CAAC;QACnB,gBAAgB,EAAE,OAAO,CAAC;QAC1B,MAAM,EAAE,OAAO,CAAC;QAChB,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC;IACF,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B,CAkEA;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,OAAO,CAAC,sBAAsB,CAAC,GACvC,gBAAgB,CAsBlB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,OAAO,CAAC,sBAAsB,CAAC,GACvC,MAAM,CA8ER;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,OAAO,CAAC,sBAAsB,CAAC,GACvC,MAAM,EAAE,CAiBV"}
|
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
* - Module progress/started event emission
|
|
8
8
|
* - Overall status determination
|
|
9
9
|
* - Summary and recommendations generation
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
* @module orchestratorHelpers
|
|
10
13
|
*/
|
|
11
14
|
// Import score calculation helpers from shared module
|
|
12
15
|
import { calculateModuleScore, normalizeModuleKey, INSPECTOR_VERSION, SCHEMA_VERSION, } from "../../lib/moduleScoring.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bryan-thompson/inspector-assessment-client",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.30.1",
|
|
4
4
|
"description": "Client-side application for the Enhanced MCP Inspector with assessment capabilities",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Bryan Thompson <bryan@triepod.ai>",
|