@mcp-shark/mcp-shark 1.5.13 → 1.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/README.md +482 -56
  2. package/bin/mcp-shark.js +146 -52
  3. package/core/cli/AutoFixEngine.js +93 -0
  4. package/core/cli/ConfigScanner.js +193 -0
  5. package/core/cli/DataLoader.js +200 -0
  6. package/core/cli/DeclarativeRuleEngine.js +363 -0
  7. package/core/cli/DoctorCommand.js +218 -0
  8. package/core/cli/FixHandlers.js +222 -0
  9. package/core/cli/HtmlReportGenerator.js +203 -0
  10. package/core/cli/IdeConfigPaths.js +175 -0
  11. package/core/cli/ListCommand.js +255 -0
  12. package/core/cli/LockCommand.js +164 -0
  13. package/core/cli/LockDiffEngine.js +152 -0
  14. package/core/cli/RuleRegistryConfig.js +131 -0
  15. package/core/cli/ScanCommand.js +244 -0
  16. package/core/cli/ScanService.js +200 -0
  17. package/core/cli/SecretDetector.js +92 -0
  18. package/core/cli/SharkScoreCalculator.js +109 -0
  19. package/core/cli/ToolClassifications.js +51 -0
  20. package/core/cli/ToxicFlowAnalyzer.js +212 -0
  21. package/core/cli/UpdateCommand.js +188 -0
  22. package/core/cli/WalkthroughGenerator.js +195 -0
  23. package/core/cli/WatchCommand.js +129 -0
  24. package/core/cli/YamlRuleEngine.js +197 -0
  25. package/core/cli/data/rule-packs/aauth-visibility.json +117 -0
  26. package/core/cli/data/rule-packs/agentic-security-2026.json +180 -0
  27. package/core/cli/data/rule-packs/general-security.json +173 -0
  28. package/core/cli/data/rule-packs/owasp-mcp-2026.json +244 -0
  29. package/core/cli/data/rule-packs/toxic-flow-heuristics.json +21 -0
  30. package/core/cli/data/rule-sources.json +5 -0
  31. package/core/cli/data/secret-patterns.json +18 -0
  32. package/core/cli/data/tool-classifications.json +111 -0
  33. package/core/cli/data/toxic-flow-rules.json +47 -0
  34. package/core/cli/index.js +23 -0
  35. package/core/cli/output/Banner.js +52 -0
  36. package/core/cli/output/Formatter.js +183 -0
  37. package/core/cli/output/JsonFormatter.js +106 -0
  38. package/core/cli/output/index.js +16 -0
  39. package/core/cli/secureRegistryFetch.js +157 -0
  40. package/core/cli/symbols.js +16 -0
  41. package/core/configs/environment.js +3 -1
  42. package/core/configs/index.js +3 -64
  43. package/core/container/DependencyContainer.js +4 -1
  44. package/core/mcp-server/index.js +4 -1
  45. package/core/mcp-server/server/external/all.js +10 -3
  46. package/core/mcp-server/server/external/config.js +62 -5
  47. package/core/models/RequestFilters.js +3 -0
  48. package/core/repositories/PacketRepository.js +16 -0
  49. package/core/services/AuditService.js +2 -0
  50. package/core/services/ConfigService.js +9 -1
  51. package/core/services/ConfigTransformService.js +34 -2
  52. package/core/services/RequestService.js +58 -5
  53. package/core/services/ServerManagementService.js +59 -4
  54. package/core/services/security/StaticRulesService.js +69 -13
  55. package/core/services/security/TrafficAnalysisService.js +19 -1
  56. package/core/services/security/TrafficToxicFlowService.js +154 -0
  57. package/core/services/security/aauthGraph.js +199 -0
  58. package/core/services/security/aauthParser.js +274 -0
  59. package/core/services/security/aauthSelfTest.js +346 -0
  60. package/core/services/security/index.js +2 -1
  61. package/core/services/security/rules/index.js +25 -59
  62. package/core/services/security/rules/scans/configPermissions.js +91 -0
  63. package/core/services/security/rules/scans/duplicateToolNames.js +85 -0
  64. package/core/services/security/rules/scans/insecureTransport.js +148 -0
  65. package/core/services/security/rules/scans/missingContainment.js +123 -0
  66. package/core/services/security/rules/scans/shellEnvInjection.js +101 -0
  67. package/core/services/security/rules/scans/unsafeDefaults.js +99 -0
  68. package/core/services/security/toolsListFromTrafficParser.js +70 -0
  69. package/core/tui/App.js +144 -0
  70. package/core/tui/FindingsPanel.js +115 -0
  71. package/core/tui/FixPanel.js +132 -0
  72. package/core/tui/Header.js +51 -0
  73. package/core/tui/HelpBar.js +42 -0
  74. package/core/tui/ServersPanel.js +109 -0
  75. package/core/tui/ToxicFlowsPanel.js +100 -0
  76. package/core/tui/h.js +8 -0
  77. package/core/tui/index.js +11 -0
  78. package/core/tui/render.js +22 -0
  79. package/package.json +24 -16
  80. package/ui/dist/assets/index-D6zDrtMV.js +81 -0
  81. package/ui/dist/index.html +1 -1
  82. package/ui/server/controllers/AauthController.js +279 -0
  83. package/ui/server/controllers/RequestController.js +12 -1
  84. package/ui/server/controllers/SecurityFindingsController.js +46 -1
  85. package/ui/server/routes/aauth.js +18 -0
  86. package/ui/server/routes/requests.js +8 -1
  87. package/ui/server/routes/security.js +5 -1
  88. package/ui/server/setup.js +224 -6
  89. package/ui/server/swagger/paths/components.js +55 -0
  90. package/ui/server/swagger/paths/securityTrafficFlows.js +59 -0
  91. package/ui/server/swagger/paths.js +2 -2
  92. package/ui/server/swagger/swagger.js +5 -2
  93. package/ui/server.js +1 -1
  94. package/ui/src/App.jsx +26 -52
  95. package/ui/src/PacketFilters.jsx +31 -1
  96. package/ui/src/PacketList.jsx +2 -2
  97. package/ui/src/Security.jsx +10 -0
  98. package/ui/src/TabNavigation.jsx +8 -0
  99. package/ui/src/components/AAuthBadge.jsx +92 -0
  100. package/ui/src/components/AauthExplorer/AauthExplorerGraph.jsx +231 -0
  101. package/ui/src/components/AauthExplorer/AauthExplorerView.jsx +387 -0
  102. package/ui/src/components/AauthExplorer/NodeDetailPanel.jsx +272 -0
  103. package/ui/src/components/App/ActionMenu.jsx +4 -31
  104. package/ui/src/components/App/ApiDocsButton.jsx +0 -1
  105. package/ui/src/components/App/ShutdownButton.jsx +0 -1
  106. package/ui/src/components/App/useAppState.js +19 -26
  107. package/ui/src/components/DetailsTab/AAuthIdentitySection.jsx +119 -0
  108. package/ui/src/components/DetailsTab/RequestDetailsSection.jsx +2 -0
  109. package/ui/src/components/DetailsTab/ResponseDetailsSection.jsx +2 -0
  110. package/ui/src/components/DetectedPathsList.jsx +1 -5
  111. package/ui/src/components/FileInput.jsx +0 -1
  112. package/ui/src/components/PacketFilters/AAuthPostureFilter.jsx +81 -0
  113. package/ui/src/components/RequestRow/RequestRowMain.jsx +7 -1
  114. package/ui/src/components/Security/AAuthPosturePanel.jsx +360 -0
  115. package/ui/src/components/Security/ScannerContent.jsx +33 -1
  116. package/ui/src/components/Security/TrafficToxicFlowsPanel.jsx +253 -0
  117. package/ui/src/components/Security/securityApi.js +15 -0
  118. package/ui/src/components/Security/useSecurity.js +60 -3
  119. package/ui/src/components/ServerControl.jsx +0 -1
  120. package/ui/src/components/TabNavigation/DesktopTabs.jsx +0 -11
  121. package/ui/src/components/TabNavigationIcons.jsx +5 -0
  122. package/ui/src/components/ViewModeTabs.jsx +0 -1
  123. package/ui/src/utils/animations.js +26 -9
  124. package/core/services/security/rules/scans/agentic01GoalHijack.js +0 -130
  125. package/core/services/security/rules/scans/agentic02ToolMisuse.js +0 -129
  126. package/core/services/security/rules/scans/agentic03IdentityAbuse.js +0 -130
  127. package/core/services/security/rules/scans/agentic04SupplyChain.js +0 -130
  128. package/core/services/security/rules/scans/agentic06MemoryPoisoning.js +0 -130
  129. package/core/services/security/rules/scans/agentic07InsecureCommunication.js +0 -135
  130. package/core/services/security/rules/scans/agentic08CascadingFailures.js +0 -135
  131. package/core/services/security/rules/scans/agentic09TrustExploitation.js +0 -135
  132. package/core/services/security/rules/scans/agentic10RogueAgent.js +0 -130
  133. package/core/services/security/rules/scans/hardcodedSecrets.js +0 -130
  134. package/core/services/security/rules/scans/mcp01TokenMismanagement.js +0 -127
  135. package/core/services/security/rules/scans/mcp02ScopeCreep.js +0 -130
  136. package/core/services/security/rules/scans/mcp03ToolPoisoning.js +0 -132
  137. package/core/services/security/rules/scans/mcp04SupplyChain.js +0 -131
  138. package/core/services/security/rules/scans/mcp06PromptInjection.js +0 -200
  139. package/core/services/security/rules/scans/mcp07InsufficientAuth.js +0 -130
  140. package/core/services/security/rules/scans/mcp08LackAudit.js +0 -129
  141. package/core/services/security/rules/scans/mcp09ShadowServers.js +0 -129
  142. package/core/services/security/rules/scans/mcp10ContextInjection.js +0 -130
  143. package/ui/dist/assets/index-CiCSDYf-.js +0 -97
  144. package/ui/server/routes/help.js +0 -44
  145. package/ui/server/swagger/paths/help.js +0 -82
  146. package/ui/src/HelpGuide/HelpGuideContent.jsx +0 -118
  147. package/ui/src/HelpGuide/HelpGuideFooter.jsx +0 -59
  148. package/ui/src/HelpGuide/HelpGuideHeader.jsx +0 -57
  149. package/ui/src/HelpGuide.jsx +0 -78
  150. package/ui/src/IntroTour.jsx +0 -154
  151. package/ui/src/components/App/HelpButton.jsx +0 -90
  152. package/ui/src/components/TourOverlay.jsx +0 -117
  153. package/ui/src/components/TourTooltip/TourTooltipButtons.jsx +0 -120
  154. package/ui/src/components/TourTooltip/TourTooltipHeader.jsx +0 -71
  155. package/ui/src/components/TourTooltip/TourTooltipIcons.jsx +0 -54
  156. package/ui/src/components/TourTooltip/useTooltipPosition.js +0 -135
  157. package/ui/src/components/TourTooltip.jsx +0 -91
  158. package/ui/src/config/tourSteps.jsx +0 -140
@@ -5,8 +5,10 @@ import {
5
5
  fetchRunningServersCount,
6
6
  fetchScanHistory,
7
7
  fetchSummary,
8
+ fetchTrafficToxicFlows,
8
9
  postAnalyseRunningServers,
9
10
  postClearFindings,
11
+ postReplayTrafficToxicFlows,
10
12
  } from './securityApi.js';
11
13
  import { useYaraRules } from './useYaraRules.js';
12
14
 
@@ -30,6 +32,11 @@ export function useSecurity() {
30
32
  // Track whether a scan has been completed (to show appropriate empty state)
31
33
  const [scanComplete, setScanComplete] = useState(false);
32
34
 
35
+ // Traffic-derived toxic flows (tools/list via HTTP proxy)
36
+ const [trafficToxicSnapshot, setTrafficToxicSnapshot] = useState(null);
37
+ const [trafficToxicLoading, setTrafficToxicLoading] = useState(false);
38
+ const [trafficToxicError, setTrafficToxicError] = useState(null);
39
+
33
40
  // Use YARA rules hook
34
41
  const yaraRules = useYaraRules();
35
42
 
@@ -88,6 +95,48 @@ export function useSecurity() {
88
95
  }
89
96
  }, []);
90
97
 
98
+ const loadTrafficToxicFlows = useCallback(async () => {
99
+ setTrafficToxicLoading(true);
100
+ setTrafficToxicError(null);
101
+ try {
102
+ const data = await fetchTrafficToxicFlows();
103
+ if (data && data.success === false) {
104
+ setTrafficToxicError(data.error || 'Could not load traffic toxic flows');
105
+ setTrafficToxicSnapshot(null);
106
+ } else if (data?.error && !data.toxicFlows) {
107
+ setTrafficToxicError(data.error);
108
+ setTrafficToxicSnapshot(null);
109
+ } else {
110
+ setTrafficToxicSnapshot(data);
111
+ }
112
+ } catch (err) {
113
+ console.error('Traffic toxic flows:', err);
114
+ setTrafficToxicError(err.message || 'Request failed');
115
+ setTrafficToxicSnapshot(null);
116
+ } finally {
117
+ setTrafficToxicLoading(false);
118
+ }
119
+ }, []);
120
+
121
+ const replayTrafficToxicFlows = useCallback(async () => {
122
+ setTrafficToxicLoading(true);
123
+ setTrafficToxicError(null);
124
+ try {
125
+ const data = await postReplayTrafficToxicFlows();
126
+ if (data.success === false || data.error) {
127
+ setTrafficToxicError(data.error || 'Replay failed');
128
+ setTrafficToxicSnapshot(null);
129
+ } else {
130
+ setTrafficToxicSnapshot(data);
131
+ }
132
+ } catch (err) {
133
+ console.error('Traffic toxic replay:', err);
134
+ setTrafficToxicError(err.message || 'Request failed');
135
+ } finally {
136
+ setTrafficToxicLoading(false);
137
+ }
138
+ }, []);
139
+
91
140
  const discoverAndScan = useCallback(async () => {
92
141
  setScanning(true);
93
142
  setError(null);
@@ -109,6 +158,7 @@ export function useSecurity() {
109
158
  await loadSummary();
110
159
  await loadScanHistory(); // Refresh history
111
160
  setScanComplete(true); // Mark scan as complete
161
+ await loadTrafficToxicFlows();
112
162
  }
113
163
  } catch (err) {
114
164
  console.error('Analysis error:', err);
@@ -116,7 +166,7 @@ export function useSecurity() {
116
166
  } finally {
117
167
  setScanning(false);
118
168
  }
119
- }, [loadFindings, loadSummary, loadScanHistory]);
169
+ }, [loadFindings, loadSummary, loadScanHistory, loadTrafficToxicFlows]);
120
170
 
121
171
  const clearFindings = useCallback(async () => {
122
172
  setClearing(true);
@@ -130,13 +180,14 @@ export function useSecurity() {
130
180
  setError(null);
131
181
  setScanComplete(false); // Reset scan complete state
132
182
  await loadScanHistory(); // Refresh history after clear
183
+ await loadTrafficToxicFlows(); // Server cleared in-memory toxic-flow registry
133
184
  }
134
185
  } catch (err) {
135
186
  console.error('Failed to clear findings:', err);
136
187
  } finally {
137
188
  setClearing(false);
138
189
  }
139
- }, [loadScanHistory]);
190
+ }, [loadScanHistory, loadTrafficToxicFlows]);
140
191
 
141
192
  const selectHistoricalScan = useCallback(async (scanId) => {
142
193
  setSelectedScanId(scanId);
@@ -160,7 +211,8 @@ export function useSecurity() {
160
211
  loadRules();
161
212
  loadScanHistory();
162
213
  checkRunningServers();
163
- }, [loadRules, loadScanHistory, checkRunningServers]);
214
+ loadTrafficToxicFlows();
215
+ }, [loadRules, loadScanHistory, checkRunningServers, loadTrafficToxicFlows]);
164
216
 
165
217
  return {
166
218
  rules,
@@ -183,6 +235,11 @@ export function useSecurity() {
183
235
  runningServersCount,
184
236
  checkRunningServers,
185
237
  scanComplete,
238
+ trafficToxicSnapshot,
239
+ trafficToxicLoading,
240
+ trafficToxicError,
241
+ loadTrafficToxicFlows,
242
+ replayTrafficToxicFlows,
186
243
  // YARA rules (spread from useYaraRules)
187
244
  ...yaraRules,
188
245
  };
@@ -62,7 +62,6 @@ function ServerControl({ status, loading, onStart, onStop, canStart }) {
62
62
  ) : (
63
63
  <button
64
64
  type="button"
65
- data-tour="start-button"
66
65
  onClick={onStart}
67
66
  disabled={loading || !canStart}
68
67
  style={{
@@ -28,17 +28,6 @@ export default function DesktopTabs({ tabs, activeTab, onTabChange, tabRefs, ind
28
28
  tabRefs.current[tab.id] = el;
29
29
  }
30
30
  }}
31
- data-tour={
32
- tab.id === 'traffic'
33
- ? 'traffic-tab'
34
- : tab.id === 'logs'
35
- ? 'logs-tab'
36
- : tab.id === 'setup'
37
- ? 'setup-tab'
38
- : tab.id === 'playground'
39
- ? 'playground-tab'
40
- : 'smart-scan-tab'
41
- }
42
31
  onClick={() => onTabChange(tab.id)}
43
32
  style={{
44
33
  padding: '14px 24px',
@@ -4,6 +4,7 @@ import {
4
4
  IconBrandStackoverflow,
5
5
  IconChevronDown,
6
6
  IconFileText,
7
+ IconKey,
7
8
  IconMenu2,
8
9
  IconNetwork,
9
10
  IconSettings,
@@ -43,3 +44,7 @@ export const ChevronDownIcon = ({ size = 16, color = 'currentColor' }) => (
43
44
  export const SecurityIcon = ({ size = 16, color = 'currentColor' }) => (
44
45
  <IconShieldCheck size={size} stroke={1.5} color={color} />
45
46
  );
47
+
48
+ export const AauthIcon = ({ size = 16, color = 'currentColor' }) => (
49
+ <IconKey size={size} stroke={1.5} color={color} />
50
+ );
@@ -4,7 +4,6 @@ import { colors, fonts } from '../theme';
4
4
  function ViewModeTabs({ viewMode, onViewModeChange }) {
5
5
  return (
6
6
  <div
7
- data-tour="view-modes"
8
7
  style={{
9
8
  display: 'flex',
10
9
  borderBottom: `1px solid ${colors.borderLight}`,
@@ -5,18 +5,35 @@ import anime from 'animejs';
5
5
  */
6
6
 
7
7
  /**
8
- * Stagger animation for list items
8
+ * Stagger animation for list items.
9
+ * @param {object} [options]
10
+ * @param {boolean} [options.fade=true] When false, rows stay at full opacity so
11
+ * traffic tables are never invisible during the tween (fixes empty screenshots
12
+ * and reduces flash for long lists).
9
13
  */
10
14
  export const staggerIn = (selector, options = {}) => {
11
- return anime({
15
+ const {
16
+ fade = true,
17
+ duration = 400,
18
+ delay = 50,
19
+ easing = 'easeOutExpo',
20
+ translateY = [20, 0],
21
+ ...rest
22
+ } = options;
23
+ const cfg = {
12
24
  targets: selector,
13
- opacity: [0, 1],
14
- translateY: [20, 0],
15
- duration: options.duration || 400,
16
- delay: anime.stagger(options.delay || 50),
17
- easing: options.easing || 'easeOutExpo',
18
- ...options,
19
- });
25
+ translateY,
26
+ duration,
27
+ delay: anime.stagger(delay),
28
+ easing,
29
+ ...rest,
30
+ };
31
+ if (fade) {
32
+ cfg.opacity = [0, 1];
33
+ } else {
34
+ cfg.opacity = 1;
35
+ }
36
+ return anime(cfg);
20
37
  };
21
38
 
22
39
  /**
@@ -1,130 +0,0 @@
1
- import { convertPacketFinding, createRuleAdapter } from '../utils/adapter.js';
2
- import { packetToText, promptToText, resourceToText, toolToText } from '../utils/text.js';
3
-
4
- const RULE_ID = 'asi01-goal-hijack';
5
- const OWASP_ID = 'ASI01';
6
- const RECOMMENDATION =
7
- 'Implement goal validation and verification. Monitor for unauthorized goal changes. Use goal isolation and protection mechanisms.';
8
-
9
- const GOAL_HIJACK_PATTERNS = [
10
- /(?:hijack|override|replace|change|modify)\s+(?:goal|objective|purpose|mission|task)/i,
11
- /(?:ignore|forget|disregard)\s+(?:original|initial|intended|primary)\s+(?:goal|objective|purpose)/i,
12
- /(?:new|different|alternative|malicious)\s+(?:goal|objective|purpose|mission)/i,
13
- /(?:steer|redirect|manipulate)\s+(?:agent|system)\s+(?:toward|to|into)/i,
14
- /(?:unauthorized|malicious|harmful)\s+(?:goal|objective|purpose|action)/i,
15
- ];
16
-
17
- function scanText(text) {
18
- if (!text) {
19
- return null;
20
- }
21
- const matches = [];
22
- for (const pattern of GOAL_HIJACK_PATTERNS) {
23
- const match = text.match(pattern);
24
- if (match) {
25
- matches.push(match[0]);
26
- }
27
- }
28
- return matches.length > 0 ? matches : null;
29
- }
30
-
31
- function buildReason(entity, matches) {
32
- return `Potential agent goal hijack in ${entity}: ${matches.join(', ')}`;
33
- }
34
-
35
- export function scanAgentic01GoalHijack(mcpData = {}) {
36
- const results = {
37
- toolFindings: [],
38
- resourceFindings: [],
39
- promptFindings: [],
40
- notablePatterns: [],
41
- recommendations: [RECOMMENDATION],
42
- };
43
-
44
- for (const tool of mcpData.tools || []) {
45
- const matches = scanText(toolToText(tool));
46
- if (matches) {
47
- results.toolFindings.push({
48
- issueType: 'Goal Hijack',
49
- name: tool?.name || 'tool',
50
- severity: 'high',
51
- reasons: [buildReason(`tool "${tool?.name || 'unknown'}"`, matches)],
52
- tags: ['goal-hijack', 'agent-manipulation'],
53
- agenticCategory: OWASP_ID,
54
- safeUseNotes:
55
- 'Review tool behavior for goal hijacking vulnerabilities. Ensure agent goals cannot be modified by tools.',
56
- });
57
- }
58
- }
59
-
60
- for (const resource of mcpData.resources || []) {
61
- const matches = scanText(resourceToText(resource));
62
- if (matches) {
63
- results.resourceFindings.push({
64
- issueType: 'Goal Hijack',
65
- uri: resource?.uri || resource?.name || 'resource',
66
- severity: 'high',
67
- reasons: [
68
- buildReason(`resource "${resource?.name || resource?.uri || 'unknown'}"`, matches),
69
- ],
70
- tags: ['goal-hijack', 'agent-manipulation'],
71
- agenticCategory: OWASP_ID,
72
- });
73
- }
74
- }
75
-
76
- for (const prompt of mcpData.prompts || []) {
77
- const matches = scanText(promptToText(prompt));
78
- if (matches) {
79
- results.promptFindings.push({
80
- issueType: 'Goal Hijack',
81
- name: prompt?.name || 'prompt',
82
- severity: 'critical',
83
- reasons: [buildReason(`prompt "${prompt?.name || 'unknown'}"`, matches)],
84
- tags: ['goal-hijack', 'agent-manipulation'],
85
- agenticCategory: OWASP_ID,
86
- });
87
- }
88
- }
89
-
90
- return results;
91
- }
92
-
93
- const adapter = createRuleAdapter(scanAgentic01GoalHijack, RULE_ID, OWASP_ID, RECOMMENDATION);
94
-
95
- export const analyzeTool = adapter.analyzeTool;
96
- export const analyzePrompt = adapter.analyzePrompt;
97
- export const analyzeResource = adapter.analyzeResource;
98
-
99
- export function analyzePacket(packet) {
100
- const text = packetToText(packet);
101
- const matches = scanText(text);
102
- if (!matches) {
103
- return [];
104
- }
105
- return [
106
- convertPacketFinding(
107
- {
108
- issueType: 'Goal Hijack',
109
- severity: 'high',
110
- title: 'Goal Hijack Pattern in Traffic',
111
- description: `Potential agent goal hijack in packet: ${matches.join(', ')}`,
112
- evidence: matches[0]?.substring(0, 50) || '',
113
- },
114
- RULE_ID,
115
- OWASP_ID,
116
- RECOMMENDATION,
117
- packet
118
- ),
119
- ];
120
- }
121
-
122
- export const ruleMetadata = {
123
- id: RULE_ID,
124
- name: 'Agent Goal Hijack Detection',
125
- owasp_id: OWASP_ID,
126
- severity: 'high',
127
- description: 'Detects attempts to hijack or modify agent goals.',
128
- source: 'static',
129
- type: 'agentic-security',
130
- };
@@ -1,129 +0,0 @@
1
- import { convertPacketFinding, createRuleAdapter } from '../utils/adapter.js';
2
- import { packetToText, promptToText, resourceToText, toolToText } from '../utils/text.js';
3
-
4
- const RULE_ID = 'asi02-tool-misuse';
5
- const OWASP_ID = 'ASI02';
6
- const RECOMMENDATION =
7
- 'Implement tool usage monitoring and restrictions. Enforce scope boundaries for tool usage. Monitor for unauthorized tool combinations.';
8
-
9
- const TOOL_MISUSE_PATTERNS = [
10
- /(?:misuse|abuse|exploit|manipulate)\s+(?:tool|function|capability|feature)/i,
11
- /(?:use|utilize|invoke)\s+(?:tool|function)\s+(?:outside|beyond|outside\s+of)\s+(?:intended|authorized|allowed)\s+(?:scope|purpose|context)/i,
12
- /(?:unauthorized|illegitimate|improper)\s+(?:tool|function)\s+(?:usage|use|invocation)/i,
13
- /(?:combine|chain|sequence)\s+(?:tools|functions)\s+(?:to|for)\s+(?:achieve|perform|execute)\s+(?:unauthorized|malicious)/i,
14
- ];
15
-
16
- function scanText(text) {
17
- if (!text) {
18
- return null;
19
- }
20
- const matches = [];
21
- for (const pattern of TOOL_MISUSE_PATTERNS) {
22
- const match = text.match(pattern);
23
- if (match) {
24
- matches.push(match[0]);
25
- }
26
- }
27
- return matches.length > 0 ? matches : null;
28
- }
29
-
30
- function buildReason(entity, matches) {
31
- return `Potential tool misuse/exploitation in ${entity}: ${matches.join(', ')}`;
32
- }
33
-
34
- export function scanAgentic02ToolMisuse(mcpData = {}) {
35
- const results = {
36
- toolFindings: [],
37
- resourceFindings: [],
38
- promptFindings: [],
39
- notablePatterns: [],
40
- recommendations: [RECOMMENDATION],
41
- };
42
-
43
- for (const tool of mcpData.tools || []) {
44
- const matches = scanText(toolToText(tool));
45
- if (matches) {
46
- results.toolFindings.push({
47
- issueType: 'Tool Misuse',
48
- name: tool?.name || 'tool',
49
- severity: 'high',
50
- reasons: [buildReason(`tool "${tool?.name || 'unknown'}"`, matches)],
51
- tags: ['tool-misuse', 'exploitation'],
52
- agenticCategory: OWASP_ID,
53
- safeUseNotes:
54
- 'Review tool usage patterns. Ensure tools are used only within their intended scope.',
55
- });
56
- }
57
- }
58
-
59
- for (const resource of mcpData.resources || []) {
60
- const matches = scanText(resourceToText(resource));
61
- if (matches) {
62
- results.resourceFindings.push({
63
- issueType: 'Tool Misuse',
64
- uri: resource?.uri || resource?.name || 'resource',
65
- severity: 'medium',
66
- reasons: [
67
- buildReason(`resource "${resource?.name || resource?.uri || 'unknown'}"`, matches),
68
- ],
69
- tags: ['tool-misuse', 'exploitation'],
70
- agenticCategory: OWASP_ID,
71
- });
72
- }
73
- }
74
-
75
- for (const prompt of mcpData.prompts || []) {
76
- const matches = scanText(promptToText(prompt));
77
- if (matches) {
78
- results.promptFindings.push({
79
- issueType: 'Tool Misuse',
80
- name: prompt?.name || 'prompt',
81
- severity: 'high',
82
- reasons: [buildReason(`prompt "${prompt?.name || 'unknown'}"`, matches)],
83
- tags: ['tool-misuse', 'exploitation'],
84
- agenticCategory: OWASP_ID,
85
- });
86
- }
87
- }
88
-
89
- return results;
90
- }
91
-
92
- const adapter = createRuleAdapter(scanAgentic02ToolMisuse, RULE_ID, OWASP_ID, RECOMMENDATION);
93
-
94
- export const analyzeTool = adapter.analyzeTool;
95
- export const analyzePrompt = adapter.analyzePrompt;
96
- export const analyzeResource = adapter.analyzeResource;
97
-
98
- export function analyzePacket(packet) {
99
- const text = packetToText(packet);
100
- const matches = scanText(text);
101
- if (!matches) {
102
- return [];
103
- }
104
- return [
105
- convertPacketFinding(
106
- {
107
- issueType: 'Tool Misuse',
108
- severity: 'high',
109
- title: 'Tool Misuse Pattern in Traffic',
110
- description: `Potential tool misuse in packet: ${matches.join(', ')}`,
111
- evidence: matches[0]?.substring(0, 50) || '',
112
- },
113
- RULE_ID,
114
- OWASP_ID,
115
- RECOMMENDATION,
116
- packet
117
- ),
118
- ];
119
- }
120
-
121
- export const ruleMetadata = {
122
- id: RULE_ID,
123
- name: 'Tool Misuse Detection',
124
- owasp_id: OWASP_ID,
125
- severity: 'high',
126
- description: 'Detects tool misuse and exploitation patterns.',
127
- source: 'static',
128
- type: 'agentic-security',
129
- };
@@ -1,130 +0,0 @@
1
- import { convertPacketFinding, createRuleAdapter } from '../utils/adapter.js';
2
- import { packetToText, promptToText, resourceToText, toolToText } from '../utils/text.js';
3
-
4
- const RULE_ID = 'asi03-identity-abuse';
5
- const OWASP_ID = 'ASI03';
6
- const RECOMMENDATION =
7
- 'Implement strict identity and privilege management. Monitor for privilege escalation. Enforce least privilege principles.';
8
-
9
- const IDENTITY_ABUSE_PATTERNS = [
10
- /(?:abuse|misuse|exploit|impersonate|spoof)\s+(?:identity|privilege|permission|access|role)/i,
11
- /(?:escalate|elevate|raise|upgrade)\s+(?:privilege|permission|access|authority)/i,
12
- /(?:assume|take|steal|hijack)\s+(?:identity|role|privilege|permission)/i,
13
- /(?:unauthorized|illegitimate|improper)\s+(?:privilege|permission|access|authority)\s+(?:use|usage|exercise)/i,
14
- /(?:bypass|circumvent|override)\s+(?:identity|authentication|authorization|access\s+control)/i,
15
- ];
16
-
17
- function scanText(text) {
18
- if (!text) {
19
- return null;
20
- }
21
- const matches = [];
22
- for (const pattern of IDENTITY_ABUSE_PATTERNS) {
23
- const match = text.match(pattern);
24
- if (match) {
25
- matches.push(match[0]);
26
- }
27
- }
28
- return matches.length > 0 ? matches : null;
29
- }
30
-
31
- function buildReason(entity, matches) {
32
- return `Potential identity/privilege abuse in ${entity}: ${matches.join(', ')}`;
33
- }
34
-
35
- export function scanAgentic03IdentityAbuse(mcpData = {}) {
36
- const results = {
37
- toolFindings: [],
38
- resourceFindings: [],
39
- promptFindings: [],
40
- notablePatterns: [],
41
- recommendations: [RECOMMENDATION],
42
- };
43
-
44
- for (const tool of mcpData.tools || []) {
45
- const matches = scanText(toolToText(tool));
46
- if (matches) {
47
- results.toolFindings.push({
48
- issueType: 'Identity Abuse',
49
- name: tool?.name || 'tool',
50
- severity: 'high',
51
- reasons: [buildReason(`tool "${tool?.name || 'unknown'}"`, matches)],
52
- tags: ['identity-abuse', 'privilege-abuse'],
53
- agenticCategory: OWASP_ID,
54
- safeUseNotes:
55
- 'Review tool privilege requirements. Ensure agents cannot abuse their assigned identities or privileges.',
56
- });
57
- }
58
- }
59
-
60
- for (const resource of mcpData.resources || []) {
61
- const matches = scanText(resourceToText(resource));
62
- if (matches) {
63
- results.resourceFindings.push({
64
- issueType: 'Identity Abuse',
65
- uri: resource?.uri || resource?.name || 'resource',
66
- severity: 'high',
67
- reasons: [
68
- buildReason(`resource "${resource?.name || resource?.uri || 'unknown'}"`, matches),
69
- ],
70
- tags: ['identity-abuse', 'privilege-abuse'],
71
- agenticCategory: OWASP_ID,
72
- });
73
- }
74
- }
75
-
76
- for (const prompt of mcpData.prompts || []) {
77
- const matches = scanText(promptToText(prompt));
78
- if (matches) {
79
- results.promptFindings.push({
80
- issueType: 'Identity Abuse',
81
- name: prompt?.name || 'prompt',
82
- severity: 'medium',
83
- reasons: [buildReason(`prompt "${prompt?.name || 'unknown'}"`, matches)],
84
- tags: ['identity-abuse', 'privilege-abuse'],
85
- agenticCategory: OWASP_ID,
86
- });
87
- }
88
- }
89
-
90
- return results;
91
- }
92
-
93
- const adapter = createRuleAdapter(scanAgentic03IdentityAbuse, RULE_ID, OWASP_ID, RECOMMENDATION);
94
-
95
- export const analyzeTool = adapter.analyzeTool;
96
- export const analyzePrompt = adapter.analyzePrompt;
97
- export const analyzeResource = adapter.analyzeResource;
98
-
99
- export function analyzePacket(packet) {
100
- const text = packetToText(packet);
101
- const matches = scanText(text);
102
- if (!matches) {
103
- return [];
104
- }
105
- return [
106
- convertPacketFinding(
107
- {
108
- issueType: 'Identity Abuse',
109
- severity: 'high',
110
- title: 'Identity Abuse Pattern in Traffic',
111
- description: `Potential identity/privilege abuse in packet: ${matches.join(', ')}`,
112
- evidence: matches[0]?.substring(0, 50) || '',
113
- },
114
- RULE_ID,
115
- OWASP_ID,
116
- RECOMMENDATION,
117
- packet
118
- ),
119
- ];
120
- }
121
-
122
- export const ruleMetadata = {
123
- id: RULE_ID,
124
- name: 'Identity Abuse Detection',
125
- owasp_id: OWASP_ID,
126
- severity: 'high',
127
- description: 'Detects identity and privilege abuse patterns.',
128
- source: 'static',
129
- type: 'agentic-security',
130
- };