OpenAI ChatGPT Enterprise User Activity From High Number of Countries


Description

Detects ChatGPT Enterprise activity for the same user email from at least three countries and two unique user agents within a four-hour interval across any compliance data stream. Stolen session cookies often produce post-auth activity (conversation views, deletions, downloads) without a new login event, so this rule is not limited to authentication logs.

Query · esql

from logs-openai_chatgpt_enterprise.*
| where
    user.email is not null and
    source.ip is not null and
    source.geo.country_iso_code is not null
| stats
    Esql.country_count = count_distinct(source.geo.country_iso_code),
    Esql.region_count = count_distinct(source.geo.region_name),
    Esql.source_ip_count = count_distinct(source.ip),
    Esql.user_agent_count = count_distinct(user_agent.original),
    Esql.event_count = count(*),
    Esql.event_action_values = values(event.action),
    Esql.source_ip_values = values(source.ip),
    Esql.source_geo_country_iso_code_values = values(source.geo.country_iso_code),
    Esql.source_geo_region_name_values = values(source.geo.region_name),
    Esql.source_geo_city_name_values = values(source.geo.city_name),
    Esql.user_agent_original_values = values(user_agent.original),
    Esql.timestamp_first_seen = min(@timestamp),
    Esql.timestamp_last_seen = max(@timestamp)
  by user.email
| where Esql.country_count >= 3 and Esql.user_agent_count >= 2
| keep user.email, Esql.*

Investigation fields

Pivot points the source recommends for triage.

  • user.email
  • Esql.country_count
  • Esql.source_ip_count
  • Esql.user_agent_count
  • Esql.event_count
  • Esql.event_action_values
  • Esql.source_ip_values
  • Esql.source_geo_country_iso_code_values
  • Esql.source_geo_region_name_values
  • Esql.region_count
  • Esql.user_agent_original_values
  • Esql.timestamp_first_seen
  • Esql.timestamp_last_seen

Implementation guide

This rule requires the OpenAI ChatGPT Enterprise integration to collect compliance logs into Elasticsearch.

https://www.elastic.co/docs/reference/integrations/openai_chatgpt_enterprise

Known false positives

  • Users on VPN or proxy egress that geo-resolves through multiple regions in a short window.
  • Cloud egress, split-tunnel, or dual-homed clients that present different public IPs for concurrent sessions.

Analyst notes

Investigating OpenAI ChatGPT Enterprise User Activity From High Number of Countries

Activity for the same email spans multiple countries and user agents in a short window across ChatGPT Enterprise compliance streams. That pattern can indicate session reuse, token abuse, or shared-account access through distant egress points, including cases where no new authentication event is logged.

Escalate when countries and user agents diverge sharply, the user denies travel or VPN use, or privileged actions appear on distant IPs. Close as a false positive for documented dual-homed VPN or cloud egress with consistent corporate clients.

Possible investigation steps

  • Review Esql.source_geo_country_iso_code_values, Esql.source_geo_region_name_values, and Esql.user_agent_original_values.
  • Compare source IPs and timestamps (Esql.timestamp_first_seen, Esql.timestamp_last_seen) for physical travel feasibility.
  • Check for privileged audit actions, downloads, or shares from the distant IPs.
  • Contact the user only after geo and user-agent triage to confirm expected VPN or travel.

False positive analysis

  • Split-tunnel, dual-homed, or VPN egress that geo-resolves through multiple regions is the most common false positive. Corroborate with ASN and user-agent consistency before escalating.

Response and remediation

  • On suspected compromise: force logout, revoke sessions, reset credentials and MFA, and review role changes or exports for the same email after the distant activity.
Raw source OpenAI ChatGPT Enterprise User Activity From High Number of Countries · Elastic TOML
Esc
Published by elastic/detection-rules ↗, licensed under Elastic License 2.0 ↗. Reproduced here unmodified.
[metadata]
creation_date = "2026/10/06"
integration = ["openai_chatgpt_enterprise"]
maturity = "production"
updated_date = "2026/10/06"

[rule]
author = ["Elastic"]
description = """
Detects ChatGPT Enterprise activity for the same user email from at least three countries and two unique user agents
within a four-hour interval across any compliance data stream. Stolen session cookies often produce post-auth activity
(conversation views, deletions, downloads) without a new login event, so this rule is not limited to authentication
logs.
"""
false_positives = [
    "Users on VPN or proxy egress that geo-resolves through multiple regions in a short window.",
    "Cloud egress, split-tunnel, or dual-homed clients that present different public IPs for concurrent sessions.",
]
from = "now-4h"
interval = "5m"
language = "esql"
license = "Elastic License v2"
name = "OpenAI ChatGPT Enterprise User Activity From High Number of Countries"
note = """## Triage and analysis

### Investigating OpenAI ChatGPT Enterprise User Activity From High Number of Countries

Activity for the same email spans multiple countries and user agents in a short window across ChatGPT Enterprise compliance streams. That pattern can indicate session reuse, token abuse, or shared-account access through distant egress points, including cases where no new authentication event is logged.

Escalate when countries and user agents diverge sharply, the user denies travel or VPN use, or privileged actions appear on distant IPs. Close as a false positive for documented dual-homed VPN or cloud egress with consistent corporate clients.

#### Possible investigation steps

- Review `Esql.source_geo_country_iso_code_values`, `Esql.source_geo_region_name_values`, and `Esql.user_agent_original_values`.
- Compare source IPs and timestamps (`Esql.timestamp_first_seen`, `Esql.timestamp_last_seen`) for physical travel feasibility.
- Check for privileged audit actions, downloads, or shares from the distant IPs.
- Contact the user only after geo and user-agent triage to confirm expected VPN or travel.

### False positive analysis

- Split-tunnel, dual-homed, or VPN egress that geo-resolves through multiple regions is the most common false positive. Corroborate with ASN and user-agent consistency before escalating.

### Response and remediation

- On suspected compromise: force logout, revoke sessions, reset credentials and MFA, and review role changes or exports for the same email after the distant activity.
"""
references = [
    "https://www.elastic.co/docs/reference/integrations/openai_chatgpt_enterprise",
    "https://platform.openai.com/docs/compliance",
]
risk_score = 99
rule_id = "d7e01c19-4463-4693-bd98-451875737fc8"
setup = """## Setup

This rule requires the OpenAI ChatGPT Enterprise integration to collect compliance logs into Elasticsearch.

https://www.elastic.co/docs/reference/integrations/openai_chatgpt_enterprise
"""
severity = "critical"
tags = [
    "Domain: GenAI",
    "Platform: OpenAI",
    "Data Source: OpenAI ChatGPT Enterprise",
    "Service: OpenAI ChatGPT Enterprise",
    "Use Case: Threat Detection",
    "Resources: Investigation Guide",
    "Rule Type: ES|QL",
    "Domain: Identity",
    "Use Case: Identity and Access Audit",
    "Tactic: Credential Access",
    "Tactic: Initial Access",
    "Mitre Atlas: AML.T0012",
    "Threat: Impossible Travel",
]
timestamp_override = "event.ingested"
type = "esql"

query = '''
from logs-openai_chatgpt_enterprise.*
| where
    user.email is not null and
    source.ip is not null and
    source.geo.country_iso_code is not null
| stats
    Esql.country_count = count_distinct(source.geo.country_iso_code),
    Esql.region_count = count_distinct(source.geo.region_name),
    Esql.source_ip_count = count_distinct(source.ip),
    Esql.user_agent_count = count_distinct(user_agent.original),
    Esql.event_count = count(*),
    Esql.event_action_values = values(event.action),
    Esql.source_ip_values = values(source.ip),
    Esql.source_geo_country_iso_code_values = values(source.geo.country_iso_code),
    Esql.source_geo_region_name_values = values(source.geo.region_name),
    Esql.source_geo_city_name_values = values(source.geo.city_name),
    Esql.user_agent_original_values = values(user_agent.original),
    Esql.timestamp_first_seen = min(@timestamp),
    Esql.timestamp_last_seen = max(@timestamp)
  by user.email
| where Esql.country_count >= 3 and Esql.user_agent_count >= 2
| keep user.email, Esql.*
'''


[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1539"
name = "Steal Web Session Cookie"
reference = "https://attack.mitre.org/techniques/T1539/"


[rule.threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"

[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1078"
name = "Valid Accounts"
reference = "https://attack.mitre.org/techniques/T1078/"
[[rule.threat.technique.subtechnique]]
id = "T1078.004"
name = "Cloud Accounts"
reference = "https://attack.mitre.org/techniques/T1078/004/"


[rule.threat.tactic]
id = "TA0001"
name = "Initial Access"
reference = "https://attack.mitre.org/tactics/TA0001/"

[[rule.threat_mappings]]
framework = "MITRE ATLAS"
version = "2026.08"
[[rule.threat_mappings.threat]]
framework = "MITRE ATLAS"
[[rule.threat_mappings.threat.technique]]
id = "AML.T0012"
name = "Valid Accounts"
reference = "https://atlas.mitre.org/techniques/AML.T0012/"


[rule.threat_mappings.threat.tactic]
id = "AML.TA0004"
name = "Initial Access"
reference = "https://atlas.mitre.org/tactics/AML.TA0004/"

[rule.alert_suppression]
group_by = ["user.email"]
missing_fields_strategy = "suppress"

[rule.alert_suppression.duration]
unit = "h"
value = 4

[rule.investigation_fields]
field_names = [
    "user.email",
    "Esql.country_count",
    "Esql.source_ip_count",
    "Esql.user_agent_count",
    "Esql.event_count",
    "Esql.event_action_values",
    "Esql.source_ip_values",
    "Esql.source_geo_country_iso_code_values",
    "Esql.source_geo_region_name_values",
    "Esql.region_count",
    "Esql.user_agent_original_values",
    "Esql.timestamp_first_seen",
    "Esql.timestamp_last_seen",
]

Detection rules belong to the projects that publish them and remain under their own licenses. This site indexes and links to them; it claims no rights in them.