-
Notifications
You must be signed in to change notification settings - Fork 135
Description
Is your feature request related to a problem? Please describe.
Monkey365 HTML reports can contain a large volume of findings, and during manual review many of these may be identified as false positives or not applicable to a particular environment. Currently, there is no way to annotate or visually mark these findings in the report itself. This makes it difficult for analysts to track which items have already been reviewed, which ones are confirmed issues, and which ones have been ruled out.
Describe the solution you'd like
Add a “Mark false positive” toggle button to each finding card in the HTML report.
When clicked:
- the card becomes visually muted (greyed out / lower opacity)
- the header is struck through
- a small “False positive” badge is added
- the state persists across page reloads using localStorage
- Clicking again should revert the card back to normal.
Describe alternatives you've considered
- Maintaining a separate spreadsheet or notes file during analysis (inefficient and detached from the report).
- Editing the HTML manually after generation to grey out findings (not practical and must be repeated for every report).
Additional context
Below is the working but a bit messy code that implements this feature.
CSS to grey-out false positives (placed in <head>):
<style>
.monkey-finding-card.false-positive {
opacity: 0.4;
filter: grayscale(1);
}
.monkey-finding-card.false-positive .card-header {
text-decoration: line-through;
}
.monkey-finding-card.false-positive .false-positive-badge {
font-size: 0.75rem;
margin-left: 0.5rem;
text-transform: uppercase;
}
</style>
JavaScript to add toggle buttons & persist state (added before </body>):
<script>
document.addEventListener('DOMContentLoaded', function () {
const FP_KEY = 'monkey365_false_positive_findings';
let savedFalsePositives = [];
try {
savedFalsePositives = JSON.parse(localStorage.getItem(FP_KEY) || '[]');
} catch (e) {
savedFalsePositives = [];
}
function setFalsePositiveState(card, isFalsePositive) {
const id = card.id;
const btn = card.querySelector('.monkey-fp-toggle');
if (isFalsePositive) {
card.classList.add('false-positive');
if (btn) btn.textContent = 'Unmark false positive';
let badge = card.querySelector('.false-positive-badge');
if (!badge) {
badge = document.createElement('span');
badge.className = 'badge bg-secondary false-positive-badge';
badge.textContent = 'False positive';
const header = card.querySelector('.monkey-finding-header');
if (header) header.appendChild(badge);
}
if (!savedFalsePositives.includes(id)) {
savedFalsePositives.push(id);
}
} else {
card.classList.remove('false-positive');
if (btn) btn.textContent = 'Mark false positive';
const badge = card.querySelector('.false-positive-badge');
if (badge && badge.parentNode) {
badge.parentNode.removeChild(badge);
}
savedFalsePositives = savedFalsePositives.filter(x => x !== id);
}
localStorage.setItem(FP_KEY, JSON.stringify(savedFalsePositives));
}
document.querySelectorAll('.monkey-finding-card').forEach(card => {
const id = card.id;
if (!id) return;
const header = card.querySelector('.monkey-finding-header');
if (!header) return;
const btn = document.createElement('button');
btn.type = 'button';
btn.className = 'btn btn-sm btn-outline-secondary float-end monkey-fp-toggle';
btn.textContent = 'Mark false positive';
btn.addEventListener('click', e => {
e.stopPropagation();
const isFP = !card.classList.contains('false-positive');
setFalsePositiveState(card, isFP);
});
header.appendChild(btn);
if (savedFalsePositives.includes(id)) {
setFalsePositiveState(card, true);
}
});
});
</script>