← Back to Engineering Notes

November 4, 2026

A 403 Is Not Proof: The MockForge CVE Toolkit, From Signature Packs to Managed Labs

Your load balancer returned a 403. Did the request still reach the origin? That question is harder to answer than it should be. Plenty of edge rules respond with a rejection after forwarding the request anyway. The status code says blocked. The origin logs say otherwise. Most teams find out which one is true during an incident, which is the worst time to learn it.

MockForge's CVE toolkit exists to answer that question in a lab, before it matters. It has grown in three layers over the last few releases, and each layer answers a different part of the problem.

Layer 1: per-CVE rule packs, safety by schema

A rule pack is a small profile you author from a vendor advisory: the route, the header or query parameter names your rule keys on, benign control requests, and the outcome you expect. The harness stands up a MockForge mock as a realistic but inert origin, sends the signature request and the controls through your load balancer or WAF, and records which requests actually reached the origin.

The verdict words are chosen carefully. Pass means the signature got the expected block status and never reached the origin, while every benign control passed through. Fail includes the uncomfortable case: the rule returned a rejection and forwarded the request anyway. Inconclusive means the evidence could not establish blocking, because a test that cannot prove a negative should say so.

The safety model is the schema itself. A profile's values are inert markers, restricted to letters, digits, and a few punctuation characters. There is no request body field at all. A profile cannot carry a command, a template expression, or a traversal payload, so the harness physically cannot become an exploit tool. It tests rules that key on the presence of a header or parameter, like the x-middleware-subrequest header from the Next.js CVE-2025-29927 advisory. It will never carry the literal payload of a content-matching CVE like Log4Shell, by design.

When you cannot instrument the origin, a probe mode compares the signature response against benign controls at the front door. It is weaker evidence and the guide says so plainly: status-only, never proof.

Layer 2: know what to patch, and what to test next

Two companion tools keep the packs useful after the first run.

cve_pack.py tips <CVE> aggregates remediation guidance from every feed it can reach: the version to upgrade to (OSV per-package fixes, NVD as a fallback), whether the CVE is actively exploited or ransomware-linked (CISA KEV), its EPSS exploitation probability, the CWE classes, and the authoritative references. The failure semantics are honest: if the KEV feed is unreachable, actively_exploited comes back null, not false, and partial results are flagged as partial.

The monitor is KEV-driven. It triages new actively exploited CVEs to the weakness classes a request-facing rule can actually act on, enriches the urgent ones with tips, and writes a candidate pack for each. It reads feeds only. It sends no traffic and opens no pull requests. You can even wire an LLM command in as a signature drafter, and the design assumes you will: advisory text is untrusted input, so every drafted proposal is validated against the schema, rebuilt with the feed-authoritative details, and written out as needs-review. A prompt-injected draft cannot produce a runnable payload, because the schema admits nothing runnable.

Layer 3: managed labs, the real application

Signature packs test rules. Sometimes you need to test against the vulnerable software itself.

MockForge 0.3.240 adds managed CVE labs. One command, mockforge cve run CVE-2025-29927, downloads pinned Vulhub and Nuclei container images (pinned by digest, from a reviewed catalog), reproduces the Next.js middleware authorization bypass against a real vulnerable application, and records the evidence. A baseline run confirms the reproduction: an ordinary request gets an authentication redirect, the test request reaches the protected dashboard.

Then point your test load balancer at the lab's recorder. The recorder forwards requests to the vulnerable application and logs which ones arrived. The verdict is the same discipline as the rule packs, one level deeper: pass requires the LB to reject the signature request, no correlated request at the origin, and benign traffic still flowing. The output directory keeps the full evidence, request and response data, application logs, and the final report. When the run ends, cleanup removes only the containers the run owns.

What none of this proves

The toolkit tests request-blocking scenarios and rule behavior at the transport layer. It does not prove an application is patched, does not establish protection against every variant of a CVE, and does not evaluate an LB policy that intentionally forwards a sanitized request. Reports mark patch evidence as unverified, because it is. Those limits are printed in the guides rather than buried, because a security tool that oversells its verdicts is worse than no tool.

Try it

The rule-pack tools ship with MockForge 0.3.238 and later:

cargo install mockforge-cli --version 0.3.238 --locked
mockforge tools export --output-dir mockforge-tools

Managed labs arrive in 0.3.240:

mockforge cve doctor
mockforge cve run CVE-2025-29927 --output-dir nextjs-baseline

A 403 is a claim. These tools exist so you can check it.