I built a CVE patch-ops tool for indie SaaS shops in a weekend (open scan, honest comparison vs vuls.io)
Last week Hostinger emailed every customer about CVE-2026-31431 — the "Copy Fail" Linux kernel local-privilege-escalation. A 732-byte Python script gets root via algif_aead AF_ALG + splice(). Every kernel between 2017 and the upstream fix in early 2026.
I run a one-person SaaS on a Hostinger VPS. I read the advisory, dropped a modprobe blacklist, and was patched in 30 minutes. Then I realized: most indie SaaS founders running their own boxes wouldn't read that email until tomorrow. Some would never read it at all.
Patch ops for the indie-SaaS tier doesn't exist. vuls.io is great if you have a security engineer with half a day. Enterprise tools are unaffordable. The gap is "I have 1–10 Linux servers, I know I should patch, the workflow is too annoying to do consistently."
So I built StackPatch — curl https://mindsparkstack.com/scan.sh | bash for a free anonymous CVE check, $99 lifetime founder seat for hourly monitoring with a public audit URL.
This post is the build log: architecture, the honest vs-vuls comparison, and the bash one-liner you can run on your VPS in five seconds to see what it does.
The free quickscan: 5 seconds, 0 signup
curl https://mindsparkstack.com/scan.sh | bash
The script reads /etc/os-release, uname -r, the top 200 packages from dpkg-query, and POSTs them to a public API. The API runs the live USN feed (Ubuntu) and the Debian Security Tracker (~110K fix-records across bookworm/trixie/bullseye) against your inventory using dpkg --compare-versions, returns matching CVEs with the exact remediation command.
The source is served as text/plain so you can curl https://mindsparkstack.com/scan.sh and read it before piping to bash. No persistent state server-side beyond a 5-min cache. No identifying info collected (no hostname, no IP, no env vars).
On a real noble box with openssh-client 1:9.6p1-3ubuntu13.10:
=== StackPatch quickscan ===
distro: ubuntu
codename: noble
kernel: 6.8.0-100-generic
packages: 187
⚠️ 2 active CVE matches on your stack right now (worst: high).
Run the recommended commands above. To monitor every server hourly...
[HIGH] CVE-2026-31431 Linux kernel "Copy Fail" — local-priv-esc via algif_aead
why: Linux kernel local-priv-esc; 732-byte Python script gets root...
match: Running kernel: 6.8.0-100-generic
recommend: Apply persistent modprobe blacklist for algif_aead now...
[HIGH] USN-8222-1 OpenSSH 9.6p1 vulnerabilities
match: openssh-client: installed 1:9.6p1-3ubuntu13.10 < fixed 1:9.6p1-3ubuntu13.16
recommend: sudo apt-get install --only-upgrade -y openssh-client
That's the demo. Five seconds, real CVEs, exact commands.
Architecture: file-based, Python stdlib, no DB
The whole backend is JSONL files on disk + cron + a small Next.js layer. There's no Postgres. There's no Kubernetes. The matcher is one Python script:
# Pseudocode of the matcher join
for usn in cached_usns:
for pkg in usn.release_packages[user_codename]:
installed = user_inventory.packages.get(pkg.name)
if installed and dpkg_lt(installed, pkg.fixed):
yield Finding(usn, pkg, installed, fixed)
A few details that mattered:
-
Use
dpkg --compare-versionsfor Debian-policy-correct version comparison. Lexicographic compare is wrong for1:9.6p1-3ubuntu13.10vs1:9.6p1-3ubuntu13.16(lex says "10" > "16"). Spawningdpkgonce per pair is cheap. -
Pre-filter by codename. USN
release_packagesis keyed bynoble | jammy | focal | bionic. Reading the user's/etc/os-releaseVERSION_CODENAMEupfront lets the matcher skip 90% of records. - Cap the USN window. I scan the last 200 USNs (sorted by ID). Older ones are fine to stale; if a 2017 USN matters to your 2024 box, you have bigger problems.
-
Debian Security Tracker is huge. The
tracker.jsonis 70 MB with 36K fix-records per release. I pre-build per-codename indexes ({package: [{cve, fixed_version, urgency}]}) once daily so the matcher loads ~12 MB instead of 70 MB per request.
Inventory + matcher run on three crons:
3 * * * * inventory (reads /etc/os-release, uname, dpkg, docker, ports, modprobe)
23,53 * * * * USN poll (Ubuntu Security Notices feed, twice hourly)
0 4 * * * DSA poll (Debian Security Tracker, daily — file is huge)
33 * * * * matcher (joins inventory × USN × DSA, writes findings JSONL)
40 * * * * alerts (emails customers when findings change)
That's the whole thing. The Next.js layer is a thin wrapper that exposes:
-
/api/stackpatch/quickscan— anonymous POST, returns matches in <1s -
/api/stackpatch/enroll— paid customer enrolls a server with a token, returns audit URL -
/api/stackpatch/inventory— authenticated inventory POST from the agent -
/patch/audit/<slug>— public posture page per server
The killer workflow: the public audit URL
This is what I didn't see in any other tool. Every monitored server gets a URL like:
https://mindsparkstack.com/patch/audit/mss-vps
It shows current findings, applied mitigations, recent resolutions, package counts, kernel state. Updates hourly. Customers (or your customers' enterprise prospects) can verify your security posture without an NDA, without a stale PDF.
When a $3K/year customer asks "how do you handle server security updates?" — you send the link. Done.
This isn't a security scanner. It's a security-response receipt. That distinction is the whole reason the product exists.
Honest vs vuls.io
vuls.io is the obvious comparison. It's free, OSS, mature since 2016, 10K+ GitHub stars, supports Ubuntu/Debian/RHEL/CentOS/Amazon Linux/openSUSE/Alpine/FreeBSD/Windows.
I built /patch/vs-vuls as an honest 12-row green/red/grey side-by-side. Honest enough that the page actively recommends vuls.io if you fit those constraints:
- You have a security engineer with half a day to set up
go-cve-dictionary+goval-dictionary+gost+cve-searchand rebuild them on cron - You need FreeBSD / Windows / openSUSE support
- Compliance forbids any package data leaving your network
Pick StackPatch instead if:
- You're a one-person SaaS shop with 1–10 boxes on Ubuntu, Debian, Alpine, AlmaLinux, or Rocky Linux
- You want the answer in 5 minutes, not half a day
- You want the exact
apt/apk/dnf/ kernel-reboot / modprobe-blacklist one-liner, not just a CVE link - You want a public audit URL for sales due diligence
If a Sunday-afternoon scanner project sounds fun: vuls.io. If you want to be patched and provably so by tomorrow morning: StackPatch.
What V1 doesn't do
I'm not going to lie about the gaps:
- No FreeBSD / Windows / openSUSE yet (V1+ covers Ubuntu, Debian, Alpine, AlmaLinux, Rocky Linux — 18 release versions across those 5 distros, 41K unique CVEs cross-indexed from USN + DSA + Alpine secdb + OSV-rpm + NVD)
- No auto-apply (deliberate — you should review the command, security-product trust is fragile)
- No multi-user RBAC, no SSO, no compliance attestations (this is for solo founders, not security teams)
- No Kubernetes (out of scope for V1; you're not running k8s on a $5/mo VPS anyway)
- No SLA on remediation (we tell you the command; you run it)
If any of those are dealbreakers, vuls.io or an enterprise tool is the right call.
Pricing: $99 lifetime for the first 50
- Free quickscan: anonymous, no signup, no limits. Run it on as many boxes as you like.
- $99 lifetime founder seat: 3 servers, hourly monitoring, real-time email alerts, public audit URL, every V2+ feature included. 50 only, then it's a monthly subscription tier.
There's no growth-hack reason for the lifetime price. It's a forcing function — a recurring-revenue product is cheaper for me long-term but it lets me delay shipping. Lifetime sales mean I have to keep adding founders, which means I have to keep shipping.
Try it
curl https://mindsparkstack.com/scan.sh | bash
Source: https://mindsparkstack.com/scan.sh (read first, then pipe).
Comparison: https://mindsparkstack.com/patch/vs-vuls
Live demo audit: https://mindsparkstack.com/patch/audit/mss-vps (our own VPS, public)
Buy ($99 lifetime, 50 only): https://mindsparkstack.com/patch
Comments welcome — what's missing, what's wrong, what would make you switch from vuls.io. I read everything.
Aiden runs MindSparkStack. StackPatch is the patch-ops layer. Source: this is shipped on Hostinger, with Next.js 16 + Python stdlib + cron, running on the same VPS whose audit URL is public above.
Top comments (0)