Platforms & Data
VMS: vulnerability management platform
A multi-tenant vulnerability lifecycle platform that runs findings through an event-driven pipeline: scan, correlate, score, remediate, enforce policy.
Problem
Security teams pull findings from several scanners at once, and the same real vulnerability shows up multiple times under different scanner records. Without a single authoritative record per issue, the same problem gets tracked, assigned, and reported more than once.
Raw CVSS severity alone does not tell a team what to fix first. A medium-severity flaw on an internet-facing critical asset can matter more than a high-severity one on an isolated workstation, so prioritization has to account for asset criticality and exposure.
The platform also serves multiple tenants from one deployment, so every piece of data has to stay scoped to its owning tenant. A query that could return another tenant’s assets or vulnerabilities is a data-isolation failure.
How it works
VMS is a TypeScript monorepo with a React frontend and a Node.js/Express backend. Domain logic is split into around twenty services wired together in a single composition root, so no service constructs its own dependencies.
The core is an event-driven pipeline over an in-process event bus. A scan completes, correlation deduplicates its findings, the risk scorer assigns a composite score, the remediation tracker opens tasks, the policy engine checks for violations, and the notification service delivers alerts. Stages communicate only through typed domain events.
All data access goes through a typed Repository interface with a fluent query builder. Storage is selected at startup: PostgreSQL with connection pooling and schema-per-tenant isolation when a database URL is set, or an in-memory store for local development and tests. Identity is handled by Keycloak over OIDC, with the gateway validating JWTs and applying role-based authorization and per-tenant rate limiting; API keys are supported as a second auth path.
Scan Engine -> SCAN_COMPLETED -> Correlation Engine -> VULNERABILITIES_CORRELATED
-> Risk Scorer -> VULNERABILITIES_SCORED -> Remediation Tracker + Policy Engine
-> POLICY_VIOLATION_DETECTED -> Notification Service (Email / Slack / Teams / Webhook)Hard parts
- Finding deduplication: the correlation engine matches incoming findings to existing vulnerabilities by CVE ID, asset ID, and fingerprinting, merges metadata from multiple scanners into one canonical record, and flags low-confidence matches for manual review.
- Composite risk scoring: the risk scorer combines weighted CVSS base score, exploitability, asset criticality, and exposure into a single score, maps it to a priority tier, and raises the priority when threat intelligence reports a known active exploit; scores recalculate when an asset’s criticality changes.
- Multi-tenant isolation: a tenant context is required to obtain any repository, PostgreSQL gives each tenant its own schema, and query handlers re-check tenant ownership on reads so a request cannot return another tenant’s records.
- Declarative policy evaluation: policies are JSON rule conditions with equals/in/greaterThan/lessThan operators and AND/OR logic, evaluated automatically against scored vulnerabilities, with a waiver lifecycle that re-opens violations when a waiver expires.
- Scan orchestration and graceful degradation: scanners plug in through a common adapter interface with progress tracking and backoff retries; notification channels with missing configuration are switched off and the service keeps running, and the backend runs against in-memory storage when no database is configured.
Results
The repository ships with a test suite covering unit tests for every service, property-based tests (fast-check) for scoring and correlation invariants, frontend component tests with Testing Library and MSW, and integration tests that exercise the full vulnerability pipeline end to end.
The full stack stands up through Docker Compose (PostgreSQL, Keycloak, the Node backend, and an nginx-served frontend), and a demo mode provisions sample tenants, users, assets, vulnerabilities, scans, and policies from a single toggle.
Artifacts
- Private repository; no public link.
- Monorepo layout: backend composition root and route handlers, roughly twenty domain services, and shared packages (database, event-bus, logger, shared types, task-manager, frontend).
- Infrastructure as code: a Docker Compose stack for the full system plus Docker and Keycloak realm configuration.