Case study

SecOps Dashboard

A self-hosted workspace for turning scattered scanner findings into investigation, ownership, and follow-through.

Independent project · Open source · MIT License

The problem

Findings need a workflow after the scan.

A report can identify a problem without establishing who will investigate it, whether it duplicates an existing finding, or how the fix will be tracked. I built SecOps Dashboard to connect those steps in one workspace.

My work
Application design, API and frontend implementation, security controls, tests, and deployment tooling.
What you can inspect
Public source, tagged releases, a threat model, and documented operating procedures.
SecOps Dashboard showing eight active sample findings, one critical finding, and three assets, with links to triage and imports.
Actual application screenshot from the public repository, using synthetic demo findings. View full image.

Interactive sample · Synthetic data

Take a finding from signal to action.

Filter the sample findings, inspect the evidence, then update the status or owner. Changes stay in this page and reset when you reload.

  1. 01 Filter
  2. 02 Investigate
  3. 03 Triage

These examples describe the sample workflow. Enable JavaScript to try filtering and triage.

Unparameterized query in checkout API · Critical

A sample query combines request text with a database statement. Confirm that the code path is reachable and that the input is untrusted.

Next action: Use parameterized queries and verify the change with regression cases for untrusted input.

Container dependency needs review · High

The sample report flags an outdated package in a worker image. A version match is a lead; the affected behavior still needs a reachability review.

Next action: Review the affected dependency path, update the image where appropriate, and scan the rebuilt artifact.

Storage bucket allows public reads · High

An example storage policy permits anonymous reads. Establish whether the bucket contents are intended to be public before changing access.

Next action: Remove unintended public access, verify the application still works, and add a policy check for recurrence.

Session cookie missing Secure flag · Medium

The synthetic response sets a session cookie without the Secure attribute. Review the application's HTTPS and cookie configuration together.

Next action: Set Secure for the session cookie and verify login, logout, and session renewal over HTTPS.

Debug header disclosed · Low

A sample response included a development-only header. In this scenario, a follow-up response confirms the header has been removed.

Next action: Keep development headers out of production responses and retain a regression check.

Architecture

A visible path from import to follow-up.

Interface

Next.js

Findings, investigation, team workflows, and user sessions.

Application boundary

FastAPI

Scanner imports, normalization, identity, and project access checks.

Persistent state

PostgreSQL

Findings, accounts, sessions, activity, and queued notification jobs.

Follow-up

Notification worker

Deliver Slack and Jira jobs with retries and delivery-state review.

Browser requests reach the API through Next.js; scanner reports enter at the API. The worker reads queued jobs from the database. The local quickstart uses SQLite and disables external notifications.

Engineering decisions

The choices behind the interface.

01 / Data quality

Make imports explainable.

Enable scanner formats backed by representative fixtures, record import outcomes, and use project and component evidence when identifying duplicate findings.

Trade-off: incomplete context can produce a distinct finding. The application avoids guessing how to merge historical records.

02 / Access

Enforce scope at the API.

Use individual accounts, roles, and project grants. Check access on reads and writes, including saved views, exports, and bulk triage.

Trade-off: this is a deployment for one trusted team. Project grants are not isolation between separate organizations.

03 / Evidence

Treat scanner text as untrusted.

Keep administrative credentials out of the frontend, omit raw scan payloads by default, and neutralize formula-like cells in CSV exports.

Trade-off: targeted redaction helps limit exposure, but operators still control access, retention, and backups.

04 / Delivery

Keep failures reviewable.

Persist notification jobs, record delivery state, and provide bounded retries. Apply migrations and document backup, restore, and account recovery.

Trade-off: an interrupted external request can have an uncertain outcome that needs review before retrying.

Inspect the work

Code, decisions, and a way to run it.

The case study covers the core workflow and team controls shipped in v0.2.0. The repository tracks subsequent development.

← All case studies Discuss this work →