Skip to content

soc-ai 1.5.3

soc-ai 1.5.3 is the detection ladder release. Cheaper detection steps now run before the model investigation. Each run records its cost. The Hosts list shows one row per machine. A hunt investigates its own findings. Each count in the console states its scope. The full list is in CHANGELOG.md under 1.5.3.

Detection ladder

Every triage run, hunt and lead hunt stores its model requests, tokens, tool calls, searches and wall time. soc-ai usage --days N prints the cost per entry point. On one grid, 2,051 scheduled triage runs in 30 days used 163.4 million tokens for one true positive.

Each run has a budget class. A cheap run is one synthesis request with no loop and no Oracle. The scheduler uses it only when a dispositive template cleared the alert. A standard run is the investigation loop with the prompt sections and tools that the alert needs. A deep run has every tool. An Investigate click, a re-run and a bulk selection always run the loop.

The rule prior gives a scheduled alert the verdict of the latest model run on its rule. Six safeguards must hold. rule_prior_mode takes off, shadow or live, and the default is shadow. In shadow mode, the model runs as before, and soc-ai records what the prior would decide. A rule-prior run never acknowledges an alert in Security Onion.

The prior sweep tests a rate departure hour by hour against the same hour of the week. A burst of one to four hours now moves the test. A new member that fewer than 3 hosts in the estate know forms an observation at weight 0.6. A new member that more than 20 % of the profiled hosts know forms none. Each observation stores its statistic, the baseline, up to 10 document ids and an OQL query.

The estate model learns peer groups and scores each host against the estate. It is off by default, and it writes shadow observations only. An estate_outlier observation names the top three features, with the value of the host and the median of its peers. The run refuses a model file whose sha256 the store does not record. At 20,000 hosts, the fit takes 8.8 s.

Analytics

A spec file can declare ships_as: shadow, a daily hit limit and a minimum precision. Such an analytic starts in shadow, and the analyst approves it to live. After each sweep, soc-ai checks each live analytic against its limits. A breach moves the analytic back to shadow with the numbers as evidence. soc-ai never approves an analytic to live and never retires one. The setting analytic_self_heal_enabled controls the check.

A third evaluator, model, runs learned detectors in the hourly profile sweep. Two detectors ship in shadow. model-cross-plane-silence fires when one telemetry plane of a machine stops sending documents and another plane keeps its expected count. model-logon-chain fires on a first logon to a host outside the learned edge set within 15 minutes of an inbound session.

Three match analytics replace three role priors. Each prior tested a different fact from the one its title stated. On a test network, the Defender prior missed all 10 Defender detections. The new analytics read Defender events 1116 and 1117, event 4719 and the group events 4728, 4732 and 4756. docs/HUNTING.md maps each old id to its new id.

Oracle

oracle_rule_mode selects the rule that sends a verdict to the Oracle: classic, shadow or uncertainty. The default shadow keeps the classic rule and records what the uncertainty rule would send. The uncertainty rule sends a verdict with a confidence from 0.4 to below 0.7. It also sends a verdict where the decision template and the model disagree. A deep run that ends with needs more info goes to the Oracle too.

An Oracle verdict changes the local verdict only when the Oracle cites evidence. On one grid, 6 answers changed needs more info to false positive with no evidence. After a usage limit, the Oracle route pauses until the reset time. notify_on_oracle_failure reports each pause.

Hosts

The Hosts list shows one row per machine. The old list showed one row per address. On one grid, one proxy had 14 rows. The dossier sweep groups the addresses into machines by five rules: agent, bridge and container, DHCP lease, unique short name and single address. Search reads every name, address, MAC, OS, role and agent name. The sweep reads the DHCP leases of Security Onion 3.x. An address unseen for dossier_stale_address_days leaves the census. The host page lists every open lead on the host first, then the alert verdicts of the last 7 days. The entity page states the type of a user, a domain or an address. It counts the open leads that name the value.

Scale and the store

A synthetic estate of 20,000 hosts ran through the sweeps. The profile build reads every host in batches of 500, and profile_build_workers caps the batches in flight. The census reads past 10,000 addresses. The machine clustering took 102 seconds at 20,000 hosts. It now takes about 1 s.

soc-ai can keep the store in PostgreSQL. Set SOC_AI_DATABASE_URL to a postgresql+asyncpg:// URL. SQLite stays the default. soc-ai store migrate --to <url> copies a store into an empty store. Back up a PostgreSQL store with pg_dump. The SQLite store files now have mode 0600.

Hunts and leads

A hunt opens one investigation for each finding that names an entity. Two investigations run at a time, the highest severity first. The hunt then states its result, for example "2 of 3 findings are threats". When every finding of a lead hunt has a verdict, the lead closes as promoted. hunt_findings_investigate_max caps the investigations of one hunt.

A hunt closes a lead only after it reads its evidence. A hunt with a visibility gap or a failed tool call keeps the lead open under "Needs decision". The lead offers one verb, "Hunt this lead". The analyst can mark a hit benign.

A backtest replay writes no observation, forms no lead and writes nothing to Security Onion. Before this change, an inherited false positive from a replay could acknowledge a live alert. The Investigations list hides replays by default.

Console

One Ask soc-ai panel replaces the chat bubbles and the Dashboard chat panel. The key c opens it. A flow strip under the page header names each step of the flow and its state. The peer diagram, the hunt map and the investigation graph use React Flow 12.12.0. No label overlaps another. The chips of a row sit in one Tags column. The console shows each title in full, with no ellipsis.

The Dashboard panels move and resize. soc-ai keeps one layout for each user account. The Needs-you tile counts five parts: leads, unread shadow hits, alert groups with no verdict, verdicts that need more info and pending actions. The tile that it replaces said "queue clear" while 11 leads waited. On the investigation page, the acknowledge card states its scope before the click.

Alert verdicts and the bell

The runs inside the page window decide the verdict of an alert group. The worst verdict of those runs counts. One rule held one true positive and five later false positives, and the Dashboard breakdown read "True positive 0". The old counts also reached back seven days past a 24-hour window. A group with no run in the window keeps its older verdict. The Alerts row marks that verdict "inherited" with its age. The Dashboard breakdown states how many groups that applies to. The Alerts verdict filter and the verdict sort read the same verdict. GET /api/v1/alerts adds windowVerdict, windowConf, windowInvId and verdictAt. verdictCounts, worstVerdict, worstConf and worstInvId now read the runs of the window only.

The bell panel accounts for every unit of its badge. A badge read 309 while the panel listed 12 rows. A "Needs you" block now states each part of the count with its scope, and the parts add up to the badge. Show more loads 20 more rows. Dismiss all replaces Clear all. It hides the events and marks the unread shadow hits as read, with an audit record. The server marks no hit when new hits arrived after the count. Leads, alert groups with no verdict, verdicts that need more info and recommended actions stay. They are decisions.

The time filter of a page filters everything on it. A count that the filter does not change states its scope in words, for example "all open" or "last 7 days".

Security

The lock moves pydantic-ai-slim and pydantic-graph to 1.107.7. The new version closes PYSEC-2026-4283 to PYSEC-2026-4291.

Upgrade

  1. Back up the store with soc-ai backup. Migrations run at start. soc-ai has no schema downgrade.
  2. Docker: run SOC_AI_IMAGE_TAG=1.5.3 docker compose pull soc-ai && docker compose up -d. The image includes the ml extra for the estate model.
  3. Source install: run uv sync, with --extra ml for the estate model. Copy scripts/systemd/soc-ai.service over the unit. Run systemctl daemon-reload and restart soc-ai.
  4. Migrations 0053 to 0063 run at the first start. 0053 backfills the lead decision list and clears stale dismissals. 0055 clears the rebound stamps on addresses with no declaration. The other migrations add tables and columns.
  5. Let the first dossier sweep run. It groups the addresses into machines and rebuilds the profiles. A rate baseline from an older build is blind until then.
  6. Read the defaults. rule_prior_mode and oracle_rule_mode are shadow. Read a week of shadow records before you switch either one. estate_model_enabled is off.