dsh-pentester 2.0.0 → 2.3.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/README.md +54 -6
- package/agents/vulnerability/profile.yml +6 -3
- package/lib/build-id.json +1 -1
- package/lib/client.js +680 -184
- package/lib/client.js.map +3 -3
- package/lib/index.js +107 -44
- package/lib/index.js.map +1 -1
- package/package.json +5 -3
package/lib/client.js
CHANGED
|
@@ -36,7 +36,6 @@ __export(plugin_exports, {
|
|
|
36
36
|
getPentesterEndpointState: () => getPentesterEndpointState2,
|
|
37
37
|
getRemoteMountError: () => getRemoteMountError,
|
|
38
38
|
inject: () => inject,
|
|
39
|
-
isBuildOk: () => isBuildOk,
|
|
40
39
|
isRemoteMounted: () => isRemoteMounted,
|
|
41
40
|
setPentesterEndpointState: () => setPentesterEndpointState
|
|
42
41
|
});
|
|
@@ -14772,7 +14771,7 @@ function resetPentesterEndpointState() {
|
|
|
14772
14771
|
pentesterEndpointState = "unknown";
|
|
14773
14772
|
}
|
|
14774
14773
|
}
|
|
14775
|
-
function pentesterViewCommand(face, input2, timeoutMs =
|
|
14774
|
+
function pentesterViewCommand(face, input2, timeoutMs = 3e4) {
|
|
14776
14775
|
if (face === void 0 || typeof face.command !== "function") {
|
|
14777
14776
|
return Promise.resolve({ ok: false, error: "rpc_unavailable", code: "rpc_unavailable" });
|
|
14778
14777
|
}
|
|
@@ -16118,170 +16117,587 @@ var SEVERITY_COLORS = {
|
|
|
16118
16117
|
low: "#3b82f6",
|
|
16119
16118
|
info: "#6b7280"
|
|
16120
16119
|
};
|
|
16121
|
-
|
|
16122
|
-
|
|
16123
|
-
|
|
16124
|
-
|
|
16125
|
-
{ style: { marginBottom: "4px" } },
|
|
16126
|
-
import_react10.default.createElement(
|
|
16127
|
-
"div",
|
|
16128
|
-
{
|
|
16129
|
-
onClick: () => setOpen(!open),
|
|
16130
|
-
style: {
|
|
16131
|
-
display: "flex",
|
|
16132
|
-
alignItems: "center",
|
|
16133
|
-
gap: "6px",
|
|
16134
|
-
padding: "6px 8px",
|
|
16135
|
-
cursor: "pointer",
|
|
16136
|
-
borderRadius: "4px",
|
|
16137
|
-
fontSize: "13px",
|
|
16138
|
-
fontWeight: 600,
|
|
16139
|
-
color: "var(--dsw-fg)",
|
|
16140
|
-
userSelect: "none"
|
|
16141
|
-
}
|
|
16142
|
-
},
|
|
16143
|
-
import_react10.default.createElement("span", {
|
|
16144
|
-
style: { fontSize: "12px", transition: "transform 0.15s", transform: open ? "rotate(90deg)" : "rotate(0deg)" }
|
|
16145
|
-
}, "\u25B6"),
|
|
16146
|
-
import_react10.default.createElement("span", null, props.title)
|
|
16147
|
-
),
|
|
16148
|
-
open && import_react10.default.createElement("div", { style: { paddingLeft: "20px" } }, props.children)
|
|
16149
|
-
);
|
|
16150
|
-
}
|
|
16120
|
+
var FILTER_TABS = [
|
|
16121
|
+
{ id: "all", label: "All" },
|
|
16122
|
+
...SEVERITY_ORDER.map((s) => ({ id: s, label: SEVERITY_LABELS[s] }))
|
|
16123
|
+
];
|
|
16151
16124
|
function FindingsView(props) {
|
|
16152
|
-
const { snapshot, command, sessionId } = props;
|
|
16153
|
-
const
|
|
16125
|
+
const { snapshot, command, sessionId, onNavigate } = props;
|
|
16126
|
+
const findings = snapshot?.findings ?? [];
|
|
16127
|
+
const [selectedId, setSelectedId] = (0, import_react10.useState)(null);
|
|
16154
16128
|
const [detailContent, setDetailContent] = (0, import_react10.useState)(null);
|
|
16155
16129
|
const [detailLoading, setDetailLoading] = (0, import_react10.useState)(false);
|
|
16156
|
-
const
|
|
16157
|
-
const
|
|
16158
|
-
|
|
16159
|
-
|
|
16160
|
-
|
|
16161
|
-
|
|
16162
|
-
|
|
16163
|
-
|
|
16164
|
-
|
|
16165
|
-
}
|
|
16166
|
-
return groups;
|
|
16130
|
+
const [detailError, setDetailError] = (0, import_react10.useState)(false);
|
|
16131
|
+
const [filter, setFilter] = (0, import_react10.useState)("all");
|
|
16132
|
+
const [search, setSearch] = (0, import_react10.useState)("");
|
|
16133
|
+
const [focusDone, setFocusDone] = (0, import_react10.useState)(false);
|
|
16134
|
+
const loadSeqRef = (0, import_react10.useRef)(0);
|
|
16135
|
+
const severityCounts = (0, import_react10.useMemo)(() => {
|
|
16136
|
+
const counts = { critical: 0, high: 0, medium: 0, low: 0, info: 0 };
|
|
16137
|
+
for (const f of findings) counts[f.severity]++;
|
|
16138
|
+
return counts;
|
|
16167
16139
|
}, [findings]);
|
|
16168
|
-
const
|
|
16169
|
-
|
|
16140
|
+
const filtered = (0, import_react10.useMemo)(() => {
|
|
16141
|
+
let list = [...findings];
|
|
16142
|
+
if (filter !== "all") list = list.filter((f) => f.severity === filter);
|
|
16143
|
+
if (search.trim() !== "") {
|
|
16144
|
+
const q = search.toLowerCase();
|
|
16145
|
+
list = list.filter(
|
|
16146
|
+
(f) => f.title.toLowerCase().includes(q) || (f.affectedAsset?.toLowerCase().includes(q) ?? false) || f.sourceStage.toLowerCase().includes(q) || f.sourceDelegationId.toLowerCase().includes(q)
|
|
16147
|
+
);
|
|
16148
|
+
}
|
|
16149
|
+
const orderMap = new Map(SEVERITY_ORDER.map((s, i) => [s, i]));
|
|
16150
|
+
list.sort((a, b) => {
|
|
16151
|
+
const oa = orderMap.get(a.severity) ?? 99;
|
|
16152
|
+
const ob = orderMap.get(b.severity) ?? 99;
|
|
16153
|
+
if (oa !== ob) return oa - ob;
|
|
16154
|
+
return 0;
|
|
16155
|
+
});
|
|
16156
|
+
return list;
|
|
16157
|
+
}, [findings, filter, search]);
|
|
16158
|
+
const selectedFinding = (0, import_react10.useMemo)(
|
|
16159
|
+
() => selectedId !== null ? findings.find((f) => f.id === selectedId) ?? null : null,
|
|
16160
|
+
[findings, selectedId]
|
|
16161
|
+
);
|
|
16162
|
+
(0, import_react10.useEffect)(() => {
|
|
16163
|
+
if (props.focusFinding !== void 0 && !focusDone) {
|
|
16164
|
+
const match = findings.find((f) => f.id === props.focusFinding);
|
|
16165
|
+
if (match !== void 0) {
|
|
16166
|
+
setSelectedId(match.id);
|
|
16167
|
+
setFilter("all");
|
|
16168
|
+
setSearch("");
|
|
16169
|
+
setFocusDone(true);
|
|
16170
|
+
}
|
|
16171
|
+
}
|
|
16172
|
+
}, [props.focusFinding, focusDone, findings]);
|
|
16173
|
+
(0, import_react10.useEffect)(() => {
|
|
16174
|
+
setFocusDone(false);
|
|
16175
|
+
}, [props.focusFinding]);
|
|
16176
|
+
const loadDetail = (0, import_react10.useCallback)(async (finding) => {
|
|
16177
|
+
setSelectedId(finding.id);
|
|
16170
16178
|
setDetailContent(null);
|
|
16171
16179
|
setDetailLoading(true);
|
|
16180
|
+
setDetailError(false);
|
|
16181
|
+
const seq = ++loadSeqRef.current;
|
|
16172
16182
|
try {
|
|
16173
16183
|
const result = await command({
|
|
16174
16184
|
kind: "readFinding",
|
|
16175
16185
|
detailFile: finding.detailFile,
|
|
16176
16186
|
sessionId
|
|
16177
16187
|
});
|
|
16188
|
+
if (seq !== loadSeqRef.current) return;
|
|
16178
16189
|
if (result.ok) {
|
|
16179
16190
|
const fileResult = result.value;
|
|
16180
16191
|
setDetailContent(fileResult.content ?? "");
|
|
16192
|
+
setDetailError(false);
|
|
16181
16193
|
} else {
|
|
16182
|
-
setDetailContent(
|
|
16194
|
+
setDetailContent(null);
|
|
16195
|
+
setDetailError(true);
|
|
16183
16196
|
}
|
|
16184
16197
|
} catch {
|
|
16185
|
-
|
|
16198
|
+
if (seq !== loadSeqRef.current) return;
|
|
16199
|
+
setDetailContent(null);
|
|
16200
|
+
setDetailError(true);
|
|
16186
16201
|
} finally {
|
|
16187
|
-
setDetailLoading(false);
|
|
16202
|
+
if (seq === loadSeqRef.current) setDetailLoading(false);
|
|
16188
16203
|
}
|
|
16189
16204
|
}, [command, sessionId]);
|
|
16190
|
-
|
|
16191
|
-
|
|
16192
|
-
|
|
16193
|
-
|
|
16194
|
-
|
|
16195
|
-
|
|
16196
|
-
|
|
16197
|
-
|
|
16198
|
-
|
|
16199
|
-
|
|
16200
|
-
|
|
16201
|
-
|
|
16202
|
-
|
|
16203
|
-
|
|
16205
|
+
return import_react10.default.createElement(
|
|
16206
|
+
"div",
|
|
16207
|
+
{
|
|
16208
|
+
style: {
|
|
16209
|
+
display: "flex",
|
|
16210
|
+
flexDirection: "column",
|
|
16211
|
+
height: "100%",
|
|
16212
|
+
minHeight: 0,
|
|
16213
|
+
overflow: "hidden"
|
|
16214
|
+
}
|
|
16215
|
+
},
|
|
16216
|
+
// ── Top: severity summary strip ──────────────────────────────────────
|
|
16217
|
+
import_react10.default.createElement(SeveritySummary, {
|
|
16218
|
+
total: findings.length,
|
|
16219
|
+
counts: severityCounts,
|
|
16220
|
+
activeFilter: filter,
|
|
16221
|
+
onFilter: setFilter
|
|
16222
|
+
}),
|
|
16223
|
+
// ── Bottom: split view ───────────────────────────────────────────────
|
|
16224
|
+
import_react10.default.createElement(
|
|
16225
|
+
"div",
|
|
16226
|
+
{
|
|
16227
|
+
style: {
|
|
16228
|
+
flex: 1,
|
|
16229
|
+
minHeight: 0,
|
|
16230
|
+
display: "flex",
|
|
16231
|
+
overflow: "hidden"
|
|
16232
|
+
}
|
|
16233
|
+
},
|
|
16234
|
+
// ── Left: Navigator ───────────────────────────────────────────────
|
|
16235
|
+
import_react10.default.createElement(
|
|
16204
16236
|
"div",
|
|
16205
16237
|
{
|
|
16206
|
-
key: finding.id,
|
|
16207
16238
|
style: {
|
|
16239
|
+
flex: "0 0 340px",
|
|
16240
|
+
minWidth: "280px",
|
|
16241
|
+
maxWidth: "380px",
|
|
16242
|
+
minHeight: 0,
|
|
16208
16243
|
display: "flex",
|
|
16244
|
+
flexDirection: "column",
|
|
16245
|
+
overflow: "hidden",
|
|
16246
|
+
borderRight: "1px solid var(--dsw-alias-border-l2)"
|
|
16247
|
+
}
|
|
16248
|
+
},
|
|
16249
|
+
// Search + filter (fixed header)
|
|
16250
|
+
import_react10.default.createElement(
|
|
16251
|
+
"div",
|
|
16252
|
+
{
|
|
16253
|
+
style: {
|
|
16254
|
+
flex: "none",
|
|
16255
|
+
padding: "8px 12px 4px"
|
|
16256
|
+
}
|
|
16257
|
+
},
|
|
16258
|
+
import_react10.default.createElement("input", {
|
|
16259
|
+
type: "text",
|
|
16260
|
+
placeholder: "Search findings...",
|
|
16261
|
+
value: search,
|
|
16262
|
+
onChange: (e) => setSearch(e.target.value),
|
|
16263
|
+
style: {
|
|
16264
|
+
width: "100%",
|
|
16265
|
+
boxSizing: "border-box",
|
|
16266
|
+
padding: "6px 10px",
|
|
16267
|
+
border: "1px solid var(--dsw-alias-border-l2)",
|
|
16268
|
+
borderRadius: "6px",
|
|
16269
|
+
background: "var(--dsw-alias-bg-base)",
|
|
16270
|
+
color: "var(--dsw-alias-label-primary)",
|
|
16271
|
+
fontSize: "13px",
|
|
16272
|
+
outline: "none",
|
|
16273
|
+
marginBottom: "4px"
|
|
16274
|
+
}
|
|
16275
|
+
}),
|
|
16276
|
+
import_react10.default.createElement(PentesterTabBar, {
|
|
16277
|
+
items: FILTER_TABS,
|
|
16278
|
+
active: filter,
|
|
16279
|
+
onSelect: (id) => setFilter(id),
|
|
16280
|
+
variant: "compact"
|
|
16281
|
+
})
|
|
16282
|
+
),
|
|
16283
|
+
// FindingList (scrollable)
|
|
16284
|
+
import_react10.default.createElement(
|
|
16285
|
+
"div",
|
|
16286
|
+
{
|
|
16287
|
+
style: {
|
|
16288
|
+
flex: 1,
|
|
16289
|
+
minHeight: 0,
|
|
16290
|
+
overflowY: "auto",
|
|
16291
|
+
overflowX: "hidden",
|
|
16292
|
+
overscrollBehaviorY: "contain",
|
|
16293
|
+
scrollbarGutter: "stable"
|
|
16294
|
+
}
|
|
16295
|
+
},
|
|
16296
|
+
filtered.length === 0 ? import_react10.default.createElement("div", {
|
|
16297
|
+
style: {
|
|
16298
|
+
padding: "24px 12px",
|
|
16299
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
16300
|
+
fontSize: "13px",
|
|
16301
|
+
textAlign: "center"
|
|
16302
|
+
}
|
|
16303
|
+
}, findings.length === 0 ? "No findings yet" : "No matching findings") : filtered.map(
|
|
16304
|
+
(finding) => import_react10.default.createElement(FindingRow, {
|
|
16305
|
+
key: finding.id,
|
|
16306
|
+
finding,
|
|
16307
|
+
isSelected: finding.id === selectedId,
|
|
16308
|
+
onClick: () => loadDetail(finding)
|
|
16309
|
+
})
|
|
16310
|
+
)
|
|
16311
|
+
)
|
|
16312
|
+
),
|
|
16313
|
+
// ── Right: Detail ──────────────────────────────────────────────────
|
|
16314
|
+
import_react10.default.createElement(
|
|
16315
|
+
"div",
|
|
16316
|
+
{
|
|
16317
|
+
style: {
|
|
16318
|
+
flex: 1,
|
|
16319
|
+
minWidth: 0,
|
|
16320
|
+
minHeight: 0,
|
|
16321
|
+
display: "flex",
|
|
16322
|
+
flexDirection: "column",
|
|
16323
|
+
overflow: "hidden"
|
|
16324
|
+
}
|
|
16325
|
+
},
|
|
16326
|
+
selectedFinding === null ? import_react10.default.createElement(
|
|
16327
|
+
"div",
|
|
16328
|
+
{
|
|
16329
|
+
style: {
|
|
16330
|
+
flex: 1,
|
|
16331
|
+
display: "flex",
|
|
16332
|
+
alignItems: "center",
|
|
16333
|
+
justifyContent: "center",
|
|
16334
|
+
flexDirection: "column",
|
|
16335
|
+
gap: "8px",
|
|
16336
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
16337
|
+
fontSize: "13px"
|
|
16338
|
+
}
|
|
16339
|
+
},
|
|
16340
|
+
findings.length === 0 ? import_react10.default.createElement(
|
|
16341
|
+
import_react10.default.Fragment,
|
|
16342
|
+
null,
|
|
16343
|
+
import_react10.default.createElement("div", { style: { fontWeight: 500, color: "var(--dsw-alias-label-primary)" } }, "No findings yet"),
|
|
16344
|
+
import_react10.default.createElement("div", null, "Validated findings will appear here as the assessment progresses.")
|
|
16345
|
+
) : "Select a finding to inspect"
|
|
16346
|
+
) : import_react10.default.createElement(FindingDetail, {
|
|
16347
|
+
finding: selectedFinding,
|
|
16348
|
+
content: detailContent,
|
|
16349
|
+
loading: detailLoading,
|
|
16350
|
+
error: detailError,
|
|
16351
|
+
onNavigate
|
|
16352
|
+
})
|
|
16353
|
+
)
|
|
16354
|
+
)
|
|
16355
|
+
);
|
|
16356
|
+
}
|
|
16357
|
+
function SeveritySummary(props) {
|
|
16358
|
+
const { total, counts, activeFilter, onFilter } = props;
|
|
16359
|
+
const items = [
|
|
16360
|
+
{ key: "all", label: "Total", count: total },
|
|
16361
|
+
...SEVERITY_ORDER.map((s) => ({
|
|
16362
|
+
key: s,
|
|
16363
|
+
label: SEVERITY_LABELS[s],
|
|
16364
|
+
count: counts[s],
|
|
16365
|
+
color: SEVERITY_COLORS[s]
|
|
16366
|
+
}))
|
|
16367
|
+
];
|
|
16368
|
+
return import_react10.default.createElement(
|
|
16369
|
+
"div",
|
|
16370
|
+
{
|
|
16371
|
+
style: {
|
|
16372
|
+
flex: "none",
|
|
16373
|
+
display: "flex",
|
|
16374
|
+
alignItems: "center",
|
|
16375
|
+
gap: "4px",
|
|
16376
|
+
padding: "8px 12px",
|
|
16377
|
+
borderBottom: "1px solid var(--dsw-alias-border-l2)",
|
|
16378
|
+
flexWrap: "wrap",
|
|
16379
|
+
fontSize: "13px",
|
|
16380
|
+
color: "var(--dsw-alias-label-secondary)"
|
|
16381
|
+
}
|
|
16382
|
+
},
|
|
16383
|
+
...items.map((item) => {
|
|
16384
|
+
const isActive = activeFilter === item.key;
|
|
16385
|
+
return import_react10.default.createElement(
|
|
16386
|
+
"button",
|
|
16387
|
+
{
|
|
16388
|
+
key: item.key,
|
|
16389
|
+
type: "button",
|
|
16390
|
+
onClick: () => onFilter(item.key),
|
|
16391
|
+
style: {
|
|
16392
|
+
display: "inline-flex",
|
|
16209
16393
|
alignItems: "center",
|
|
16210
|
-
gap: "
|
|
16211
|
-
padding: "
|
|
16394
|
+
gap: "5px",
|
|
16395
|
+
padding: "3px 10px",
|
|
16396
|
+
borderRadius: "12px",
|
|
16397
|
+
border: "none",
|
|
16398
|
+
background: isActive ? "var(--dsw-alias-interactive-bg-hover)" : "transparent",
|
|
16399
|
+
color: isActive ? "var(--dsw-alias-label-primary)" : "var(--dsw-alias-label-secondary)",
|
|
16212
16400
|
cursor: "pointer",
|
|
16213
|
-
borderRadius: "4px",
|
|
16214
16401
|
fontSize: "13px",
|
|
16215
|
-
|
|
16216
|
-
|
|
16217
|
-
|
|
16218
|
-
},
|
|
16219
|
-
onClick: () => openDetail(finding)
|
|
16402
|
+
fontWeight: isActive ? 500 : 400,
|
|
16403
|
+
whiteSpace: "nowrap"
|
|
16404
|
+
}
|
|
16220
16405
|
},
|
|
16221
|
-
import_react10.default.createElement("span", {
|
|
16406
|
+
item.color !== void 0 && import_react10.default.createElement("span", {
|
|
16222
16407
|
style: {
|
|
16223
16408
|
width: "8px",
|
|
16224
16409
|
height: "8px",
|
|
16225
16410
|
borderRadius: "50%",
|
|
16226
|
-
background:
|
|
16411
|
+
background: item.color,
|
|
16227
16412
|
flexShrink: 0
|
|
16228
16413
|
}
|
|
16229
16414
|
}),
|
|
16230
|
-
import_react10.default.createElement("span",
|
|
16231
|
-
|
|
16232
|
-
style: {
|
|
16233
|
-
},
|
|
16234
|
-
)
|
|
16235
|
-
)
|
|
16236
|
-
|
|
16237
|
-
|
|
16238
|
-
|
|
16239
|
-
|
|
16240
|
-
|
|
16241
|
-
|
|
16242
|
-
|
|
16243
|
-
const modalContent = selectedFinding !== null ? import_react10.default.createElement(
|
|
16244
|
-
import_dsh_client_ui_primitives3.Modal,
|
|
16415
|
+
import_react10.default.createElement("span", null, item.label),
|
|
16416
|
+
import_react10.default.createElement("span", {
|
|
16417
|
+
style: { fontWeight: 600, color: isActive ? "var(--dsw-alias-label-primary)" : "var(--dsw-alias-label-tertiary)" }
|
|
16418
|
+
}, String(item.count))
|
|
16419
|
+
);
|
|
16420
|
+
})
|
|
16421
|
+
);
|
|
16422
|
+
}
|
|
16423
|
+
function FindingRow(props) {
|
|
16424
|
+
const { finding, isSelected, onClick } = props;
|
|
16425
|
+
const color = SEVERITY_COLORS[finding.severity];
|
|
16426
|
+
return import_react10.default.createElement(
|
|
16427
|
+
"div",
|
|
16245
16428
|
{
|
|
16246
|
-
|
|
16247
|
-
|
|
16248
|
-
|
|
16249
|
-
|
|
16429
|
+
role: "button",
|
|
16430
|
+
tabIndex: 0,
|
|
16431
|
+
onClick,
|
|
16432
|
+
onKeyDown: (e) => {
|
|
16433
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
16434
|
+
e.preventDefault();
|
|
16435
|
+
onClick();
|
|
16436
|
+
}
|
|
16437
|
+
},
|
|
16438
|
+
style: {
|
|
16439
|
+
display: "flex",
|
|
16440
|
+
flexDirection: "column",
|
|
16441
|
+
gap: "2px",
|
|
16442
|
+
padding: "8px 12px",
|
|
16443
|
+
cursor: "pointer",
|
|
16444
|
+
borderLeft: `3px solid ${isSelected ? color : "transparent"}`,
|
|
16445
|
+
background: isSelected ? "var(--dsw-alias-state-business-primary)" : "transparent",
|
|
16446
|
+
color: isSelected ? "var(--dsw-alias-state-business-primary-fg, #fff)" : "var(--dsw-alias-label-primary)",
|
|
16447
|
+
fontSize: "13px",
|
|
16448
|
+
lineHeight: "18px",
|
|
16449
|
+
borderBottom: "1px solid var(--dsw-alias-border-l2)",
|
|
16450
|
+
transition: "background 0.1s"
|
|
16451
|
+
},
|
|
16452
|
+
onMouseEnter: (e) => {
|
|
16453
|
+
if (!isSelected) e.currentTarget.style.background = "var(--dsw-alias-interactive-bg-hover)";
|
|
16454
|
+
},
|
|
16455
|
+
onMouseLeave: (e) => {
|
|
16456
|
+
if (!isSelected) e.currentTarget.style.background = "transparent";
|
|
16457
|
+
}
|
|
16250
16458
|
},
|
|
16459
|
+
// Row 1: title + severity
|
|
16251
16460
|
import_react10.default.createElement(
|
|
16252
16461
|
"div",
|
|
16253
|
-
{
|
|
16254
|
-
import_react10.default.createElement("div", {
|
|
16462
|
+
{
|
|
16255
16463
|
style: {
|
|
16256
|
-
display: "
|
|
16257
|
-
|
|
16258
|
-
|
|
16259
|
-
|
|
16260
|
-
|
|
16261
|
-
|
|
16464
|
+
display: "flex",
|
|
16465
|
+
alignItems: "center",
|
|
16466
|
+
gap: "8px",
|
|
16467
|
+
minWidth: 0
|
|
16468
|
+
}
|
|
16469
|
+
},
|
|
16470
|
+
import_react10.default.createElement("span", {
|
|
16471
|
+
style: {
|
|
16472
|
+
width: "7px",
|
|
16473
|
+
height: "7px",
|
|
16474
|
+
borderRadius: "50%",
|
|
16475
|
+
background: color,
|
|
16476
|
+
flexShrink: 0
|
|
16477
|
+
}
|
|
16478
|
+
}),
|
|
16479
|
+
import_react10.default.createElement("span", {
|
|
16480
|
+
style: {
|
|
16481
|
+
overflow: "hidden",
|
|
16482
|
+
textOverflow: "ellipsis",
|
|
16483
|
+
whiteSpace: "nowrap",
|
|
16484
|
+
fontWeight: 500,
|
|
16485
|
+
flex: 1,
|
|
16486
|
+
minWidth: 0
|
|
16487
|
+
}
|
|
16488
|
+
}, finding.title),
|
|
16489
|
+
import_react10.default.createElement("span", {
|
|
16490
|
+
style: {
|
|
16491
|
+
fontSize: "11px",
|
|
16262
16492
|
fontWeight: 600,
|
|
16263
|
-
|
|
16493
|
+
color: isSelected ? "rgba(255,255,255,0.75)" : color,
|
|
16494
|
+
flexShrink: 0
|
|
16264
16495
|
}
|
|
16265
|
-
}, SEVERITY_LABELS[
|
|
16266
|
-
|
|
16267
|
-
|
|
16268
|
-
|
|
16269
|
-
|
|
16270
|
-
|
|
16271
|
-
|
|
16272
|
-
|
|
16273
|
-
|
|
16274
|
-
|
|
16275
|
-
|
|
16276
|
-
|
|
16277
|
-
|
|
16496
|
+
}, SEVERITY_LABELS[finding.severity].toUpperCase())
|
|
16497
|
+
),
|
|
16498
|
+
// Row 2: affected asset (if exists)
|
|
16499
|
+
finding.affectedAsset !== void 0 && import_react10.default.createElement("div", {
|
|
16500
|
+
style: {
|
|
16501
|
+
fontSize: "12px",
|
|
16502
|
+
color: isSelected ? "rgba(255,255,255,0.6)" : "var(--dsw-alias-label-tertiary)",
|
|
16503
|
+
overflow: "hidden",
|
|
16504
|
+
textOverflow: "ellipsis",
|
|
16505
|
+
whiteSpace: "nowrap",
|
|
16506
|
+
marginLeft: "15px"
|
|
16507
|
+
}
|
|
16508
|
+
}, finding.affectedAsset),
|
|
16509
|
+
// Row 3: source stage + delegation
|
|
16510
|
+
import_react10.default.createElement("div", {
|
|
16511
|
+
style: {
|
|
16512
|
+
fontSize: "11px",
|
|
16513
|
+
color: isSelected ? "rgba(255,255,255,0.5)" : "var(--dsw-alias-label-tertiary)",
|
|
16514
|
+
marginLeft: "15px",
|
|
16515
|
+
overflow: "hidden",
|
|
16516
|
+
textOverflow: "ellipsis",
|
|
16517
|
+
whiteSpace: "nowrap"
|
|
16518
|
+
}
|
|
16519
|
+
}, `${finding.sourceStage} \xB7 ${finding.sourceDelegationId}`)
|
|
16520
|
+
);
|
|
16521
|
+
}
|
|
16522
|
+
function FindingDetail(props) {
|
|
16523
|
+
const { finding, content, loading, error: error51, onNavigate } = props;
|
|
16524
|
+
const color = SEVERITY_COLORS[finding.severity];
|
|
16278
16525
|
return import_react10.default.createElement(
|
|
16279
16526
|
"div",
|
|
16280
|
-
{
|
|
16281
|
-
|
|
16282
|
-
|
|
16527
|
+
{
|
|
16528
|
+
style: {
|
|
16529
|
+
flex: 1,
|
|
16530
|
+
minHeight: 0,
|
|
16531
|
+
display: "flex",
|
|
16532
|
+
flexDirection: "column",
|
|
16533
|
+
overflow: "hidden"
|
|
16534
|
+
}
|
|
16535
|
+
},
|
|
16536
|
+
// ── Metadata header (fixed) ─────────────────────────────────────────
|
|
16537
|
+
import_react10.default.createElement(
|
|
16538
|
+
"div",
|
|
16539
|
+
{
|
|
16540
|
+
style: {
|
|
16541
|
+
flex: "none",
|
|
16542
|
+
padding: "12px 16px",
|
|
16543
|
+
borderBottom: "1px solid var(--dsw-alias-border-l2)"
|
|
16544
|
+
}
|
|
16545
|
+
},
|
|
16546
|
+
// Title + severity
|
|
16547
|
+
import_react10.default.createElement(
|
|
16548
|
+
"div",
|
|
16549
|
+
{
|
|
16550
|
+
style: {
|
|
16551
|
+
display: "flex",
|
|
16552
|
+
alignItems: "center",
|
|
16553
|
+
gap: "10px",
|
|
16554
|
+
marginBottom: "8px"
|
|
16555
|
+
}
|
|
16556
|
+
},
|
|
16557
|
+
import_react10.default.createElement("span", {
|
|
16558
|
+
style: {
|
|
16559
|
+
fontSize: "15px",
|
|
16560
|
+
fontWeight: 600,
|
|
16561
|
+
color: "var(--dsw-alias-label-primary)",
|
|
16562
|
+
overflow: "hidden",
|
|
16563
|
+
textOverflow: "ellipsis",
|
|
16564
|
+
whiteSpace: "nowrap",
|
|
16565
|
+
flex: 1,
|
|
16566
|
+
minWidth: 0
|
|
16567
|
+
}
|
|
16568
|
+
}, finding.title),
|
|
16569
|
+
import_react10.default.createElement("span", {
|
|
16570
|
+
style: {
|
|
16571
|
+
display: "inline-block",
|
|
16572
|
+
padding: "2px 8px",
|
|
16573
|
+
borderRadius: "10px",
|
|
16574
|
+
background: color,
|
|
16575
|
+
color: "#fff",
|
|
16576
|
+
fontSize: "11px",
|
|
16577
|
+
fontWeight: 600,
|
|
16578
|
+
flexShrink: 0
|
|
16579
|
+
}
|
|
16580
|
+
}, SEVERITY_LABELS[finding.severity].toUpperCase())
|
|
16581
|
+
),
|
|
16582
|
+
// Affected asset
|
|
16583
|
+
finding.affectedAsset !== void 0 && import_react10.default.createElement(
|
|
16584
|
+
"div",
|
|
16585
|
+
{
|
|
16586
|
+
style: {
|
|
16587
|
+
fontSize: "13px",
|
|
16588
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
16589
|
+
marginBottom: "6px",
|
|
16590
|
+
display: "flex",
|
|
16591
|
+
gap: "6px"
|
|
16592
|
+
}
|
|
16593
|
+
},
|
|
16594
|
+
import_react10.default.createElement("span", { style: { color: "var(--dsw-alias-label-tertiary)", flexShrink: 0 } }, "Affected asset"),
|
|
16595
|
+
import_react10.default.createElement("code", {
|
|
16596
|
+
style: {
|
|
16597
|
+
fontSize: "12px",
|
|
16598
|
+
background: "var(--dsw-alias-bg-subtle)",
|
|
16599
|
+
padding: "1px 6px",
|
|
16600
|
+
borderRadius: "3px"
|
|
16601
|
+
}
|
|
16602
|
+
}, finding.affectedAsset)
|
|
16603
|
+
),
|
|
16604
|
+
// Stage + Delegation metadata
|
|
16605
|
+
import_react10.default.createElement(
|
|
16606
|
+
"div",
|
|
16607
|
+
{
|
|
16608
|
+
style: {
|
|
16609
|
+
display: "flex",
|
|
16610
|
+
gap: "20px",
|
|
16611
|
+
fontSize: "12px",
|
|
16612
|
+
color: "var(--dsw-alias-label-tertiary)"
|
|
16613
|
+
}
|
|
16614
|
+
},
|
|
16615
|
+
import_react10.default.createElement(
|
|
16616
|
+
"div",
|
|
16617
|
+
null,
|
|
16618
|
+
import_react10.default.createElement("span", { style: { fontWeight: 500, color: "var(--dsw-alias-label-secondary)" } }, "Stage"),
|
|
16619
|
+
" ",
|
|
16620
|
+
import_react10.default.createElement("span", null, finding.sourceStage)
|
|
16621
|
+
),
|
|
16622
|
+
import_react10.default.createElement(
|
|
16623
|
+
"div",
|
|
16624
|
+
null,
|
|
16625
|
+
import_react10.default.createElement("span", { style: { fontWeight: 500, color: "var(--dsw-alias-label-secondary)" } }, "Delegation"),
|
|
16626
|
+
" ",
|
|
16627
|
+
import_react10.default.createElement("span", null, finding.sourceDelegationId)
|
|
16628
|
+
)
|
|
16629
|
+
)
|
|
16630
|
+
),
|
|
16631
|
+
// ── DetailBody (scrollable) ────────────────────────────────────────
|
|
16632
|
+
import_react10.default.createElement(
|
|
16633
|
+
"div",
|
|
16634
|
+
{
|
|
16635
|
+
style: {
|
|
16636
|
+
flex: 1,
|
|
16637
|
+
minHeight: 0,
|
|
16638
|
+
overflowY: "auto",
|
|
16639
|
+
overflowX: "auto",
|
|
16640
|
+
overscrollBehaviorY: "contain",
|
|
16641
|
+
scrollbarGutter: "stable",
|
|
16642
|
+
padding: "16px",
|
|
16643
|
+
fontSize: "13px",
|
|
16644
|
+
lineHeight: "1.6",
|
|
16645
|
+
color: "var(--dsw-alias-label-primary)"
|
|
16646
|
+
}
|
|
16647
|
+
},
|
|
16648
|
+
loading && import_react10.default.createElement("div", {
|
|
16649
|
+
style: { color: "var(--dsw-alias-label-tertiary)", padding: "16px 0" }
|
|
16650
|
+
}, "Loading finding..."),
|
|
16651
|
+
error51 && import_react10.default.createElement("div", {
|
|
16652
|
+
style: { color: "var(--dsw-status-error)", padding: "16px 0" }
|
|
16653
|
+
}, "Unable to load finding detail"),
|
|
16654
|
+
content !== null && import_react10.default.createElement(import_dsh_client_ui_primitives3.MarkdownText, { text: content })
|
|
16655
|
+
),
|
|
16656
|
+
// ── Footer actions (fixed) ──────────────────────────────────────────
|
|
16657
|
+
import_react10.default.createElement(
|
|
16658
|
+
"div",
|
|
16659
|
+
{
|
|
16660
|
+
style: {
|
|
16661
|
+
flex: "none",
|
|
16662
|
+
padding: "8px 16px",
|
|
16663
|
+
borderTop: "1px solid var(--dsw-alias-border-l2)",
|
|
16664
|
+
display: "flex",
|
|
16665
|
+
gap: "8px"
|
|
16666
|
+
}
|
|
16667
|
+
},
|
|
16668
|
+
import_react10.default.createElement(ActionButton, {
|
|
16669
|
+
label: "View Stage",
|
|
16670
|
+
onClick: () => onNavigate("stages", { stage: finding.sourceStage })
|
|
16671
|
+
}),
|
|
16672
|
+
import_react10.default.createElement(ActionButton, {
|
|
16673
|
+
label: "View in Output",
|
|
16674
|
+
onClick: () => onNavigate("output", { output: `findings/${finding.detailFile}` })
|
|
16675
|
+
})
|
|
16676
|
+
)
|
|
16283
16677
|
);
|
|
16284
16678
|
}
|
|
16679
|
+
function ActionButton(props) {
|
|
16680
|
+
return import_react10.default.createElement("button", {
|
|
16681
|
+
type: "button",
|
|
16682
|
+
onClick: props.onClick,
|
|
16683
|
+
style: {
|
|
16684
|
+
padding: "4px 12px",
|
|
16685
|
+
border: "1px solid var(--dsw-alias-border-l2)",
|
|
16686
|
+
borderRadius: "4px",
|
|
16687
|
+
background: "transparent",
|
|
16688
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
16689
|
+
cursor: "pointer",
|
|
16690
|
+
fontSize: "12px",
|
|
16691
|
+
lineHeight: "20px"
|
|
16692
|
+
},
|
|
16693
|
+
onMouseEnter: (e) => {
|
|
16694
|
+
e.currentTarget.style.background = "var(--dsw-alias-interactive-bg-hover)";
|
|
16695
|
+
},
|
|
16696
|
+
onMouseLeave: (e) => {
|
|
16697
|
+
e.currentTarget.style.background = "transparent";
|
|
16698
|
+
}
|
|
16699
|
+
}, props.label);
|
|
16700
|
+
}
|
|
16285
16701
|
|
|
16286
16702
|
// src/ui/client/pentester/TraceView.tsx
|
|
16287
16703
|
var import_react15 = __toESM(require("react"), 1);
|
|
@@ -17768,7 +18184,7 @@ function TargetRow(props) {
|
|
|
17768
18184
|
);
|
|
17769
18185
|
}
|
|
17770
18186
|
function OutputView(props) {
|
|
17771
|
-
const { snapshot, command, sessionId } = props;
|
|
18187
|
+
const { snapshot, command, sessionId, focusOutput } = props;
|
|
17772
18188
|
const [filter, setFilter] = (0, import_react17.useState)("all");
|
|
17773
18189
|
const [preview, setPreview] = (0, import_react17.useState)(null);
|
|
17774
18190
|
const [previewContent, setPreviewContent] = (0, import_react17.useState)(null);
|
|
@@ -17850,6 +18266,16 @@ function OutputView(props) {
|
|
|
17850
18266
|
setPreview(null);
|
|
17851
18267
|
setPreviewContent(null);
|
|
17852
18268
|
}, []);
|
|
18269
|
+
const focusAppliedRef = (0, import_react17.useRef)(void 0);
|
|
18270
|
+
(0, import_react17.useEffect)(() => {
|
|
18271
|
+
if (focusOutput === void 0 || focusOutput === focusAppliedRef.current) return;
|
|
18272
|
+
if (outputTree === null) return;
|
|
18273
|
+
focusAppliedRef.current = focusOutput;
|
|
18274
|
+
const entry = findEntryByPath(outputTree.children, focusOutput);
|
|
18275
|
+
if (entry !== void 0) {
|
|
18276
|
+
openPreview(entry, outputTree.targetId);
|
|
18277
|
+
}
|
|
18278
|
+
}, [focusOutput, outputTree, openPreview]);
|
|
17853
18279
|
const initialLoading = outputTree === null && outputLoading;
|
|
17854
18280
|
if (initialLoading) {
|
|
17855
18281
|
return import_react17.default.createElement("div", {
|
|
@@ -17908,7 +18334,7 @@ function OutputView(props) {
|
|
|
17908
18334
|
return import_react17.default.createElement(
|
|
17909
18335
|
"div",
|
|
17910
18336
|
{
|
|
17911
|
-
style: { display: "flex", gap: "16px",
|
|
18337
|
+
style: { display: "flex", gap: "16px", flex: 1, height: "100%", minHeight: 0, minWidth: 0, overflow: "hidden" }
|
|
17912
18338
|
},
|
|
17913
18339
|
// Left: file tree
|
|
17914
18340
|
import_react17.default.createElement(
|
|
@@ -17916,16 +18342,24 @@ function OutputView(props) {
|
|
|
17916
18342
|
{
|
|
17917
18343
|
style: {
|
|
17918
18344
|
flex: "0 0 320px",
|
|
17919
|
-
|
|
17920
|
-
|
|
17921
|
-
paddingRight: "12px",
|
|
18345
|
+
minHeight: 0,
|
|
18346
|
+
overflow: "hidden",
|
|
17922
18347
|
display: "flex",
|
|
17923
|
-
flexDirection: "column"
|
|
18348
|
+
flexDirection: "column",
|
|
18349
|
+
borderRight: "1px solid var(--dsw-alias-border-l2)",
|
|
18350
|
+
paddingRight: "12px"
|
|
17924
18351
|
}
|
|
17925
18352
|
},
|
|
18353
|
+
// Filter tabs (fixed)
|
|
17926
18354
|
import_react17.default.createElement(
|
|
17927
18355
|
"div",
|
|
17928
|
-
{
|
|
18356
|
+
{
|
|
18357
|
+
style: {
|
|
18358
|
+
flex: "none",
|
|
18359
|
+
marginBottom: "12px",
|
|
18360
|
+
paddingTop: "2px"
|
|
18361
|
+
}
|
|
18362
|
+
},
|
|
17929
18363
|
import_react17.default.createElement(PentesterTabBar, {
|
|
17930
18364
|
items: OUTPUT_FILTER_TABS,
|
|
17931
18365
|
active: filter,
|
|
@@ -17933,10 +18367,20 @@ function OutputView(props) {
|
|
|
17933
18367
|
variant: "compact"
|
|
17934
18368
|
})
|
|
17935
18369
|
),
|
|
17936
|
-
// ──
|
|
18370
|
+
// ── TreeViewport (scrollable) ──────────────────────────────────
|
|
17937
18371
|
import_react17.default.createElement(
|
|
17938
18372
|
"div",
|
|
17939
|
-
{
|
|
18373
|
+
{
|
|
18374
|
+
style: {
|
|
18375
|
+
flex: 1,
|
|
18376
|
+
minHeight: 0,
|
|
18377
|
+
minWidth: 0,
|
|
18378
|
+
overflowY: "auto",
|
|
18379
|
+
overflowX: "hidden",
|
|
18380
|
+
overscrollBehaviorY: "contain",
|
|
18381
|
+
scrollbarGutter: "stable"
|
|
18382
|
+
}
|
|
18383
|
+
},
|
|
17940
18384
|
import_react17.default.createElement("div", {
|
|
17941
18385
|
style: {
|
|
17942
18386
|
fontSize: "11px",
|
|
@@ -17970,14 +18414,13 @@ function OutputView(props) {
|
|
|
17970
18414
|
style: {
|
|
17971
18415
|
flex: 1,
|
|
17972
18416
|
minWidth: 0,
|
|
18417
|
+
minHeight: 0,
|
|
17973
18418
|
display: "flex",
|
|
17974
18419
|
flexDirection: "column",
|
|
17975
18420
|
overflow: "hidden",
|
|
17976
18421
|
border: "1px solid var(--dsw-alias-border-l2)",
|
|
17977
18422
|
borderRadius: "8px",
|
|
17978
|
-
background: "var(--dsw-alias-bg-base)"
|
|
17979
|
-
minHeight: "320px",
|
|
17980
|
-
maxHeight: "clamp(320px, 65vh, 680px)"
|
|
18423
|
+
background: "var(--dsw-alias-bg-base)"
|
|
17981
18424
|
}
|
|
17982
18425
|
},
|
|
17983
18426
|
preview === null ? import_react17.default.createElement("div", {
|
|
@@ -17992,6 +18435,7 @@ function OutputView(props) {
|
|
|
17992
18435
|
}, "Select a file to preview") : import_react17.default.createElement(
|
|
17993
18436
|
import_react17.default.Fragment,
|
|
17994
18437
|
null,
|
|
18438
|
+
// PreviewHeader (fixed)
|
|
17995
18439
|
import_react17.default.createElement(
|
|
17996
18440
|
"div",
|
|
17997
18441
|
{
|
|
@@ -18020,10 +18464,20 @@ function OutputView(props) {
|
|
|
18020
18464
|
"aria-label": "Close preview"
|
|
18021
18465
|
}, "\xD7")
|
|
18022
18466
|
),
|
|
18467
|
+
// PreviewBody (scrollable)
|
|
18023
18468
|
import_react17.default.createElement(
|
|
18024
18469
|
"div",
|
|
18025
18470
|
{
|
|
18026
|
-
style: {
|
|
18471
|
+
style: {
|
|
18472
|
+
flex: 1,
|
|
18473
|
+
minHeight: 0,
|
|
18474
|
+
minWidth: 0,
|
|
18475
|
+
overflowY: "auto",
|
|
18476
|
+
overflowX: "auto",
|
|
18477
|
+
overscrollBehaviorY: "contain",
|
|
18478
|
+
scrollbarGutter: "stable",
|
|
18479
|
+
padding: "12px"
|
|
18480
|
+
}
|
|
18027
18481
|
},
|
|
18028
18482
|
previewLoading && import_react17.default.createElement("div", {
|
|
18029
18483
|
style: { color: "var(--dsw-alias-label-tertiary)", padding: "16px 0" }
|
|
@@ -18110,6 +18564,16 @@ function formatSize(bytes) {
|
|
|
18110
18564
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
18111
18565
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
18112
18566
|
}
|
|
18567
|
+
function findEntryByPath(entries, targetPath) {
|
|
18568
|
+
for (const entry of entries) {
|
|
18569
|
+
if (entry.path === targetPath) return entry;
|
|
18570
|
+
if (entry.kind === "directory" && entry.children !== void 0) {
|
|
18571
|
+
const found = findEntryByPath(entry.children, targetPath);
|
|
18572
|
+
if (found !== void 0) return found;
|
|
18573
|
+
}
|
|
18574
|
+
}
|
|
18575
|
+
return void 0;
|
|
18576
|
+
}
|
|
18113
18577
|
|
|
18114
18578
|
// src/ui/client/pentester-view.tsx
|
|
18115
18579
|
var CORE_REFRESH_MS = 1e4;
|
|
@@ -18245,18 +18709,17 @@ function PentesterView(props) {
|
|
|
18245
18709
|
if (isPerf) console.log(`${RPC_PREFIX} circuit-open endpoint=missing reason=${reason}`);
|
|
18246
18710
|
return;
|
|
18247
18711
|
}
|
|
18248
|
-
|
|
18249
|
-
|
|
18250
|
-
|
|
18251
|
-
|
|
18252
|
-
|
|
18253
|
-
|
|
18712
|
+
const mismatch = getBuildMismatch();
|
|
18713
|
+
if (mismatch !== null) {
|
|
18714
|
+
pollingPausedRef.current = true;
|
|
18715
|
+
setDataState({
|
|
18716
|
+
kind: "error",
|
|
18717
|
+
error: `Pentester Host/Client build mismatch
|
|
18254
18718
|
Host: ${mismatch.host}
|
|
18255
18719
|
Client: ${mismatch.client}`,
|
|
18256
|
-
|
|
18257
|
-
|
|
18258
|
-
|
|
18259
|
-
}
|
|
18720
|
+
code: "build_mismatch"
|
|
18721
|
+
});
|
|
18722
|
+
setRequestState("idle");
|
|
18260
18723
|
return;
|
|
18261
18724
|
}
|
|
18262
18725
|
if (pendingRef.current !== null) {
|
|
@@ -18282,7 +18745,7 @@ Client: ${mismatch.client}`,
|
|
|
18282
18745
|
}
|
|
18283
18746
|
}
|
|
18284
18747
|
try {
|
|
18285
|
-
const result = await pentesterCommand({ kind: "snapshot", sessionId },
|
|
18748
|
+
const result = await pentesterCommand({ kind: "snapshot", sessionId }, 3e4);
|
|
18286
18749
|
if (pendingRef.current?.id !== id) {
|
|
18287
18750
|
if (isPerf) console.log(`${RPC_PREFIX} id=${id} stale (current=${pendingRef.current?.id})`);
|
|
18288
18751
|
return;
|
|
@@ -18413,12 +18876,14 @@ Client: ${mismatch.client}`,
|
|
|
18413
18876
|
{
|
|
18414
18877
|
"data-testid": "pentester-view",
|
|
18415
18878
|
"data-pentester-view": "",
|
|
18879
|
+
"data-conversation-composer-overlay": "",
|
|
18416
18880
|
style: {
|
|
18417
18881
|
display: "flex",
|
|
18418
18882
|
flexDirection: "column",
|
|
18419
18883
|
width: "100%",
|
|
18420
|
-
|
|
18421
|
-
|
|
18884
|
+
height: "100%",
|
|
18885
|
+
minHeight: 0,
|
|
18886
|
+
overflow: "hidden"
|
|
18422
18887
|
}
|
|
18423
18888
|
},
|
|
18424
18889
|
// ── Layer 1: TabsBar (sticky) ────────────────────────────────────────
|
|
@@ -18428,8 +18893,6 @@ Client: ${mismatch.client}`,
|
|
|
18428
18893
|
"data-testid": "pentester-tabs-bar",
|
|
18429
18894
|
style: {
|
|
18430
18895
|
flex: "none",
|
|
18431
|
-
position: "sticky",
|
|
18432
|
-
top: 0,
|
|
18433
18896
|
zIndex: 29,
|
|
18434
18897
|
background: "var(--dsw-alias-bg-base)",
|
|
18435
18898
|
borderBottom: "1px solid var(--dsw-alias-border-l2)",
|
|
@@ -18484,15 +18947,18 @@ Client: ${mismatch.client}`,
|
|
|
18484
18947
|
}
|
|
18485
18948
|
}, isRetrying ? "Retrying\u2026" : "Retry")
|
|
18486
18949
|
),
|
|
18487
|
-
// ── Body: flex
|
|
18950
|
+
// ── Body: bounded flex viewport ────────────────────────────────────
|
|
18488
18951
|
import_react18.default.createElement(
|
|
18489
18952
|
"div",
|
|
18490
18953
|
{
|
|
18491
18954
|
style: {
|
|
18492
18955
|
flex: 1,
|
|
18493
18956
|
minHeight: 0,
|
|
18494
|
-
overflow: "
|
|
18495
|
-
|
|
18957
|
+
overflow: "hidden",
|
|
18958
|
+
display: "flex",
|
|
18959
|
+
flexDirection: "column",
|
|
18960
|
+
padding: "16px",
|
|
18961
|
+
boxSizing: "border-box"
|
|
18496
18962
|
}
|
|
18497
18963
|
},
|
|
18498
18964
|
// Initial loading: shell is already visible, show skeleton
|
|
@@ -18599,23 +19065,40 @@ Client: ${mismatch.client}`,
|
|
|
18599
19065
|
}
|
|
18600
19066
|
}, "Refresh")
|
|
18601
19067
|
),
|
|
18602
|
-
// Bound content
|
|
19068
|
+
// Bound content — wrapped in a bounded viewport
|
|
18603
19069
|
dataState.kind === "bound" && import_react18.default.createElement(
|
|
18604
|
-
|
|
18605
|
-
|
|
18606
|
-
|
|
18607
|
-
|
|
18608
|
-
|
|
18609
|
-
|
|
18610
|
-
|
|
18611
|
-
|
|
18612
|
-
|
|
18613
|
-
|
|
18614
|
-
|
|
18615
|
-
|
|
18616
|
-
|
|
18617
|
-
|
|
18618
|
-
|
|
19070
|
+
"div",
|
|
19071
|
+
{
|
|
19072
|
+
style: {
|
|
19073
|
+
flex: 1,
|
|
19074
|
+
minHeight: 0,
|
|
19075
|
+
minWidth: 0,
|
|
19076
|
+
overflow: "hidden",
|
|
19077
|
+
display: "flex",
|
|
19078
|
+
flexDirection: "column"
|
|
19079
|
+
}
|
|
19080
|
+
},
|
|
19081
|
+
tab === "overview" && import_react18.default.createElement(
|
|
19082
|
+
ScrollablePage,
|
|
19083
|
+
null,
|
|
19084
|
+
import_react18.default.createElement(OverviewView, {
|
|
19085
|
+
snapshot,
|
|
19086
|
+
liveActivity,
|
|
19087
|
+
onNavigate: navigate,
|
|
19088
|
+
onOpenSession: openSession
|
|
19089
|
+
})
|
|
19090
|
+
),
|
|
19091
|
+
tab === "stages" && import_react18.default.createElement(
|
|
19092
|
+
ScrollablePage,
|
|
19093
|
+
null,
|
|
19094
|
+
import_react18.default.createElement(StagesView, {
|
|
19095
|
+
snapshot,
|
|
19096
|
+
liveActivity,
|
|
19097
|
+
onNavigate: navigate,
|
|
19098
|
+
onOpenSession: openSession,
|
|
19099
|
+
focusStage: navFocus.stage
|
|
19100
|
+
})
|
|
19101
|
+
),
|
|
18619
19102
|
tab === "findings" && import_react18.default.createElement(FindingsView, {
|
|
18620
19103
|
snapshot,
|
|
18621
19104
|
command: pentesterCommand,
|
|
@@ -18623,13 +19106,17 @@ Client: ${mismatch.client}`,
|
|
|
18623
19106
|
onNavigate: navigate,
|
|
18624
19107
|
focusFinding: navFocus.finding
|
|
18625
19108
|
}),
|
|
18626
|
-
tab === "trace" && import_react18.default.createElement(
|
|
18627
|
-
|
|
18628
|
-
|
|
18629
|
-
|
|
18630
|
-
|
|
18631
|
-
|
|
18632
|
-
|
|
19109
|
+
tab === "trace" && import_react18.default.createElement(
|
|
19110
|
+
ScrollablePage,
|
|
19111
|
+
null,
|
|
19112
|
+
import_react18.default.createElement(TraceView, {
|
|
19113
|
+
snapshot,
|
|
19114
|
+
liveActivity,
|
|
19115
|
+
onNavigate: navigate,
|
|
19116
|
+
onOpenSession: openSession,
|
|
19117
|
+
activeTargetId
|
|
19118
|
+
})
|
|
19119
|
+
),
|
|
18633
19120
|
tab === "output" && import_react18.default.createElement(OutputView, {
|
|
18634
19121
|
snapshot,
|
|
18635
19122
|
command: pentesterCommand,
|
|
@@ -18640,6 +19127,17 @@ Client: ${mismatch.client}`,
|
|
|
18640
19127
|
)
|
|
18641
19128
|
);
|
|
18642
19129
|
}
|
|
19130
|
+
function ScrollablePage(props) {
|
|
19131
|
+
return import_react18.default.createElement("div", {
|
|
19132
|
+
style: {
|
|
19133
|
+
flex: 1,
|
|
19134
|
+
minHeight: 0,
|
|
19135
|
+
overflowY: "auto",
|
|
19136
|
+
overflowX: "hidden",
|
|
19137
|
+
overscrollBehavior: "contain"
|
|
19138
|
+
}
|
|
19139
|
+
}, props.children);
|
|
19140
|
+
}
|
|
18643
19141
|
|
|
18644
19142
|
// src/ui/client/pentester/locales.ts
|
|
18645
19143
|
var NS = "dsh-pentester-view";
|
|
@@ -18721,7 +19219,7 @@ var en = {
|
|
|
18721
19219
|
};
|
|
18722
19220
|
|
|
18723
19221
|
// src/build-id.ts
|
|
18724
|
-
var BUILD_ID = "2.
|
|
19222
|
+
var BUILD_ID = "2.3.0+2a31301";
|
|
18725
19223
|
|
|
18726
19224
|
// src/ui/client/plugin.tsx
|
|
18727
19225
|
var SESSION_SWITCH_PERF = "[SESSION_SWITCH_PERF]";
|
|
@@ -18735,11 +19233,7 @@ function getPentesterEndpointState2() {
|
|
|
18735
19233
|
function setPentesterEndpointState(state) {
|
|
18736
19234
|
pentesterEndpointState2 = state;
|
|
18737
19235
|
}
|
|
18738
|
-
var buildOk = false;
|
|
18739
19236
|
var buildMismatch = null;
|
|
18740
|
-
function isBuildOk() {
|
|
18741
|
-
return buildOk;
|
|
18742
|
-
}
|
|
18743
19237
|
function getBuildMismatch() {
|
|
18744
19238
|
return buildMismatch;
|
|
18745
19239
|
}
|
|
@@ -18753,7 +19247,7 @@ function getRemoteMountError() {
|
|
|
18753
19247
|
}
|
|
18754
19248
|
var inject = ["slots", "remote", "sessions", "locale"];
|
|
18755
19249
|
function apply(ctx) {
|
|
18756
|
-
console.log(`[dsh-pentester]
|
|
19250
|
+
console.log(`[dsh-pentester/client] build=${BUILD_ID}`);
|
|
18757
19251
|
ctx.effect(() => ctx.locale.register(NS, { zh, en }), "pentester: locale");
|
|
18758
19252
|
ctx.effect(() => {
|
|
18759
19253
|
let disposeMount;
|
|
@@ -18786,18 +19280,20 @@ function apply(ctx) {
|
|
|
18786
19280
|
if (result.ok && result.value !== null && typeof result.value === "object" && "ok" in result.value) {
|
|
18787
19281
|
const inner = result.value.value;
|
|
18788
19282
|
if (inner?.ready === true && typeof inner.buildId === "string") {
|
|
19283
|
+
console.log(`[dsh-pentester/client] health host=${inner.buildId} client=${BUILD_ID}`);
|
|
18789
19284
|
if (inner.buildId === BUILD_ID) {
|
|
18790
|
-
|
|
19285
|
+
if (buildMismatch !== null) {
|
|
19286
|
+
console.log(`[dsh-pentester/client] build mismatch cleared (was host=${buildMismatch.host} client=${buildMismatch.client})`);
|
|
19287
|
+
}
|
|
18791
19288
|
buildMismatch = null;
|
|
18792
|
-
console.log(`[dsh-pentester] health check passed host=${inner.buildId} client=${BUILD_ID}`);
|
|
18793
19289
|
} else {
|
|
18794
|
-
buildOk = false;
|
|
18795
19290
|
buildMismatch = { host: inner.buildId, client: BUILD_ID };
|
|
18796
|
-
console.error(`[dsh-pentester]
|
|
19291
|
+
console.error(`[dsh-pentester/client] build mismatch set host=${inner.buildId} client=${BUILD_ID}`);
|
|
18797
19292
|
}
|
|
18798
19293
|
}
|
|
18799
19294
|
}
|
|
18800
|
-
} catch {
|
|
19295
|
+
} catch (error51) {
|
|
19296
|
+
console.warn("[dsh-pentester/client] build health check unavailable", error51);
|
|
18801
19297
|
}
|
|
18802
19298
|
})();
|
|
18803
19299
|
}).catch((error51) => {
|