alias3-web / README.md
vmayoral's picture
alias3-web: 4-bit WebGPU graph, readout files, library and demo
2ab2e60 verified
|
Raw History Blame Contribute Delete
10.4 kB
---
license: apache-2.0
language:
- en
base_model:
- aliasrobotics/alias3-micro-1026
base_model_relation: finetune
pipeline_tag: text-generation
library_name: onnx
tags:
- cybersecurity
- security
- onnx
- onnxruntime-genai
- webgpu
- browser
- int4
- dual-system
- decision-head
- system-1
- system-2
- phishing
- malware-detection
---
# alias3-web
**A cybersecurity transformer that runs in the browser.** It answers a typed security question in about
150 ms and writes an explanation on request, on the user's GPU through WebGPU. The page under test never
leaves the machine.
<p align="center">
<img src="assets/bis-overview.png" alt="alias3-web inside the Browser Immune System: a page is reduced to typed observations, the model answers one directed question per threat class, and explains a verdict on request" width="920">
</p>
alias3-web is the model behind the **Browser Immune System (BIS)**, a browser extension that screens every
page a user visits. Both are described in the paper *Browser Immune System (BIS): Innate and Adaptive
Threat Detection in the Browser with a Cybersecurity Transformer* (Mayoral-Vilches and Worrel, 2026), where
the model is called `alias-web`. The figure above is the paper's overview: the model sits in the centre lane.
It serves two regimes from one loaded set of 4-bit weights:
| Regime | What it does | Cost on a laptop GPU |
|---|---|---|
| **System 1** | One typed question, one forward pass, no token decoded: a probability per option. | 152 ms per question |
| **System 2** | Ordinary text generation from the same weights, on request. | 10.5 tokens/s |
> **Research artefact.** Released to make the paper reproducible. Read the limits below before relying on
> its answers.
## What is in this repository
| Path | What it is |
|---|---|
| `model/model.onnx`, `model/model.onnx.data` | The 4-bit graph for WebGPU (ONNX Runtime GenAI, 2,440,274,944 bytes of weights). It returns logits and the hidden states at requested positions. |
| `model/tokenizer.json`, `model/tokenizer_config.json`, `model/chat_template.jinja`, `model/genai_config.json` | Tokenizer and runtime configuration. `model/tok/` and `model/heads/` hold copies where the runner looks for them. |
| `heads/head.bin` | The complete pointer head (1.3 M parameters, fp16, 2,622,545 bytes): weights and biases of both projections. |
| `heads/norm.bin` | The weight of the model's final RMSNorm (10,289 bytes). The graph exports hidden states before that norm and the head was trained after it. |
| `aliasweb.mjs` | The library: the typed encoding, the norm, the head, and the calls `ask()` and `generate()`. |
| `index.html`, `serve.py` | A demo page and a local server with HTTP Range support. |
| `vendor/ct0.js`, `vendor/ct0-edge.LICENSE` | The prefill engine: the distribution of [ct0-edge](https://github.com/eduardoworrel/ct0-edge) by Eduardo Worrel (MIT), unchanged. |
## Quick start
```bash
hf download aliasrobotics/alias3-web --local-dir alias3-web
cd alias3-web && python3 serve.py 8924
# open http://127.0.0.1:8924 in Chrome or Edge and press "Load model"
```
The first load reads 2.44 GB from the local server and takes a few seconds. The demo page fetches its two
runtime modules (ONNX Runtime Web 1.30.0 and Transformers.js 3.7.5) from a public CDN; the model, the
material you paste and the answers stay on your machine.
From your own page, with the same import map as `index.html`:
```js
import { AliasWeb } from "./aliasweb.mjs";
const model = await AliasWeb.load({ base: "./" });
// System 1: a directed yes/no question about a piece of evidence
const r = await model.ask({
kind: "noul",
state: `const q = new URLSearchParams(location.search).get("q");
document.getElementById("out").innerHTML = "result: " + q;`,
q: "Is user input written into the DOM without escaping?",
});
console.log(r.p, r.ms); // 0.822, about 150 ms
// System 2: an explanation, only when it is worth seconds
const t = await model.generate({
state: "...the same evidence...",
prompt: "You are a security reviewer. Name the vulnerability in this code and the fix, in 2-3 sentences.",
maxNewTokens: 90,
});
console.log(t.text, t.tokPerS);
```
## The typed interface
A decision is one causal sequence, `<state> s <q> q <opt> o1 </opt> … <opt> oK </opt> <decide>`. The markers
are not new vocabulary: they are five special tokens of the base tokenizer, and the library writes them by
id.
| Marker | Token | Id | Role |
|---|---|---|---|
| `<state>` | `<\|fim_prefix\|>` | 248060 | opens the evidence |
| `<q>` | `<\|fim_middle\|>` | 248061 | opens the question |
| `<opt>` | `<\|box_start\|>` | 248049 | opens an option |
| `</opt>` | `<\|box_end\|>` | 248050 | closes an option: the key is read here |
| `<decide>` | `<\|fim_suffix\|>` | 248062 | closes the row: the query is read here |
The head scores option *i* as `q(h_decide) · k(h_opt_i) / (sqrt(256) · T)` on the normalised hidden states
and a softmax over the options gives the probabilities. Text supplied by the caller is sanitised (a literal
`<|name|>` becomes `<¦name¦>`), so that the evidence cannot forge an option boundary.
| `kind` | Options | Returns | Status |
|---|---|---|---|
| `noul` | Yes, No | `p`, the probability of yes | the kind to use |
| `choice` | your list | `choice`, `top` | answers in the categories of this checkpoint's training, see the limits |
| `score` | 1 to 5 | `level`, `expected` | orders severity only weakly, see the limits |
## Measurements
All on one Apple M3 Max laptop (128 GB) in Chrome with WebGPU, the weights served from the local server.
| Quantity | Value |
|---|---|
| Model ready, second load in the same browser | 2.33 s |
| System 1, per question on short code snippets | 152 ms mean of twelve (110 to 200 ms); the head itself takes 1.18 ms |
| System 2 | 10.5 tokens/s, about 96 ms per token |
| A generated answer against a decision on the same snippet | 6 to 39 times the cost |
One directed yes/no question per snippet:
| Snippet | Question | P(yes) |
|---|---|---|
| DOM XSS: `innerHTML` with a query parameter | Is user input written into the DOM without escaping? | **0.822** |
| SQL injection: string concatenation in `db.query` | Does this code concatenate user input into a SQL query? | **1.000** |
| Command injection: `exec("curl " + url)` | Does this code pass user input to a shell command? | **1.000** |
| Path traversal: `sendFile("/var/data/" + f)` | Can user input escape the intended directory in this file path? | 0.428 |
| Hard-coded secret: an API key in the source | Does this code contain a hardcoded secret? | **1.000** |
| Safe: pure arithmetic | Is user input written into the DOM without escaping? | **0.000** |
Before publication the files of this repository were loaded in Chrome for Testing 157 and asked the same
six questions: every probability above was reproduced to the third decimal. A first load in a fresh
browser profile took 2.5 to 4.0 s.
The question is the lever. On the DOM XSS snippet the generic question "Does this code contain a security
vulnerability?" returns 0.040 and the directed one 0.822: same head, same evidence. Ask one directed
question per class.
In BIS, a battery of seven such questions returned the expected page verdict on 7 of the 8 sites of the
paper's benchmark, in 0.9 to 6.4 s per page, with identical verdicts across samples and across Chrome and
Firefox.
## Limits
- **WebGPU only.** The 4-bit graph has no CPU path. Measured in Chrome; Firefox Nightly with a window runs
it 5.9 times slower; Safari and Windows are unmeasured.
- **Text inside the evidence can move the answer.** In the paper's benchmark a comment that declared a
script harmless took a miner detection from 1.00 to 0.00. Treat the state as untrusted input.
- **Questions need calibration before they filter anything.** Two of the seven BIS questions, one about
scripts loaded from another server and one about keystroke capture asked of a login form, answer yes on
ordinary pages.
- **`choice` and `score` speak the language of this checkpoint's training,** the context categories of
capture-the-flag campaigns. Asked to pick among weakness classes, `choice` returns the same label for any
injectable snippet, and `score` is not a calibrated severity. Use `noul`.
- **System 2 needs a forced prefix.** The 4-bit checkpoint does not close its deliberation block on its
own; `generate()` starts the answer after the closing marker. A directive prompt and a temperature of 0.3
avoid narrated pseudo-deliberation.
- **Agreement with the full-precision weights was checked on one prompt,** where the 4-bit graph returned
the same decision direction. How often the two precisions agree is not measured.
- **One machine.** There is no measurement on a modest integrated GPU.
## Provenance
- **Parent.** [alias3-micro](https://huggingface.co/aliasrobotics/alias3-micro-1026), a 4B cybersecurity
transformer on a `Qwen3.5-4B` backbone (32 layers, hidden width 2560, a 248,320-token vocabulary),
described in the first paper cited below.
- **What alias3-web adds to the weights.** Two rank-16 adapters, fused: the parent's decision adapter,
trained together with the pointer head, and a context-category sensor trained for two epochs on 12,576
replayed decision examples and 4,172 context-category examples, with the head frozen.
- **The graph.** ONNX Runtime GenAI model builder 0.18 with `-p int4 -e webgpu` and
`include_hidden_states=true exclude_mtp=true`, run on Linux x86_64, following the recipe of the edge
study by Eduardo Worrel that this work reproduces and extends.
- **Not included.** The fused full-precision checkpoint (8.4 GB) and the BIS extension are not part of this
repository.
## License
Apache-2.0 for the model files, the library, the demo page and the server, as for the parent model. The
vendored runner in `vendor/` is MIT; its licence file is beside it.
## Citation
```bibtex
@article{mayoralvilches2026bis,
author = {Mayoral-Vilches, V{\'i}ctor and Worrel, Eduardo},
title = {Browser Immune System ({BIS}): Innate and Adaptive Threat Detection in the Browser with a Cybersecurity Transformer},
year = {2026}
}
@article{mayoralvilches2026transformer,
author = {Mayoral-Vilches, V{\'i}ctor},
title = {{CT0}: Cybersecurity Transformer},
journal = {arXiv preprint arXiv:2610.16550},
year = {2026}
}
```