Chris Enoch · · Field notes
I got blindsided by a 9.8 CVE. Thirteen hours later, an agentic watch was running.
This month I ran a security review of my own production application. While that was underway, a critical vulnerability surfaced in the software stack underneath it. The review cycle caught it: I patched by hand, rebuilt, verified the fix on the running system, then ran a second review to confirm. The process worked — because I happened to be mid-review.
Then yesterday a critical kernel CVE hit my feed on X, hours after a stranger posted it. We moved fast — a host-level mitigation in place while neither Canonical nor Red Hat had shipped a fix — but the discovery channel was luck, twice in one month: once because I happened to be reviewing, once because I happened to be scrolling. I run systems for a living, and my vulnerability alerting plan amounted to "happen to be looking."
So Friday evening I wrote the frustration down as a product question: what would it take for an agent to watch this for me — not a dashboard I have to remember to open, but something that knows what I'm actually running, reads the advisory feeds, and tells my phone when the two intersect?
By Saturday morning it was running unattended against my production application, on a schedule, with a dead-man's switch configured to alert my phone if the watch goes quiet.
The kernel bug, briefly
The CVE in question is CVE-2026-98432: a use-after-free in the Linux kernel's IPv4 TCP request handling. The shape of it, per public reporting: when a request socket carries IPv4 options, one CPU can still be reading those options while another frees them; the upstream fix protects the readers with RCU-delayed freeing. Incoming TCP with IP options to a reachable listener is the exposure; early reports centered on multipath-TCP listeners, but the bug is not MPTCP-specific.
Two details worth noticing beyond the mechanics:
- Even the severity is contested. Canonical lists it Critical at 9.8; Red Hat's CVE page assesses its own products at 5.9 and describes denial of service as the practical concern; a separate Red Hat bulletin rates the issue critical. When the authorities disagree by four points, the headline number can't be your triage signal — your own exposure has to be.
- The timeline is the indictment. The CVE was published in mid-October. On October 27, Anthropic described a working research exploit against a server with an MPTCP listener. As of October 31, Ubuntu's tracker still lists its fix as work in progress, while Red Hat's CVE page lists fixes as deferred. Debian has released fixed kernels. The gap between an upstream fix and a vendor package matters when that vendor runs your host.
What we did while the vendor patch doesn't exist
To be precise about the words: we mitigated at the host level while awaiting Canonical's kernel update. We did not patch, and we don't call it fixed. Our production host runs Ubuntu 26.04 LTS; Canonical's tracker lists the fix for that series as work in progress.
The mitigation, two layers:
- Disabled multipath TCP via a persistent sysctl (
net.mptcp.enabled = 0) — an additional restriction that narrows exposure, not by itself proof of complete exploit prevention. - An early packet filter. The tested path involves incoming IPv4 TCP carrying
IP options — and almost no legitimate modern traffic uses IPv4 options. So a dedicated
nftables table hooks
preroutingat priority -300 and drops IPv4 TCP packets whose header length exceeds five 32-bit words (i.e., packets with options), logging matches at a limited rate and counting every drop:
ip protocol tcp ip hdrlength gt 5 limit rate 3/minute log prefix "cve98432 drop "
ip protocol tcp ip hdrlength gt 5 counter drop The rate limit applies to logging only — matches are dropped regardless. The table loads from a dedicated service at boot.
What we verified — and the limits of that verification:
- Before touching the host path, the rule was tested in an isolated network namespace on the same machine: ordinary TCP connected; the options-bearing test traffic was dropped. That demonstrates the rule's behavior for the tested traffic — it was not a full exploit test.
- Persistence was then proven the only way that counts: an authorized reboot. The mitigation service started on boot, the table and both rules were present, and MPTCP stayed disabled.
- As of this writing the drop counter reads zero. That is an observation about the counter, not evidence that nobody has probed the host.
- The filter covers the specified incoming IPv4 TCP path. It is not proof that every possible route to the underlying bug is blocked.
For this specific case, our watch now polls Ubuntu's security feed for the notice naming this CVE and a kernel package, and can send a phone alert. It reads the latest 20 feed entries, deduplicates by notice ID, and depends on the vendor's CVE and package fields and on notification delivery; it can miss a notice or a later revision. It does not verify the running kernel or establish that the host is patched. When the applicable USN ships, we plan to install Canonical's kernel, reboot, verify the running version and review the temporary filter for removal.
What got built
A small evidence pipeline with one organizing idea: never claim more than the evidence supports.
- Runtime-verified inventory. The watch doesn't trust what the repo says is deployed. A locked-down, read-only collector observes the running system — a runtime version and container identity — rather than relying only on what the repository says is deployed.
- Default-deny validation. An observation counts only if it passes a strict schema and semantic checks: evidence bound to the right host and component, timestamps sane and fresh, raw command output that actually supports the claimed version. Anything less is UNKNOWN, loudly — never silently "covered."
- Feeds + matching. Vendor release and security feeds plus CISA's KEV catalog, matched against the verified inventory. "Covered" requires a sourced CVE-to-fix mapping; heuristic matches are labeled candidates for investigation, not verdicts.
- Health separate from findings. A monitoring tool's worst failure mode is looking green while dead. Runs write structured local receipts; a gate distinguishes "no findings" from "no data"; and a successful cycle signals the external monitor only after its receipt commits. The monitor is configured to alert on missed heartbeats, including if the machine dies. The receipts are not tamper-evident attestations, and notification delivery remains best-effort.
Deliberate boundary: it watches and prepares. It does not patch. Remediation on my own infrastructure is the next phase, approval-gated, with the same evidence chain re-verifying that a fix actually landed.
How it got built — the part that's actually the product
Every layer went through adversarial review by a different AI agent than the one that wrote it, plus live runs on real infrastructure by a third. The loop: build → an independent reviewer probes the actual artifact with counterexamples → counterexamples are retained as regression tests or review probes → minimal fix → the reviewer re-executes against the fixed artifact → acceptance records bound to the exact bytes by hash. Then the next layer.
Across the night that loop caught, among others: evidence that could vouch for the wrong machine; empty observations masquerading as verified ones; a health check that could report green from leftover receipts after the producers crashed; a success signal that could fire before results were saved; and — found by a reviewer after deployment, fixed within the hour — findings that arrived during a feed outage being silently swallowed by deduplication. Those cases show why the independent probes mattered: they exercised failure states the existing tests had not covered. The resulting counterexamples were added to the review and regression trail.
For calibration, it took roughly thirteen hours from frustration to unattended operation. Across the stack, independent acceptances are tied to the reviewed artifact hashes.
Honest limits, because that's the point
The pilot watches one application. Its vulnerability map is deliberately empty until real CVE-to-fix mappings are sourced, so it currently reports candidates, not coverage. Observing a runtime version proves what a fresh process reports, not what a long-running process loaded before a patch. None of this is an attestation system — a compromised host can lie about itself. Each of those limits is written into the tool's own output rather than discovered by a disappointed customer later.
Why this matters for your business
Patch latency is an SMB problem disguised as an enterprise problem. The enterprise has a security team watching feeds; you have whoever happens to scroll past the news. The fix isn't a $100k platform — it's a watch that knows your actual systems, holds its claims to evidence, and escalates to a human with a receipt.
If a blindside like mine is a risk you're carrying, that's a conversation I'm equipped to have — with the receipts to show how this gets built. [email protected]
Chris Enoch is the founder of Enoch AI LLC, an AI consulting practice for small and mid-sized businesses. Before that: 23 years in enterprise IT, culminating in a role as a cloud architect at Dell Technologies.