And this version comes to an end
So, i just added some features to get extra space to write this devlog, amongst these are:
Vuln intel service — feed it installed software, get back which CVEs actually apply to it. 27 commits, empty lockfile to a dockerized app with a working sync pipeline and admin panel.Started with the schema: CpeMap, Product, Vendor, Vulnerability, VulnerabilityRange, ScanHost, Source, SyncState. That’s basically the whole app in one commit — vendors/products are a catalog I curate, CVEs link to them through ranges, hosts get matched against those ranges via CPE strings. Seeded sources instead of hardcoding “nvd” everywhere, since I figured I’d want other feeds eventually.Added scan_logs and unmatched_lookups, folded the 2FA columns migration into the users table migration instead of leaving it bolted on separately. Wrote VersionComparator, gave NVD explicit precedence over whatever else might get added later.Pulled in Sanctum, cleaned out migration cruft, updated models to match.Core loop went in next: SyncNvdVulnerabilities command, VulnCheckController, rate limiting, POST /api/vulns/check. CPE lookup → range join → version comparison → vulnerable list, with unmatched stuff parked in its own table so I can go add it to the catalog later instead of it just vanishing. Wrote a pile of tests right after — factories for everything, sync tests, vuln check tests, CPE resolver tests, rate limit tests.Small cleanup pass: slugs in the seeder, more test coverage. Then went back and tore hardcoded NVD assumptions out of the sync command and controller — added a migration so sources can carry their own driver config instead of assuming NVD forever. Wanted that fixed before the app grew around the assumption.Docker next — Dockerfile, compose, entrypoint, opcache config, a CreateScanHost command for provisioning from the CLI. Then the whole frontend in one go: dashboard, a tokens page so scan hosts can self-serve Sanctum tokens, admin dashboard, admin user management, GrantAdmin command, rewrote Welcome (cut it by more than half, mostly bloat). Wired up HandleInertiaRequests so props actually reach the frontend.Wrote the wiki same day as the features it documents — API reference, CLI reference, deployment, schema, operations. Doing it same-day beats doing it a month later once I’ve forgotten why something works the way it does.Found and fixed a memory leak in the sync command — only showed up once I ran it against the real NVD feed instead of test fixtures. Built out actual vendor/product matching: RelinkVulnerabilityRanges command, an admin products page for curating the catalog through the UI, vendor/product seeders with a real starter set.Then a commit I titled, honestly, “deshittified plugin detection.” Pulled the matching logic out of the sync command into its own VulnerabilityRangeBuilder, added an OR-group clause to vulnerability_ranges so one CVE can express “affects 1.2–1.5 OR 2.0–2.3” without hacks, added RebuildVulnerabilityRanges to regenerate ranges without re-hitting NVD. Every project has one of these commits where you fix the thing you hated three days ago.Simplified SECURITY.md, moved the wiki over to GitHub’s wiki and trimmed the in-repo copies to a README with links, merged, added CI and dependabot. Then put the full wiki files back in the repo right after — GitHub wikis are a separate repo under the hood and they drift, didn’t want to rely on it alone.Last commit: made the vuln-check API return a confidence level when it can’t pin down a version instead of silently guessing. Better to say “not sure, but here’s our best guess” than fake precision.Net result: NVD ingest → CPE resolution → version ranges → match API, admin UI to curate the catalog, dockerized, test coverage across the sync command, comparator, API, rate limits, and admin auth.
Started Rozhanisty today — a tool that pulls vulnerability data from the NIST NVD API and lets a CLI scanner check local software for known CVEs against installed versions.
Spent most of today on the database schema instead of anything flashy, but this is the part that has to be right before anything else works:
wordpress) can have multiple products (core, plugin, theme, etc.), since NVD data is a mess of vendor/product pairs that need de-duping.exact vs fuzzy match types since NVD naming is inconsistent and I’ll need fuzzy matching for products that don’t map 1:1.version_start/version_end (inclusive flags included, because NVD ranges are sometimes open-ended) and a match_confidence enum so the scanner can flag “we’re not 100% sure this applies to you.”Stack is Laravel on the backend (queues will probably handle the NVD pulls later) with Vue for whatever dashboard/UI ends up existing for making API keys.
Next up: writing the ingestion job that actually pulls from the NVD API and populates these tables.
CTFp — Devlog #1CTFp is a self-hosted CTF (Capture The Flag) competition platform I’m building from scratch. Backend is Laravel 13 (PHP 8.3), frontend is Vue 3 + TypeScript with Tailwind and shadcn-vue components, everything running in Docker for dev. Started the repo on July 16. First few days were mostly scaffolding, got the Laravel + Vue split running together in Docker with hot reload on both sides (PHP/Blade changes need nothing, Vite handles the frontend), wrote a small qol script to spin the dev environment up, and set up CI with ESLint/Prettier. From there I built out auth, login and register pages on the frontend, an auth controller on the backend using Sanctum, and added Authentik as an OAuth provider so the platform can hook into an existing identity provider instead of only rolling its own accounts. Alongside that I added Gravatar support with a fallback to generated initials for users without one. Usernames needed some care for a public platform, so I pulled in a blocklist (based on LDNOOBW) with validation, and set up a workflow to keep it synced from upstream.On the data model side: users, orgs, and invites all have migrations and factories now, laying the groundwork for team-based competitions rather than just solo accounts. Most recently I’ve been on the frontend shell, landing page, branding, a sidebar for the user area, and pulling in shadcn UI blocks to speed up building out the rest of the interface. Still early. Core auth and org/invite data model are in place. Next is actually building out CTF-specific functionality (challenges, scoring, competitions) on top of this foundation.
Also i am too lazy to spin the docker containers rn so here is a git tree instead :3
Played around with sso via google, github and discord, I only managed to implement github for now because google cloud is not very intuitive and discord is a feature i am not sure i want to use [the plan was that someone who sso’d via dc would have a dc connection in their profile so you could actually contact them to merge trees or whatever…] and ci pipelines
Added a minimalistic dashboard, fixed ci pipeline and started working on oauth via google, discord and gh. Also updated composer and pnpm, and added README
I have written a database schema that could possibly work for my project, and i have thought about possible features that could be useful to add now