EXPLORE
← Back to Explore
elasticmediumTTP

Anthropic Admin API Key Created

Admin API keys grant programmatic access to organization and compliance APIs outside an interactive browser session. An attacker who creates one after compromise can automate role grants, exports, and logging changes without holding a user session that would time out under SSO. The key also survives password resets and IdP lockout if defenders revoke the interactive account but miss the API credential.

MITRE ATT&CK

persistence

Detection Query

from logs-anthropic.audit-* metadata _id, _version, _index
| where
    data_stream.dataset == "anthropic.audit" and
    mv_contains(event.category, "iam") and
    event.action == "admin_api_key_created"
| keep _id, _version, _index, @timestamp, event.*, organization.*, user.*, source.*, user_agent.*, anthropic.audit.*, data_stream.*

Author

Elastic

Created

2026/09/12

Data Sources

Anthropic Audit Logs

Tags

Domain: GenAIPlatform: AnthropicData Source: Anthropic Audit LogsUse Case: Identity and Access AuditUse Case: Threat DetectionResources: Investigation GuideRule Type: ES|QLTactic: Persistence
Raw Content
[metadata]
creation_date = "2026/09/12"
integration = ["anthropic"]
maturity = "production"
updated_date = "2026/09/25"

[rule]
author = ["Elastic"]
description = """
Admin API keys grant programmatic access to organization and compliance APIs outside an interactive browser session. An
attacker who creates one after compromise can automate role grants, exports, and logging changes without holding a user
session that would time out under SSO. The key also survives password resets and IdP lockout if defenders revoke the
interactive account but miss the API credential.
"""
false_positives = [
    """
    Platform, security, and observability teams create admin API keys during integration setup or scheduled key
    rotation. Verify the actor, `anthropic.audit.scopes`, and whether the creation matches an approved change.
    """,
]
from = "now-9m"
language = "esql"
license = "Elastic License v2"
name = "Anthropic Admin API Key Created"
note = """## Triage and analysis

### Investigating Anthropic Admin API Key Created

Admin API keys provide durable programmatic org/compliance access that survives interactive session revocation.
Scopes at creation determine blast radius.

Unauthorized = key not in the approved credentials inventory, no integration/onboarding ticket, or creation by an
actor who just received admin / ownership and immediately mints a key — especially before exports or SSO changes.

#### Possible investigation steps

- Record `anthropic.audit.admin_api_key_id` and `anthropic.audit.scopes` for later revoke and correlation.
- Branch actor: `user_actor` → is `user.email` / `source.ip` / UA a known platform admin? Scripting UA is higher
  priority than a normal browser admin console session.
- Check whether the actor recently gained admin or primary ownership; look ±hours for exports, SSO changes, or
  compliance logging changes from the same org.
- Close as FP when inventory + ticket match. Escalate when the key is unknown or precedes control-plane abuse.

### False positive analysis

- Fleet / SIEM onboarding and scheduled rotation routinely create admin keys — require inventory evidence.

### Response and remediation

- On unauthorized creation: revoke the key in Anthropic admin, rotate other admin credentials, and review API activity
  attributable to that `anthropic.audit.admin_api_key_id` during the exposure window.
"""
references = ["https://platform.claude.com/docs/en/api/compliance/activities/list"]
risk_score = 47
rule_id = "4051e709-03b6-4782-aae3-e58dde33642b"
severity = "medium"
tags = [
    "Domain: GenAI",
    "Platform: Anthropic",
    "Data Source: Anthropic Audit Logs",
    "Use Case: Identity and Access Audit",
    "Use Case: Threat Detection",
    "Resources: Investigation Guide",
    "Rule Type: ES|QL",
    "Tactic: Persistence",
]
timestamp_override = "event.ingested"
type = "esql"

query = '''
from logs-anthropic.audit-* metadata _id, _version, _index
| where
    data_stream.dataset == "anthropic.audit" and
    mv_contains(event.category, "iam") and
    event.action == "admin_api_key_created"
| keep _id, _version, _index, @timestamp, event.*, organization.*, user.*, source.*, user_agent.*, anthropic.audit.*, data_stream.*
'''


[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1098"
name = "Account Manipulation"
reference = "https://attack.mitre.org/techniques/T1098/"
[[rule.threat.technique.subtechnique]]
id = "T1098.001"
name = "Additional Cloud Credentials"
reference = "https://attack.mitre.org/techniques/T1098/001/"



[rule.threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"
[[rule.threat_mappings]]
framework = "MITRE ATLAS"
version = "2026.08"
[[rule.threat_mappings.threat]]
framework = "MITRE ATLAS"

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

[rule.investigation_fields]
field_names = [
    "@timestamp",
    "event.action",
    "event.id",
    "organization.id",
    "user.email",
    "user.id",
    "anthropic.audit.admin_api_key_id",
    "anthropic.audit.scopes",
    "source.ip",
    "user_agent.original",
    "anthropic.audit.actor.type",
]