@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.
- package/README.md +482 -56
- package/bin/mcp-shark.js +146 -52
- package/core/cli/AutoFixEngine.js +93 -0
- package/core/cli/ConfigScanner.js +193 -0
- package/core/cli/DataLoader.js +200 -0
- package/core/cli/DeclarativeRuleEngine.js +363 -0
- package/core/cli/DoctorCommand.js +218 -0
- package/core/cli/FixHandlers.js +222 -0
- package/core/cli/HtmlReportGenerator.js +203 -0
- package/core/cli/IdeConfigPaths.js +175 -0
- package/core/cli/ListCommand.js +255 -0
- package/core/cli/LockCommand.js +164 -0
- package/core/cli/LockDiffEngine.js +152 -0
- package/core/cli/RuleRegistryConfig.js +131 -0
- package/core/cli/ScanCommand.js +244 -0
- package/core/cli/ScanService.js +200 -0
- package/core/cli/SecretDetector.js +92 -0
- package/core/cli/SharkScoreCalculator.js +109 -0
- package/core/cli/ToolClassifications.js +51 -0
- package/core/cli/ToxicFlowAnalyzer.js +212 -0
- package/core/cli/UpdateCommand.js +188 -0
- package/core/cli/WalkthroughGenerator.js +195 -0
- package/core/cli/WatchCommand.js +129 -0
- package/core/cli/YamlRuleEngine.js +197 -0
- package/core/cli/data/rule-packs/aauth-visibility.json +117 -0
- package/core/cli/data/rule-packs/agentic-security-2026.json +180 -0
- package/core/cli/data/rule-packs/general-security.json +173 -0
- package/core/cli/data/rule-packs/owasp-mcp-2026.json +244 -0
- package/core/cli/data/rule-packs/toxic-flow-heuristics.json +21 -0
- package/core/cli/data/rule-sources.json +5 -0
- package/core/cli/data/secret-patterns.json +18 -0
- package/core/cli/data/tool-classifications.json +111 -0
- package/core/cli/data/toxic-flow-rules.json +47 -0
- package/core/cli/index.js +23 -0
- package/core/cli/output/Banner.js +52 -0
- package/core/cli/output/Formatter.js +183 -0
- package/core/cli/output/JsonFormatter.js +106 -0
- package/core/cli/output/index.js +16 -0
- package/core/cli/secureRegistryFetch.js +157 -0
- package/core/cli/symbols.js +16 -0
- package/core/configs/environment.js +3 -1
- package/core/configs/index.js +3 -64
- package/core/container/DependencyContainer.js +4 -1
- package/core/mcp-server/index.js +4 -1
- package/core/mcp-server/server/external/all.js +10 -3
- package/core/mcp-server/server/external/config.js +62 -5
- package/core/models/RequestFilters.js +3 -0
- package/core/repositories/PacketRepository.js +16 -0
- package/core/services/AuditService.js +2 -0
- package/core/services/ConfigService.js +9 -1
- package/core/services/ConfigTransformService.js +34 -2
- package/core/services/RequestService.js +58 -5
- package/core/services/ServerManagementService.js +59 -4
- package/core/services/security/StaticRulesService.js +69 -13
- package/core/services/security/TrafficAnalysisService.js +19 -1
- package/core/services/security/TrafficToxicFlowService.js +154 -0
- package/core/services/security/aauthGraph.js +199 -0
- package/core/services/security/aauthParser.js +274 -0
- package/core/services/security/aauthSelfTest.js +346 -0
- package/core/services/security/index.js +2 -1
- package/core/services/security/rules/index.js +25 -59
- package/core/services/security/rules/scans/configPermissions.js +91 -0
- package/core/services/security/rules/scans/duplicateToolNames.js +85 -0
- package/core/services/security/rules/scans/insecureTransport.js +148 -0
- package/core/services/security/rules/scans/missingContainment.js +123 -0
- package/core/services/security/rules/scans/shellEnvInjection.js +101 -0
- package/core/services/security/rules/scans/unsafeDefaults.js +99 -0
- package/core/services/security/toolsListFromTrafficParser.js +70 -0
- package/core/tui/App.js +144 -0
- package/core/tui/FindingsPanel.js +115 -0
- package/core/tui/FixPanel.js +132 -0
- package/core/tui/Header.js +51 -0
- package/core/tui/HelpBar.js +42 -0
- package/core/tui/ServersPanel.js +109 -0
- package/core/tui/ToxicFlowsPanel.js +100 -0
- package/core/tui/h.js +8 -0
- package/core/tui/index.js +11 -0
- package/core/tui/render.js +22 -0
- package/package.json +24 -16
- package/ui/dist/assets/index-D6zDrtMV.js +81 -0
- package/ui/dist/index.html +1 -1
- package/ui/server/controllers/AauthController.js +279 -0
- package/ui/server/controllers/RequestController.js +12 -1
- package/ui/server/controllers/SecurityFindingsController.js +46 -1
- package/ui/server/routes/aauth.js +18 -0
- package/ui/server/routes/requests.js +8 -1
- package/ui/server/routes/security.js +5 -1
- package/ui/server/setup.js +224 -6
- package/ui/server/swagger/paths/components.js +55 -0
- package/ui/server/swagger/paths/securityTrafficFlows.js +59 -0
- package/ui/server/swagger/paths.js +2 -2
- package/ui/server/swagger/swagger.js +5 -2
- package/ui/server.js +1 -1
- package/ui/src/App.jsx +26 -52
- package/ui/src/PacketFilters.jsx +31 -1
- package/ui/src/PacketList.jsx +2 -2
- package/ui/src/Security.jsx +10 -0
- package/ui/src/TabNavigation.jsx +8 -0
- package/ui/src/components/AAuthBadge.jsx +92 -0
- package/ui/src/components/AauthExplorer/AauthExplorerGraph.jsx +231 -0
- package/ui/src/components/AauthExplorer/AauthExplorerView.jsx +387 -0
- package/ui/src/components/AauthExplorer/NodeDetailPanel.jsx +272 -0
- package/ui/src/components/App/ActionMenu.jsx +4 -31
- package/ui/src/components/App/ApiDocsButton.jsx +0 -1
- package/ui/src/components/App/ShutdownButton.jsx +0 -1
- package/ui/src/components/App/useAppState.js +19 -26
- package/ui/src/components/DetailsTab/AAuthIdentitySection.jsx +119 -0
- package/ui/src/components/DetailsTab/RequestDetailsSection.jsx +2 -0
- package/ui/src/components/DetailsTab/ResponseDetailsSection.jsx +2 -0
- package/ui/src/components/DetectedPathsList.jsx +1 -5
- package/ui/src/components/FileInput.jsx +0 -1
- package/ui/src/components/PacketFilters/AAuthPostureFilter.jsx +81 -0
- package/ui/src/components/RequestRow/RequestRowMain.jsx +7 -1
- package/ui/src/components/Security/AAuthPosturePanel.jsx +360 -0
- package/ui/src/components/Security/ScannerContent.jsx +33 -1
- package/ui/src/components/Security/TrafficToxicFlowsPanel.jsx +253 -0
- package/ui/src/components/Security/securityApi.js +15 -0
- package/ui/src/components/Security/useSecurity.js +60 -3
- package/ui/src/components/ServerControl.jsx +0 -1
- package/ui/src/components/TabNavigation/DesktopTabs.jsx +0 -11
- package/ui/src/components/TabNavigationIcons.jsx +5 -0
- package/ui/src/components/ViewModeTabs.jsx +0 -1
- package/ui/src/utils/animations.js +26 -9
- package/core/services/security/rules/scans/agentic01GoalHijack.js +0 -130
- package/core/services/security/rules/scans/agentic02ToolMisuse.js +0 -129
- package/core/services/security/rules/scans/agentic03IdentityAbuse.js +0 -130
- package/core/services/security/rules/scans/agentic04SupplyChain.js +0 -130
- package/core/services/security/rules/scans/agentic06MemoryPoisoning.js +0 -130
- package/core/services/security/rules/scans/agentic07InsecureCommunication.js +0 -135
- package/core/services/security/rules/scans/agentic08CascadingFailures.js +0 -135
- package/core/services/security/rules/scans/agentic09TrustExploitation.js +0 -135
- package/core/services/security/rules/scans/agentic10RogueAgent.js +0 -130
- package/core/services/security/rules/scans/hardcodedSecrets.js +0 -130
- package/core/services/security/rules/scans/mcp01TokenMismanagement.js +0 -127
- package/core/services/security/rules/scans/mcp02ScopeCreep.js +0 -130
- package/core/services/security/rules/scans/mcp03ToolPoisoning.js +0 -132
- package/core/services/security/rules/scans/mcp04SupplyChain.js +0 -131
- package/core/services/security/rules/scans/mcp06PromptInjection.js +0 -200
- package/core/services/security/rules/scans/mcp07InsufficientAuth.js +0 -130
- package/core/services/security/rules/scans/mcp08LackAudit.js +0 -129
- package/core/services/security/rules/scans/mcp09ShadowServers.js +0 -129
- package/core/services/security/rules/scans/mcp10ContextInjection.js +0 -130
- package/ui/dist/assets/index-CiCSDYf-.js +0 -97
- package/ui/server/routes/help.js +0 -44
- package/ui/server/swagger/paths/help.js +0 -82
- package/ui/src/HelpGuide/HelpGuideContent.jsx +0 -118
- package/ui/src/HelpGuide/HelpGuideFooter.jsx +0 -59
- package/ui/src/HelpGuide/HelpGuideHeader.jsx +0 -57
- package/ui/src/HelpGuide.jsx +0 -78
- package/ui/src/IntroTour.jsx +0 -154
- package/ui/src/components/App/HelpButton.jsx +0 -90
- package/ui/src/components/TourOverlay.jsx +0 -117
- package/ui/src/components/TourTooltip/TourTooltipButtons.jsx +0 -120
- package/ui/src/components/TourTooltip/TourTooltipHeader.jsx +0 -71
- package/ui/src/components/TourTooltip/TourTooltipIcons.jsx +0 -54
- package/ui/src/components/TourTooltip/useTooltipPosition.js +0 -135
- package/ui/src/components/TourTooltip.jsx +0 -91
- package/ui/src/config/tourSteps.jsx +0 -140
|
@@ -2,13 +2,12 @@ import { IconMenu2, IconX } from '@tabler/icons-react';
|
|
|
2
2
|
import { useEffect, useRef, useState } from 'react';
|
|
3
3
|
import { colors, fonts } from '../../theme';
|
|
4
4
|
import ApiDocsButton from './ApiDocsButton';
|
|
5
|
-
import HelpButton from './HelpButton';
|
|
6
5
|
import ShutdownButton from './ShutdownButton';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
|
-
* Expandable action menu grouping API
|
|
8
|
+
* Expandable action menu grouping API docs and shutdown
|
|
10
9
|
*/
|
|
11
|
-
export default function ActionMenu(
|
|
10
|
+
export default function ActionMenu() {
|
|
12
11
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
13
12
|
const menuRef = useRef(null);
|
|
14
13
|
|
|
@@ -73,39 +72,13 @@ export default function ActionMenu({ onHelpClick }) {
|
|
|
73
72
|
<div ref={menuRef} style={{ position: 'fixed', bottom: '20px', right: '20px', zIndex: 9999 }}>
|
|
74
73
|
{/* API Docs Button - Top */}
|
|
75
74
|
<ApiDocsButton
|
|
76
|
-
style={{
|
|
77
|
-
...menuItemStyle,
|
|
78
|
-
bottom: isExpanded ? '180px' : '0',
|
|
79
|
-
position: 'absolute',
|
|
80
|
-
left: 'auto', // Ensure no left positioning conflicts
|
|
81
|
-
}}
|
|
82
|
-
onClick={() => setIsExpanded(false)}
|
|
83
|
-
onMouseEnter={(e) => {
|
|
84
|
-
if (isExpanded) {
|
|
85
|
-
e.currentTarget.style.transform = 'scale(1.1) translateY(0)';
|
|
86
|
-
e.currentTarget.style.boxShadow = `0 6px 16px ${colors.shadowLg}`;
|
|
87
|
-
}
|
|
88
|
-
}}
|
|
89
|
-
onMouseLeave={(e) => {
|
|
90
|
-
if (isExpanded) {
|
|
91
|
-
e.currentTarget.style.transform = 'scale(1) translateY(0)';
|
|
92
|
-
e.currentTarget.style.boxShadow = `0 4px 12px ${colors.shadowMd}`;
|
|
93
|
-
}
|
|
94
|
-
}}
|
|
95
|
-
/>
|
|
96
|
-
|
|
97
|
-
{/* Help Button - Middle */}
|
|
98
|
-
<HelpButton
|
|
99
|
-
onClick={() => {
|
|
100
|
-
onHelpClick();
|
|
101
|
-
setIsExpanded(false);
|
|
102
|
-
}}
|
|
103
75
|
style={{
|
|
104
76
|
...menuItemStyle,
|
|
105
77
|
bottom: isExpanded ? '120px' : '0',
|
|
106
78
|
position: 'absolute',
|
|
107
79
|
left: 'auto', // Ensure no left positioning conflicts
|
|
108
80
|
}}
|
|
81
|
+
onClick={() => setIsExpanded(false)}
|
|
109
82
|
onMouseEnter={(e) => {
|
|
110
83
|
if (isExpanded) {
|
|
111
84
|
e.currentTarget.style.transform = 'scale(1.1) translateY(0)';
|
|
@@ -120,7 +93,7 @@ export default function ActionMenu({ onHelpClick }) {
|
|
|
120
93
|
}}
|
|
121
94
|
/>
|
|
122
95
|
|
|
123
|
-
{/* Shutdown Button
|
|
96
|
+
{/* Shutdown Button — closest to main toggle */}
|
|
124
97
|
<ShutdownButton
|
|
125
98
|
style={{
|
|
126
99
|
...menuItemStyle,
|
|
@@ -22,9 +22,27 @@ function appendFilterParams(queryParams, filters) {
|
|
|
22
22
|
if (filters.jsonrpcId) {
|
|
23
23
|
queryParams.append('jsonrpcId', filters.jsonrpcId);
|
|
24
24
|
}
|
|
25
|
+
if (filters.aauthPosture) {
|
|
26
|
+
queryParams.append('aauthPosture', filters.aauthPosture);
|
|
27
|
+
}
|
|
28
|
+
if (filters.aauthAgent) {
|
|
29
|
+
queryParams.append('aauthAgent', filters.aauthAgent);
|
|
30
|
+
}
|
|
31
|
+
if (filters.aauthMission) {
|
|
32
|
+
queryParams.append('aauthMission', filters.aauthMission);
|
|
33
|
+
}
|
|
25
34
|
}
|
|
26
35
|
|
|
27
|
-
const VALID_TABS = [
|
|
36
|
+
const VALID_TABS = [
|
|
37
|
+
'traffic',
|
|
38
|
+
'logs',
|
|
39
|
+
'setup',
|
|
40
|
+
'playground',
|
|
41
|
+
'security',
|
|
42
|
+
'aauth-explorer',
|
|
43
|
+
'smart-scan',
|
|
44
|
+
'shutdown',
|
|
45
|
+
];
|
|
28
46
|
const DEFAULT_TAB = 'traffic';
|
|
29
47
|
|
|
30
48
|
function getTabFromHash() {
|
|
@@ -47,8 +65,6 @@ export function useAppState() {
|
|
|
47
65
|
const [filters, setFilters] = useState({});
|
|
48
66
|
const [stats, setStats] = useState(null);
|
|
49
67
|
const [firstRequestTime, setFirstRequestTime] = useState(null);
|
|
50
|
-
const [showTour, setShowTour] = useState(false);
|
|
51
|
-
const [tourDismissed, setTourDismissed] = useState(true);
|
|
52
68
|
const wsRef = useRef(null);
|
|
53
69
|
const prevTabRef = useRef(activeTab);
|
|
54
70
|
const filtersRef = useRef(filters);
|
|
@@ -117,25 +133,6 @@ export function useAppState() {
|
|
|
117
133
|
};
|
|
118
134
|
|
|
119
135
|
useEffect(() => {
|
|
120
|
-
const checkTourState = async () => {
|
|
121
|
-
try {
|
|
122
|
-
const response = await fetch('/api/help/state');
|
|
123
|
-
const data = await response.json();
|
|
124
|
-
setTourDismissed(data.dismissed || data.tourCompleted);
|
|
125
|
-
if (!data.dismissed && !data.tourCompleted) {
|
|
126
|
-
setTimeout(() => {
|
|
127
|
-
setShowTour(true);
|
|
128
|
-
}, 500);
|
|
129
|
-
}
|
|
130
|
-
} catch (error) {
|
|
131
|
-
console.error('Failed to load tour state:', error);
|
|
132
|
-
setTimeout(() => {
|
|
133
|
-
setShowTour(true);
|
|
134
|
-
}, 500);
|
|
135
|
-
setTourDismissed(false);
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
|
|
139
136
|
const initData = async () => {
|
|
140
137
|
try {
|
|
141
138
|
const queryParams = new URLSearchParams();
|
|
@@ -165,7 +162,6 @@ export function useAppState() {
|
|
|
165
162
|
}
|
|
166
163
|
};
|
|
167
164
|
|
|
168
|
-
checkTourState();
|
|
169
165
|
initData();
|
|
170
166
|
|
|
171
167
|
const wsUrl = import.meta.env.DEV
|
|
@@ -289,9 +285,6 @@ export function useAppState() {
|
|
|
289
285
|
setFilters,
|
|
290
286
|
stats,
|
|
291
287
|
firstRequestTime,
|
|
292
|
-
showTour,
|
|
293
|
-
setShowTour,
|
|
294
|
-
tourDismissed,
|
|
295
288
|
prevTabRef,
|
|
296
289
|
wsRef,
|
|
297
290
|
loadRequests,
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { colors, fonts } from '../../theme';
|
|
2
|
+
import AAuthBadge from '../AAuthBadge';
|
|
3
|
+
import CollapsibleSection from '../CollapsibleSection';
|
|
4
|
+
|
|
5
|
+
function Field({ label, value, mono = false }) {
|
|
6
|
+
if (!value) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
return (
|
|
10
|
+
<div style={{ display: 'flex', gap: '12px', padding: '4px 0' }}>
|
|
11
|
+
<div
|
|
12
|
+
style={{
|
|
13
|
+
minWidth: '140px',
|
|
14
|
+
color: colors.textSecondary,
|
|
15
|
+
fontSize: '11px',
|
|
16
|
+
fontFamily: fonts.body,
|
|
17
|
+
fontWeight: 500,
|
|
18
|
+
textTransform: 'uppercase',
|
|
19
|
+
letterSpacing: '0.04em',
|
|
20
|
+
}}
|
|
21
|
+
>
|
|
22
|
+
{label}
|
|
23
|
+
</div>
|
|
24
|
+
<div
|
|
25
|
+
style={{
|
|
26
|
+
color: colors.textPrimary,
|
|
27
|
+
fontSize: '12px',
|
|
28
|
+
fontFamily: mono ? fonts.mono : fonts.body,
|
|
29
|
+
wordBreak: 'break-all',
|
|
30
|
+
}}
|
|
31
|
+
>
|
|
32
|
+
{value}
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Renders an AAuth Identity panel for a single packet (request or response).
|
|
40
|
+
* Always read-only and observation-only — values describe what was on the
|
|
41
|
+
* wire, never claims of cryptographic validity.
|
|
42
|
+
*/
|
|
43
|
+
export default function AAuthIdentitySection({ aauth, titleColor }) {
|
|
44
|
+
if (!aauth) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const hasAnySignal =
|
|
49
|
+
aauth.posture !== 'none' ||
|
|
50
|
+
aauth.agent ||
|
|
51
|
+
aauth.mission ||
|
|
52
|
+
aauth.requirement ||
|
|
53
|
+
aauth.sig_present ||
|
|
54
|
+
aauth.error;
|
|
55
|
+
|
|
56
|
+
if (!hasAnySignal) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const coveredText =
|
|
61
|
+
Array.isArray(aauth.sig_covered) && aauth.sig_covered.length > 0
|
|
62
|
+
? aauth.sig_covered.join(', ')
|
|
63
|
+
: null;
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<CollapsibleSection
|
|
67
|
+
title={
|
|
68
|
+
<span style={{ display: 'inline-flex', alignItems: 'center', gap: '8px' }}>
|
|
69
|
+
Identity
|
|
70
|
+
<AAuthBadge aauth={aauth} size="sm" />
|
|
71
|
+
</span>
|
|
72
|
+
}
|
|
73
|
+
titleColor={titleColor || colors.accentBlue}
|
|
74
|
+
defaultExpanded={true}
|
|
75
|
+
>
|
|
76
|
+
<div
|
|
77
|
+
style={{
|
|
78
|
+
padding: '12px 14px',
|
|
79
|
+
background: colors.bgSecondary,
|
|
80
|
+
border: `1px solid ${colors.borderLight}`,
|
|
81
|
+
borderRadius: '8px',
|
|
82
|
+
}}
|
|
83
|
+
>
|
|
84
|
+
<Field label="Agent" value={aauth.agent} mono />
|
|
85
|
+
<Field label="Mission" value={aauth.mission} mono />
|
|
86
|
+
<Field label="Signature" value={aauth.sig_present ? 'present (not verified)' : null} />
|
|
87
|
+
<Field label="Algorithm" value={aauth.sig_alg} mono />
|
|
88
|
+
<Field label="Key ID" value={aauth.sig_keyid_short || aauth.sig_keyid} mono />
|
|
89
|
+
<Field label="Key thumbprint" value={aauth.key_thumbprint_short} mono />
|
|
90
|
+
<Field label="Covered components" value={coveredText} mono />
|
|
91
|
+
<Field label="Requirement" value={aauth.requirement} />
|
|
92
|
+
<Field label="Signature error" value={aauth.error} />
|
|
93
|
+
<div
|
|
94
|
+
style={{
|
|
95
|
+
marginTop: '10px',
|
|
96
|
+
paddingTop: '8px',
|
|
97
|
+
borderTop: `1px dashed ${colors.borderLight}`,
|
|
98
|
+
color: colors.textTertiary,
|
|
99
|
+
fontSize: '11px',
|
|
100
|
+
fontFamily: fonts.body,
|
|
101
|
+
lineHeight: 1.45,
|
|
102
|
+
}}
|
|
103
|
+
>
|
|
104
|
+
mcp-shark records AAuth signals as observed only. No signatures are cryptographically
|
|
105
|
+
verified. Learn more at{' '}
|
|
106
|
+
<a
|
|
107
|
+
href="https://www.aauth.dev"
|
|
108
|
+
target="_blank"
|
|
109
|
+
rel="noreferrer noopener"
|
|
110
|
+
style={{ color: colors.accentBlue }}
|
|
111
|
+
>
|
|
112
|
+
aauth.dev
|
|
113
|
+
</a>
|
|
114
|
+
.
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
</CollapsibleSection>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { colors } from '../../theme';
|
|
2
2
|
import CollapsibleSection from '../CollapsibleSection';
|
|
3
|
+
import AAuthIdentitySection from './AAuthIdentitySection';
|
|
3
4
|
import BodySection from './BodySection';
|
|
4
5
|
import CollapsibleRequestResponse from './CollapsibleRequestResponse';
|
|
5
6
|
import HeadersSection from './HeadersSection';
|
|
@@ -21,6 +22,7 @@ export default function RequestDetailsSection({ request, requestHeaders, request
|
|
|
21
22
|
<InfoSection data={request} titleColor={colors.accentBlue} />
|
|
22
23
|
<NetworkInfoSection data={request} showUserAgent={true} />
|
|
23
24
|
<ProtocolInfoSection data={request} titleColor={colors.accentBlue} />
|
|
25
|
+
<AAuthIdentitySection aauth={request.aauth} titleColor={colors.accentBlue} />
|
|
24
26
|
<HeadersSection headers={requestHeaders} titleColor={colors.accentBlue} />
|
|
25
27
|
<BodySection body={requestBody} titleColor={colors.accentBlue} />
|
|
26
28
|
{request.jsonrpc_params && (
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { colors, fonts } from '../../theme';
|
|
2
2
|
import CollapsibleSection from '../CollapsibleSection';
|
|
3
|
+
import AAuthIdentitySection from './AAuthIdentitySection';
|
|
3
4
|
import BodySection from './BodySection';
|
|
4
5
|
import CollapsibleRequestResponse from './CollapsibleRequestResponse';
|
|
5
6
|
import HeadersSection from './HeadersSection';
|
|
@@ -21,6 +22,7 @@ export default function ResponseDetailsSection({ response, responseHeaders, resp
|
|
|
21
22
|
<InfoSection data={response} titleColor={colors.accentGreen} />
|
|
22
23
|
<NetworkInfoSection data={response} />
|
|
23
24
|
<ProtocolInfoSection data={response} titleColor={colors.accentGreen} />
|
|
25
|
+
<AAuthIdentitySection aauth={response.aauth} titleColor={colors.accentGreen} />
|
|
24
26
|
<HeadersSection headers={responseHeaders} titleColor={colors.accentGreen} />
|
|
25
27
|
<BodySection body={responseBody} titleColor={colors.accentGreen} />
|
|
26
28
|
{response.jsonrpc_result && (
|
|
@@ -62,15 +62,11 @@ function DetectedPathsList({ detectedPaths, detecting, onDetect, onSelect, onVie
|
|
|
62
62
|
)}
|
|
63
63
|
</button>
|
|
64
64
|
</div>
|
|
65
|
-
<div
|
|
66
|
-
data-tour="detected-editors"
|
|
67
|
-
style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}
|
|
68
|
-
>
|
|
65
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}>
|
|
69
66
|
{detectedPaths.map((item, idx) => (
|
|
70
67
|
<button
|
|
71
68
|
key={`${item.editor}-${item.path}-${idx}`}
|
|
72
69
|
type="button"
|
|
73
|
-
data-tour={idx === 0 ? 'first-detected-editor' : undefined}
|
|
74
70
|
onClick={() => onSelect(item.path)}
|
|
75
71
|
onDoubleClick={() => {
|
|
76
72
|
if (item.exists) {
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { colors, fonts } from '../../theme';
|
|
2
|
+
|
|
3
|
+
const POSTURES = [
|
|
4
|
+
{ id: null, label: 'All', dotColor: colors.textTertiary },
|
|
5
|
+
{ id: 'signed', label: 'Signed', dotColor: colors.success },
|
|
6
|
+
{ id: 'aauth-aware', label: 'AAuth-aware', dotColor: colors.accentBlue },
|
|
7
|
+
{ id: 'bearer', label: 'Bearer', dotColor: colors.warning },
|
|
8
|
+
{ id: 'none', label: 'No auth', dotColor: colors.textTertiary },
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Segmented selector that filters captured traffic by AAuth posture.
|
|
13
|
+
* Visualization-only — does not change the underlying traffic in any way.
|
|
14
|
+
*/
|
|
15
|
+
export default function AAuthPostureFilter({ value, onChange }) {
|
|
16
|
+
return (
|
|
17
|
+
<div
|
|
18
|
+
title="Filter packets by observed AAuth posture (no verification)"
|
|
19
|
+
style={{
|
|
20
|
+
display: 'inline-flex',
|
|
21
|
+
alignItems: 'center',
|
|
22
|
+
gap: 0,
|
|
23
|
+
background: colors.bgPrimary,
|
|
24
|
+
border: `1px solid ${colors.borderLight}`,
|
|
25
|
+
borderRadius: '999px',
|
|
26
|
+
padding: '2px',
|
|
27
|
+
height: '34px',
|
|
28
|
+
}}
|
|
29
|
+
>
|
|
30
|
+
<span
|
|
31
|
+
style={{
|
|
32
|
+
fontSize: '10px',
|
|
33
|
+
fontFamily: fonts.body,
|
|
34
|
+
color: colors.textTertiary,
|
|
35
|
+
textTransform: 'uppercase',
|
|
36
|
+
letterSpacing: '0.05em',
|
|
37
|
+
padding: '0 8px 0 10px',
|
|
38
|
+
}}
|
|
39
|
+
>
|
|
40
|
+
AAuth
|
|
41
|
+
</span>
|
|
42
|
+
{POSTURES.map((option) => {
|
|
43
|
+
const active = (value || null) === (option.id || null);
|
|
44
|
+
return (
|
|
45
|
+
<button
|
|
46
|
+
key={option.label}
|
|
47
|
+
type="button"
|
|
48
|
+
onClick={() => onChange(option.id)}
|
|
49
|
+
style={{
|
|
50
|
+
display: 'inline-flex',
|
|
51
|
+
alignItems: 'center',
|
|
52
|
+
gap: '6px',
|
|
53
|
+
padding: '4px 10px',
|
|
54
|
+
border: 'none',
|
|
55
|
+
cursor: 'pointer',
|
|
56
|
+
fontSize: '11px',
|
|
57
|
+
fontFamily: fonts.body,
|
|
58
|
+
fontWeight: active ? 600 : 500,
|
|
59
|
+
color: active ? colors.textPrimary : colors.textSecondary,
|
|
60
|
+
background: active ? colors.bgSelected : 'transparent',
|
|
61
|
+
borderRadius: '999px',
|
|
62
|
+
transition: 'background-color 0.15s ease',
|
|
63
|
+
}}
|
|
64
|
+
>
|
|
65
|
+
<span
|
|
66
|
+
aria-hidden="true"
|
|
67
|
+
style={{
|
|
68
|
+
width: '6px',
|
|
69
|
+
height: '6px',
|
|
70
|
+
borderRadius: '50%',
|
|
71
|
+
background: option.dotColor,
|
|
72
|
+
display: 'inline-block',
|
|
73
|
+
}}
|
|
74
|
+
/>
|
|
75
|
+
{option.label}
|
|
76
|
+
</button>
|
|
77
|
+
);
|
|
78
|
+
})}
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
getEndpoint,
|
|
7
7
|
getSourceDest,
|
|
8
8
|
} from '../../utils/requestUtils.js';
|
|
9
|
+
import AAuthBadge from '../AAuthBadge';
|
|
9
10
|
|
|
10
11
|
const ChevronDown = ({ size = 12, rotated = false }) => (
|
|
11
12
|
<IconChevronDown
|
|
@@ -182,7 +183,12 @@ export default function RequestRowMain({
|
|
|
182
183
|
fontWeight: '500',
|
|
183
184
|
}}
|
|
184
185
|
>
|
|
185
|
-
{
|
|
186
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'wrap' }}>
|
|
187
|
+
<span>{dest}</span>
|
|
188
|
+
{request.aauth && request.aauth.posture !== 'none' && (
|
|
189
|
+
<AAuthBadge aauth={request.aauth} size="sm" showLabel={false} />
|
|
190
|
+
)}
|
|
191
|
+
</div>
|
|
186
192
|
</td>
|
|
187
193
|
<td
|
|
188
194
|
style={{
|