-
Notifications
You must be signed in to change notification settings - Fork 254
Open
Description
Report as you'd initially see it
Report after clicking to expand the summary
HTML + JS + DataTables.js:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Report: GoTestWAF testing Web Application Firewall</title>
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css">
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
h2 { margin-top: 40px; }
.tooltip {
position: relative;
display: inline-block;
cursor: pointer;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 600px;
background-color: #f9f9f9;
color: #333;
text-align: left;
border-radius: 6px;
padding: 10px;
position: absolute;
z-index: 1;
bottom: 125%; /* Position above the text */
left: 50%;
margin-left: -150px;
opacity: 0;
transition: opacity 0.3s;
box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.1);
}
.tooltip:hover .tooltiptext {
visibility: visible;
opacity: 1;
}
</style>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
</head>
<body>
<h1>Report: GoTestWAF testing Web Application Firewall</h1>
<div id="summary"></div>
<div id="tables"></div>
<script>
function toggleSummary() {
const summaryContent = document.getElementById('summary-content');
const toggleButton = document.getElementById('toggle-summary');
if (summaryContent.style.display === 'none') {
summaryContent.style.display = 'block';
toggleButton.innerHTML = '[V] Hide Summary';
} else {
summaryContent.style.display = 'none';
toggleButton.innerHTML = '[>] Show Summary';
}
}
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
function formatDate(dateString) {
const date = new Date(dateString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
function generateSummaryTables(summary) {
const descriptions = {
"true_positive_tests": "Malicious requests that were correctly identified and blocked by the WAF, preventing them from reaching the application.",
"true_negative_tests": "Legitimate requests that were correctly allowed through by the WAF without being flagged or blocked."
};
let html = '';
for (const [key, value] of Object.entries(summary)) {
const description = descriptions[key] || key.replace(/_/g, ' ');
html += `<h3>${description}</h3>`;
html += '<table><thead><tr>';
for (const header in value) {
if (header !== 'test_sets') {
html += `<th>${header.replace(/_/g, ' ')}</th>`;
}
}
html += '</tr></thead><tbody><tr>';
for (const cell in value) {
if (cell !== 'test_sets') {
const cellValue = value[cell];
if (typeof cellValue === 'object') {
html += '<td><table><tbody>';
for (const [subKey, subValue] of Object.entries(cellValue)) {
html += `<tr><th>${subKey.replace(/_/g, ' ')}</th><td>${subValue}</td></tr>`;
}
html += '</tbody></table></td>';
} else {
html += `<td>${cellValue}</td>`;
}
}
}
html += '</tr></tbody></table>';
if (value.test_sets) {
const tableId = `table-${key.replace(/\s+/g, '-')}-test-sets`;
html += `<table id="${tableId}" class="display"><thead><tr><th>Set</th><th>Test</th><th>Percentage</th><th>Sent</th><th>Blocked</th><th>Bypassed</th><th>Unresolved</th><th>Failed</th></tr></thead><tbody>`;
for (const [set, tests] of Object.entries(summary[key].test_sets)) {
for (const [test, results] of Object.entries(tests)) {
html += `<tr><td>${set}</td><td>${test}</td>`;
html += `<td>${results.percentage !== undefined ? results.percentage : 'N/A'}</td>`;
html += `<td>${results.sent !== undefined ? results.sent : 'N/A'}</td>`;
html += `<td>${results.blocked !== undefined ? results.blocked : 'N/A'}</td>`;
html += `<td>${results.bypassed !== undefined ? results.bypassed : 'N/A'}</td>`;
html += `<td>${results.unresolved !== undefined ? results.unresolved : 'N/A'}</td>`;
html += `<td>${results.failed !== undefined ? results.failed : 'N/A'}</td></tr>`;
}
}
html += '</tbody></table>';
}
}
return html;
}
fetch('output.json')
.then(response => response.json())
.then(data => {
const summaryDiv = document.getElementById('summary');
const tablesDiv = document.getElementById('tables');
// Display summary
const summaryHtml = `
<p><strong>Date:</strong> ${formatDate(data.date)}</p>
<p><strong>Project Name:</strong> ${data.project_name}</p>
<p><strong>URL:</strong> ${data.url}</p>
<p><strong>Score:</strong> ${data.score}</p>
<div id="summary-section">
<button id="toggle-summary" onclick="toggleSummary()">[>] Show Summary</button>
<div id="summary-content" style="display: none;">
${generateSummaryTables(data.summary)}
</div>
</div>
`;
summaryDiv.innerHTML = summaryHtml;
// Function to create tables
function createTable(title, testData) {
const tableId = `table-${title.replace(/\s+/g, '-')}`;
const tooltipText = {
"true negative tests payloads - allowed": `Legitimate requests that were correctly allowed through by the WAF without being flagged or blocked.`,
"true negative tests payloads - blocked": `Legitimate requests that should have been allowed through by the WAF, but were incorrectly blocked as if they were malicious.`,
"true negative tests payloads - unresolved": `Legitimate requests where the WAF's response was unclear or the result could not be determined.`,
"true positive tests payloads - blocked": `Malicious requests that were correctly identified and blocked by the WAF, preventing them from reaching the application.`,
"true positive tests payloads - bypassed": `Malicious requests that should have been detected and blocked by the WAF, but instead incorrectly bypassed the WAF as it failed to identify them.`,
"true positive tests payloads - unresolved": `Malicious requests that should have been detected and blocked by the WAF, but the outcome is unclear or indeterminate due to an ambiguous response or incomplete analysis by the WAF.`
};
let tableHtml = `<h2 class="tooltip">${tooltipText[title]}<span class="tooltiptext">${title}</span></h2><table id="${tableId}" class="display"><thead><tr>`;
const headers = Object.keys(testData[0]);
// Move 'payload' to the end
const reorderedHeaders = headers.filter(header => header !== 'payload').concat('payload');
reorderedHeaders.forEach(header => {
tableHtml += `<th>${header}</th>`;
});
tableHtml += `</tr></thead><tbody>`;
testData.forEach(row => {
tableHtml += `<tr>`;
reorderedHeaders.forEach(header => {
if (header === 'payload') {
let payload = row[header];
if (payload.length > 256) {
payload = payload.substring(0, 256) + '...';
}
tableHtml += `<td><pre>${escapeHtml(payload)}</pre></td>`;
} else if (header === 'test_result') {
let icon = '';
if (row[header] === 'passed') {
icon = '✅';
} else if (row[header] === 'failed') {
icon = '❌';
} else if (row[header] === 'unknown') {
icon = '❓';
}
tableHtml += `<td>${icon}</td>`;
} else {
tableHtml += `<td>${row[header]}</td>`;
}
});
tableHtml += `</tr>`;
});
tableHtml += `</tbody></table>`;
return tableHtml;
}
// Create tables for each test type
const testTypes = ['true_positive_tests_payloads', 'true_negative_tests_payloads'];
testTypes.forEach(type => {
for (const [key, value] of Object.entries(data[type])) {
tablesDiv.innerHTML += createTable(`${type.replace(/_/g, ' ')} - ${key}`, value);
}
});
// Initialize DataTables for each table
$(document).ready(function() {
$('table.display').DataTable();
});
})
.catch(error => console.error('Error loading JSON:', error));
</script>
</body>
</html>
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels

