← Usman Chaudhary Project write-up · 2026

Security · AI · Critical infrastructure

Patching C vulnerabilities in disconnected environments An AI can write a security patch. In an air-gapped environment you can't call a cloud model to check it, and a bad patch can be hard to undo. So how do you decide whether to trust it?

EdgePatch checks AI-written security patches for C code, completely offline. It runs a fixed set of automated checks on each patch and gives a person one report to approve or reject.

TL;DR · the 60-second version

An offline tool that checks whether to trust an AI's security patch

For systems with no internet access, where a bad patch is hard to undo: an AI suggests the patch, EdgePatch runs automated checks on it, and a person makes the final call.

Step 1
An AI suggests a patch
Step 2
EdgePatch checks it
Step 3
A person approves
4
real C libraries tested
zlib · libpng · expat · libxml2
9/9
patches judged correctly
good ones accepted, bad ones rejected
3
real AI mistakes caught
in raw model output
1
command re-runs
the whole benchmark

Who it's for: teams that run offline, high-stakes systems — critical infrastructure, industrial control, regulated finance and healthcare, defense and allied networks — and the engineers who have to approve a machine-written fix. Not for a connected team with full cloud access and testing infrastructure; they have easier options.

How it works

Follow one patch through EdgePatch

An AI can write a patch that looks right. Whether it's actually correct is a separate question. In these systems the margin for error is even smaller — a bad patch can mean downtime, a failed audit, or a safety problem, and you often can't simply undo it. So you need a way to check the fix that doesn't depend on the AI that wrote it. EdgePatch does this with a fixed sequence of checks: each one looks at the patch and either stops it or passes it to the next. Only a patch that passes every check reaches a person.

Works offline.  The patch can come from a small AI model running on-site, a fix brought in from a secure system, or an official fix delivered on physical media. EdgePatch never needs an internet connection.
the AI's suggestionan automated checka person
1

A patch arrives

The patch can come from an AI model on-site, a secure system, or an official update — EdgePatch treats them all the same. What actually arrives is a diff: a list of the exact lines to remove and add.

What a patch looks like — a diff
inflate.c
avail = state->avail_out;
- memcpy(out, next, len);
+ if (len <= avail) memcpy(out, next, len);
A diff is just the difference: lines to remove (shown in red, ) and lines to add (green, +). Here the patch adds a check that the data fits before copying it.
Lesson learned
An AI-written patch is a suggestion, not a proven fix. EdgePatch checks it before anyone trusts it.
2

Is it a valid patch?

Every diff says "find these exact lines and change them." EdgePatch does a dry run: it takes the lines the patch expects to find and checks they actually exist, exactly, in the real file — without changing anything yet. If the file has moved on, or the patch is malformed, the lines won't match and it's rejected right away, before any more effort is spent.

The dry run — do the expected lines exist?
the patch expects to find, in inflate.c:
avail = state->avail_out;
memcpy(out, next, len);
EdgePatch looks for these lines in the actual file. Found exactly → the patch fits. Missing or changed → rejected. Nothing is written to disk during this check.
✓ lines match → continue ✗ no match → rejected
Lesson learned
The easiest problem to catch is a patch that was never valid to begin with. Catch it first.
3

Did it change the right place? optional · needs a reference

This check runs only when we have a known-correct fix to compare against (for example, an official fix delivered offline). Here's how it works: EdgePatch reads the patch to see which lines changed, then scans the code to find which function those lines belong to. It does the same for the known-correct fix, then compares the two — same file? same function? about the same size? If they line up, the patch is in the right place. If it's in a different function, or far bigger or smaller, that's a red flag.

Comparing the patch to a known-correct fix
The AI's patch
file: pngrtran.c function: png_set_quantize + if (i < num_palette)
Known-correct fix
file: pngrtran.c function: png_set_quantize + if (i >= 0 && i < num_palette)
same file ✓same function ✓similar size ✓→ right place
Both changes land in the same function, at about the same size — so the patch is in the right spot. Note this says where the patch is, not whether it's correct. That's the next check.
Lesson learned
Being in the right place doesn't make a patch correct. A fix can be in exactly the right function and still be wrong.
4

Does it actually work?

This is where correctness is checked, and it doesn't need a reference. In a safe, separate environment the patched code is compiled and run: does it build, is the original crash gone, and do all the existing tests still pass? Those results are recorded and passed to EdgePatch. (EdgePatch reads the results — it doesn't run the code or trigger the vulnerability itself.)

Evidence from building and running the patch
  • the patched code compiles
  • the original crash no longer happens
  • all existing tests still pass
Lesson learned
Building and running the patch is what proves it works. When there's no reference to compare against, this is the check that decides.
5

Put the results in one report

EdgePatch collects everything — did it apply, did it land in the right place, does it build and pass tests, plus the supporting evidence — into a single report. The report gives a clear verdict, the reasons for it, and the evidence behind it. It also serves as the audit record: a durable account of what was checked and why the decision was made, so the approval can be reviewed later.

What the report looks like
VerdictREADY
Appliesyes
Right placeyes — strong match
Builds & testsyes — crash gone, tests pass
Evidencebuild log, test results, proof — attached
Kept asan audit record — what was checked, when
Today the report is a plain document (readable by people and machines) that doubles as the audit trail. Signed reports and standard security formats (SBOM, SARIF) are on the roadmap.
Lesson learned
Give the reviewer a clear verdict with the evidence attached — not a pile of output to sort through.
6

A person approves

A person reads the report and makes the call. EdgePatch never applies the patch itself — it lays out the evidence and recommends; a person approves or rejects. If approved, the fix is then applied through the site's normal change-control process (a maintenance window, the usual sign-offs) — a deliberate, human-run step, not something EdgePatch does. The rule for a ready verdict is strict: the patch must apply, build, stop the crash, pass all tests, and — when checked — land in the right place.

The final decision is a person's
report a person ✓ Approve Reject applied via change control
Once approved, the team applies the fix through their normal change-control process. EdgePatch never applies it automatically.
Lesson learned
In these systems, applying a bad patch is a serious event — so a person makes the final decision.
What makes it reliable
Every check EdgePatch runs is plain, repeatable code — no AI is involved in the decision. That means the checks are deterministic: the same patch and the same evidence always produce the same verdict. A reviewer can rely on it, and get the same answer tomorrow.
Why not let the AI check its own work?
An AI can grade its own patch, or even produce its own SBOM or SARIF file — but that's the same AI vouching for itself, and there's no reason to trust that more than the patch. A report is only worth the independent process behind it. EdgePatch's checks run separately from whatever wrote the patch, and an SBOM or SARIF only counts when it's built from the real code, not written by the model. That separation is the whole point.
How we know EdgePatch judges well
We tested the checks on their own. We took old bugs in four real libraries that have already been fixed, and used each real fix as the answer key — writing down the expected result before running anything. Given a mix of good patches and deliberately bad ones, EdgePatch got every one right: it accepted the good patches and rejected the bad ones. It also caught three different real mistakes in raw AI output. The full numbers are in the appendix.

What it isn't

EdgePatch is deliberately narrow — that focus is what makes it reliable:

This is an early-stage need: AI help with patching reaches offline, high-stakes systems last, and matters there most. The same pattern — a change that has to be checked and approved by a person — also fits regulated cloud and cross-domain work.

What's next

On the roadmap

v1 is the core: the checks, the report, and the benchmark that proves the checks work. The next steps add stronger evidence and cover more code.

Why it matters

Checking the patch is the hard part

AI is going to write a lot of security patches. The hard part isn't getting a model to suggest a fix — it's knowing whether to trust one, especially offline and in systems where a bad patch is hard to undo. EdgePatch turns an AI's suggestion into a checked report a person can approve, and gives the same answer every time. The AI writes the patch; the checking doesn't rely on the AI. That's what these systems need, and it works today.

Appendix — the evidence

The numbers, in the same order as the checks

This follows the six steps above: how the patches were graded, then the results for the "right place" check, then the full build-and-test run, then what the report can say, then how to reproduce it.

Setup · how the patches were graded

Testing the checks, not fixing live bugs

To test whether the checks are any good, we needed cases where the right answer was already known. So we used old bugs that have long since been fixed, and treated each real fix as the answer key. Only patches whose correct answer was established independently count toward the score — three kinds qualify; a fourth is analyzed but never counted.

from the real fix
Built directly from the known upstream fix.
counts
deliberately wrong
Altered to be wrong in a specific, known way (e.g. moved to the wrong file).
counts
AI patch, verified
A model's patch confirmed by building and testing it.
counts
AI patch, unverified
Raw model output we never independently confirmed. Reported separately, never in the score.
separate

The expected result for each case was written down before scoring, so the grading can't drift to fit the outcome.

Step 3 · the "right place" check

Results

Across the nine graded patches, every one was classified correctly in both directions — good patches accepted, bad patches rejected — with no misses.

MetricValue
Graded patches9
Classified correctly9 / 9
Good patches acceptedall
Bad patches rejectedall
Mistakes0
By libraryRightBy bug typeRight
zlib2 / 2out-of-bounds read (CWE-125)3 / 3
libpng3 / 3integer overflow (CWE-190)4 / 4
expat2 / 2out-of-bounds write (CWE-787)2 / 2
libxml22 / 2

We also pointed the checks at three unverified AI patches — kept out of the score above — and each was caught for a different reason:

LibraryCaught asIn plain terms
expatmalformedthe diff didn't even apply
libpngwrong functionchanged the wrong part of the code
libxml2incompletetoo small to be the real fix

Step 4 · building and testing

What was tested end-to-end

The nine results above are all from the "right place" check. Exactly one case — zlib CVE-2022-37434 — was carried all the way through: the patch was built and run, the crash confirmed gone, and the existing tests confirmed still passing. So read it as one full build-and-test run plus nine "right place" checks — not nine full fixes.

Step 5 · what the report can say

The verdicts

For the "right place" check, a patch is marked as right place or flagged as wrong file wrong function incomplete too broad malformed.

Combining that with the build-and-test evidence, the overall verdict is one of: READY READY, WITH CAVEATS NEEDS REVIEW NEEDS TESTING REJECT — wrong location REJECT — broke a test REJECT — incomplete CAN'T TELL — missing evidence. The key rule: READY requires the crash resolved and tests passing and a matching location. Nothing is marked ready on location alone.

Reproduce

Run it yourself

# 1. download the code from GitHub: git clone https://github.com/usmanaminch/ai-mastery-2026.git # 2. go to the project folder: cd ai-mastery-2026/p6-edgepatch # 3. run the benchmark (no extra setup needed): python3 -m edgepatch bench # prints the results tables above

Cases & sources

LibraryCVEBug typeWhere the fix goes
zlibCVE-2022-37434CWE-787inflate.c · inflate
libpngCVE-2025-64505CWE-125pngrtran.c · png_set_quantize
expatCVE-2022-25315CWE-190xmlparse.c · storeRawNames
libxml2CVE-2022-40303CWE-190parser.c · xmlParseNameComplex
  1. Repository: github.com/usmanaminch/ai-mastery-2026 · p6-edgepatch. Each case's exact upstream fix commit is recorded with it; third-party source licences are listed in the repo.
  2. Worked case: zlib CVE-2022-37434 — publicly disclosed and long since fixed upstream, used only as a known reference. No steps to reproduce the bug are given or needed.
  3. Other test cases (public, already fixed): libpng CVE-2025-64505, expat CVE-2022-25315, libxml2 CVE-2022-40303.
  4. Bug types: CWE-125 (out-of-bounds read), CWE-190 (integer overflow), CWE-787 (out-of-bounds write). Everything here is drawn from public sources.