BXUP Track progress & test yourself — free
Security & AI Security · Playbook · Foundation · ~4 min read
SECURITY & AI SECURITY · PLAYBOOK · FOUNDATION

Generate SIEM Queries from Plain-English Hunts

You know the hunt you want to run; you just do not want to hand-write the KQL or SPL for it. LLMs are strong at query generation and terrible at knowing your schema — they will confidently reference a field that does not exist in your index.

Tier: Foundation · Workflow area: AI-assisted SOC & detection

This playbook turns a plain-English hunt into a runnable SIEM query, with a validation loop that rejects hallucinated fields before they waste a search cycle.

When to reach for this

  • You have a clear hunt hypothesis ("logons from service accounts outside business hours") but not the exact query dialect fresh in your head.
  • You are switching between SIEMs and keep confusing KQL and SPL syntax.
  • You are building a library of reusable hunt queries against a known schema.

Skip AI for a one-field filter change to a query you already have open — editing is faster than reviewing a regenerated search.

The workflow

  1. Give the model your schema, not just your hunt. The single biggest quality lever is pasting the table/index name and its real field list. Without it, the model invents SourceIP when your schema says src_ip.

    Write a Microsoft Sentinel KQL query for this hunt against sample data.
    
    Hunt: interactive logons by accounts named like service accounts
    (starting "svc_") outside 08:00-20:00 IST, in the last 24h.
    
    Table: SigninLogs
    Available fields: TimeGenerated, UserPrincipalName, ResultType,
    AppDisplayName, IPAddress, ClientAppUsed, Location.
    
    Rules: use only fields I listed. If the hunt needs a field I did not
    provide, stop and tell me which field is missing instead of inventing one.
    Add a comment above each clause explaining what it filters.
    

    Expected output: a commented KQL query using only your listed fields, or an explicit "I need a field for logon-type that you did not provide" — both are useful answers.

  2. Read the WHERE/where clauses before you run. Confirm each referenced field is in your schema and each literal (time window, account prefix) matches your intent. The comments the model wrote make this a 30-second read.

  3. Run against sample data first. Execute in your community-edition SIEM against a bounded, non-production index. A query that returns zero rows on data you know contains matches is a logic bug — usually an over-tight time filter or a wrong operator (== vs has).

  4. Sanity-check the row count. A hunt that returns millions of rows or zero rows is almost always wrong. Ask the model to explain: "This returned 0 rows but I expect ~50; what clause is too strict?" and fix the named clause only.

  5. Save the validated query with its schema note. Store the query alongside the schema version it was written against, so the next person knows why it references those exact fields.

Pro Tip

Paste the field list every single time. A model that guessed your schema correctly last week will guess differently this week — grounding it in the real fields is cheaper than debugging a silent mismatch.

Verify before you trust it

  • Hallucinated-field rejection: diff every field the query references against your actual schema (.getschema in KQL, | fieldsummary in SPL). One unknown field means the model reasoned from an imagined table — reject and re-prompt with a tighter field list.
  • Operator check: confirm string matches use the intended operator. UserPrincipalName == "svc" matches nothing; startswith "svc_" is what the hunt meant. Models mix these up constantly.
  • False-positive catch: run the query against a known-benign window and confirm it does not light up on sanctioned service-account activity you already expect. If it does, add the exclusion and note why.

Pitfalls

  • Invented fields and functions. The top failure mode: plausible-looking parse_json() or Computer fields that your schema does not have. The schema diff is non-negotiable.
  • Wrong time semantics. Models default to UTC and to ago(24h) regardless of your stated timezone or business hours. Re-read every time clause against your intent.
  • Silent zero-result queries. A syntactically valid query that returns nothing looks like "no threats" but usually means a logic error. Always test against data you know contains hits.
  • Over-broad hunts. Left loose, a generated query scans every index and every field — slow and expensive. Constrain the table and time window in the prompt.

Tools

  • SIEM query language (Sentinel KQL, Splunk SPL, Elastic ES|QL): the target dialect the model writes and you validate against.
  • SIEM community edition (Splunk Free, Elastic, Wazuh): the sandbox where you run generated queries against sample data before they touch production.
  • Open LLM run locally (Ollama + a code-capable model): generates the query without sending your schema to a third-party endpoint.

Client-safe variant

Client schemas are themselves sensitive — field names can reveal architecture. In a services engagement, run the generation on a local Ollama model or the client's approved AI endpoint, and hand the model a generalized schema: keep the field names it needs to write correct syntax, but strip anything identifying (index names, client-specific prefixes) to placeholders. Validate exclusively against the client's sample or lab indices, never their production data, and store the query inside the client's own repository so the schema note travels with it. The query logic is portable; the identifiers stay behind the client boundary.

This is the free reading view. Open BXUP to track your progress, run the hands-on labs, and prove it with original, exam-pattern assessments.
© Anvi Innovate · BXUP — Be Exponentially Upskilled · BXUP is an independent learning platform, not affiliated with or endorsed by AWS, Microsoft, Google, NVIDIA, IBM, Salesforce, Databricks, Oracle or Anthropic. All trademarks belong to their respective owners. · bxup.in