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
- OpenAI ChatGPT Enterprise Impossible Travel Login
- OpenAI ChatGPT Enterprise User Activity From High Number of Countries
- OpenAI ChatGPT Enterprise Account Owner Role Assigned
- OpenAI ChatGPT Enterprise Domain Created
- OpenAI ChatGPT Enterprise Multiple Authentication Failures