DEV Community

Guido Tapia
Guido Tapia

Posted on • Originally published at picnet.com.au

An LLM-triaged SIEM: reviewing thousands of security events a day with a small team

Most health providers we talk to have the same shape of problem. Log sources everywhere, a security budget that funds part of one person's week, and an alert console nobody has opened since the fortnight after it was installed. The logs are being collected, which satisfies the auditor. Nobody is reading them, which satisfies nobody.

We have that problem too. PicNet is a small senior team, and we run our own infrastructure, so somebody has to look at the firewall and endpoint logs. For about a year now that somebody has been a language model doing a first pass, with a human reading whatever it escalates. This post describes how the pipeline actually works, what it costs, and where it is weak. It is part of our Practical AI in Cyber Security series.

What goes in

Collectors pull from the sources we already had, on a schedule, into flat files in an object store partitioned by day and source:

  • FortiGate firewall traffic and IPS events
  • Microsoft 365 unified audit log (mail rules, sharing, admin activity)
  • Entra ID sign-in logs and directory change events
  • AWS CloudTrail
  • SentinelOne endpoint detections and agent health
  • Windows event logs from servers, shipped with a lightweight agent
  • Remote-access logs from the VPN and RDP gateway

Nothing clever here, and deliberately so. The collectors are dumb, they retry, and they never drop a source silently. A missing source is itself an escalation, because the most common reason a log stops arriving is that someone turned something off.

One pass over everything, then selective deep dives

The design decision that made this work was refusing to do per-alert triage. Feeding a model one alert at a time gives it no way to know what normal looks like, so it either flags everything or nothing.

Instead there is a single global pass. For each window, the pipeline builds a compact per-host, per-source summary: counts by event type, new-this-window values (source IPs, user agents, service principals, parent processes), failed-versus-successful ratios, and anything that deviates from that host's own trailing baseline. The whole fleet's summary goes into one prompt. The model's job is comparative, not forensic. Which of these hosts looks unlike itself yesterday, and unlike its peers today?

That output is a ranked list, and only the top of it earns a second, expensive call with the raw log lines attached. This is the pattern Gwern describes as a "guardian angel": a model watching a whole activity stream continuously and surfacing only the parts that look off, rather than being wired into every individual rule.

The triage call returns structured JSON, one object per host, and anything malformed is treated as a flag rather than a pass:

{
  "host": "app-prd-03",
  "verdict": "deep_dive",
  "confidence": 0.72,
  "reason": "First observed successful RDP from an ASN not seen in 30d baseline, followed by service install event 7045.",
  "sources": ["windows_event", "remote_access"],
  "suggested_window_hours": 48
}
Enter fullscreen mode Exit fullscreen mode

The deep-dive pass gets the raw events for that host and window and produces a written incident note: what happened, in what order, what would confirm or rule it out. That note lands in a human inbox. It does not close anything, page anyone, or touch a firewall rule.

Cost control

We serialise the LLM calls. One at a time, in a loop, with the deep dives running only after triage has finished and ranked. That is not an engineering constraint, it is a spend and rate-limit choice: a serial loop has a predictable ceiling, and a runaway parallel job on a noisy day does not. If our event volume grows enough to matter, the throughput is sitting there to reclaim, because modern inference servers get their speed from continuous batching and paged KV-cache scheduling rather than from anything we would have to redesign (a good walkthrough of how vLLM does it here).

The two-tier split is where the money is saved. ISGroup published costs for an LLM-driven security review of the GlobaLeaks codebase: about US$3,140 of model spend for 41 confirmed findings, roughly US$77 each before human validation. The detail worth stealing is the cost distribution, where the strongest reasoning model consumed 62% of the budget while processing only 7% of the tokens. Broad coverage is cheap. Deep reasoning is not. Any pipeline that sends every event to the expensive model is paying reasoning prices for volume work.

The floor on the cheap tier keeps dropping. Cactus released Needle2, a 14MB agentic model aimed at phones and smart-home hardware, and someone has demonstrated a 28.9M-parameter model running on an $8 ESP32. For a health client who cannot send raw Entra ID or CloudTrail records to an offshore API, a local classification tier in front of a hosted deep-dive tier is now a realistic build, particularly since GPU passthrough into isolated macOS VMs for llama.cpp is documented and working. We are not running that configuration ourselves yet. We have costed it for clients where the data cannot leave the building, and it prices better than most people assume.

Logs are attacker-controlled input

Anything a model reads from a log is text an attacker may have written. Hostnames, user agents, filenames, email subjects, HTTP paths, process command lines. All of it is user-supplied, and all of it lands in your prompt.

We assume the triage model will eventually be told, by a log line, to ignore its instructions and report all clear. The defences are structural rather than clever. Log content is passed as data inside delimited fields, never concatenated into the instruction block. The model has no tools, no network access and no write permissions of any kind, so the worst case is a bad verdict rather than a bad action. Output is validated against a schema and anything unexpected escalates. Most importantly, the deterministic rules run independently of the model: impossible-travel sign-ins, MFA being disabled, a new global administrator, a stopped collector. Those fire on their own logic and cannot be talked out of it.

Every escalation lands with a person

No model verdict closes an incident. A named human reads the note and records the decision. That is a hard rule, and the reason is not squeamishness about AI. It is that an unreviewed automated verdict is not evidence you can put in front of a board, an auditor, or the OAIC after a notifiable breach, where assessment timeframes leave no room to reconstruct why nobody looked. This kind of disclosure-and-review requirement is becoming normal practice elsewhere too: Debian spent mid-2026 voting on competing proposals for how LLM-generated contributions must be disclosed and reviewed before acceptance.

For health organisations specifically, keep the boundary obvious. This pipeline reads infrastructure and identity logs. It does not touch clinical records, it makes no clinical inference, and any use that drifts towards patient data needs the human sign-off designed into the workflow from the start rather than bolted on as a disclaimer.

Honest about what it misses

The reduction in reading volume is large. Thousands of events a day compress into a page of summaries and, on a typical day, no escalations at all. That is the win, and it is a real one: the logs get read every day now instead of never.

What we cannot tell you is our false-negative rate, and neither can anyone else selling you this. We know what the model escalated. We do not know what it quietly passed over. Two things make that less uncomfortable. The deterministic rules catch the known-bad patterns regardless of what the model thinks. And once a week someone reads a random sample of "no action" verdicts against the underlying logs, which is slow and boring and the only honest check we have found.

The model is good at "this host is behaving unlike itself". It is poor at slow campaigns that stay inside the baseline, because it only sees a window at a time. If your threat model is a patient attacker, this pipeline is one layer, not the answer. Also worth publishing your prompts and review method internally rather than just the findings, the way that GlobaLeaks review did. A security committee can audit a documented process. It cannot audit a black box that says everything is fine.

PicNet builds production AI systems for Australian organisations. Talk to us about what a first project could look like.


Originally published at picnet.com.au.

Top comments (0)