Skip to content

Commit 2434d60

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

File tree

1 file changed

+75
-2
lines changed

1 file changed

+75
-2
lines changed

src/webview/usage/main.ts

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,74 @@ function renderToolsTable(byTool: { [key: string]: number }, limit = 10, nameRes
279279
</table>`;
280280
}
281281

282+
function sanitizeStats(raw: any): UsageAnalysisStats | null {
283+
if (!raw || typeof raw !== 'object') {
284+
return null;
285+
}
286+
287+
const coerceNumber = (value: any): number => {
288+
const n = Number(value);
289+
return Number.isFinite(n) ? n : 0;
290+
};
291+
292+
const sanitizeModeUsage = (mode: any): ModeUsage => ({
293+
ask: coerceNumber(mode?.ask),
294+
edit: coerceNumber(mode?.edit),
295+
agent: coerceNumber(mode?.agent),
296+
plan: coerceNumber(mode?.plan),
297+
customAgent: coerceNumber(mode?.customAgent),
298+
});
299+
300+
const sanitizeContextRefs = (refs: any): ContextReferenceUsage => ({
301+
file: coerceNumber(refs?.file),
302+
selection: coerceNumber(refs?.selection),
303+
implicitSelection: coerceNumber(refs?.implicitSelection),
304+
symbol: coerceNumber(refs?.symbol),
305+
codebase: coerceNumber(refs?.codebase),
306+
workspace: coerceNumber(refs?.workspace),
307+
});
308+
309+
try {
310+
const today = raw.today ?? {};
311+
const last30Days = raw.last30Days ?? {};
312+
313+
const sanitized: UsageAnalysisStats = {
314+
today: {
315+
modeUsage: sanitizeModeUsage(today.modeUsage ?? {}),
316+
contextReferences: sanitizeContextRefs(today.contextReferences ?? {}),
317+
toolUsage: {
318+
total: coerceNumber(today.toolUsage?.total),
319+
byTool: today.toolUsage?.byTool ?? {},
320+
},
321+
mcpToolUsage: {
322+
total: coerceNumber(today.mcpToolUsage?.total),
323+
byServer: today.mcpToolUsage?.byServer ?? {},
324+
byTool: today.mcpToolUsage?.byTool ?? {},
325+
},
326+
},
327+
last30Days: {
328+
modeUsage: sanitizeModeUsage(last30Days.modeUsage ?? {}),
329+
contextReferences: sanitizeContextRefs(last30Days.contextReferences ?? {}),
330+
toolUsage: {
331+
total: coerceNumber(last30Days.toolUsage?.total),
332+
byTool: last30Days.toolUsage?.byTool ?? {},
333+
},
334+
mcpToolUsage: {
335+
total: coerceNumber(last30Days.mcpToolUsage?.total),
336+
byServer: last30Days.mcpToolUsage?.byServer ?? {},
337+
byTool: last30Days.mcpToolUsage?.byTool ?? {},
338+
},
339+
},
340+
backendConfigured: !!raw.backendConfigured,
341+
repoAnalysis: raw.repoAnalysis,
342+
};
343+
344+
return sanitized;
345+
} catch {
346+
return null;
347+
}
348+
}
349+
282350
function renderLayout(stats: UsageAnalysisStats): void {
283351
const root = document.getElementById('root');
284352
if (!root) {
@@ -1007,8 +1075,13 @@ window.addEventListener('message', (event) => {
10071075
if (message.data?.locale) {
10081076
setFormatLocale(message.data.locale);
10091077
}
1010-
renderLayout(message.data as UsageAnalysisStats);
1011-
renderRepositoryHygienePanels();
1078+
{
1079+
const sanitized = sanitizeStats(message.data);
1080+
if (sanitized) {
1081+
renderLayout(sanitized);
1082+
renderRepositoryHygienePanels();
1083+
}
1084+
}
10121085
break;
10131086
case 'highlightUnknownTools': {
10141087
const el = document.getElementById('unknown-mcp-tools-section');

0 commit comments

Comments
 (0)