rootxhacker commited on
Commit
6e7a6ab
Β·
verified Β·
1 Parent(s): da9aa7c

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +199 -91
README.md CHANGED
@@ -1,24 +1,136 @@
1
  ---
2
  license: apache-2.0
 
 
 
 
 
 
3
  library_name: safetensors
 
 
 
 
 
 
 
 
4
  pipeline_tag: text-generation
5
- tags: [security, vulnerability-detection, cwe, owasp, code, moe, hobbylm]
6
  ---
 
7
 
8
- # CodeAstra-500M
9
 
10
- A 500M-parameter sparse-MoE **code vulnerability detector**, fine-tuned from
11
- [rootxhacker/HobbyLM-Chat](https://huggingface.co/rootxhacker/HobbyLM-Chat) on the full
12
- [`ayshajavd/code-security-vulnerability-dataset`](https://huggingface.co/datasets/ayshajavd/code-security-vulnerability-dataset)
13
- (140,335 train / 17,542 test rows, 100% coverage β€” nothing subsampled).
 
14
 
15
- Given a code snippet it returns one JSON object: whether the code is vulnerable, the CWE, and the
16
- OWASP Top-10 category.
17
 
18
- ## Prompt format
19
 
20
- The model is format-sensitive β€” it was trained on exactly this layout (note the inner fence is part
21
- of the prompt):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
  ````text
24
  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.
@@ -31,114 +143,110 @@ Language: C
31
  ASSISTANT:
32
  ````
33
 
34
- `hobbylm.security_data.detect_prompt(code, language)` builds this for you β€” use it rather than
35
- hand-assembling the string.
36
-
37
- It answers:
38
-
39
- ```json
40
- {"vulnerable": true, "cwe": "CWE-89", "cwe_name": "Improper Neutralization of Special Elements used in an SQL Command (SQL Injection)", "owasp": "A03: Injection"}
41
- ```
42
-
43
- ## Usage
44
 
45
  ```python
46
- import json, torch
47
  from huggingface_hub import hf_hub_download
48
  from safetensors.torch import load_file
49
- from hobbylm.config import ModelConfig # github.com/<your>/moe-lab
50
  from hobbylm.model import MoETransformer
51
  from hobbylm.security_data import detect_prompt, VERDICT_PREFIX, TRUE_ID, FALSE_ID
52
- import tiktoken
53
 
54
  repo = "rootxhacker/codeastra-500M"
55
  cfg_d = json.load(open(hf_hub_download(repo, "config.json")))
56
  cfg_d.pop("preset", None)
57
  model = MoETransformer(ModelConfig(**cfg_d)).cuda().eval()
58
  model.load_state_dict(load_file(hf_hub_download(repo, "model.safetensors")))
59
-
60
  enc = tiktoken.get_encoding("gpt2")
61
- prompt = detect_prompt(my_code, "C") + VERDICT_PREFIX # force the verdict position
 
 
 
 
 
 
 
 
62
  ids = torch.tensor([enc.encode_ordinary(prompt)], device="cuda")
63
  with torch.no_grad():
64
  logits, _ = model(ids)
65
  p_vuln = torch.softmax(logits[0, -1, [TRUE_ID, FALSE_ID]].float(), -1)[0].item()
66
- print(p_vuln >= 0.3346) # see the threshold note below
67
  ```
68
 
69
- Reading `p_vuln` in one forward pass is ~26x faster than generating the JSON, and it gives you a
70
- tunable score instead of a fixed decision. Generating the full JSON works too if you want the CWE.
71
-
72
- ## Threshold β€” please read
73
-
74
- **The default 0.5 is not the balanced operating point.** Pick deliberately:
75
-
76
- | threshold | precision | recall | use case |
77
- |---|---|---|---|
78
- | 0.3346 | 75.57% | 76.89% | balanced (best F1 = 76.23%) |
79
- | 0.3775 | 80.02% | 70.27% | |
80
- | 0.4378 | 85.03% | 59.88% | |
81
- | 0.5156 | 90.01% | 45.36% | CI gating |
82
- | 0.6514 | 95.07% | 23.53% | high-confidence only |
83
 
84
- At the naive 0.5 you get 88.79% precision but only 48.70% recall β€” a conservative detector.
85
 
86
- ## Evaluation
87
-
88
- All numbers are from the held-out test split (17,542 rows, 1,887 vulnerable), scored by this repo's
89
- own harness. Base model = un-finetuned HobbyLM-Chat, identical prompts.
90
-
91
- | metric | HobbyLM-Chat | CodeAstra-500M |
92
- |---|---|---|
93
- | JSON parse rate | 1.20% | 99.98% |
94
- | ROC AUC | β€” | 96.97% |
95
- | average precision | β€” | 82.64% |
96
- | best F1 | 0.00% | 76.23% |
97
- | exact CWE (of 28 classes) | 0.00% | ~55% |
98
- | OWASP category | 0.00% | ~74% |
99
-
100
- ### Paired evaluation β€” the number that matters
101
 
102
- Standard splits of CVE-derived datasets are confounded: vulnerable functions come from large C
103
- projects (kernel, Chromium, PHP) while "safe" ones are often unrelated code, so a model can score
104
- well by recognising *style* rather than *flaws*. We therefore also evaluate PrimeVul-style, on 894
105
- pairs of a vulnerable function and **its own patched version**:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
 
107
- | | first SFT pass | CodeAstra-500M |
108
- |---|---|---|
109
- | **P-C β€” flags flawed, clears patched** | 6.94% | **27.40%** |
110
- | P-V β€” flags both (style shortcut) | 84.90% | **33.45%** |
111
- | P-B β€” clears both | 6.71% | 36.02% |
112
- | specificity on patched code | 13.65% | **63.42%** |
113
- | within-pair ranking accuracy | 66.22% | 69.46% |
 
114
 
115
- The published model was produced by adding the ~7,000 patched functions back as *safe* training
116
- examples β€” minimal pairs that differ only by the fix. That quadrupled paired accuracy and raised
117
- specificity on patched code from 13.65% to 63.42%.
118
 
119
- **Be honest about what this means:** within-pair ranking accuracy only moved 66.22% β†’ 69.46%, so most
120
- of the gain is better calibration rather than deeper understanding. **27.40% paired accuracy is the
121
- realistic estimate of true detection ability β€” not the 96.97% AUC.**
122
 
123
- ## Training
 
124
 
125
- 8xH100 on [Modal](https://modal.com). Main SFT: 6,000 steps, lr 2e-5, micro-batch 8, 176,216
126
- examples (~27 min). Hard-negative pass: 500 steps, lr 5e-6 (~2.5 min). Loss masked to the completion;
127
- MoE aux-free balancing bias frozen. Architecture is unchanged from HobbyLM: 768 hidden / 16 layers,
128
- 36 experts top-6 + 1 shared, GQA with per-head QK-norm, GPT-2 BPE, 2048 context.
129
 
130
- ## Limitations
131
 
132
- - **Function-level only.** It sees one function; interprocedural and data-flow bugs are largely
133
- invisible to it. Access-control flaws needing caller context are its weakest class.
134
- - **92% of training data is C.** Treat other languages as out-of-distribution.
135
- - **CWE labels confuse related classes.** CWE-89 and CWE-94 are strong (85%/82% exact); catch-all
136
- buckets like CWE-399 and CWE-416 are weak. It often finds the bug and picks a sibling CWE.
137
- - **Training labels are noisy.** Sources include mislabeled languages and prose spliced into code.
138
- - **Code over 2048 tokens is head+tail truncated**, so the middle of long functions is unseen.
139
- - **This is a 500M research model, not a security product.** It complements review and SAST; it does
140
- not replace them. Do not gate a release on it alone.
141
 
142
- ## License
143
 
144
- Apache-2.0.
 
 
 
1
  ---
2
  license: apache-2.0
3
+ language:
4
+ - en
5
+ metrics:
6
+ - accuracy
7
+ - f1
8
+ - roc_auc
9
  library_name: safetensors
10
+ tags:
11
+ - code
12
+ - security
13
+ - vulnerability-detection
14
+ - cwe
15
+ - owasp
16
+ - moe
17
+ - hobbylm
18
  pipeline_tag: text-generation
 
19
  ---
20
+ # CodeAstra-500M: Laptop-Scale Vulnerability Detection πŸ”πŸ›‘οΈ
21
 
22
+ ## Model Description
23
 
24
+ CodeAstra-500M is the small sibling of [CodeAstra-7B](https://huggingface.co/rootxhacker/CodeAstra-7B) β€” a
25
+ 500M-parameter **sparse Mixture-of-Experts** model fine-tuned for security vulnerability detection in
26
+ source code. Where CodeAstra-7B is built on Mistral-7B, CodeAstra-500M is built on
27
+ [HobbyLM-Chat](https://huggingface.co/rootxhacker/HobbyLM-Chat), a MoE language model trained from
28
+ scratch on a hobby budget β€” so the whole thing runs on a laptop CPU.
29
 
30
+ It answers with a single structured JSON verdict: is this vulnerable, which CWE, which OWASP category.
 
31
 
32
+ ### Key Features
33
 
34
+ - πŸͺΆ **Tiny**: 500M total parameters, only ~150M active per token thanks to top-6-of-36 expert routing.
35
+ - πŸ“ **Structured output**: emits parseable JSON on 99.98% of inputs β€” no regex-scraping prose.
36
+ - 🎚️ **Tunable**: returns a calibrated probability, so you pick the precision/recall trade-off at
37
+ inference time instead of retraining.
38
+ - 🌐 **Multi-language**: C, C++, Python, Java, JavaScript, PHP, Go, Ruby, Swift, Kotlin, C#, Fortran β€”
39
+ though the training mix is heavily C-weighted (see Limitations).
40
+ - πŸ§ͺ **Honestly evaluated**: scored on the standard split *and* on vulnerable/patched function pairs,
41
+ which is the harder and more meaningful test.
42
+ - πŸ’» **Runs locally**: shares the HobbyLM architecture, so it loads in the from-scratch Rust CPU engine
43
+ (`hobby-rs`) with no Python at runtime.
44
+
45
+ ## Performance πŸ“Š
46
+
47
+ Evaluated on the held-out test split (17,542 snippets, 1,887 vulnerable) of
48
+ [`ayshajavd/code-security-vulnerability-dataset`](https://huggingface.co/datasets/ayshajavd/code-security-vulnerability-dataset).
49
+ The base model is un-finetuned HobbyLM-Chat under identical prompts.
50
+
51
+ | Metric | HobbyLM-Chat (base) | **CodeAstra-500M** |
52
+ |---|---|---|
53
+ | JSON parse rate | 1.20% | **99.98%** |
54
+ | ROC AUC | β€” | **96.97%** |
55
+ | Average precision | β€” | **82.64%** |
56
+ | Best F1 | 0.00% | **76.23%** |
57
+ | Precision / Recall @ best F1 | 0.00 / 0.00 | **75.57% / 76.89%** |
58
+ | Exact CWE (28 classes) | 0.00% | **~55%** |
59
+ | OWASP category | 0.00% | **~74%** |
60
+
61
+ ⚠️ **A note on accuracy.** This dataset is 89% non-vulnerable, so a model that answers "safe" every
62
+ time scores **90.5% accuracy** β€” which is exactly what the un-finetuned base model does, at 0% recall.
63
+ That is why this card leads with F1, AUC and recall rather than accuracy. Treat any headline accuracy
64
+ figure on this dataset with suspicion, including for other models.
65
+
66
+ ### Paired evaluation β€” the number that actually matters 🎯
67
+
68
+ Standard splits of CVE-derived vulnerability datasets are **confounded**: the vulnerable functions come
69
+ from big C projects (Linux kernel, Chromium, PHP, ffmpeg) while the "safe" ones are often unrelated
70
+ code. A model can score very well by recognising *code style* rather than *code flaws*.
71
+
72
+ So CodeAstra-500M is also evaluated PrimeVul-style, on 894 pairs of a vulnerable function and **its own
73
+ patched version** β€” near-identical code differing only by the security fix.
74
+
75
+ | | First SFT pass | **CodeAstra-500M** |
76
+ |---|---|---|
77
+ | **P-C β€” flags the flawed one, clears the patched one** | 6.94% | **27.40%** |
78
+ | P-V β€” flags both (the style shortcut) | 84.90% | **33.45%** |
79
+ | P-B β€” clears both | 6.71% | 36.02% |
80
+ | P-R β€” reversed | 1.45% | 3.13% |
81
+ | Specificity on patched code | 13.65% | **63.42%** |
82
+ | Within-pair ranking accuracy | 66.22% | **69.46%** |
83
+
84
+ The released model was produced by feeding the ~7,000 patched functions back in as *safe* training
85
+ examples β€” minimal pairs that differ only by the fix. This quadrupled paired accuracy and lifted
86
+ specificity on patched code from 13.65% to 63.42%.
87
+
88
+ **Read this honestly:** within-pair ranking accuracy moved only 66.22% β†’ 69.46%, meaning most of the
89
+ improvement is better calibration rather than deeper understanding. **27.40% is the realistic estimate
90
+ of true detection ability β€” not the 96.97% AUC.** Very few vulnerability models publish this number;
91
+ it is here because it is the one that predicts real-world behaviour.
92
+
93
+ ## Intended Use
94
+
95
+ CodeAstra-500M is for developers, security researchers and code auditors who want a fast first-pass
96
+ triage filter that runs locally β€” in a pre-commit hook, a CI step, or an editor plugin β€” without
97
+ sending source code to an API. It is a **filter that decides what a human looks at**, not an oracle.
98
+
99
+ ## Threshold β€” please read 🎚️
100
+
101
+ The model returns a probability. **The default 0.5 is not the balanced operating point.**
102
+
103
+ | Threshold | Precision | Recall | Use case |
104
+ |---|---|---|---|
105
+ | 0.3346 | 75.57% | 76.89% | **Balanced (best F1 = 76.23%)** |
106
+ | 0.3775 | 80.02% | 70.27% | Triage |
107
+ | 0.4378 | 85.03% | 59.88% | |
108
+ | 0.5156 | 90.01% | 45.36% | CI gating |
109
+ | 0.6514 | 95.07% | 23.53% | High-confidence alerts only |
110
+
111
+ At the naive 0.5 you get 88.79% precision but only **48.70% recall** β€” it will quietly miss half the
112
+ vulnerabilities. Set the threshold deliberately.
113
+
114
+ ## Training πŸ‹οΈβ€β™‚οΈ
115
+
116
+ Fine-tuned from HobbyLM-Chat on 8Γ—H100 GPUs via [Modal](https://modal.com), using the **full** dataset β€”
117
+ all 140,335 training rows, nothing subsampled, with over-long code head+tail truncated rather than
118
+ dropped.
119
+
120
+ | | |
121
+ |---|---|
122
+ | Main SFT | 6,000 steps, lr 2e-5, micro-batch 8 Γ— 8 GPUs, 176,216 examples, ~27 min |
123
+ | Hard-negative pass | 500 steps, lr 5e-6, 7,023 minimal pairs, ~2.5 min |
124
+ | Objective | next-token CE masked to the JSON verdict; MoE aux-free balancing bias frozen |
125
+ | Class balance | vulnerable rows oversampled 3Γ— (10.9% β†’ 26.0% positives) |
126
+
127
+ Architecture is unchanged from HobbyLM: 768 hidden / 16 layers, 36 experts with top-6 routing plus one
128
+ shared expert, GQA attention with per-head QK-norm, RoPE, GPT-2 byte-level BPE, 2048-token context.
129
+
130
+ ## Usage πŸ’»
131
+
132
+ The model uses the HobbyLM MoE architecture, so it needs the `hobbylm` package rather than
133
+ `transformers`. The prompt format matters β€” the model was trained on exactly one layout:
134
 
135
  ````text
136
  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.
 
143
  ASSISTANT:
144
  ````
145
 
146
+ Use `detect_prompt()` rather than assembling that by hand:
 
 
 
 
 
 
 
 
 
147
 
148
  ```python
149
+ import json, torch, tiktoken
150
  from huggingface_hub import hf_hub_download
151
  from safetensors.torch import load_file
152
+ from hobbylm.config import ModelConfig
153
  from hobbylm.model import MoETransformer
154
  from hobbylm.security_data import detect_prompt, VERDICT_PREFIX, TRUE_ID, FALSE_ID
 
155
 
156
  repo = "rootxhacker/codeastra-500M"
157
  cfg_d = json.load(open(hf_hub_download(repo, "config.json")))
158
  cfg_d.pop("preset", None)
159
  model = MoETransformer(ModelConfig(**cfg_d)).cuda().eval()
160
  model.load_state_dict(load_file(hf_hub_download(repo, "model.safetensors")))
 
161
  enc = tiktoken.get_encoding("gpt2")
162
+
163
+ code_to_analyze = """
164
+ $query = $_GET['query'];
165
+ $stmt = $db->prepare($query);
166
+ $stmt->execute();
167
+ """
168
+
169
+ # Fast path: force the verdict position and read one probability (~4ms, no generation)
170
+ prompt = detect_prompt(code_to_analyze, "PHP") + VERDICT_PREFIX
171
  ids = torch.tensor([enc.encode_ordinary(prompt)], device="cuda")
172
  with torch.no_grad():
173
  logits, _ = model(ids)
174
  p_vuln = torch.softmax(logits[0, -1, [TRUE_ID, FALSE_ID]].float(), -1)[0].item()
175
+ print(f"P(vulnerable) = {p_vuln:.3f} -> {'VULNERABLE' if p_vuln >= 0.3346 else 'safe'}")
176
  ```
177
 
178
+ Scoring this way is ~26Γ— faster than generating the JSON (4.3 ms vs 110 ms per snippet) and gives you
179
+ the tunable probability. If you also want the CWE and OWASP labels, generate the completion normally
180
+ from `detect_prompt(code, lang)` and parse the JSON with `hobbylm.security_data.parse_verdict`.
 
 
 
 
 
 
 
 
 
 
 
181
 
182
+ A typical answer:
183
 
184
+ ```json
185
+ {"vulnerable": true, "cwe": "CWE-89", "cwe_name": "Improper Neutralization of Special Elements used in an SQL Command (SQL Injection)", "owasp": "A03: Injection"}
186
+ ```
 
 
 
 
 
 
 
 
 
 
 
 
187
 
188
+ ## Limitations ⚠️
189
+
190
+ 1. **Function-level only.** It sees a single function, so interprocedural and data-flow vulnerabilities
191
+ are largely invisible. Access-control bugs needing caller context are its weakest class.
192
+ 2. **Heavily C-weighted training data** (92% C). Other languages work but are out-of-distribution β€”
193
+ expect lower reliability on Go, Swift, Kotlin and TypeScript.
194
+ 3. **CWE labels confuse related classes.** CWE-89 (SQL injection, 85% exact) and CWE-94 (code
195
+ injection, 82%) are strong; catch-all buckets like CWE-399 and CWE-416 are weak. It frequently finds
196
+ the right bug and picks a sibling CWE β€” the detection is better than the label suggests.
197
+ 4. **Multiple vulnerabilities in one snippet** are not reliably enumerated; it returns a single verdict.
198
+ 5. **Long code is truncated.** Snippets beyond 2048 tokens are head+tail truncated, so the middle of
199
+ very long functions is unseen.
200
+ 6. **False positives are expected** at the recall-oriented thresholds. Results need human verification.
201
+ 7. **It is a 500M research model, not a security product.** Use it alongside code review and SAST, not
202
+ instead of them, and do not gate a release on it alone.
203
+
204
+ ## Test Apparatus
205
+
206
+ All figures come from the held-out test split of `ayshajavd/code-security-vulnerability-dataset`
207
+ (17,542 snippets, never trained on), scored with a purpose-built harness that generates the verdict and
208
+ parses it, plus the calibrated single-forward-pass scorer for threshold-free metrics. The paired
209
+ evaluation uses 894 vulnerable/patched function pairs drawn from the same held-out split. The base
210
+ HobbyLM-Chat comparison was run through the **identical** prompts and harness, so the two columns are
211
+ directly comparable.
212
+
213
+ Numbers on this page were not copied from other model cards, and no comparison against external models
214
+ is claimed β€” CodeAstra-7B was evaluated on a different corpus and protocol, so the two are **not**
215
+ directly comparable.
216
+
217
+ ## Citation πŸ“œ
218
 
219
+ ```
220
+ @software{CodeAstra-500M,
221
+ author = {Harish Santhanalakshmi Ganesan},
222
+ title = {CodeAstra-500M: Laptop-Scale Vulnerability Detection},
223
+ year = {2026},
224
+ howpublished = {\url{https://huggingface.co/rootxhacker/codeastra-500M}}
225
+ }
226
+ ```
227
 
228
+ ## License πŸ“„
 
 
229
 
230
+ CodeAstra-500M is released under the Apache License 2.0.
 
 
231
 
232
+ ```
233
+ Copyright 2026 [Harish Santhanalakshmi Ganesan]
234
 
235
+ Licensed under the Apache License, Version 2.0 (the "License");
236
+ you may not use this file except in compliance with the License.
237
+ You may obtain a copy of the License at
 
238
 
239
+ http://www.apache.org/licenses/LICENSE-2.0
240
 
241
+ Unless required by applicable law or agreed to in writing, software
242
+ distributed under the License is distributed on an "AS IS" BASIS,
243
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
244
+ See the License for the specific language governing permissions and
245
+ limitations under the License.
246
+ ```
 
 
 
247
 
248
+ ## Acknowledgements πŸ™
249
 
250
+ Thanks to the HobbyLM project for the 500M MoE base model, and to
251
+ [@ayshajavd](https://huggingface.co/ayshajavd) for compiling the vulnerability dataset this model was
252
+ trained on.