In an earlier series, Teaching a machine to spot vulnerable code, I built a vulnerable code detector using CodeBERT and TorchSharp, trained and executed 100% in C#. It works: you hand it a snippet of code, it hands back a probability. The problem is where it lives. It runs inside a console app, waiting for someone to paste a snippet by hand. No team works like that.
This is the series that fixes that. The detector leaves the console and goes where real code is born, the pull request. And it gains a partner, because on its own it cannot be the gatekeeper.
Why the detector alone is not enough
Before any architecture, the number that shapes the whole project. I trained the classifier on the five vulnerability categories this series covers, and measured it against code it had never seen: 77.3% correct.
Seventy seven percent is good for a small model trained in an afternoon. And it is terrible for a gatekeeper. More than one in every five verdicts is wrong, and the error that hurts most has a name: the false positive, when the model flags as vulnerable a piece of code that is perfectly correct.
Blocking someone's merge over one of those, a few times a week, is the fastest way to get the team to turn the tool off.
And this is not hypothetical. Later in this series you will watch the classifier look at a snippet that deserializes XML the right way, with the type set by the code itself, and call it Insecure Deserialization with 97.7% confidence. It gets it wrong, and it gets it wrong with conviction.
Second opinion: who actually decides
That is where NeuralGuard's shape comes from. The local classifier does not deliver the verdict, it raises the suspicion. When the suspicion is confident enough, the snippet goes to Claude, which reads the code with context and answers one question only: is this really exploitable, or did the model get confused by a pattern that looks similar?
The division of labour has a practical reason beyond quality. The classifier runs locally, in milliseconds, and costs nothing. Claude costs per call. Letting the small model filter first means a pull request with nothing suspicious generates no paid call at all, and a pull request with three suspicious snippets generates three.
GitHub Actions: what it is, and why it fits here
GitHub Actions is GitHub's own automation system. It reacts to events in the repository, such as a pull request being opened, and runs a sequence of steps on GitHub's infrastructure, without you keeping a server running.
It is the natural home for this detector, because the event that matters, someone proposed a code change, is exactly the event Actions listens for. And because the result has somewhere to show up: a comment on the pull request, and a check that can hold the merge.
Three repositories, three jobs
NeuralGuard is the engine: the classifier, the client that talks to Claude, and a command line tool that puts the two together. It analyzes only the lines the pull request adds, not the whole repository.
NeuralGuard.Action is the GitHub Action: a thin package that installs that tool inside the workflow, runs it against the diff, publishes the result as a comment and fails the check when Claude confirms a vulnerability.
NeuralGuard.Playground is the target: a small API where every endpoint exists in two versions, one with the flaw and one with the same feature done correctly. It is where the series shows the pipeline running end to end, including the false positive I mentioned above.
The five vulnerabilities
The detector from that series knew a single pattern. This one knows five: SQL Injection, Cross-Site Scripting, Command Injection, Path Traversal and Insecure Deserialization.
How the series will unfold
The next five articles are fundamentals, one per vulnerability: what it is, why it goes unnoticed, and how the same snippet looks written the wrong way and the right way. Anyone who read what vulnerable code is already knows the format.
Then comes the training, and an article I was not planning to write: the first result looked perfectly reasonable, I wrote it down and moved on, and it was wrong. That mistake has a name, it is easy to make without noticing, and it fills a whole article.
After that, the engineering: packaging the detector as a command line tool, teaching Claude to give the second opinion, assembling the Action, commenting on the pull request and blocking the merge. And at the end, everything running together in the Playground.
The next article starts the fundamentals with the vulnerability that earlier series already introduced, now looked at up close.