This release focuses on the assessment and remediation workflows. The Manager Dashboard gains a vulnerability-level search with its own CSV export, the assessment History tab is reorganized into Open/Closed sub-tabs with one-click finding reuse and a slide-out detail panel, and CSV assessment uploads are now fault-tolerant — one bad row no longer aborts the whole import. Alongside these, several long-standing rendering bugs in the remediation table, report sections, and docx generation are fixed, and the default Docker Compose stack works out of the box again.
🎉 🚀 Upgrades 🎉 🚀
Manager Dashboard: vulnerability search and export
The Manager Dashboard search now returns results in two tabbed views — Assessments and Vulnerabilities. The new Vulnerabilities tab lists each finding with its assessment, app ID, severity, CVSS score, category, open/closed dates, status, and tracking ID, and each row has an Action button that opens the finding's detail. Date-range filtering is now driven by a single shared AssessmentSearchQuery helper so the dashboard view and both CSV exports apply identical overlap semantics (an assessment matches when its lifecycle overlaps the selected window).
Two export buttons are available from the dashboard:
| Button | Output |
|---|---|
| Export Assessments to CSV | One row per assessment in the current search |
| Export Vulnerabilities to CSV | One row per vulnerability in the current search |
Assessment history: Open/Closed tabs, finding reuse, and detail panel
The assessment History tab is split into Open Vulnerabilities and Closed Vulnerabilities sub-tabs, themed to match the main assessment tabs. You can now pull historical findings forward into the current assessment without re-entering them:
- An Add Open Findings to this Assessment button bulk-clones every open finding from the application's history (closed findings are skipped).
- A per-row Add button clones a single historical finding.
In both cases, findings whose tracking ID already exists on the current assessment are deduplicated, so re-running the bulk add is safe. Clicking any history row opens a slide-out side panel showing the full vulnerability details; access is restricted to findings belonging to the same application.
Fault-tolerant CSV assessment upload
The assessment CSV upload servlet was refactored to process each row independently instead of aborting the entire upload on the first error. The upload now returns three result sets, rendered as separate tables on the upload page:
- Added — assessments that were saved, each with a new-tab Edit link (
/portal/EditAssessment?action=get&aid=<id>). - Warnings — rows saved despite a non-fatal issue (for example, an unknown or invalid assessor is skipped rather than failing the row).
- Errors — rows that could not be processed (missing columns, bad date, non-numeric days, or malformed custom-fields JSON).
Report section labels in the vulnerability list
Each vulnerability in the list now shows a colored report-section label, with the color derived from a hash of the section name and live-updated on edit/broadcast. The update broadcast now carries reportSection, so the left-hand table stays in sync when a finding's section changes.
🐛 Bugfixes 🐛
- Remediation table failed to render when any value contained a single quote (#134). Struts'
escapeJavaScriptemits\', which is not a valid JSON escape sequence and brokeJSON.parseon the DataTable. A newjsonEscape()helper backed by Jackson'sJsonStringEncodernow produces strictly valid JSON for the values rendered invulnsJson.jsp. - Section names with underscores were silently altered. The vulnerability section getter was replacing
_with spaces, corrupting section names that legitimately contain underscores; it now returns the stored value unchanged. - docx report generation: embedded images failed to resolve unless the assessment ID matched exactly, and the
${end-section}tag was not found for named sections — both are fixed inDocxUtils. - Category create/rename via the API now creates a category by name when no ID is supplied and renames it when the name changes, instead of requiring a pre-existing ID.
- Default Docker Compose stack was broken. Mongo environment variables are now quoted,
FACTION_MONGO_AUTH_DATABASE=adminis set, and the Hibernate OGMreplicaSetrequirement was removed so the default single-node Mongo container connects without replica-set configuration. - Logging noise reduced: pac4j logging is quieted to ERROR, and the CMS image reload timeout was extended.
🧰 Internal / Test infrastructure
- Added a GitHub Actions Tests workflow that runs
mvn testagainst a Mongo service container on pushes and PRs tomain, and a Release workflow that buildsfaction.warand attaches it to published GitHub Releases. - Added extensive unit test coverage for the new dashboard exports (
ManagerDashboardCSVTest,ManagerDashboardVulnerabilitiesCSVTest,AssessmentSearchQueryTest) and reworked the assessment upload tests around the new per-row result model. - Added contributor tooling:
mise.tomltask definitions mirroring the editor tasks, a hot-reload Docker setup (docker-compose-hotreload.yml,Dockerfile.dev-hotreload), and anAGENTS.mdwith project conventions.
Upgrade notes
- Database migration: not required.
- API: all existing endpoints continue to work unchanged. Category create/rename behavior is additive (create-by-name and rename now supported where they previously required an existing ID).
- Configuration: no new required settings for existing deployments. If you use the bundled
docker-compose.yml, note that it now setsFACTION_MONGO_AUTH_DATABASE=adminand no longer configures a Mongo replica set. - Permissions: no new permission scopes or role changes.