OpenAI ChatGPT Enterprise Authentication from a Suspicious User Agent

Detects successful ChatGPT Enterprise authentication events where the user agent looks scripted (for example Python, curl, Go HTTP clients, aiohttp, scrapers, or headless browsers) rather than a normal browser. Adversaries and automation often reuse stolen sessions or tokens with non-browser clients.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2026/10/06"
  3integration = ["openai_chatgpt_enterprise"]
  4maturity = "production"
  5updated_date = "2026/10/09"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10Detects successful ChatGPT Enterprise authentication events where the user agent looks scripted (for example Python,
 11curl, Go HTTP clients, aiohttp, scrapers, or headless browsers) rather than a normal browser. Adversaries and automation
 12often reuse stolen sessions or tokens with non-browser clients.
 13"""
 14false_positives = ["Approved automation, compliance API tooling, or SSO libraries that use non-browser user agents."]
 15from = "now-9m"
 16language = "esql"
 17license = "Elastic License v2"
 18name = "OpenAI ChatGPT Enterprise Authentication from a Suspicious User Agent"
 19note = """## Triage and analysis
 20
 21### Investigating OpenAI ChatGPT Enterprise Authentication from a Suspicious User Agent
 22
 23A successful authentication event used a scripted user agent (for example Python, curl, Go HTTP clients, or similar) rather than a typical browser.
 24
 25Escalate when the user has no approved CLI or API access, the user agent is unfamiliar, or privileged activity follows the sign-in. Close as a false positive for documented automation, compliance collectors, or SSO libraries that use non-browser clients.
 26
 27#### Possible investigation steps
 28
 29- Confirm `user_agent.original`, `source.ip`, `source.geo.country_iso_code`, and the authenticated user.
 30- Determine whether the account is expected to use CLI, API, or compliance automation.
 31- Search for role changes, file downloads, conversation shares, or admin actions from the same user shortly after the event.
 32- Compare with the user's normal browser-based authentication history.
 33
 34### False positive analysis
 35
 36- Approved automation, compliance API tooling, and some SSO client libraries use non-browser user agents by design.
 37
 38### Response and remediation
 39
 40- Revoke sessions for the user, rotate credentials where appropriate, and inventory automation that uses that user agent.
 41- If takeover is suspected, review subsequent data-access and admin activity for the same account.
 42"""
 43references = [
 44    "https://www.elastic.co/docs/reference/integrations/openai_chatgpt_enterprise",
 45    "https://platform.openai.com/docs/compliance",
 46]
 47risk_score = 47
 48rule_id = "c461f0cf-54df-4e93-bb05-076ea22fe84b"
 49setup = """## Setup
 50
 51This rule requires the OpenAI ChatGPT Enterprise integration to collect compliance logs into Elasticsearch.
 52
 53https://www.elastic.co/docs/reference/integrations/openai_chatgpt_enterprise
 54"""
 55severity = "medium"
 56tags = [
 57    "Domain: GenAI",
 58    "Platform: OpenAI",
 59    "Data Source: OpenAI ChatGPT Enterprise",
 60    "Service: OpenAI ChatGPT Enterprise",
 61    "Use Case: Threat Detection",
 62    "Resources: Investigation Guide",
 63    "Rule Type: ES|QL",
 64    "Domain: Identity",
 65    "Tactic: Initial Access",
 66    "Mitre Atlas: AML.T0012",
 67]
 68timestamp_override = "event.ingested"
 69type = "esql"
 70
 71query = '''
 72from logs-openai_chatgpt_enterprise.auth_log-* metadata _id, _version, _index
 73| where
 74    data_stream.dataset == "openai_chatgpt_enterprise.auth_log" and
 75    event.action in ("login_success", "native_login_success", "token_issued") and
 76    user_agent.original is not null and
 77    (
 78        to_lower(user_agent.original) like "*python*" or
 79        to_lower(user_agent.original) like "*curl/*" or
 80        to_lower(user_agent.original) like "*wget*" or
 81        to_lower(user_agent.original) like "*httpie*" or
 82        to_lower(user_agent.original) like "*go-http*" or
 83        to_lower(user_agent.original) like "*aiohttp*" or
 84        to_lower(user_agent.original) like "*fasthttp*" or
 85        to_lower(user_agent.original) like "*httpclient*" or
 86        to_lower(user_agent.original) like "*postmanruntime*" or
 87        to_lower(user_agent.original) like "*headlesschrome*" or
 88        to_lower(user_agent.original) like "*phantomjs*" or
 89        to_lower(user_agent.original) like "*selenium*" or
 90        to_lower(user_agent.original) like "*okhttp*" or
 91        to_lower(user_agent.original) like "*scrapy*" or
 92        to_lower(user_agent.original) like "*hydra*" or
 93        to_lower(user_agent.original) like "*patator*" or
 94        to_lower(user_agent.original) like "*metasploit*" or
 95        to_lower(user_agent.original) like "*curio*" or
 96        to_lower(user_agent.original) like "*hyper*" or
 97        to_lower(user_agent.original) like "*kali*" or
 98        to_lower(user_agent.original) like "ruby*" or
 99        to_lower(user_agent.original) like "node*" or
100        to_lower(user_agent.original) like "undici*" or
101        to_lower(user_agent.original) like "java*" or
102        to_lower(user_agent.original) like "php*" or
103        to_lower(user_agent.original) like "*bun/*" or
104        to_lower(user_agent.original) like "*axios*"
105    )
106| keep _id, _version, _index, @timestamp, event.action, event.outcome, user.email, user.id, source.ip, source.geo.country_iso_code, user_agent.original, data_stream.*
107'''
108
109
110[[rule.threat]]
111framework = "MITRE ATT&CK"
112[[rule.threat.technique]]
113id = "T1078"
114name = "Valid Accounts"
115reference = "https://attack.mitre.org/techniques/T1078/"
116[[rule.threat.technique.subtechnique]]
117id = "T1078.004"
118name = "Cloud Accounts"
119reference = "https://attack.mitre.org/techniques/T1078/004/"
120
121
122
123[rule.threat.tactic]
124id = "TA0001"
125name = "Initial Access"
126reference = "https://attack.mitre.org/tactics/TA0001/"
127[[rule.threat_mappings]]
128framework = "MITRE ATLAS"
129version = "2026.08"
130[[rule.threat_mappings.threat]]
131framework = "MITRE ATLAS"
132[[rule.threat_mappings.threat.technique]]
133id = "AML.T0012"
134name = "Valid Accounts"
135reference = "https://atlas.mitre.org/techniques/AML.T0012/"
136
137
138[rule.threat_mappings.threat.tactic]
139id = "AML.TA0004"
140name = "Initial Access"
141reference = "https://atlas.mitre.org/tactics/AML.TA0004/"
142
143[rule.investigation_fields]
144field_names = [
145    "@timestamp",
146    "event.action",
147    "user.email",
148    "user.id",
149    "source.ip",
150    "source.geo.country_iso_code",
151    "user_agent.original",
152]

Triage and analysis

Investigating OpenAI ChatGPT Enterprise Authentication from a Suspicious User Agent

A successful authentication event used a scripted user agent (for example Python, curl, Go HTTP clients, or similar) rather than a typical browser.

Escalate when the user has no approved CLI or API access, the user agent is unfamiliar, or privileged activity follows the sign-in. Close as a false positive for documented automation, compliance collectors, or SSO libraries that use non-browser clients.

Possible investigation steps

  • Confirm user_agent.original, source.ip, source.geo.country_iso_code, and the authenticated user.
  • Determine whether the account is expected to use CLI, API, or compliance automation.
  • Search for role changes, file downloads, conversation shares, or admin actions from the same user shortly after the event.
  • Compare with the user's normal browser-based authentication history.

False positive analysis

  • Approved automation, compliance API tooling, and some SSO client libraries use non-browser user agents by design.

Response and remediation

  • Revoke sessions for the user, rotate credentials where appropriate, and inventory automation that uses that user agent.
  • If takeover is suspected, review subsequent data-access and admin activity for the same account.

References

Related rules

to-top