Skip to main content

GlobWarden

One obfuscated pattern in, regex-based detection logic out — in five query languages.

License: Apache 2.0 Python 3.10+ CI Ruff MITRE ATT&CK T1027.010

What is this

GlobWarden reads a threat-intel report — a URL, a local PDF, raw text, a code/script file, or a screenshot — and uses an LLM (cloud or fully local) to identify command obfuscation techniques described or shown in it: the T1027.010 family of tricks (character masking, wildcard/glob-based alias resolution, string concatenation, environment-variable indirection, encoded download cradles, and similar pattern-matching-evasion techniques). For each technique it finds, it generates the matching regex — formatted for up to five query languages at once — regex, KQL, SPL, YARA-L, and Sigma — in one pass, rendered in a colorized terminal UI. Output is the matching expression itself (a bare regex line for KQL/SPL/YARA-L, just the detection: block for Sigma), not a complete standalone rule — GlobWarden expects you to drop it into your own rule structure, not ship it as one.

It exists because of a gap. Wildcard-based Get-Alias/Get-CommandInvoke-Expression resolution used to invoke a cmdlet indirectly is exactly the kind of pattern that had no name in MITRE ATT&CK until T1027.010 was written — and that gap only closes when someone sits down, reads a report by hand, and translates "here's the pattern" into "here's how you'd actually detect it." GlobWarden automates that translation as a starting point. It's a detection-engineering assistant that requires analyst review, not a certified translation engine that replaces one — say that plainly, because it's true and because overselling accuracy on a security tool is how trust gets burned.

See it run

$ globwarden scan demo --provider fake --rules regex,sigma,kql

┏━ GlobWarden ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃                                                                                              ┃
┃    ◈  G L O B W A R D E N                                                                    ┃
┃                                                                                              ┃
┃    one obfuscated pattern in — regex-based detection logic out, in five query languages      ┃
┃                                                                                              ┃
┃    T1027.010 command obfuscation  ·  v0.3.0                                                  ┃
┃                                                                                              ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ feed it a report, get detection content ━┛
    target  demo             
  provider  fake (fake-mini) 
rule types  regex, sigma, kql
────────────────────────────────────────────────────────────────────────────────────────────────
⠋ pipeline complete. ━━━━━━━━━━━━━━━━━━━━━━━━ 0:00:00

───────────────────────────────────── detected techniques ──────────────────────────────────────

╭─ [1/4] Wildcard Get-Alias Resolution to Invoke-Expression ───────────────────────────────────╮
│                                                                                              │
│      category Wildcard / Glob Resolution                                                     │
│        att&ck T1027.010 (parent: T1027)                                                      │
│    confidence ▰▰▰▰▰▰▰▰▰▱  91%                                                                │
│                                                                                              │
│               Command-line alias lookups are performed with a truncated wildcard pattern     │
│               (e.g. `Get-Alias i*x`) instead of the literal alias name, resolving to iex at  │
│               runtime and defeating substring-match detections written against the literal   │
│               string.                                                                        │
│                                                                                              │
│       example (Get-Alias i*x)[0].Definition | % { & $_ $cmd }                                │
│                                                                                              │
╰──────────────────────────────────────────────────────────────────────────────────────────────╯

    ┌─ ✓ REGEX ────────────────────────────────────────────────────────────────────────────────┐
    │                                                                                          │
    │  (?i)get-(alias|command)\s+[a-z]{1,3}\*[a-z]{0,4}\b                                      │
    │                                                                                          │
    │  Flags the characteristic tokens of this technique in command-line/script-block          │
    │  telemetry.                                                                              │
    │                                                                                          │
    └──────────────────────────────────────────────────────────────────────────────────────────┘
    ┌─ ✓ SIGMA ────────────────────────────────────────────────────────────────────────────────┐
    │                                                                                          │
    │  selection:                                                                              │
    │    CommandLine|re: (?i)get-(alias|command)\s+[a-z]{1,3}\*[a-z]{0,4}\b                    │
    │  condition: selection                                                                    │
    │                                                                                          │
    │                                                                                          │
    │  Flags the characteristic tokens of this technique in command-line/script-block          │
    │  telemetry.                                                                              │
    │                                                                                          │
    └──────────────────────────────────────────────────────────────────────────────────────────┘
    ┌─ ✓ KQL  (Microsoft Sentinel) ────────────────────────────────────────────────────────────┐
    │                                                                                          │
    │  ProcessCommandLine matches regex @"(?i)get-(alias|command)\s+[a-z]{1,3}\*[a-z]{0,4}\b"  │
    │                                                                                          │
    │  Flags the characteristic tokens of this technique in command-line/script-block          │
    │  telemetry.                                                                              │
    │                                                                                          │
    └──────────────────────────────────────────────────────────────────────────────────────────┘

    … 2 more findings, same layout (backtick-split masking, env-var-assembled cmdlet) …

╭─ [4/4] Base64-Encoded Download Cradle ───────────────────────────────────────────────────────╮
│                                                                                              │
│      category Encoded Download Cradle                                                        │
│        att&ck T1027.010 (parent: T1027), T1140 (Deobfuscate/Decode)                          │
│    confidence ▰▰▰▰▰▰▰▰▰▱  93%                                                                │
│                                                                                              │
│               A -EncodedCommand/-enc invocation carries a base64-encoded UTF-16LE payload    │
│               that downloads and executes a secondary stage, hiding the actual               │
│               download-and-execute logic from plain-text command-line scans.                 │
│                                                                                              │
│       example powershell -nop -w hidden -enc SQBFAFgAIAAoAE4AZQB3...                         │
│                                                                                              │
╰──────────────────────────────────────────────────────────────────────────────────────────────╯

    ┌─ ✗ REGEX ────────────────────────────────────────────────────────────────────────────────┐
    │                                                                                          │
    │  ⚠ VALIDATION FAILED — Pattern did not compile with Python's re module: missing ),       │
    │  unterminated subpattern at position 44 (still invalid after 2 retries)                  │
    │                                                                                          │
    │  (?i)-enc(odedcommand)?\s+[A-Za-z0-9+/=]{20,}(                                           │
    │                                                                                          │
    │  Flags the characteristic tokens of this technique in command-line/script-block          │
    │  telemetry.                                                                              │
    │                                                                                          │
    └──────────────────────────────────────────────────────────────────────────────────────────┘
    ┌─ ✓ SIGMA ────────────────────────────────────────────────────────────────────────────────┐
    │                                                                                          │
    │  selection:                                                                              │
    │    CommandLine|re: (?i)-enc(odedcommand)?\s+[A-Za-z0-9+/=]{20,}(                         │
    │  condition: selection                                                                    │
    │                                                                                          │
    │                                                                                          │
    │  Flags the characteristic tokens of this technique in command-line/script-block          │
    │  telemetry.                                                                              │
    │                                                                                          │
    └──────────────────────────────────────────────────────────────────────────────────────────┘
    ┌─ ✗ KQL  (Microsoft Sentinel) ────────────────────────────────────────────────────────────┐
    │                                                                                          │
    │  ⚠ VALIDATION FAILED — Generated content has unbalanced parentheses/braces/brackets.     │
    │  (still invalid after 2 retries)                                                         │
    │                                                                                          │
    │  ProcessCommandLine matches regex @"(?i)-enc(odedcommand)?\s+[A-Za-z0-9+/=]{20,}("       │
    │                                                                                          │
    │  Flags the characteristic tokens of this technique in command-line/script-block          │
    │  telemetry.                                                                              │
    │                                                                                          │
    └──────────────────────────────────────────────────────────────────────────────────────────┘


                 scan summary                  
╭───────────────────┬─────────────────────────╮
│ metric            │                   value │
├───────────────────┼─────────────────────────┤
│ findings          │                       4 │
│ rules generated   │                      12 │
│ passed validation │                      10 │
│ failed validation │                       2 │
│ by rule type      │ kql:4  regex:4  sigma:4 │
╰───────────────────┴─────────────────────────╯

--provider fake above is real, not a mockup — it's a network-free built-in stub (globwarden scan demo --provider fake) that reproduces this output byte-for-byte with zero setup and no API key, right now. Point it at a real provider and a real report — globwarden scan ./notes.pdf --provider openai — and the pipeline, validation, and rendering are identical; only the findings come from a real model instead of the demo stub, and generation makes one combined LLM call per finding (covering every requested format at once) rather than one call per format. And that ✗ REGEX / ✗ KQL pair above isn't a glitch left in by accident — it's the validation step doing its job: content that fails its syntactic check gets the failure reason fed back to the model for another attempt (capped at a couple of retries, so a stubborn format can't run away with your API budget), and if it's still invalid after that — as it deliberately is here, to show the path — it's shown anyway, flagged, with the real compiler/parser error and retry count attached. Nothing gets silently dropped. Notice the REGEX/SIGMA/KQL panels above are just the matching expression for each language, not a complete standalone rule — no title, no logsource, no rule id — that's deliberate: GlobWarden hands you the detection logic to drop into your own rule structure, not a finished rule file.

Quickstart

pip install globwarden

# or, with PDF/web/image ingestion support included:
pip install "globwarden[all]"

Pick any one of the five providers — cloud or fully local:

# OpenAI
export OPENAI_API_KEY="sk-..."
globwarden scan ./report.pdf --provider openai

# Anthropic
export ANTHROPIC_API_KEY="sk-ant-..."
globwarden scan ./report.pdf --provider anthropic

# Google Gemini
export GOOGLE_API_KEY="..."
globwarden scan "https://example.com/blog/campaign-writeup" --provider gemini

# Ollama — local, fully offline
ollama pull llama3.2
globwarden scan ./sample.ps1 --provider ollama

# LM Studio — local, fully offline
# (start the local server from the LM Studio app's Developer tab first)
globwarden scan ./screenshot.png --provider lmstudio

Full per-provider setup (API key details, local server install commands) lives in docs/providers.md.

CLI reference

globwarden scan <source>source is a URL, a local PDF/text/code/image path, or the literal demo for a built-in, network-free demo source.

Flag Default What it does
--provider auto-detect LLM provider: openai, anthropic, gemini, ollama, lmstudio, or fake (built-in, network-free stub for demos/testing). Omit to auto-detect the first available real provider.
--model provider default Model name/tag to use with the chosen provider.
--rules regex,kql,spl,yara-l,sigma Comma-separated rule types to generate.
--output terminal How to render results: terminal (colorized panels), json, or markdown (both print clean, scriptable output with no rich styling).
--output-file <path> stdout Write results to this file instead of stdout, in whichever --output format was chosen. terminal writes the same colorized panel layout shown on screen as plain text (box-drawing preserved, no ANSI codes) at a fixed, portable width — for a scan too long for terminal scrollback.
--api-key provider's env var Override the provider's default API key env var (OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.).
--base-url provider default Override the provider's base URL — mainly for Ollama/LM Studio or a self-hosted OpenAI-compatible endpoint.
--user-agent a standard browser UA Override the User-Agent sent for URL fetches. Some sites — security/threat-intel blogs especially — block requests that self-identify as a bot. Env var: GLOBWARDEN_USER_AGENT.
--dry-run off Ingest + detect only; skip rule generation.
-v, --verbose, --debug off Show full tracebacks and extra pipeline detail on failure.
--help Show this message and exit.

Two other commands: globwarden --version (show the installed version and exit) and globwarden providers (list every known provider and whether each is currently available/configured).

This table is checked against the CLI's real --help output by the test suite — see tests/test_cli.py::test_scan_help_documents_all_real_cli_options and test_readme_documents_all_real_cli_options — so it can't quietly drift out of sync the way a hand-maintained list normally would.

Features

  • Five input types — URL, local PDF, raw text, a code/script file, or an image, auto-detected from what you point it at.
  • One combined call, five outputs — regex, KQL, SPL, YARA-L, and Sigma matching logic generated together per finding, cross-referenced back to the technique that produced them. Output is the matching expression itself (a bare regex line, or just Sigma's detection: block), not a complete standalone rule.
  • Cloud or fully offline — OpenAI, Anthropic, and Gemini for cloud use; Ollama and LM Studio for orgs that can't send threat intel to a third-party API.
  • Vision-aware — a screenshot of a report, tweet, or slide works as a source on providers/models that support vision; embedded screenshots in a fetched web page are pulled out and analyzed too.
  • Validated output, retried until it's right, never silently dropped — every generated matching expression is checked for syntactic validity (does it compile as regex, parse as YAML, etc.); a format that fails gets the failure reason fed back to the model and another attempt, capped at a few retries so a stubborn format can't run away with your API budget. Still invalid after that, it's shown flagged with a reason — never hidden, never silently wrong.
  • Confidence + ATT&CK mapping on every finding — so you know what to double-check first, not just what the model produced.
  • Terminal output built for demos — colorized, structured rich rendering, not a wall of raw JSON — and --output-file report.txt saves that exact same layout as a clean, portable text file when a scan's too long for scrollback. --output markdown/json work with --output-file too.

How it's different

Narrow input (obfuscation TTPs specifically, not general IOC/TTP extraction), broad output (five query languages' worth of matching logic in one pass, not one), and first-class local-LLM support for orgs that can't send threat intel to a cloud API. That's the real, defensible niche — GlobWarden doesn't replace analyst review or a certified rule-translation engine, and doesn't claim to.

Worth knowing what else is out there, honestly:

  • DIANA is the closest analog — report/URL/doc text → detection logic via LLM (OpenAI/Anthropic/Groq). GlobWarden differs by fanning out to five rule languages in one pass instead of one, staying obfuscation-technique-focused rather than doing general IOC/TTP extraction, adding first-class local-LLM support, and being PDF/code-file-first rather than URL/text-first.
  • Uncoder AI / Uncoder.io (SOC Prime) is the dominant rule translation tool — Sigma/Roota into 48+ SIEM languages. It translates existing, already-written rules. GlobWarden does the step before that: reading a report that has no detection logic yet and drafting the matching expression for it. Complementary, not competing.
  • LLMCloudHunter and SigmaGen are academic/research pipelines that proved the report-to-Sigma concept works (LLMCloudHunter reports 92% precision), but neither is a maintained OSS CLI, and both target a single output format.
  • Revoke-Obfuscation, PSDecode, and CyberChef solve the other half of the problem — deobfuscating or scoring a sample you already have, not extracting techniques described in a report you're reading. Good prior art in the obfuscation-detection space generally, just a different input.

Supported rule languages

Format Targets
Regex Universal pattern matching — portable into EDR custom detections, log pipeline filters, or anywhere a plain pattern works.
KQL Kusto Query Language — Microsoft Sentinel / Defender for Endpoint hunting queries.
SPL Search Processing Language — Splunk.
YARA-L Google Security Operations (Chronicle) detection rules.
Sigma Vendor-neutral detection-as-code — convertible to dozens of SIEMs via pySigma/sigma-cli or Uncoder.io; the closest thing to a lingua franca here.

Supported providers

Provider Type Vision support Setup
OpenAI Cloud Yes (gpt-4o family) OPENAI_API_KEY
Anthropic Cloud Yes (Claude 3+; claude-opus-5 by default) ANTHROPIC_API_KEY
Google Gemini Cloud Yes (Gemini 2.0+) GOOGLE_API_KEY (or GEMINI_API_KEY)
Ollama Local Model-dependent (e.g. llama3.2-vision) ollama serve
LM Studio Local Model-dependent Local server via app's Developer tab

Full setup instructions (env vars, local install/pull commands) are in docs/providers.md.

Docs

  • docs/cli.md — full command/flag reference, kept in sync with --help and this README by the test suite.
  • docs/architecture.md — pipeline internals, module map, and the design decisions behind them.
  • docs/providers.md — detailed setup for all five LLM providers, including local server installation.

Contributing

Contributions are welcome, especially new LLM providers (the OpenAI-compatible base class makes this close to a five-line change) and new rule languages. See CONTRIBUTING.md for dev environment setup, how to run the test suite, and the PR process.

License

Apache License 2.0 — see LICENSE. Copyright (c) 2026 Tim Peck.


A wildcard Get-Alias/Get-Command trick didn't get a name until someone read a report describing it and did the translation work by hand — GlobWarden exists to make that translation faster, not to replace the read.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

globwarden-0.3.1.tar.gz (157.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

globwarden-0.3.1-py3-none-any.whl (96.7 kB view details)

Uploaded Python 3

File details

Details for the file globwarden-0.3.1.tar.gz.

File metadata

  • Download URL: globwarden-0.3.1.tar.gz
  • Upload date:
  • Size: 157.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for globwarden-0.3.1.tar.gz
Algorithm Hash digest
SHA256 5238850d98ac51fe5d10cc20a6e62a3010827ae62e5a8d8ded3261bfb6f3577d
MD5 c83d1d9d0f4407e99d986995091cbf1a
BLAKE2b-256 fe56f7c2d4d63689094bf30dbc584e760944b2063ff0fd344831809645a71faa

See more details on using hashes here.

Provenance

The following attestation bundles were made for globwarden-0.3.1.tar.gz:

Publisher: publish.yml on bobby-tablez/GlobWarden

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file globwarden-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: globwarden-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 96.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for globwarden-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 6dc1c83a15988c3066caeb842ec57fe1b21c0b38ea2f35ead808f95b56753dff
MD5 b0d1d7451f7901a4f222970fb2585f35
BLAKE2b-256 2ec8349864ff32ab9a596de26f24855554da29f54fafc66f7572d28489c3be04

See more details on using hashes here.

Provenance

The following attestation bundles were made for globwarden-0.3.1-py3-none-any.whl:

Publisher: publish.yml on bobby-tablez/GlobWarden

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.3.2

2 files

This release

0.3.1 This release

2 files

0.3.0

2 files

0.2.4

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page