Anthropic Impossible Travel Login
Detects successful Anthropic magic link or SSO sign-ins for the same user email from source IP addresses whose query-time geo-locations (via IP_LOCATION) are separated by at least 1,000 km, with implied travel faster than 800 km/h, within a 24-hour window. That pattern can indicate account sharing, VPN or proxy egress mismatches, or an adversary authenticating from a geography far from the legitimate user's baseline.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2026/09/15"
3integration = ["anthropic"]
4maturity = "production"
5min_stack_comments = "ES|QL IP_LOCATION requires 9.5.0+. FIRST/LAST aggregations and st_distance require 9.4.0+."
6min_stack_version = "9.5.0"
7updated_date = "2026/09/21"
8
9[rule]
10author = ["Elastic"]
11description = """
12Detects successful Anthropic magic link or SSO sign-ins for the same user email from source IP addresses whose
13query-time geo-locations (via IP_LOCATION) are separated by at least 1,000 km, with implied travel faster than
14800 km/h, within a 24-hour window. That pattern can indicate account sharing, VPN or proxy egress mismatches, or
15an adversary authenticating from a geography far from the legitimate user's baseline.
16"""
17false_positives = [
18 """
19 Users on VPN or proxy egress that geo-resolves through a region distant from the user's physical location. Mobile
20 clients on cellular networks that peer through regional hubs may geo-resolve differently than the user's location.
21 """,
22]
23from = "now-24h"
24interval = "1h"
25language = "esql"
26license = "Elastic License v2"
27name = "Anthropic Impossible Travel Login"
28note = """## Triage and analysis
29
30### Investigating Anthropic Impossible Travel Login
31
32Two successful magic-link or SSO sign-ins for the same `user.email` appear too far apart, too quickly, to be physical
33travel. That can be account sharing, VPN/proxy geo mismatch, or adversary authentication from a distant egress.
34
35Note: an A-B-A return to the first location may not alert (first/last coords can be close) — always sort raw Timeline
36auth events before concluding.
37
38Unauthorized / escalate when the distant IP/UA is unfamiliar, the user denies travel/VPN use, or failures / SSO
39weakening sit nearby. Close as FP when the user confirms known travel, split home/office VPN, or geo DB noise with
40matching corporate ASN/UA.
41
42#### Possible investigation steps
43
44- Read `Esql.distance_km`, `Esql.travel_kmh`, `Esql.window_minutes`, and the geo/IP value lists — high speed with a
45 country change is stronger than a same-region VPN hop.
46- Timeline-sort successful logins; compare each `source.ip`, geo, and `user_agent.original`. A browser→curl/python
47 shift on the distant hop is higher priority than two similar corporate browsers.
48- Pair with **Anthropic Multiple Authentication Failures** or SSO / magic-link second-factor changes when takeover is
49 plausible.
50- Ask the user only after geo/UA triage: expected travel or VPN egress vs unrecognized location.
51
52### False positive analysis
53
54- VPN pools and anycast/satellite geo misplacements commonly inflate implied speed — corroborate ASN and UA first.
55
56### Response and remediation
57
58- On suspected compromise: revoke sessions, reset credentials/MFA, and review admin or data-access activity after the
59 distant sign-in.
60"""
61references = [
62 "https://platform.claude.com/docs/en/api/compliance/activities/list",
63]
64risk_score = 73
65rule_id = "e89e4744-039e-4290-9835-63ea42fe531e"
66severity = "high"
67tags = [
68 "Domain: GenAI",
69 "Domain: Identity",
70 "Platform: Anthropic",
71 "Data Source: Anthropic Audit Logs",
72 "Use Case: Identity and Access Audit",
73 "Use Case: Threat Detection",
74 "Resources: Investigation Guide",
75 "Rule Type: ES|QL",
76 "Tactic: Initial Access",
77]
78timestamp_override = "event.ingested"
79type = "esql"
80
81query = '''
82from logs-anthropic.audit-*
83| where
84 data_stream.dataset == "anthropic.audit" and
85 mv_contains(event.category, "authentication") and
86 event.outcome == "success" and
87 event.action in ("magic_link_login_succeeded", "sso_login_succeeded") and
88 user.email is not null and
89 source.ip is not null
90| IP_LOCATION geo = source.ip with { "properties": ["country_name", "city_name", "location"] }
91| eval
92 Esql.source_geo_lat = st_y(geo.location),
93 Esql.source_geo_lon = st_x(geo.location)
94| where Esql.source_geo_lat is not null and Esql.source_geo_lon is not null
95| stats
96 Esql.first_lat = first(Esql.source_geo_lat, @timestamp),
97 Esql.first_lon = first(Esql.source_geo_lon, @timestamp),
98 Esql.last_lat = last(Esql.source_geo_lat, @timestamp),
99 Esql.last_lon = last(Esql.source_geo_lon, @timestamp),
100 Esql.event_count = count(*),
101 Esql.event_id_values = values(event.id),
102 Esql.event_action_values = values(event.action),
103 Esql.source_ip_values = values(source.ip),
104 Esql.source_geo_country_name_values = values(geo.country_name),
105 Esql.source_geo_city_name_values = values(geo.city_name),
106 Esql.user_agent_original_values = values(user_agent.original),
107 Esql.anthropic_audit_actor_type_values = values(anthropic.audit.actor.type),
108 Esql.timestamp_first_seen = min(@timestamp),
109 Esql.timestamp_last_seen = max(@timestamp)
110 by user.email
111| where Esql.event_count >= 2
112| eval
113 Esql.p1 = to_geopoint(concat("POINT(", to_string(Esql.first_lon), " ", to_string(Esql.first_lat), ")")),
114 Esql.p2 = to_geopoint(concat("POINT(", to_string(Esql.last_lon), " ", to_string(Esql.last_lat), ")"))
115| eval
116 Esql.distance_km = round(st_distance(Esql.p1, Esql.p2) / 1000.0, 0),
117 Esql.window_minutes = date_diff("minute", Esql.timestamp_first_seen, Esql.timestamp_last_seen),
118 Esql.travel_kmh = case(Esql.window_minutes > 0, round(Esql.distance_km * 60.0 / Esql.window_minutes, 0), null)
119| where Esql.distance_km >= 1000 and Esql.travel_kmh >= 800
120| keep user.email, Esql.*
121'''
122
123
124[[rule.threat]]
125framework = "MITRE ATT&CK"
126[[rule.threat.technique]]
127id = "T1078"
128name = "Valid Accounts"
129reference = "https://attack.mitre.org/techniques/T1078/"
130[[rule.threat.technique.subtechnique]]
131id = "T1078.004"
132name = "Cloud Accounts"
133reference = "https://attack.mitre.org/techniques/T1078/004/"
134
135
136[rule.threat.tactic]
137id = "TA0001"
138name = "Initial Access"
139reference = "https://attack.mitre.org/tactics/TA0001/"
140
141[rule.alert_suppression]
142group_by = ["user.email"]
143duration = {value = 24, unit = "h"}
144missing_fields_strategy = "suppress"
145
146[rule.investigation_fields]
147field_names = [
148 "user.email",
149 "Esql.distance_km",
150 "Esql.travel_kmh",
151 "Esql.window_minutes",
152 "Esql.event_count",
153 "Esql.event_id_values",
154 "Esql.event_action_values",
155 "Esql.source_ip_values",
156 "Esql.source_geo_country_name_values",
157 "Esql.source_geo_city_name_values",
158 "Esql.first_lat",
159 "Esql.first_lon",
160 "Esql.last_lat",
161 "Esql.last_lon",
162 "Esql.user_agent_original_values",
163 "Esql.anthropic_audit_actor_type_values",
164 "Esql.timestamp_first_seen",
165 "Esql.timestamp_last_seen",
166]
Triage and analysis
Investigating Anthropic Impossible Travel Login
Two successful magic-link or SSO sign-ins for the same user.email appear too far apart, too quickly, to be physical
travel. That can be account sharing, VPN/proxy geo mismatch, or adversary authentication from a distant egress.
Note: an A-B-A return to the first location may not alert (first/last coords can be close) — always sort raw Timeline auth events before concluding.
Unauthorized / escalate when the distant IP/UA is unfamiliar, the user denies travel/VPN use, or failures / SSO weakening sit nearby. Close as FP when the user confirms known travel, split home/office VPN, or geo DB noise with matching corporate ASN/UA.
Possible investigation steps
- Read
Esql.distance_km,Esql.travel_kmh,Esql.window_minutes, and the geo/IP value lists — high speed with a country change is stronger than a same-region VPN hop. - Timeline-sort successful logins; compare each
source.ip, geo, anduser_agent.original. A browser→curl/python shift on the distant hop is higher priority than two similar corporate browsers. - Pair with Anthropic Multiple Authentication Failures or SSO / magic-link second-factor changes when takeover is plausible.
- Ask the user only after geo/UA triage: expected travel or VPN egress vs unrecognized location.
False positive analysis
- VPN pools and anycast/satellite geo misplacements commonly inflate implied speed — corroborate ASN and UA first.
Response and remediation
- On suspected compromise: revoke sessions, reset credentials/MFA, and review admin or data-access activity after the distant sign-in.
References
Related rules
- Anthropic Session Reuse Impossible Travel
- Anthropic Magic Link Second Factor Disabled
- Anthropic Multiple Authentication Failures
- Anthropic SSO Disabled or Connection Removed
- Anthropic Admin API Key Created