Skip to content

Commit 395a3c5

Browse files
committed
fix: dedupe JS Analysis tab and format matcher findings
Avoid duplicate JS Analysis tabs when both dataset and module keys are present, and format JS Analysis vulnerability type as matcher plus matched value for cleaner triage output. Made-with: Cursor
1 parent 24d14e5 commit 395a3c5

1 file changed

Lines changed: 20 additions & 0 deletions

File tree

  • internal/modules/gobot/ui

internal/modules/gobot/ui/app.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2011,6 +2011,21 @@ function renderRowForUnifiedTab(r, idx, activeKind, modInfo, sevMeta) {
20112011
c2 = `<td style="padding:7px 10px;max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap"><span style="color:var(--accent-purple);font-size:11px;font-weight:700">${esc(pattern)}</span></td>`;
20122012
c3 = `<td style="padding:7px 10px;max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap"><span title="${esc(value)}" style="font-family:var(--font-mono,monospace);font-size:11px;color:var(--text-primary)">${esc(value)}</span></td>`;
20132013
c4 = `<td style="padding:7px 10px;max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap"><span style="font-size:11px;color:var(--text-muted)">${esc(source)}</span></td>`;
2014+
} else if (moduleTab === 'js-analysis') {
2015+
let matcher = String(r.matcher || r.finding_type || '').trim();
2016+
let matched = String(r.value || r.match || '').trim();
2017+
if (!matcher || !matched) {
2018+
const m = finding.match(/^\s*\[([^\]]+)\]\s*(?:https?:\/\/\S+)?\s*->\s*(.+)\s*$/i);
2019+
if (m) {
2020+
if (!matcher) matcher = String(m[1] || '').trim();
2021+
if (!matched) matched = String(m[2] || '').trim();
2022+
}
2023+
}
2024+
const vulnType = matcher && matched
2025+
? `[${matcher}] ${matched}`
2026+
: (matcher ? `[${matcher}]` : findingShort);
2027+
c3 = `<td style="padding:7px 10px;max-width:0;overflow:hidden"><span title="${esc(finding)}" style="display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--font-mono,monospace);font-size:11.5px;color:var(--text-primary);">${esc(vulnType)}</span></td>`;
2028+
c4 = tdModule;
20142029
} else if (moduleTab === 'misconfig') {
20152030
const service = String(r.service || r.service_name || r.module || 'misconfig');
20162031
c3 = `<td style="padding:7px 10px;max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap"><span style="font-size:11px;color:var(--accent-amber)">${esc(service)}</span></td>`;
@@ -4241,6 +4256,11 @@ async function loadReconUnifiedTable(scanId, allFiles, containerId, scanRecord)
42414256
if (hasUrlsDatasetTab) {
42424257
excludedModuleTabs.add('url-collection');
42434258
}
4259+
// JS Analysis can appear as dataset + module; keep only one tab.
4260+
const hasJsAnalysisDatasetTab = UNIQUE_TABS.some((t) => t[0] === 'js-analysis');
4261+
if (hasJsAnalysisDatasetTab) {
4262+
excludedModuleTabs.add('js-analysis');
4263+
}
42444264
const moduleTabs = usedModules.filter((mod) => !excludedModuleTabs.has(mod)).map((mod) => {
42454265
const info = getModuleDisplayInfo(mod);
42464266
return [`mod:${mod}`, `${info.icon} ${info.name}`];

0 commit comments

Comments
 (0)