Skip to content

Commit 826cd79

Browse files
Potential fix for code scanning alert no. 25: Client-side cross-site scripting
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
1 parent ab71143 commit 826cd79

1 file changed

Lines changed: 74 additions & 29 deletions

File tree

src/webview/diagnostics/main.ts

Lines changed: 74 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -913,51 +913,96 @@ function renderLayout(data: DiagnosticsData): void {
913913
const reportTabContent = document.getElementById('tab-report');
914914
if (reportTabContent) {
915915
const sorted = [...message.sessionFolders].sort((a: any, b: any) => b.count - a.count);
916-
let sessionFilesHtml = `
917-
<div class="session-folders-table">
918-
<h4>Main Session Folders (by editor root):</h4>
919-
<table class="session-table">
920-
<thead>
921-
<tr>
922-
<th>Folder</th>
923-
<th>Editor</th>
924-
<th># of Sessions</th>
925-
<th>Open</th>
926-
</tr>
927-
</thead>
928-
<tbody>`;
916+
917+
// Build the session folders table using DOM APIs to avoid HTML injection
918+
let container = reportTabContent.querySelector('.session-folders-table') as HTMLElement | null;
919+
if (!container) {
920+
container = document.createElement('div');
921+
container.className = 'session-folders-table';
922+
} else {
923+
// Clear existing content so we can rebuild safely
924+
while (container.firstChild) {
925+
container.removeChild(container.firstChild);
926+
}
927+
}
928+
929+
const heading = document.createElement('h4');
930+
heading.textContent = 'Main Session Folders (by editor root):';
931+
container.appendChild(heading);
932+
933+
const table = document.createElement('table');
934+
table.className = 'session-table';
935+
container.appendChild(table);
936+
937+
const thead = document.createElement('thead');
938+
const headerRow = document.createElement('tr');
939+
const headers = ['Folder', 'Editor', '# of Sessions', 'Open'];
940+
headers.forEach((text) => {
941+
const th = document.createElement('th');
942+
th.textContent = text;
943+
headerRow.appendChild(th);
944+
});
945+
thead.appendChild(headerRow);
946+
table.appendChild(thead);
947+
948+
const tbody = document.createElement('tbody');
929949
sorted.forEach((sf: any) => {
930950
let display = sf.dir;
931951
const home = (window as any).process?.env?.HOME || (window as any).process?.env?.USERPROFILE || '';
932952
if (home && display.startsWith(home)) {
933953
display = display.replace(home, '~');
934954
}
935955
const editorName = sf.editorName || 'Unknown';
936-
sessionFilesHtml += `
937-
<tr>
938-
<td title="${escapeHtml(sf.dir)}">${escapeHtml(display)}</td>
939-
<td><span class="editor-badge">${escapeHtml(editorName)}</span></td>
940-
<td>${sf.count}</td>
941-
<td><a href="#" class="reveal-link" data-path="${encodeURIComponent(sf.dir)}">Open directory</a></td>
942-
</tr>`;
956+
957+
const row = document.createElement('tr');
958+
959+
// Folder cell
960+
const folderCell = document.createElement('td');
961+
folderCell.setAttribute('title', escapeHtml(sf.dir));
962+
folderCell.textContent = escapeHtml(display);
963+
row.appendChild(folderCell);
964+
965+
// Editor cell
966+
const editorCell = document.createElement('td');
967+
const editorBadge = document.createElement('span');
968+
editorBadge.className = 'editor-badge';
969+
editorBadge.textContent = escapeHtml(editorName);
970+
editorCell.appendChild(editorBadge);
971+
row.appendChild(editorCell);
972+
973+
// Count cell
974+
const countCell = document.createElement('td');
975+
countCell.textContent = String(sf.count);
976+
row.appendChild(countCell);
977+
978+
// Open link cell
979+
const openCell = document.createElement('td');
980+
const openLink = document.createElement('a');
981+
openLink.href = '#';
982+
openLink.className = 'reveal-link';
983+
openLink.setAttribute('data-path', encodeURIComponent(sf.dir));
984+
openLink.textContent = 'Open directory';
985+
openCell.appendChild(openLink);
986+
row.appendChild(openCell);
987+
988+
tbody.appendChild(row);
943989
});
944-
sessionFilesHtml += `
945-
</tbody>
946-
</table>
947-
</div>`;
948-
990+
table.appendChild(tbody);
991+
949992
// Find where to insert or replace the session folders table
950993
// It should be inserted after the report-content div but before the button-group
951994
const existingTable = reportTabContent.querySelector('.session-folders-table');
952-
if (existingTable) {
953-
existingTable.outerHTML = sessionFilesHtml;
954-
} else {
995+
if (!existingTable) {
955996
// Insert after the report-content div
956997
const reportContent = reportTabContent.querySelector('.report-content');
957998
if (reportContent) {
958-
reportContent.insertAdjacentHTML('afterend', sessionFilesHtml);
999+
reportContent.insertAdjacentElement('afterend', container);
1000+
} else {
1001+
// Fallback: append to the tab content if report-content is missing
1002+
reportTabContent.appendChild(container);
9591003
}
9601004
}
1005+
9611006
setupStorageLinkHandlers();
9621007
}
9631008
}

0 commit comments

Comments
 (0)