paiml commited on
Commit
9f6447d
·
verified ·
1 Parent(s): 95e1697

Upload folder using huggingface_hub

Browse files
Files changed (4) hide show
  1. README.md +110 -0
  2. config.json +19 -0
  3. model.safetensors +3 -0
  4. vocab.json +252 -0
README.md ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ pipeline_tag: text-classification
4
+ tags:
5
+ - shell-safety
6
+ - classifier
7
+ - aprender
8
+ - rust
9
+ - bashrs
10
+ model-index:
11
+ - name: paiml/shell-safety-classifier
12
+ results:
13
+ - task:
14
+ type: text-classification
15
+ dataset:
16
+ name: bashrs-corpus
17
+ type: custom
18
+ metrics:
19
+ - name: Train Accuracy
20
+ type: accuracy
21
+ value: 0.966
22
+ - name: Validation Accuracy
23
+ type: accuracy
24
+ value: 0.632
25
+ - name: Training Samples
26
+ type: custom
27
+ value: "17942"
28
+ ---
29
+
30
+ # Shell Safety Classifier
31
+
32
+ Classifies shell scripts into 5 safety categories using a lightweight MLP trained on the [bashrs](https://github.com/paiml/bashrs) corpus.
33
+
34
+ ## Labels
35
+
36
+ | Index | Label | Description |
37
+ |-------|-------|-------------|
38
+ | 0 | safe | Script is deterministic, idempotent, and properly quoted |
39
+ | 1 | needs-quoting | Contains unquoted variables susceptible to word splitting |
40
+ | 2 | non-deterministic | Uses `$RANDOM`, timestamps, process IDs, or other non-deterministic sources |
41
+ | 3 | non-idempotent | Operations not safe to re-run (missing `-p`, `-f` flags) |
42
+ | 4 | unsafe | Security issues (injection vectors, privilege escalation) |
43
+
44
+ ## Architecture
45
+
46
+ - **Model**: MLP classifier (ShellVocabulary token embeddings -> 128 -> 64 -> 5)
47
+ - **Tokenizer**: ShellVocabulary (250 shell-specific tokens, max_seq_len=64)
48
+ - **Format**: SafeTensors (model.safetensors) + JSON config + vocab
49
+ - **Framework**: [aprender](https://github.com/paiml/aprender) (pure Rust ML, no Python dependencies)
50
+
51
+ ## Training
52
+
53
+ - **Corpus**: bashrs v2 corpus (17,942 entries: 16,431 Bash + 804 Makefile + 707 Dockerfile)
54
+ - **Split**: 80/20 train/validation (14,353 / 3,589)
55
+ - **Epochs**: 50
56
+ - **Optimizer**: Adam (lr=0.01)
57
+ - **Loss**: CrossEntropyLoss
58
+ - **Train accuracy**: 96.6%
59
+ - **Validation accuracy**: 63.2%
60
+
61
+ ### Class Distribution
62
+
63
+ | Label | Count | Percentage |
64
+ |-------|-------|------------|
65
+ | safe | 16,126 | 89.9% |
66
+ | needs-quoting | 1,814 | 10.1% |
67
+ | unsafe | 2 | 0.01% |
68
+
69
+ ## Usage
70
+
71
+ ### With bashrs CLI
72
+
73
+ ```bash
74
+ # Classify a single script
75
+ bashrs classify script.sh
76
+
77
+ # Classify with format detection
78
+ bashrs classify Makefile --format makefile
79
+
80
+ # Multi-label classification
81
+ bashrs classify script.sh --multi-label
82
+ ```
83
+
84
+ ### With aprender (Rust)
85
+
86
+ ```rust
87
+ use aprender::models::shell_safety::{ShellSafetyClassifier, SafetyClass};
88
+
89
+ let classifier = ShellSafetyClassifier::load("/path/to/model")?;
90
+ let result = classifier.predict("echo $HOME")?;
91
+ // result: SafetyClass::NeedsQuoting
92
+ ```
93
+
94
+ ## Files
95
+
96
+ | File | Size | Description |
97
+ |------|------|-------------|
98
+ | model.safetensors | 68 KB | Model weights |
99
+ | vocab.json | 3.6 KB | Shell tokenizer vocabulary |
100
+ | config.json | 371 B | Model architecture config |
101
+
102
+ ## Limitations
103
+
104
+ - The v2.0 MLP architecture has limited validation accuracy (63.2%) due to class imbalance and simple architecture
105
+ - Best suited for binary safe/unsafe classification (96%+ accuracy when collapsing to 2 classes)
106
+ - A Qwen2.5-Coder fine-tuned version is planned for higher accuracy on minority classes
107
+
108
+ ## License
109
+
110
+ MIT
config.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "embed_dim": 64,
3
+ "framework": "aprender",
4
+ "hidden_dim": 128,
5
+ "labels": [
6
+ "safe",
7
+ "needs-quoting",
8
+ "non-deterministic",
9
+ "non-idempotent",
10
+ "unsafe"
11
+ ],
12
+ "max_seq_len": 64,
13
+ "model_type": "shell-safety-classifier",
14
+ "num_classes": 5,
15
+ "training_data": "bashrs-corpus",
16
+ "training_samples": 17942,
17
+ "version": "2.0",
18
+ "vocab_size": 251
19
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f8ae6168ed65ebdbcb442e4a7f854f0785bb737530d61755d5cadd8945f14188
3
+ size 67991
vocab.json ADDED
@@ -0,0 +1,252 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "$MACHTYPE": 170,
3
+ "(": 113,
4
+ "#!/usr/bin/env": 7,
5
+ "let": 42,
6
+ "-e": 176,
7
+ "$2": 163,
8
+ "cat": 53,
9
+ "=": 128,
10
+ "ln": 50,
11
+ "type": 26,
12
+ "home": 231,
13
+ "check": 252,
14
+ "{": 121,
15
+ "ls": 75,
16
+ "100": 211,
17
+ "||": 99,
18
+ "dest": 228,
19
+ "'": 200,
20
+ "build": 257,
21
+ "date": 81,
22
+ "head": 61,
23
+ "read": 10,
24
+ "-gt": 134,
25
+ "-v": 178,
26
+ "info": 246,
27
+ "then": 85,
28
+ "$HOME": 148,
29
+ "))": 116,
30
+ "sed": 55,
31
+ "return": 20,
32
+ "[EOS]": 4,
33
+ "unzip": 73,
34
+ "readonly": 41,
35
+ "local": 38,
36
+ "0": 204,
37
+ "255": 212,
38
+ "-k": 189,
39
+ "fi": 88,
40
+ "~": 147,
41
+ "$#": 158,
42
+ "<": 106,
43
+ "tee": 65,
44
+ "export": 13,
45
+ "if": 84,
46
+ "$HOSTNAME": 168,
47
+ "uniq": 59,
48
+ "5": 209,
49
+ "bg": 34,
50
+ "dirname": 79,
51
+ "root": 229,
52
+ "]": 118,
53
+ "-d": 140,
54
+ "exec": 18,
55
+ "builtin": 44,
56
+ "$RANDOM": 153,
57
+ "2>>": 110,
58
+ "jobs": 33,
59
+ "-ne": 132,
60
+ "tail": 62,
61
+ "declare": 39,
62
+ "-le": 135,
63
+ ";;": 102,
64
+ "-ge": 136,
65
+ "in": 90,
66
+ "$*": 160,
67
+ "kill": 32,
68
+ "$0": 161,
69
+ "--verbose": 195,
70
+ "ok": 242,
71
+ "!": 146,
72
+ "awk": 56,
73
+ "-g": 187,
74
+ "stat": 76,
75
+ "10": 210,
76
+ "4": 208,
77
+ "#!/bin/bash": 5,
78
+ "[SEP]": 3,
79
+ "$(": 125,
80
+ "test": 22,
81
+ "source": 16,
82
+ "typeset": 40,
83
+ "|": 98,
84
+ "$OSTYPE": 169,
85
+ "-a": 184,
86
+ "}": 122,
87
+ "output": 224,
88
+ "--no-clobber": 198,
89
+ "log": 220,
90
+ "path": 217,
91
+ "--quiet": 196,
92
+ "data": 226,
93
+ "etc": 234,
94
+ "-b": 185,
95
+ "gunzip": 71,
96
+ "exit": 19,
97
+ ";": 101,
98
+ "var": 235,
99
+ "debug": 247,
100
+ "2>&1": 111,
101
+ "grep": 54,
102
+ "-z": 137,
103
+ "$@": 159,
104
+ "err": 221,
105
+ "cd": 11,
106
+ "$$": 155,
107
+ "stop": 249,
108
+ "wc": 60,
109
+ "restart": 250,
110
+ "tar": 69,
111
+ "mkdir": 46,
112
+ "else": 86,
113
+ "user": 230,
114
+ "-h": 188,
115
+ "&&": 100,
116
+ "-l": 190,
117
+ "wait": 31,
118
+ "done": 92,
119
+ "$IFS": 165,
120
+ "-i": 177,
121
+ "lib": 233,
122
+ "$TMPDIR": 164,
123
+ "\\": 201,
124
+ "curl": 67,
125
+ "file": 215,
126
+ "$BASHPID": 154,
127
+ "src": 227,
128
+ "--force": 193,
129
+ "status": 251,
130
+ "-o": 183,
131
+ "$USER": 149,
132
+ "mktemp": 80,
133
+ "[[": 119,
134
+ "$": 123,
135
+ "[": 117,
136
+ "-u": 191,
137
+ "$((": 126,
138
+ "-w": 143,
139
+ "error": 243,
140
+ "[UNK]": 1,
141
+ "unset": 14,
142
+ "$1": 162,
143
+ "trap": 30,
144
+ "-rf": 174,
145
+ "config": 225,
146
+ "remove": 255,
147
+ "${": 124,
148
+ "-p": 171,
149
+ "-c": 186,
150
+ "755": 214,
151
+ "install": 253,
152
+ "$SHELL": 152,
153
+ "run": 240,
154
+ "do": 91,
155
+ "-x": 192,
156
+ "fatal": 245,
157
+ "#!/bin/sh": 6,
158
+ "cp": 48,
159
+ "--parents": 197,
160
+ "touch": 74,
161
+ "644": 213,
162
+ "-s": 181,
163
+ "gzip": 70,
164
+ "zip": 72,
165
+ "-f": 172,
166
+ "chmod": 51,
167
+ "$!": 156,
168
+ "mv": 49,
169
+ "umask": 36,
170
+ "--recursive": 194,
171
+ "for": 89,
172
+ "3": 207,
173
+ "input": 223,
174
+ "dev": 236,
175
+ "-n": 175,
176
+ "$?": 157,
177
+ "-q": 179,
178
+ "fg": 35,
179
+ ">>": 105,
180
+ "&>": 112,
181
+ "wget": 68,
182
+ "echo": 8,
183
+ "!=": 130,
184
+ "xargs": 66,
185
+ "1": 205,
186
+ "]]": 120,
187
+ "rm": 47,
188
+ "start": 248,
189
+ "sleep": 82,
190
+ "name": 218,
191
+ "sys": 239,
192
+ "case": 95,
193
+ "eval": 17,
194
+ "printf": 9,
195
+ "until": 94,
196
+ "-m": 180,
197
+ "find": 57,
198
+ "command": 43,
199
+ ")": 114,
200
+ "dir": 216,
201
+ "getopts": 37,
202
+ "function": 97,
203
+ "&": 103,
204
+ "==": 129,
205
+ ":": 25,
206
+ "enable": 45,
207
+ "while": 93,
208
+ "hash": 27,
209
+ "sort": 58,
210
+ "\"": 199,
211
+ "tmp": 219,
212
+ "$PATH": 150,
213
+ "update": 254,
214
+ "2>": 109,
215
+ "esac": 96,
216
+ "shift": 21,
217
+ "-r": 173,
218
+ "\t": 203,
219
+ "[CLS]": 2,
220
+ "<<": 107,
221
+ "false": 24,
222
+ "`": 127,
223
+ "\n": 202,
224
+ "[PAD]": 0,
225
+ "alias": 28,
226
+ "true": 23,
227
+ "tr": 64,
228
+ "bin": 232,
229
+ "pwd": 12,
230
+ "null": 237,
231
+ "$TERM": 167,
232
+ "cut": 63,
233
+ "basename": 78,
234
+ ">": 104,
235
+ "proc": 238,
236
+ "((": 115,
237
+ "<<<": 108,
238
+ "$LANG": 166,
239
+ "2": 206,
240
+ "chown": 52,
241
+ "-lt": 133,
242
+ "-t": 182,
243
+ "out": 222,
244
+ "-eq": 131,
245
+ "set": 15,
246
+ "$PWD": 151,
247
+ "elif": 87,
248
+ "opt": 241,
249
+ "clean": 256,
250
+ "unalias": 29,
251
+ "warning": 244
252
+ }