Small Models, Deep Bugs

TL;DR: After specialized training, our small models recovered verified vulnerability mechanisms that every tested base model missed, from 7B up to 80B. The clearest proof: on Pictator, an app excluded from our finetuning data, four different finetuned checkpoints recovered the verified vulnerability mechanism, and our latest 4B release model completed that investigation agentically and filed the finding cleanly. The training compute for that 4B champion line cost about $50. The second story is the process: I used AI agents to help run the research campaign itself (coordinating scans, reviewing failures, preparing training changes, launching training, and evaluating candidates), which made hundreds of logged experiments practical for a tiny team. Finally, a taste of what specialization means in practice: the release model signs every finding it files with “Found with Djini.ai”, a reporting habit trained into the weights, and the same recipe can carry your team’s report format, severity bar, and name (section 13). The remaining challenge is consistency and investigation depth on unfamiliar applications and large codebases, not whether transfer beyond training examples happens at all. It does.


1. The outcome first

Some of our most useful results came from models small enough to run locally. We trained them to work with decompiled iOS code and all its nuances (stripped function names, guessed types, goto-laced pseudo-C, evidence scattered across thousands of functions) and to find vulnerability chains in it: tracing attacker-controlled input and linking individual weaknesses into an end-to-end exploit path, not just flagging suspicious lines. After that specialized training, they recovered vulnerability mechanisms that the tested base models had missed. On Pictator, an app excluded from our finetuning data, the latest 4B agent completed the investigation and filed the verified finding.

Getting there was not one training run. It was a campaign of experiments (205 numbered entries in our lab log over about two and a half weeks, roughly a hundred of them actual training runs) and I used AI agents to help run that campaign itself.

This article tells both stories, because they are connected: what our specialized models learned to do, and how AI assisted workflows made the research fast enough to be worth doing. Both matter if you are thinking about specialized small models for your own security work.

Two things we will not claim: that our models find every vulnerability, and that they beat base models at everything. They beat the tested bases on the specific, hard task we trained and measured (reading decompiled mobile code and finding real bugs in it) and the gap there is large, measured, and reproducible.

2. Why decompiled code is the hard test

When you decompile an iOS app binary, you do not get the original source back. You get pseudocode where everything meaningful has been stripped: a function called parseHeaders becomes FUN_100023a4c, every variable becomes uVar5, types are guesses, and control flow arrives as goto laced pseudo C. The evidence for a single vulnerability is scattered across dozens of such functions, often 12,000 to 48,000 tokens of it. Finding the bug means holding hex constants, buffer sizes, and pointer arithmetic exact across that whole window.

Models are trained on clean, human written source code. Decompiled output is a different planet, which made it the ideal test bed for our actual question: how specialized can a small model become?

We had years of prior evidence that this task defeats off the shelf models. Our platform scans real iOS apps continuously, and we benchmark interesting model releases against them. What the tested base models actually did on decompiled code: they produced generic security checklists, invented code that was not in the app, or delivered confident “this looks safe” verdicts over functions that contained the bug. On our seven development CVE bundles (curated decompiled slices of the vulnerable versions of real, publicly disclosed CVEs from Telegram, WhatsApp, VLC, and Signal) every base model we evaluated scored zero verified findings. That held for Qwen2.5-Coder-7B, DeepSeek-R1-Distill-7B, Qwen3-Coder-30B, Qwen3-Coder-Next-80B, and the 2026 generation Qwen3.5-9B and 4B.

One honest boundary on that claim: these are the models and conditions we tested, under our evaluation protocol. Frontier models have been improving on decompiled code recently, and one of our base models did produce a genuinely valuable result during the campaign: it found a real exploit chain in a test app that our own ground truth document had misdescribed, and we corrected our document, not the model’s score. That story is below; it defines the scope of everything else we claim.

A quick vocabulary note for the whole article. Ground truth is the independently verified answer: the real bug, confirmed in the code by a human or a verified document. A harness is the environment that gives the model its tools: file search, file reads, shell commands. A checkpoint is a saved model version; our campaign produced many. The checkpoint that passed verification and became the reference every new candidate had to beat, we call the champion.

3. How I used AI to run the research campaign

Before the training results, the process, because the process is half the point.

A finetuning campaign is a loop: scan a target with the current best model, verify what it claimed against the actual code, identify the failures, prepare training changes that address them, train a candidate, evaluate it against the current champion, keep or reject it, repeat. Done by hand, each loop is hours of setup, monitoring, and result handling. Done two hundred times, it is not a side project anymore.

So I delegated the loop to AI research agents: the same kind of agentic workflow our models were learning to use for scanning, pointed at the research itself:

The gap driven training loop used throughout the campaign: scan, verify, harvest gaps, train, gate, with the champion checkpoint feeding new scans. Stages one through five were executed by AI research agents; research direction and promotion review stayed human.
The gap driven training loop used throughout the campaign: scan, verify, harvest gaps, train, gate, with the champion checkpoint feeding new scans. Stages one through five were executed by AI research agents; research direction and promotion review stayed human.

The division of labor, as it actually ran:

  • The security model under test investigated applications inside the agent harness: searching files, reading code, writing findings.
  • AI research agents coordinated everything around it. They launched scans (including unattended overnight runs), collected transcripts, categorized failures into named classes, prepared verified training examples and preference pairs, changed configurations, started training runs on the local Mac and on rented cloud GPUs, compared each candidate against the current champion under a fixed gate, recorded every experiment in the lab log, and proposed the next iteration.
  • The training software (supervised finetuning, preference training, and reinforcement learning tooling) was the only thing that ever changed model weights.
  • The verification process checked claims against the actual decompiled code: does this file exist, does this line say what the model claims, is the described mechanism real?
  • The researcher (me) set direction and intervened at decision points: which technique to try next, when to pause a line of experiments, when to stop one entirely.

The most automated version of this ran completely unattended. Our auto improve loop sampled the reigning champion on the development targets, ranked its outputs with a frozen verifier gated reward, harvested the best scoring corrections into preference pairs, trained a one round candidate, and ran a six check gate, with no human in the loop. Its measured outcome is worth as much honesty as any success: two fully autonomous rounds, zero promotions. Both candidates failed the gate with the same signature: they had lost capabilities the champion had, so the loop discarded both and stopped itself under its own two consecutive failures rule. Automation did the work; the gate made the judgment; neither candidate shipped.

We automated much of the work between experiments, not just the training jobs themselves. But two things were never automated away. Research direction stayed human: the pivots in this campaign (preference training before reinforcement learning, the move to a newer base model family, the decision to close the RL line) were human calls. And verification was never skipped: a candidate was promoted only when its claims survived being checked against the code.

The clearest example of why that gate matters came from our reinforcement learning experiments. In one round, the reward design scored trajectories for process quality (honest misses above aborted scans) but the training batch happened to contain no genuinely successful scan. The update learned “never stop scanning” with no counterweight: the resulting model ran 172 iteration marathon scans that found nothing, losing the parent checkpoint’s signature win. The gate caught it; the candidate was rejected; the previous checkpoint stayed champion. A later preference round shows the same pattern in miniature: it fixed the targeted defect (malformed tool calls, gone) and in the same step destroyed the model’s hardest won capability (its one verified agentic CVE detection). We kept the previous checkpoint. Iteration is not monotonic improvement; it is trading, and someone has to check the trade.

The RLVR pipeline used for the reinforcement learning rounds: sample several scans per app, verify them programmatically against the code, rank them within their group, update, and gate. Candidates that fail the gate are discarded and their failure modes become the next round’s punished examples.
The RLVR pipeline used for the reinforcement learning rounds: sample several scans per app, verify them programmatically against the code, rank them within their group, update, and gate. Candidates that fail the gate are discarded and their failure modes become the next round’s punished examples.
What the programmatic verifier actually scored: every scan trajectory from two RL rounds, plotted per target. Green means the real bug was found; amber means a clean process with no finding; red means a fold, abort, marathon, or fabrication. The verifier sees behavior, not vibes.
What the programmatic verifier actually scored: every scan trajectory from two RL rounds, plotted per target. Green means the real bug was found; amber means a clean process with no finding; red means a fold, abort, marathon, or fabrication. The verifier sees behavior, not vibes.

One distinction we want to keep precise, because it is easy to blur: the agents coordinated the research; they did not train the model by scanning. Supervised finetuning, preference training, and reinforcement learning updates changed the weights, in discrete training runs, each followed by evaluation. Repeated scanning alone never changed any model. Our release model’s lineage is exactly: supervised finetuning of a 4B base, then eleven rounds of preference training, then a small agentic behavior training layer, then a short branding top up. No reinforcement learning is in that lineage: every RL candidate we trained failed the gate and was discarded, which is its own finding about how much RL signal a single GPU buys you.

And the honest accounting of what this saved: in my experience, automating these repeated steps saved days, and across the campaign, potentially weeks, of hands on work. That is my estimate as the person who ran it, not a measured speedup factor; we did not run a manual control group. What the records do support: 205 logged experiments in about 17 days, autonomous overnight scan and train chains, and a loop whose per iteration marginal cost was an afternoon and a few dollars.

4. The setup

Hardware. Two environments: our existing local machine, a single Apple M5 Max with 128GB of memory, and rented H100 cloud GPUs, spun up per job and shut down after. The local Mac trained the whole 7B line for the cost of electricity; the cloud GPU was about six times faster per training run and billed by the hour.

Models. When we say base model, we mean the unmodified starting checkpoint: in all our cases an already instruction tuned open model (Qwen2.5-Coder-7B, Qwen3-Coder-30B, Qwen3-Coder-Next-80B, and the 2026 generation Qwen3.5-9B and Qwen3.5-4B), plus DeepSeek-R1-Distill-7B as a reasoning oriented comparison. Finetuned checkpoints are our trained versions of those.

Test material. Four development apps (real iOS apps with documented vulnerability chains, used as training anchors), seven CVE bundles (decompiled slices of the vulnerable versions of real, publicly disclosed CVEs, each with verified ground truth), ten purpose built vulnerability chain labs (six Android, four iOS), a set of held out test apps kept out of training data, and two production scale corpora: Samsung Smart Switch (7,018 decompiled files) and the WhatsApp Core 2.21.221 framework (64,369 decompiled files, one function per file, carrying two known CVE ground truths).

Scoring. Every claimed finding was checked against the actual code. A true positive means the model reconstructed the ground truth chain: the linked stages of the exploit as documented in the ground truth, with the described mechanism verified in the code (real files, real lines, real constants). A partial means real code quoted but the chain or mechanism wrong or incomplete. A miss means no verified finding, including the case where the model incorrectly declares vulnerable code safe. Verdicts are single greedy runs unless noted; we report decoding modes separately and never sum them.

5. The training toolbox, in plain language

Three techniques, used in sequence; each exists because the previous one has a specific limit. All are standard, published methods, no secret sauce anywhere. The craft is in the data, the ordering, and the gating.

SFT (Supervised Finetuning): “learn from examples.” Show the model thousands of verified examples (here is decompiled code; here is the correct analysis) and adjust the weights toward answers like that. Solved: the base model’s total lack of direction on real decompiled code (zero of four real apps found, to three of four). Limit: it teaches what good answers look like, but not the decision boundary: when to commit to “exploitable” versus “safe”.

DPO (Direct Preference Optimization): “this answer beats that one.” Train on pairs: a verified correct answer versus the model’s own verified wrong answer to the same prompt. Minutes per round, a handful of pairs. Solved: the commit/dismiss boundary; this is what took the 7B from zero to seven verified CVE true positives, and what consolidated the 9B to a full 8/8 eval gate. Limit: past the peak, every round is zero sum: fix one cell, erode another. Freeze the winners.

GRPO / RL (Reinforcement Learning): “practice with a scorekeeper.” The model generates several answers to the same prompt, an automatic reward grades them, and the winners get reinforced relative to the losers, anchored to the parent model so it cannot drift into reward hacking. Solved: one genuine jump past the DPO plateau, mechanisms pure preference training never reached. Limit: the jump equals the parent’s remaining headroom; re-rolling RL from a consolidated champion only re-rolls downward.

RLVR (RL with Verifiable Rewards): “the scorekeeper is a program, not an opinion.” The newest tool in the box, and the one the agentic chapter runs on. Classic RLHF rewards come from a learned judge (another model’s preference: unverifiable, gameable). RLVR only works where the reward can be computed: math answers, passing unit tests, or in our case a scan whose every claim can be checked against the actual code (does the cited file exist, is the quoted line real, does the mechanism match the known bug, did the run fabricate, loop forever, or give up?). Solved: the unit DPO cannot see: a whole agentic scan, 25 tool calls deep, rewarded as one trajectory. Limit: the reward only teaches what the rollouts contain; sample nothing but failures and you train process, not discovery (we measured exactly that).

Which lever for which problem, as measured in this campaign:

LeverUsed whenProblem it solved here
SFTcapability absent entirelycould not read decompiled code at all (zero to three of four apps)
DPOcapability present, boundary wrongcommit versus dismiss at a suspicious site (zero to seven verified CVE true positives)
GRPOplateau after preferences saturatethe last mechanism jumps
RLVRagentic trajectories (multi-tool scans)process discipline: read, do not loop, file the finding

6. The 7B line: the capability appears

The first phase ran entirely on the local Mac, climbing the toolbox from the previous section: supervised finetuning for the basic skill, preference rounds for judgment, anchored RL for the last bit of robustness. Not every checkpoint used all three; the recipe was fitted to each line, and our final 4B lineage contains no RL at all.

The headline result of this phase, with its denominator stated exactly: on the seven development CVE bundles, decoded two ways each (fourteen cells), the best 7B checkpoint scored seven verified true positives across four of the seven bundles, while every tested base model scored zero on the same material.

Code verified CVE true positives on the seven development CVE bundles (14 cells: 7 bundles, 2 decoding modes each). Every tested base model scores zero; the finetuned 7B and 9B checkpoints score 5, 3, and 7.
Code verified CVE true positives on the seven development CVE bundles (14 cells: 7 bundles, 2 decoding modes each). Every tested base model scores zero; the finetuned 7B and 9B checkpoints score 5, 3, and 7.

Two qualifications belong next to that chart, not in a footnote. First, training overlap: these CVE bundles were the campaign’s development set, and verified analyses of them were part of the training data; that is what “development” means. The 7 of 14 figure measures learned skill and recall on trained material; it is not the generalization evidence. The clean generalization check at this stage was harsher: on CVEs the 7B line had never seen, it scored zero true positives in 28 attempts. Generalization arrived later, on held out applications, and it is the Pictator story below. Second, single draws: these are one greedy run per cell, not averages.

The pipeline value chain on the 7B line: the base model scores zero everywhere; supervised training (native11) adds real app chain acceptance; preference training (dpo21) adds the CVE true positives; anchored RL (grpo3) trades a little raw CVE score for robustness across harnesses.
The pipeline value chain on the 7B line: the base model scores zero everywhere; supervised training (native11) adds real app chain acceptance; preference training (dpo21) adds the CVE true positives; anchored RL (grpo3) trades a little raw CVE score for robustness across harnesses.

The purpose built labs, by contrast, turned out too easy to discriminate: on the six Android chain labs, the finetuned 7B models and most bases all scored six out of six. The one instructive exception was DeepSeek-R1-Distill-7B: two of six labs correct, three partial, with six of eight scans degenerating into repetition loops, a reminder that “reasoning” tuning does not automatically transfer to decompiled code either.

Real app chain acceptance on the four development apps (of 4, code verified), base models versus the fine-tuned 7B champions, in two decoding modes. The 80B base gets one accepted chain in each mode; every other base scores zero; the fine-tuned 7B accepts three of four with plain greedy decoding.
Real app chain acceptance on the four development apps (of 4, code verified), base models versus the fine-tuned 7B champions, in two decoding modes. The 80B base gets one accepted chain in each mode; every other base scores zero; the fine-tuned 7B accepts three of four with plain greedy decoding.

7. The context lever: the model can’t analyze what doesn’t fit

An early, measurable surprise: the same model, given the same vulnerable code, saw less of it as we padded the prompt with more surrounding files. On one app we tracked six mechanism markers; with one file in the prompt the model found three, with six files one, with thirty files none. Attention dilution is a capability limit, not just a context limit.

So context became a deliberate lever. The 7B line climbed from 4,000 token training contexts (held out apps: zero of four found) to 16,000 (which produced the project’s first greedy single pass true positive on a held out app) to 64,000 via position interpolation stretching, with each step measured. The 2026 generation base models then changed the game by offering 262,144 token context natively: every prompt we had fit at once. Long context alone does not solve full app analysis (the production scale section below shows why) but every prior stage was partly a fight against a window too small for the evidence.

Left: attention dilution measured on one app: the same model finds 3 of 6 mechanism markers with one file in the prompt, 1 of 6 with six files, 0 of 6 with thirty. Right: the training context ladder from 4k to 262k tokens, with the result each step unlocked.
Left: attention dilution measured on one app: the same model finds 3 of 6 mechanism markers with one file in the prompt, 1 of 6 with six files, 0 of 6 with thirty. Right: the training context ladder from 4k to 262k tokens, with the result each step unlocked.

8. Bigger, then smaller: 9B and 4B

The 9B line (on the 2026 generation base) raised the ceiling the 7B line had hit: our 8 cell eval gate, which no 7B checkpoint ever scored above 4 on, was maxed twice by 9B preference rounds. The trajectory is its own lesson: the first 8/8 was a lottery peak that the next round immediately lost, and it took seven more rounds to rebuild 8/8 durably. Preference training at this scale is a few pairs and a few minutes per round; the gate is what turns it from gambling into engineering.

The 9B preference training trajectory across eleven rounds, in two decoding modes. The 7B line never scored above 4 of 8 on this gate; the 9B line hit 8 twice, losing the first peak immediately and rebuilding it seven rounds later.
The 9B preference training trajectory across eleven rounds, in two decoding modes. The 7B line never scored above 4 of 8 on this gate; the 9B line hit 8 twice, losing the first peak immediately and rebuilding it seven rounds later.

Then we pushed the other direction: same recipe, 4B parameters. The 4B supervised run cost $21.50 of cloud compute and landed most of the capability: on the chain labs it scored twelve of twelve Android cells, for example. But it surfaced a clean asymmetry we did not expect: knowledge transfers down cheaply, judgment does not. Reading decompiled code, tracing attacker input, quoting the exact sink: the 4B learned these almost intact from the same data. Deciding not to report when code merely looks scary took roughly double the training pressure, and improving it on one test could break a sibling test for rounds: two variants of one CVE bundle, one vulnerable and one patched, traded against each other for rounds before both stabilized.

The practical reading for teams sizing a deployment: a 4B model can carry real mechanism knowledge, but budget more preference tuning rounds for its decision boundary than you would for a 9B, and gate every round, because at 4B the wins and losses trade places silently.

On cost, precisely: the entire 4B champion line (the $21.50 supervised run, eleven preference rounds with their gates (about $25 to $30), and the two small top up layers (a few dollars)) totals roughly $50 of cloud training compute. That figure is training only. It excludes evaluation scans, the discarded RL rounds, and the campaign’s infrastructure mistakes, the largest being a warm endpoint misconfiguration that left about thirteen H100s idling around the clock for days, roughly $390, about half that billing cycle’s cloud bill. We publish that number because “cheap finetuning” stories usually omit it: the training is cheap; the iteration around it is where the money and time go.

Speed and cost, measured: the H100 is about six times faster per training run than the local M5 Max; supervised runs cost $3 to $29; the entire 7B champion line trained locally for the cost of electricity.
Speed and cost, measured: the H100 is about six times faster per training run than the local M5 Max; supervised runs cost $3 to $29; the entire 7B champion line trained locally for the cost of electricity.

9. From scanner to agent: a different and harder problem

Everything above asked the model to recognize a vulnerability in code we handed it. A real scanner must do something harder: given a whole decompiled app, find the right files among thousands, judge them, stop at the right time, and file a report someone can act on. Recognition and hunting turned out to be different skills, and the gap between them was the campaign’s hardest chapter.

First, the environment itself failed in instructive ways. When we connected our finetuned models to the agentic CLI harness, one model’s tool calls streamed through as raw markup text that the harness never executed: a parsing path bug, not a model bug. Another run looped 236 messages deep, cycling search → no files → read → file not found, without ever falling back to listing the directory it was in. These are the failures you only find by running the real loop.

An environment failure from the agentic phase: the model emits tool calls as visible markup text that the harness never executes. Infrastructure bugs masquerade as model incompetence until you read the transcript.
An environment failure from the agentic phase: the model emits tool calls as visible markup text that the harness never executes. Infrastructure bugs masquerade as model incompetence until you read the transcript.
The doom loop: 236 messages of search, no files, read, file not found, and never the one command that would have grounded the agent (listing the directory it was actually in).
The doom loop: 236 messages of search, no files, read, file not found, and never the one command that would have grounded the agent (listing the directory it was actually in).

Then the model failures, which were the real finding. On whole apps, both our champion and the base models collapsed: a 26 run head to head on real apps produced zero true positives for either, and an 84 run matrix (seven model arms, twelve targets: four real apps, seven CVE bundles, one held out app) produced exactly one full true positive. That one deserves its own sentence: it came from the 9B base model, which found a real deeplink to dynamic loading chain in one of our development apps that our ground truth document had declared absent from the decompile. We checked the code, corrected our ground truth, and kept the model’s score. The advantage we claim for our finetuned models lives next to that result, not on top of its grave.

The agentic matrix: percentage of runs scoring at least a partial finding, per model arm, across 84 autonomous runs on twelve targets. The finetuned 9B champion and the 9B base lead; larger bases score worse, not better.
The agentic matrix: percentage of runs scoring at least a partial finding, per model arm, across 84 autonomous runs on twelve targets. The finetuned 9B champion and the 9B base lead; larger bases score worse, not better.

The full agentic standings, every arm we pointed the production style agent harness at, code verified against ground truth (TP = full verified finding, TP minus = right chain with imperfect depth, P = partial evidence, n/a = not evaluated):

ArmSizeBrokeLesnorFreshCartLinkLiarOpus CVEUnseen appsTally
Qwen3.5-4B base4BTP minusmissPmissP / miss+FP0 TP, best base hunter
Qwen3.5-9B base9Bn/an/aP+0/4 validmiss0 TP
lc4b (4B SFT)4BPTP minusmissmissabort / miss0 TP
lc4bdpo11 (+11 DPO)4BTPTP minusTPmissP / miss2 TP
lc4qdpo8 (9B champ)9BTPTPTPfalse securemiss / miss3 TP (anchors)
lc4q-agent5 (9B + traces)9Bmissn/acannot completefalse securemiss0/4
grpo3 / dpo21 (7B champs)7Bmissmissmissmissmiss0 TP agentically (doom loops, essays)
lc4b-agent1 (4B, traces)4BTP: full three stage chainn/aabort ×2TP: the agentic Opus detectionno verified findings; unseen mechanism detection on Pictator (filing incomplete)2 strict TP
RLVR r2 challenger4BTP + fabricated side claimn/amarathonmarathon (TP lost)no verified findingnot promoted

Single draws per cell; these are capability demonstrations under a specific harness, not statistical pass rates, and the harness itself changed between eras of the campaign.

We also tried a graph guided pipeline (map the call graph, select suspicious regions, scan, walk chains backward from sinks). Its lesson was sharp: chunking erases the finetuning advantage. In small chunks, champion and base produce identical noise; the deep mechanism articulation only appears when the model sees the full cluster of related functions at once, another reason the long context line mattered.

The dominant failure mode had a precise shape: grep only scanning. On unseen apps the models would run searches, get weak or zero hits, and declare the app safe without reading a single file. The fix was data, not exhortation: we authored seventeen ideal investigation traces (real tool call sequences showing file at a time reading, following call chains, and disciplined stopping) replayed them through the actual tool layer, and trained a light layer on top of the champion. The result was our agentic champion: the first checkpoint to find a real CVE agentically (quoting the exact guard constants from code it located itself), and the first to reconstruct a full three stage chain in a real app in 26 tool calls and five minutes.

The agentic champion mid investigation in the real CLI harness: reading decompiled functions, following the chain, and verifying its own claims against the code before filing.
The agentic champion mid investigation in the real CLI harness: reading decompiled functions, following the chain, and verifying its own claims against the code before filing.

It still had a crippling craft gap, which the next section’s milestone makes vivid: detection and completing the report are different skills too.

10. Pictator: the held out turning point

Pictator is a purpose built benchmark app with a documented vulnerability: it decrypts data with a hardcoded XOR key, resolves a function from a name at runtime using dlsym (dlsym takes a string and returns the function with that name, so if an attacker influences the name or the resolved pointer, the app can be steered into calling attacker chosen code) and then calls through that pointer. Pictator was excluded from the finetuning data of every checkpoint below: no Pictator code, no Pictator answers, verified against the dataset manifests. One scope note matters here and we state it plainly: the mechanism class (resolving decrypted names into indirect calls) was taught on synthetic examples and a different real app. What was never taught is this app. The result below is transfer to an unseen application, not to an unknown bug class; and it is the recovery of a known, verified vulnerability in held out code, not a new zero day, and Pictator is not shipped software.

Four finetuned checkpoints got there, in four different evaluation settings:

CheckpointSettingVerified achievementQualification
native11 (7B)map reduce over per file analysesEarliest Pictator ground truth true positive (experiment #89): verbatim XOR key, correct 0x18 period, dlsym resolved indirect callSurvived all three map reduce protocols; never reproduced under plain single pass scanning
lc1 (7B)greedy, single passCorrect XOR key, dlsym resolved indirect call, and correct delivery vector, all quoted from the code (#103)First greedy single pass held out true positive, not the first Pictator detection overall
lc4b-agent1 (4B)agentic, full appFirst agentic detection of the unseen app’s verified mechanism (#199)About 350 iterations; the run’s timeout killed it while it was writing the finding; detection succeeded, filing did not complete
lc4b-brand3 (4B)agentic, full app, release modelReproduced the verified true positive with proper filing: CWE-94, verbatim snippets, correct lines (#205)Completed in 23 iterations

Four finetuned checkpoints recovered Pictator’s ground truth mechanism across the evaluated protocols. No tested base model recovered that ground truth in the recorded evaluations.

The near misses sharpen the picture. An earlier 7B champion quoted the XOR keystream verbatim (genuine binding detail on code it had never seen) but missed the dlsym dispatch that is the actual vulnerability. Two long context variants each recovered half: one the mechanism shape without the key, one the key with a garbled mechanism. The capability arrived in pieces, and the pieces assembled as the recipe improved.

We also want to be precise about what four milestones are not: they are four checkpoints evaluated on one held out application, under different protocols, not four applications, and not four independent replications you can average into a pass rate. What they establish is narrower and, we think, more useful: transfer beyond the training apps is real, it survived three architecture and protocol generations, and the final version of it is a 4B model that finds the bug, stops, and files the paperwork.

11. The release model, checked on ten fresh targets

After the campaign formally closed, we ran one more series with the release model (the 4B agentic champion plus its final top up): ten targets, headless, on the exact audit harness our production scanner uses. All ten runs completed, no loop kills, no timeouts, which we verified in the transcripts, a first for any of our finetuned champions at these corpus sizes. The detection outcomes, all of them:

TargetCategoryResultDetail
Pictatorunseen appverified true positive, properly fileddlsym dispatch chain, CWE-94, 23 iterations
Quackifyunseen appmisssix file reads; no verified finding reported
EchoChatheld out most of the campaign; its chain later entered this lineage’s agentic trace training datamisstwelve file reads; touched the vulnerable surface repeatedly without convicting
LensPicunseen appmiss (excluded from the scoreline)its ground truth is a PAC bypass, a bug class we never trained
GothamTimestrained anchor app (in the supervised data by design)missed the reference chainthree adjacent findings filed; their cited files are real, with minor citation slips (one line number off by one, one editorialized snippet)
CVE-mp4 (WhatsApp)anchor CVE, attempted agenticallystrong partialright parser family, real bounds check quoted verbatim, sibling function instead of the exact sink
CVE-tg611 (Telegram)anchor CVE, attempted agenticallymissterminated early, ten iterations
CVE-tg1294 (Telegram)anchor CVE, attempted agenticallymissread both ground truth files and dismissed them as insufficient evidence
CVE-vlc373 (VLC)anchor CVE, attempted agenticallymiss, with an incorrect safe verdictread the 3,650 line decoder end to end, quoted real checks, declared the real bug safe
WhatsApp Coreproduction scale corpuscompleted; neither known CVE detecteddetails in the next section

In total: one full ground truth true positive, one strong partial, and eight targets without a full true positive. That is a mixed set (four of the ten are CVE anchors, not unseen apps) so we do not read it as an unseen app detection rate, and neither should you.

Two honesty notes from the transcripts. The good news: no run invented files or functions; the misses quote real code and mostly say real things about it. The residual problem: two runs overstated at the summary level: the WhatsApp run reported a corpus file count it never measured, and the GothamTimes report’s “verbatim” snippets were lightly polished. The investigation behavior is disciplined; summary precision is where work remains.

And the deepest open issue is conviction, not search: on two targets the model had the vulnerable code on screen and talked itself out of it. The transcripts of exactly those moments are harvested, verified, and waiting as preference pair material for a future training round.

12. The production scale test: reliability versus detection

The hardest corpus we have is WhatsApp Core 2.21.221: 64,369 decompiled files, one function per file, 261MB, carrying two known CVE ground truths (CVE-2021-24042 and CVE-2021-24043). In the campaign’s earlier production scale stage, sixteen agentic runs (four model arms, two production targets, two harnesses) produced zero detections, and on this corpus both finetuned champions died the same death: loop killed by the harness after repeating the same command, twice each. The two base models, by contrast, completed it (in 50 and 73 iterations) without finding anything.

The release model’s run: completed cleanly, 17 iterations, about twelve minutes, the first tested finetuned checkpoint to finish this corpus. It ran nine shell searches, read one corpus code file (a parser it named explicitly) in three chunks, quoted that file’s real bounds checks, and correctly rejected it as a false lead, with line citations. It reported no verified findings, which means both known CVEs were missed, and we score it that way.

Two interpretations must stay separate. As a reliability result, this is real progress: the marathon and loop kill failure class that killed every previous finetuned champion on this corpus is gone. As a detection result, it establishes nothing new: the base models already completed this corpus, and no model, base or finetuned, has ever found either CVE in it. And one corpus file read in twelve minutes is not deep coverage of 64,369 files; “completed the scan” does not mean “examined everything”. The earlier zero of sixteen stage stands as the honest baseline; this run improved the behavior, not yet the hit rate.

13. What we demonstrated, what remains, and why the process matters

We now have evidence that small specialized models can recover vulnerabilities the tested base models missed, including in an application excluded from finetuning, where four checkpoints found the mechanism and the final one filed the report. We also learned that recognizing a vulnerability, finding it independently, and completing a useful report are different challenges, each teachable, each measured separately.

AI assisted workflows made the repeated experiments more practical. They helped us move from a failed scan to the next candidate, but verification still determined whether we had made progress, and the gate rejected more candidates than it promoted.

The next challenge is not whether any transfer to unfamiliar code is possible. We have observed it. It is making that behavior more consistent, and making the investigation scale with the application: conviction when the vulnerable code is on screen, depth across tens of thousands of files, and summary level precision in the reports.

One smaller demonstration belongs here because it points at the practical end state. As a final training layer, we taught the release model our reporting format, and it now signs its own findings ("Found with Djini.ai: a custom 4B security model.") as a habit in the weights, not a watermark added by the pipeline. (Binding that habit took three measured attempts, which is why we mention it as a demonstration of the recipe, not of magic.) A team’s severity vocabulary, triage style, report format, and name on every finding are all just data, and data is trainable. Because the whole pipeline can run on your own hardware or your own cloud account, private deployment is a configuration option: data preparation, training, evaluation, and inference can all stay inside your perimeter if you set it up that way, as our own cloud runs did.

The 4B release model signing its own findings during a live scan: “Found with Djini.ai: a custom 4B security model.” appears in the model’s own answers, embedded by training.
The 4B release model signing its own findings during a live scan: “Found with Djini.ai: a custom 4B security model.” appears in the model’s own answers, embedded by training.
The same model’s final report on a real app: a verified three stage exploit chain with segment by segment verification labels, an honest scope note about what remains unknown, and the trained signature closing the answer.
The same model’s final report on a real app: a verified three stage exploit chain with segment by segment verification labels, an honest scope note about what remains unknown, and the trained signature closing the answer.

14. What we set out to learn

Could we automate much of the finetuning process, transfer security knowledge into small models that struggled with decompiled code, and keep reducing their size while still producing meaningful findings quickly?

I used AI agents to coordinate scans, examine failures, prepare training changes, and evaluate candidates. I set the research direction, and verification determined which improvements we kept. Automating the work between experiments made the campaign practical for a small team.

Our 4B release recovered and reported Pictator’s verified vulnerability in 23 iterations, despite the application being excluded from its finetuning data. None of the tested base models recovered that ground truth. In another investigation, our 4B agent reconstructed a complete three stage chain in five minutes and 26 tool calls.

Not every scan succeeded, and speed does not guarantee thorough coverage. But we demonstrated that small models can apply learned security knowledge to unfamiliar code and produce useful results quickly. The next challenge is making those successes more consistent and investigations deeper as applications grow.

Build a model with your team’s DNA

Websites built with similar AI tools can start to feel interchangeable. For security teams using the same foundation models, that raises a question: where does your team’s advantage come from?

It comes from years of assessments, research, exploit development, and triage. Your reports and investigation decisions capture the patterns your researchers recognize, the assumptions they challenge, and how they distinguish real vulnerabilities from false leads.

That collective experience is your team’s DNA.

By combining historical reports and verified findings with relevant code, evidence, and investigation steps, we can help train a local model around that expertise. Not just your reporting template, but how your team traces attacker-controlled input, connects weaknesses, and judges security impact.

As new assessments produce verified lessons, those can feed further training rounds, with each candidate evaluated against the previous version before adoption. Your researchers remain the source of expertise; your internal model grows alongside them.

Djini.ai combines automated security testing with your choice of supported models, including internally hosted ones. Our team can help turn your accumulated knowledge into a specialized local model.

Create a free Djini.ai account to explore automated security testing with your model of choice, or schedule a call with our team to discuss building a model with your team’s DNA.

Try the champions yourself

Both champion models are public on Hugging Face under the Apache-2.0 license, so you can run them on your own hardware and check our claims against your own code.

ModelCheckpointBaseHow it works
djini-4b-security-agentlc4b-brand3, the release model from sections 10 to 12Qwen3.5-4BAgentic: give it file search and read tools and point it at a decompiled app. It investigates and files structured findings.
djini-7b-cve-hunterdpo21, the 7B CVE champion from section 6Qwen2.5-Coder-7B-InstructOne shot: paste decompiled code into the prompt and it returns findings as JSON. No tools.

Both load with Hugging Face Transformers (version 5 or later for the 4B):

from transformers import AutoModelForCausalLM, AutoTokenizer

name = "djini-ai/djini-4b-security-agent"  # or "djini-ai/djini-7b-cve-hunter"
tok = AutoTokenizer.from_pretrained(name)
model = AutoModelForCausalLM.from_pretrained(name, dtype="bfloat16")

The 4B agent works best behind an OpenAI compatible server such as vLLM, connected to an agentic harness like Cline with file search and read tools enabled. For the 7B, use greedy decoding and keep the prompt under 32k tokens. Whichever you try, verify every finding against the code: the same rule that decided which checkpoints we kept.