Skip to content

Commit c0a7386

Browse files
Merge pull request #16 from virtualsteve-star/dev
Address Snyk findings
2 parents 85ed017 + 9567b4e commit c0a7386

File tree

3 files changed

+26
-12
lines changed

3 files changed

+26
-12
lines changed

tests/escape_html.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// AppSec Best Practice: Escape user-controlled data to prevent XSS (Snyk CWE-79)
2+
// Shared by all test harnesses
3+
function escapeHTML(str) {
4+
return String(str).replace(/[&<>"']/g, function(m) {
5+
return ({
6+
'&': '&amp;',
7+
'<': '&lt;',
8+
'>': '&gt;',
9+
'"': '&quot;',
10+
"'": '&#39;'
11+
})[m];
12+
});
13+
}

tests/shared_test_setup.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ document.addEventListener('DOMContentLoaded', async () => {
3131
await runner.loadTests();
3232
} catch (error) {
3333
console.error('Error initializing tests:', error);
34+
// Uses shared escapeHTML from escape_html.js (AppSec best practice, Snyk CWE-79)
3435
document.getElementById(config.summaryContentId || 'summaryContent').innerHTML =
35-
`<p class="error">Error loading tests: ${error.message}</p>`;
36+
`<p class="error">Error loading tests: ${escapeHTML(error.message)}</p>`;
3637
}
3738
});

tests/test_runner.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,8 @@ class PromptTestRunner {
242242
}
243243
const row = document.createElement('tr');
244244
row.innerHTML = `
245-
<td>${test.name}</td>
246-
<td>${test.expected}</td>
245+
<td>${escapeHTML(test.name)}</td>
246+
<td>${escapeHTML(test.expected)}</td>
247247
${verdicts.map((v, idx) => {
248248
if (skipped[idx] || v.skipped) {
249249
return `<td style="color:#007bff;font-weight:bold;text-align:center;">–</td>`;
@@ -252,12 +252,12 @@ class PromptTestRunner {
252252
(v.blocked && test.expected === this.positiveLabel) ||
253253
(!v.blocked && test.expected === 'BENIGN')
254254
));
255-
return `<td class="${v.error ? 'incorrect' : isCorrect ? 'correct' : 'incorrect'}">${v.error ? '⚠️' : (isCorrect ? '✓' : '✗')}</td>`;
255+
return `<td class="${v.error ? 'incorrect' : isCorrect ? 'correct' : 'incorrect'}">${escapeHTML(v.error ? '⚠️' : (isCorrect ? '✓' : '✗'))}</td>`;
256256
}).join('')}
257-
${verdicts.map((v, idx) => (skipped[idx] || v.skipped) ? `<td style="color:#007bff;text-align:center;">–</td>` : `<td>${v.time.toFixed(2)}</td>`).join('')}
257+
${verdicts.map((v, idx) => (skipped[idx] || v.skipped) ? `<td style="color:#007bff;text-align:center;">–</td>` : `<td>${escapeHTML(v.time.toFixed(2))}</td>`).join('')}
258258
`;
259259
if (verdicts.some(v => v.error)) {
260-
row.title = verdicts.map(v => v.error).filter(Boolean).join('; ');
260+
row.title = escapeHTML(verdicts.map(v => v.error).filter(Boolean).join('; '));
261261
}
262262
resultsBody.appendChild(row);
263263
verdicts.forEach((v, idx) => {
@@ -270,7 +270,7 @@ class PromptTestRunner {
270270
let summaryHtml = '';
271271
this.filters.forEach((filter, idx) => {
272272
if (skipped[idx]) {
273-
summaryHtml += `<p style="color:#007bff;"><strong>${filter.name}:</strong> Not run due to missing API key</p>`;
273+
summaryHtml += `<p style="color:#007bff;"><strong>${escapeHTML(filter.name)}:</strong> Not run due to missing API key</p>`;
274274
return;
275275
}
276276
const accuracy = testsRun ? (correct[idx] / testsRun * 100).toFixed(1) : '0.0';
@@ -281,12 +281,12 @@ class PromptTestRunner {
281281
: sorted[Math.floor(sorted.length/2)] || 0;
282282
const stddev = times[idx].length ? Math.sqrt(times[idx].reduce((sq, n) => sq + Math.pow(n - avg, 2), 0) / times[idx].length) : 0;
283283
summaryHtml += `
284-
<p><strong>${filter.name}:</strong> ${accuracy}% accuracy (${correct[idx]}/${testsRun} correct)</p>
285-
<p><strong>${filter.name} Times (ms):</strong></p>
284+
<p><strong>${escapeHTML(filter.name)}:</strong> ${escapeHTML(accuracy)}% accuracy (${escapeHTML(correct[idx])}/${escapeHTML(testsRun)} correct)</p>
285+
<p><strong>${escapeHTML(filter.name)} Times (ms):</strong></p>
286286
<ul>
287-
<li>Average: ${avg.toFixed(2)}</li>
288-
<li>Median: ${median.toFixed(2)}</li>
289-
<li>Standard Deviation: ${stddev.toFixed(2)}</li>
287+
<li>Average: ${escapeHTML(avg.toFixed(2))}</li>
288+
<li>Median: ${escapeHTML(median.toFixed(2))}</li>
289+
<li>Standard Deviation: ${escapeHTML(stddev.toFixed(2))}</li>
290290
</ul>
291291
`;
292292
});

0 commit comments

Comments
 (0)