Detection rules › Elastic
Ollama DNS Query to Untrusted Domain
Detects Ollama DNS queries to domains outside official infrastructure. Adversaries can redirect Ollama to pull models from attacker-controlled servers via OLLAMA_HOST or custom manifests. Malicious models may contain backdoors, exploit parsing vulnerabilities like CVE-2025-1975, or poison inference outputs.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Initial Access | T1195.001 Supply Chain Compromise: Compromise Software Dependencies and Development Tools, T1195.002 Supply Chain Compromise: Compromise Software Supply Chain |
| Command & Control | T1105 Ingress Tool Transfer |
MITRE ATLAS coverage
Adversarial-ML threat framework (not MITRE ATT&CK).
| Tactic | Techniques |
|---|---|
| Initial Access | AML.T0010.003 AI Supply Chain Compromise: Model |
Rule body elastic
[metadata]
creation_date = "2026/01/09"
integration = ["endpoint"]
maturity = "production"
updated_date = "2026/03/24"
[rule]
author = ["Elastic"]
building_block_type = "default"
description = """
Detects Ollama DNS queries to domains outside official infrastructure. Adversaries can redirect Ollama to pull models
from attacker-controlled servers via OLLAMA_HOST or custom manifests. Malicious models may contain backdoors, exploit
parsing vulnerabilities like CVE-2025-1975, or poison inference outputs.
"""
from = "now-119m"
index = ["logs-endpoint.events.network-*"]
interval = "60m"
language = "eql"
license = "Elastic License v2"
name = "Ollama DNS Query to Untrusted Domain"
references = [
"https://www.greynoise.io/blog/threat-actors-actively-targeting-llms",
"https://atlas.mitre.org/techniques/AML.T0010.003",
"https://nvd.nist.gov/vuln/detail/CVE-2025-1975",
]
risk_score = 21
rule_id = "e9a3b2c1-d4f5-6789-0abc-def123456789"
severity = "low"
tags = [
"Domain: Endpoint",
"OS: Linux",
"OS: macOS",
"OS: Windows",
"Use Case: Threat Detection",
"Tactic: Command and Control",
"Data Source: Elastic Defend",
"Domain: LLM",
"Mitre Atlas: T0010.003",
"Rule Type: BBR",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
network where event.action == "lookup_requested" and
process.name in ("ollama", "ollama.exe") and
dns.question.name != null and
not dns.question.name : (
"ollama.ai", "*.ollama.ai", "ollama.com", "*.ollama.com",
"github.com", "*.github.com", "*.githubusercontent.com",
"*.r2.cloudflarestorage.com", "*.cloudflare.com", "*.cloudflarestorage.com",
"localhost", "*.local", "*.internal", "*.localdomain"
)
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1105"
name = "Ingress Tool Transfer"
reference = "https://attack.mitre.org/techniques/T1105/"
[rule.threat.tactic]
id = "TA0011"
name = "Command and Control"
reference = "https://attack.mitre.org/tactics/TA0011/"
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1195"
name = "Supply Chain Compromise"
reference = "https://attack.mitre.org/techniques/T1195/"
[[rule.threat.technique.subtechnique]]
id = "T1195.001"
name = "Compromise Software Dependencies and Development Tools"
reference = "https://attack.mitre.org/techniques/T1195/001/"
[[rule.threat.technique.subtechnique]]
id = "T1195.002"
name = "Compromise Software Supply Chain"
reference = "https://attack.mitre.org/techniques/T1195/002/"
[rule.threat.tactic]
id = "TA0001"
name = "Initial Access"
reference = "https://attack.mitre.org/tactics/TA0001/"
Stages and Predicates
Stage 1: network
network where event.action == "lookup_requested" and
process.name in ("ollama", "ollama.exe") and
dns.question.name != null and
not dns.question.name : (
"ollama.ai", "*.ollama.ai", "ollama.com", "*.ollama.com",
"github.com", "*.github.com", "*.githubusercontent.com",
"*.r2.cloudflarestorage.com", "*.cloudflare.com", "*.cloudflarestorage.com",
"localhost", "*.local", "*.internal", "*.localdomain"
)
Exclusions
Top-level NOT(...) conjuncts: predicates this rule actively suppresses.
| Field | Kind | Excluded values |
|---|---|---|
dns.question.name | wildcard | ollama.ai, *.ollama.ai, ollama.com, *.ollama.com, github.com, *.github.com, *.githubusercontent.com, *.r2.cloudflarestorage.com, *.cloudflare.com, *.cloudflarestorage.com, localhost, *.local, *.internal, *.localdomain |
Indicators
Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.
| Field | Kind | Values |
|---|---|---|
dns.question.name | is_not_null | |
event.action | eq |
|
process.name | in |
|