File size: 14,221 Bytes
da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab 4258688 6e7a6ab 4258688 5ac95ba 4258688 5ac95ba 4258688 5ac95ba 4258688 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab 4258688 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab da9aa7c 6e7a6ab | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 | ---
license: apache-2.0
language:
- en
metrics:
- accuracy
- f1
- roc_auc
library_name: safetensors
tags:
- code
- security
- vulnerability-detection
- cwe
- owasp
- moe
- hobbylm
pipeline_tag: text-generation
---
# CodeAstra-500M: Laptop-Scale Vulnerability Detection ππ‘οΈ
## Model Description
CodeAstra-500M is the small sibling of [CodeAstra-7B](https://huggingface.co/rootxhacker/CodeAstra-7B) β a
500M-parameter **sparse Mixture-of-Experts** model fine-tuned for security vulnerability detection in
source code. Where CodeAstra-7B is built on Mistral-7B, CodeAstra-500M is built on
[HobbyLM-Chat](https://huggingface.co/rootxhacker/HobbyLM-Chat), a MoE language model trained from
scratch on a hobby budget β so the whole thing runs on a laptop CPU.
It answers with a single structured JSON verdict: is this vulnerable, which CWE, which OWASP category.
### Key Features
- πͺΆ **Tiny**: 500M total parameters, only ~150M active per token thanks to top-6-of-36 expert routing.
- π **Structured output**: emits parseable JSON on 99.98% of inputs β no regex-scraping prose.
- ποΈ **Tunable**: returns a calibrated probability, so you pick the precision/recall trade-off at
inference time instead of retraining.
- π **Multi-language**: C, C++, Python, Java, JavaScript, PHP, Go, Ruby, Swift, Kotlin, C#, Fortran β
though the training mix is heavily C-weighted (see Limitations).
- π§ͺ **Honestly evaluated**: scored on the standard split *and* on vulnerable/patched function pairs,
which is the harder and more meaningful test.
- π₯ **Benchmarked against a frontier model**: matches DeepSeek v4 Flash on genuine flaw
discrimination while being ~10,000Γ faster per snippet.
- π» **Runs locally**: shares the HobbyLM architecture, so it loads in the from-scratch Rust CPU engine
(`hobby-rs`) with no Python at runtime.
## Performance π
Evaluated on the held-out test split (17,542 snippets, 1,887 vulnerable) of
[`ayshajavd/code-security-vulnerability-dataset`](https://huggingface.co/datasets/ayshajavd/code-security-vulnerability-dataset).
The base model is un-finetuned HobbyLM-Chat under identical prompts.
| Metric | HobbyLM-Chat (base) | **CodeAstra-500M** |
|---|---|---|
| JSON parse rate | 1.20% | **99.98%** |
| ROC AUC | β | **96.97%** |
| Average precision | β | **82.64%** |
| Best F1 | 0.00% | **76.23%** |
| Precision / Recall @ best F1 | 0.00 / 0.00 | **75.57% / 76.89%** |
| Exact CWE (28 classes) | 0.00% | **~55%** |
| OWASP category | 0.00% | **~74%** |
β οΈ **A note on accuracy.** This dataset is 89% non-vulnerable, so a model that answers "safe" every
time scores **90.5% accuracy** β which is exactly what the un-finetuned base model does, at 0% recall.
That is why this card leads with F1, AUC and recall rather than accuracy. Treat any headline accuracy
figure on this dataset with suspicion, including for other models.
### Paired evaluation β the number that actually matters π―
Standard splits of CVE-derived vulnerability datasets are **confounded**: the vulnerable functions come
from big C projects (Linux kernel, Chromium, PHP, ffmpeg) while the "safe" ones are often unrelated
code. A model can score very well by recognising *code style* rather than *code flaws*.
So CodeAstra-500M is also evaluated PrimeVul-style, on 894 pairs of a vulnerable function and **its own
patched version** β near-identical code differing only by the security fix.
| | First SFT pass | **CodeAstra-500M** |
|---|---|---|
| **P-C β flags the flawed one, clears the patched one** | 6.94% | **27.40%** |
| P-V β flags both (the style shortcut) | 84.90% | **33.45%** |
| P-B β clears both | 6.71% | 36.02% |
| P-R β reversed | 1.45% | 3.13% |
| Specificity on patched code | 13.65% | **63.42%** |
| Within-pair ranking accuracy | 66.22% | **69.46%** |
The released model was produced by feeding the ~7,000 patched functions back in as *safe* training
examples β minimal pairs that differ only by the fix. This quadrupled paired accuracy and lifted
specificity on patched code from 13.65% to 63.42%.
**Read this honestly:** within-pair ranking accuracy moved only 66.22% β 69.46%, meaning most of the
improvement is better calibration rather than deeper understanding. **27.40% is the realistic estimate
of true detection ability β not the 96.97% AUC.** Very few vulnerability models publish this number;
it is here because it is the one that predicts real-world behaviour.
## Comparison against a frontier model π₯
Benchmarked against **DeepSeek v4 Flash** (via OpenRouter, reasoning enabled) on the *same* held-out
rows, through the *same* prompts, the *same* output parser and the *same* metrics. DeepSeek answers
zero-shot; CodeAstra is fine-tuned on this corpus.
### On the standard held-out split β 1,000 rows, 93 vulnerable
| Metric | DeepSeek v4 Flash | **CodeAstra-500M** |
|---|---|---|
| JSON parse rate | 97.10% | **99.98%** |
| Precision | 16.56% | **75.57%** |
| Recall | 54.84% | **76.89%** |
| F1 | 25.44% | **76.23%** |
| Exact CWE | 10.75% | **~55%** |
| Latency per snippet | ~47 s | **4.3 ms** |
DeepSeek flagged 308 of 1,000 snippets as vulnerable when only 93 were β a 3.3Γ over-prediction, since
a general model has no way to know this corpus is 89% safe.
β οΈ **Do not read this as "CodeAstra is 3Γ better at security."** Most of that gap is *corpus
familiarity* β the base rate and the annotator's CWE conventions β not better security reasoning. The
per-CWE breakdown makes it plain: DeepSeek gets CWE-89 (SQL injection) 100% detected and 80% exact,
but 0% exact on CWE-119, a catch-all bucket whose boundaries you can only learn from the training set.
### On the paired set β 894 pairs, the unconfounded test
| | DeepSeek v4 Flash | **CodeAstra-500M** |
|---|---|---|
| **P-C β flags flawed, clears patched** | 24.05% | **27.40%** |
| P-V β flags both | 34.68% | 33.45% |
| P-B β clears both | 32.33% | 36.02% |
| P-R β reversed | 8.95% | **3.13%** |
| Recall, vulnerable half | 58.72% | **60.85%** |
| Specificity on patched code | 56.38% | **63.42%** |
On this harder, style-controlled test the two models are closely matched β CodeAstra is marginally
ahead, holds higher specificity on patched code, and is 3Γ less likely to invert a pair.
β
**The defensible claim:** CodeAstra-500M **matches a frontier reasoning model on genuine flaw
discrimination**, at ~10,000Γ lower latency, no per-call cost, and fully local.
Distinguishing a vulnerable function from its patched twin is a hard problem at the single-function
level for models of any size β see Limitations.
## Intended Use
CodeAstra-500M is for developers, security researchers and code auditors who want a fast first-pass
triage filter that runs locally β in a pre-commit hook, a CI step, or an editor plugin β without
sending source code to an API. It is a **filter that decides what a human looks at**, not an oracle.
## Threshold β please read ποΈ
The model returns a probability. **The default 0.5 is not the balanced operating point.**
| Threshold | Precision | Recall | Use case |
|---|---|---|---|
| 0.3346 | 75.57% | 76.89% | **Balanced (best F1 = 76.23%)** |
| 0.3775 | 80.02% | 70.27% | Triage |
| 0.4378 | 85.03% | 59.88% | |
| 0.5156 | 90.01% | 45.36% | CI gating |
| 0.6514 | 95.07% | 23.53% | High-confidence alerts only |
At the naive 0.5 you get 88.79% precision but only **48.70% recall** β it will quietly miss half the
vulnerabilities. Set the threshold deliberately.
## Training ποΈββοΈ
Fine-tuned from HobbyLM-Chat on 8ΓH100 GPUs via [Modal](https://modal.com), using the **full** dataset β
all 140,335 training rows, nothing subsampled, with over-long code head+tail truncated rather than
dropped.
| | |
|---|---|
| Main SFT | 6,000 steps, lr 2e-5, micro-batch 8 Γ 8 GPUs, 176,216 examples, ~27 min |
| Hard-negative pass | 500 steps, lr 5e-6, 7,023 minimal pairs, ~2.5 min |
| Objective | next-token CE masked to the JSON verdict; MoE aux-free balancing bias frozen |
| Class balance | vulnerable rows oversampled 3Γ (10.9% β 26.0% positives) |
Architecture is unchanged from HobbyLM: 768 hidden / 16 layers, 36 experts with top-6 routing plus one
shared expert, GQA attention with per-head QK-norm, RoPE, GPT-2 byte-level BPE, 2048-token context.
## Usage π»
The model uses the HobbyLM MoE architecture, so it needs the `hobbylm` package rather than
`transformers`. The prompt format matters β the model was trained on exactly one layout:
````text
SYSTEM: You are a source-code security auditor. Given a code snippet, decide whether it contains a security vulnerability and reply with one JSON object: {"vulnerable": bool, "cwe": str, "cwe_name": str, "owasp": str}. Use "none" for safe code.
USER: Audit the code below for security vulnerabilities.
Language: C
```c
<your code here>
```
ASSISTANT:
````
Use `detect_prompt()` rather than assembling that by hand:
```python
import json, torch, tiktoken
from huggingface_hub import hf_hub_download
from safetensors.torch import load_file
from hobbylm.config import ModelConfig
from hobbylm.model import MoETransformer
from hobbylm.security_data import detect_prompt, VERDICT_PREFIX, TRUE_ID, FALSE_ID
repo = "rootxhacker/codeastra-500M"
cfg_d = json.load(open(hf_hub_download(repo, "config.json")))
cfg_d.pop("preset", None)
model = MoETransformer(ModelConfig(**cfg_d)).cuda().eval()
model.load_state_dict(load_file(hf_hub_download(repo, "model.safetensors")))
enc = tiktoken.get_encoding("gpt2")
code_to_analyze = """
$query = $_GET['query'];
$stmt = $db->prepare($query);
$stmt->execute();
"""
# Fast path: force the verdict position and read one probability (~4ms, no generation)
prompt = detect_prompt(code_to_analyze, "PHP") + VERDICT_PREFIX
ids = torch.tensor([enc.encode_ordinary(prompt)], device="cuda")
with torch.no_grad():
logits, _ = model(ids)
p_vuln = torch.softmax(logits[0, -1, [TRUE_ID, FALSE_ID]].float(), -1)[0].item()
print(f"P(vulnerable) = {p_vuln:.3f} -> {'VULNERABLE' if p_vuln >= 0.3346 else 'safe'}")
```
Scoring this way is ~26Γ faster than generating the JSON (4.3 ms vs 110 ms per snippet) and gives you
the tunable probability. If you also want the CWE and OWASP labels, generate the completion normally
from `detect_prompt(code, lang)` and parse the JSON with `hobbylm.security_data.parse_verdict`.
A typical answer:
```json
{"vulnerable": true, "cwe": "CWE-89", "cwe_name": "Improper Neutralization of Special Elements used in an SQL Command (SQL Injection)", "owasp": "A03: Injection"}
```
## Limitations β οΈ
1. **Function-level only.** It sees a single function, so interprocedural and data-flow vulnerabilities
are largely invisible. Access-control bugs needing caller context are its weakest class.
2. **Heavily C-weighted training data** (92% C). Other languages work but are out-of-distribution β
expect lower reliability on Go, Swift, Kotlin and TypeScript.
3. **CWE labels confuse related classes.** CWE-89 (SQL injection, 85% exact) and CWE-94 (code
injection, 82%) are strong; catch-all buckets like CWE-399 and CWE-416 are weak. It frequently finds
the right bug and picks a sibling CWE β the detection is better than the label suggests.
4. **Multiple vulnerabilities in one snippet** are not reliably enumerated; it returns a single verdict.
5. **Long code is truncated.** Snippets beyond 2048 tokens are head+tail truncated, so the middle of
very long functions is unseen.
6. **False positives are expected** at the recall-oriented thresholds. Results need human verification.
7. **It is a 500M research model, not a security product.** Use it alongside code review and SAST, not
instead of them, and do not gate a release on it alone.
## Test Apparatus
All figures come from the held-out test split of `ayshajavd/code-security-vulnerability-dataset`
(17,542 snippets, never trained on), scored with a purpose-built harness that generates the verdict and
parses it, plus the calibrated single-forward-pass scorer for threshold-free metrics. The paired
evaluation uses 894 vulnerable/patched function pairs drawn from the same held-out split. The base
HobbyLM-Chat comparison was run through the **identical** prompts and harness, so the two columns are
directly comparable.
The DeepSeek v4 Flash comparison was run through OpenRouter on the same held-out rows, receiving the
identical system/user content in native chat format so it is not penalised for our decoder-only prompt
convention, and scored with the same parser and metrics. Reasoning was enabled at low effort: at
default effort the model spends ~98% of its output budget thinking and 37% of replies never emit an
answer within 8k tokens, which would have measured our token cap rather than its accuracy.
No numbers on this page were copied from another model card β everything here was measured directly.
**CodeAstra-7B is not comparable** to these figures: it was evaluated on a different corpus under a
different protocol, so its 83% accuracy and this card's numbers do not sit on the same scale.
## Citation π
```
@software{CodeAstra-500M,
author = {Harish Santhanalakshmi Ganesan},
title = {CodeAstra-500M: Laptop-Scale Vulnerability Detection},
year = {2026},
howpublished = {\url{https://huggingface.co/rootxhacker/codeastra-500M}}
}
```
## License π
CodeAstra-500M is released under the Apache License 2.0.
```
Copyright 2026 [Harish Santhanalakshmi Ganesan]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```
## Acknowledgements π
Thanks to the HobbyLM project for the 500M MoE base model, and to
[@ayshajavd](https://huggingface.co/ayshajavd) for compiling the vulnerability dataset this model was
trained on.
|