Glimmer-Sentry-30B
A local detection-engineering copilot for teams without a SOC. It writes, explains, tunes and translates detection rules (Sigma to KQL and SPL, YARA, Wazuh) and runs 4-bit on a single 24GB card.
I built this because most small security teams I meet have the same problem: they inherit a pile of Sigma rules, a Sentinel or Splunk deployment, and nobody with the time to translate between them. The paid copilots that do this live in someone else's cloud, which is exactly where a lot of these teams can't send their detection logic. This one runs on your own box.
It's a QLoRA fine-tune of Muse-Glimmer-30B, trained on 12,875 examples built from public detection-rule repositories. The headline feature is cross-format translation, and there's a design decision behind it worth knowing about: every translation pair in the training data was generated with the official sigma-cli converter, not by another LLM. The model learned from ground truth, and it's evaluated against ground truth below.
The numbers
Measured on 50 held-out Sigma rules the model never saw in training, greedy decoding, scored against sigma-cli output. No cherry-picking; the eval script and raw generations are in the repo.
| Task | Result |
|---|---|
| Sigma → KQL (M365 Defender), exact string match | 80% |
| Sigma → SPL (Splunk), exact string match | 90% |
| Sigma authoring: output parses as YAML | 76% |
Sigma authoring: passes sigma check |
76% |
| Sigma authoring: converts cleanly to KQL | 76% |
| YARA authoring: compiles (512-token budget) | 43% |
| YARA authoring: compiles (1536-token budget) | 57% |
Exact match means byte-for-byte identical to what the official converter produces. Most of the translation misses were near things: an extra pair of parentheses, or very long rules (one embeds 38 file hashes) blowing past the generation budget rather than being wrong.
Two honest caveats:
YARA is the weak spot. Only about 10% of the training mix was YARA and it shows. A third of the apparent failures at the 512-token budget were actually rules getting cut off mid-generation rather than bad syntax, which is why I report both budgets. Give it 1536+ tokens for YARA work, and compile-check everything it produces (you should be doing that anyway; see the responsible use section).
Memorisation check. The base model has clearly seen SigmaHQ on GitHub during pretraining; before fine-tuning it could reproduce at least one holdout rule nearly verbatim, real UUID included. So I checked: every one of the 50 authored rules was compared against the real rule it was prompted from. Zero were near-copies (mean similarity 0.35). The authoring numbers reflect the model writing rules, not reciting them.
General chat didn't collapse either. After fine-tuning it still explains DNS to a ten-year-old and writes a working palindrome function. There's a ~10% general-instruction mix in the training data for exactly that reason.
Example
Real output from the released weights, greedy decode, on a holdout rule (the SharpMove lateral-movement tool):
Input: a Sigma rule detecting SharpMove execution by image name, original filename, or its characteristic command-line pairs.
Output:
DeviceProcessEvents
| where (FolderPath endswith "\\SharpMove.exe" or ProcessVersionInfoOriginalFileName =~ "SharpMove.exe") or (ProcessCommandLine contains "computername=" and (ProcessCommandLine contains "action=create" or ProcessCommandLine contains "action=dcom" or ProcessCommandLine contains "action=executevbs" or ProcessCommandLine contains "action=hijackdcom" or ProcessCommandLine contains "action=modschtask" or ProcessCommandLine contains "action=modsvc" or ProcessCommandLine contains "action=query" or ProcessCommandLine contains "action=scm" or ProcessCommandLine contains "action=startservice" or ProcessCommandLine contains "action=taskscheduler"))
That's an exact match against sigma convert -t kusto -p microsoft_365_defender, including the field mappings (Image → FolderPath, OriginalFileName → ProcessVersionInfoOriginalFileName).
Beyond translation it handles: "write me a Sigma rule that detects X" (give it a description, tags and logsource), "explain this rule for my manager", and "this rule keeps firing on our backup jobs, how do I tune it" using the rule's own false-positives field as grounding.
Running it
You need transformers==5.15.0 or later. The architecture registered in 5.15.0; earlier versions will refuse to load it. If you use Unsloth, pip will complain about its transformers<=5.5.0 pin. The conflict warning is safe to ignore for this model; I trained the thing on that exact combination.
One trap worth knowing: this is a multimodal base, so AutoProcessor/Unsloth hand you a processor, not a tokenizer. Call it keyword-style, processor(text=...). Passed positionally, your text gets parsed as an image and dies somewhere in base64 decoding with a baffling error.
Sampling: temperature 1.0, top_p 0.95, top_k 64 (the base model's defaults). The chat template has a reasoning_strength variable. Set it to high for rule authoring and translation, medium is fine for explanations. Text-only fine-tune; the vision tower is frozen and unmodified, and I haven't tested image input at all.
VRAM: about 22GB loaded 4-bit, so it fits a 3090/4090 with little to spare. The fp16 shards are ~56GB if you have the hardware. The adapter/ folder has the 428MB LoRA on its own if you'd rather apply it to the base model yourself.
GGUF builds live in EryriLabs/Glimmer-Sentry-30B-GGUF — Q4_K_M (16.9GB, fits a 24GB card) and Q8_0 (29.6GB). Both were verified before upload: byte-exact holdout translation through the real chat template, clean termination. You need a llama.cpp build from 2026-08-13 or newer; support for this architecture is recent. Getting there was a saga — the base model's tokenizer packaging targets an unreleased transformers version, and the workaround (a verified tokenizer re-export, no hand-edited fields) is documented in the GGUF repo's card.
Training details
- QLoRA via Unsloth: r=16, alpha=16, dropout 0, LoRA on the text tower's attention and MLP projections only. No embeddings, no lm_head, vision tower frozen (verified: zero trainable parameters with vision or projector names).
- One epoch over 12,875 examples, sequence length 2048 with packing, effective batch 16, cosine schedule, loss 1.49 → 0.61.
- Hardware: one RTX 3090, about 7.5 hours. The training script checkpoints every 20 steps and supports pause/resume via a sentinel file, which got tested involuntarily more than once.
Training data mix: Sigma→KQL/SPL translation pairs from sigma-cli (25%), rule authoring from description+tags (20%), plain-English explanations (15%), Wazuh equivalent-coverage guidance (10%), false-positive tuning (10%), YARA authoring and explanation (10%), general instructions (10%). Every YAML answer parses, every YARA answer compiles, every translation is converter output verbatim. Wazuh pairings are technique-level matches, not exact translations, and the training answers say so explicitly; there's no official Sigma→Wazuh converter, so treat that capability as "closest existing coverage", not translation.
Data sources and licences
| Source | Licence |
|---|---|
| SigmaHQ/sigma | Detection Rule License 1.1 |
| Neo23x0/signature-base | Detection Rule License 1.1 |
| wazuh/wazuh ruleset (v4.14.7) | GPLv2 |
| darkknight25/YARA_Rules_Dataset | MIT |
| HuggingFaceH4/ultrachat_200k (2,000 rows) | MIT |
| meta-models/Muse-Glimmer-30B (base) | Apache 2.0 |
Rule authors' author: and references: fields were kept intact through dataset generation, per the DRL attribution requirement. Thanks to the SigmaHQ maintainers, Florian Roth and the signature-base contributors, and the Wazuh team; models like this are only possible because that community publishes its work.
Responsible use
This model assists a human detection engineer. It does not replace one. Generated rules must be reviewed and tested before they go anywhere near production: run Sigma output through sigma check, compile YARA before deploying it, and test everything against known-good data first. A rule that compiles is not a rule that detects what you think it detects, and a 90% exact-match rate means one rule in ten is wrong in some way. Detection rules are defensive, public, community-standard artefacts, and that's what this model was trained on; it has no more offensive knowledge than the public repositories it learned from.
Roadmap
A v0.2 with doubled YARA data and two new task types (fixing broken rules given the compiler error, and writing rules from supplied IOCs) is already trained, and taught me an expensive lesson: its long YARA training answers got silently truncated by sequence packing, so the model learned to write rules that never terminate. YARA compile rate went down, not up. v0.3 fixes the answer-length filtering and should ship the repair capability properly. If the numbers clear v0.1, it replaces this.
Found a problem, or got results that don't match the table? Open a discussion; the eval script is in the repo and everything here is reproducible from the seed.
- Downloads last month
- -