diff --git a/soup_cli/ui/static/app.js b/soup_cli/ui/static/app.js index 11a289a..9bb8d1c 100644 --- a/soup_cli/ui/static/app.js +++ b/soup_cli/ui/static/app.js @@ -55,7 +55,7 @@ function statusBadge(status) { failed: 'badge-danger', running: 'badge-warning', }; - return `${status}`; + return `${escapeHtml(status)}`; } function truncate(str, len = 30) { @@ -75,7 +75,7 @@ async function loadDashboard() { renderDashboard(); } catch (err) { document.getElementById('dashboard-content').innerHTML = - `
Error loading dashboard: ${err.message}
`; + `
Error loading dashboard: ${escapeHtml(err.message)}
`; } } @@ -110,10 +110,10 @@ function renderDashboard() {
System
- Device: ${systemInfo.device_name}  |  - GPU Memory: ${systemInfo.gpu_info.memory_total}  |  - Python: ${systemInfo.python_version}  |  - Soup: v${systemInfo.version} + Device: ${escapeHtml(systemInfo.device_name)}  |  + GPU Memory: ${escapeHtml(systemInfo.gpu_info.memory_total)}  |  + Python: ${escapeHtml(systemInfo.python_version)}  |  + Soup: v${escapeHtml(systemInfo.version)}
@@ -146,17 +146,17 @@ function renderRunsTable(runs) { ${runs.map(r => ` - - ${r.run_id.substring(0, 20)}... - ${r.experiment_name || '-'} - ${truncate(r.base_model)} - ${r.task || 'sft'} + + ${escapeHtml(r.run_id.substring(0, 20))}... + ${escapeHtml(r.experiment_name || '-')} + ${escapeHtml(truncate(r.base_model))} + ${escapeHtml(r.task || 'sft')} ${statusBadge(r.status)} ${r.final_loss ? r.final_loss.toFixed(4) : '-'} ${formatDuration(r.duration_secs)} ${formatDate(r.created_at)} - + `).join('')} @@ -200,7 +200,7 @@ async function showRunDetail(runId) {
Run ID
-
${run.run_id}
+
${escapeHtml(run.run_id)}
Status
@@ -208,15 +208,15 @@ async function showRunDetail(runId) {
Model
-
${run.base_model || '-'}
+
${escapeHtml(run.base_model || '-')}
Task
-
${run.task || 'sft'}
+
${escapeHtml(run.task || 'sft')}
Device
-
${run.device_name || run.device || '-'}
+
${escapeHtml(run.device_name || run.device || '-')}
Duration
@@ -268,9 +268,9 @@ async function showRunDetail(runId) { ${evalResp.eval_results.map(er => ` - ${er.benchmark} - ${typeof er.score === 'number' ? er.score.toFixed(4) : er.score} - ${er.details_json ? String(er.details_json).substring(0, 100) : '-'} + ${escapeHtml(er.benchmark)} + ${typeof er.score === 'number' ? er.score.toFixed(4) : escapeHtml(String(er.score))} + ${er.details_json ? escapeHtml(String(er.details_json).substring(0, 100)) : '-'} `).join('')} @@ -289,7 +289,7 @@ async function showRunDetail(runId) { renderCharts(metrics); } } catch (err) { - body.innerHTML = `
Error: ${err.message}
`; + body.innerHTML = `
Error: ${escapeHtml(err.message)}
`; } } @@ -389,7 +389,7 @@ async function loadTrainingPage() { renderTrainingPage(templatesResp.templates, statusResp); } catch (err) { document.getElementById('training-content').innerHTML = - `
Error: ${err.message}
`; + `
Error: ${escapeHtml(err.message)}
`; } } @@ -407,14 +407,14 @@ function renderTrainingPage(templates, status) {
@@ -437,7 +437,7 @@ function renderTrainingPage(templates, status) {
Training Status
${status.running - ? `
Running PID: ${status.pid}
+ ? `
Running PID: ${escapeHtml(String(status.pid))}
` : '
No training in progress
' } @@ -491,10 +491,10 @@ async function validateConfig() { if (result.valid) { statusEl.innerHTML = 'Config is valid!'; } else { - statusEl.innerHTML = `Invalid: ${result.error}`; + statusEl.innerHTML = `Invalid: ${escapeHtml(result.error)}`; } } catch (err) { - statusEl.innerHTML = `Error: ${err.message}`; + statusEl.innerHTML = `Error: ${escapeHtml(err.message)}`; } } @@ -512,12 +512,12 @@ async function startTraining() { body: JSON.stringify({ config_yaml: yaml }), }); document.getElementById('config-status').innerHTML = - `Training started! PID: ${result.pid}`; + `Training started! PID: ${escapeHtml(String(result.pid))}`; // Refresh status loadTrainingPage(); } catch (err) { document.getElementById('config-status').innerHTML = - `Error: ${err.message}`; + `Error: ${escapeHtml(err.message)}`; } } @@ -547,7 +547,7 @@ async function inspectData() { }); renderDataResults(result); } catch (err) { - content.innerHTML = `
Error: ${err.message}
`; + content.innerHTML = `
Error: ${escapeHtml(err.message)}
`; } }