Detection rules › Panther

Panther rules: anthropic

Anthropic Admin API Key Created

#
Severity
medium
Group by
actor.email_address
Log types
Anthropic.Activity
Tags
Anthropic, Credential Access
Source
github.com/panther-labs/panther-analysis

Detects when a new admin API key is created. Admin API keys have elevated privileges and their creation should be verified as authorized. The admin_api_key_id and scopes fields identify the key and its permissions.

MITRE ATT&CK coverage

Detection logic

from panther_anthropic_helpers import anthropic_actor_id, anthropic_alert_context


def rule(event):
    return event.get("type") == "admin_api_key_created"


def title(event):
    actor_email = anthropic_actor_id(event)
    return f"Anthropic: Admin API key created by [{actor_email}]"


def dedup(event):
    return anthropic_actor_id(event)


def alert_context(event):
    return anthropic_alert_context(event)

Rule specification

AnalysisType: rule
RuleID: Anthropic.Activity.Admin.API.Key.Created
DisplayName: "Anthropic Admin API Key Created"
Enabled: true
Filename: anthropic_admin_api_key_created.py
LogTypes:
  - Anthropic.Activity
Severity: Medium
Description: >
  Detects when a new admin API key is created. Admin API keys have elevated
  privileges and their creation should be verified as authorized. The
  admin_api_key_id and scopes fields identify the key and its permissions.
Runbook: |
  1. Find all Anthropic.Activity events by actor:email_address in the 6 hours before and after the alert to determine if this is part of routine admin work
  2. Check if actor:email_address has created admin API keys in the past 90 days to determine if this is a first-time action
  3. Check if actor:ip_address is associated with known VPN/proxy services or matches previously seen IP addresses for this actor
Tags:
  - Anthropic
  - Credential Access
Reports:
  MITRE ATT&CK:
    - TA0006:T1098.001  # Account Manipulation: Additional Cloud Credentials

Stages and Predicates

Fires on Anthropic.Activity events when the condition below holds.

Condition

  • type is admin_api_key_created

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
typeeq
  • admin_api_key_created
field:"type" kind:eq value:"admin_api_key_created"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
event_typetype
actor_typeactor.type
actor_emailactor.email_address
actor_user_idactor.user_id
ip_addressactor.ip_address
user_agentactor.user_agent
api_key_idactor.api_key_id
organization_id
ipsp_any_ip_addresses

Response runbook

1. Find all Anthropic.Activity events by actor:email_address in the 6 hours before and after the alert to determine if this is part of routine admin work

2. Check if actor:email_address has created admin API keys in the past 90 days to determine if this is a first-time action

3. Check if actor:ip_address is associated with known VPN/proxy services or matches previously seen IP addresses for this actor

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "email_address": "admin@example.com",
    "ip_address": "10.0.0.1",
    "type": "user_actor",
    "user_agent": "Mozilla/5.0",
    "user_id": "user_01ABC"
  },
  "created_at": "2026-05-07T10:00:00Z",
  "id": "activity_01ABC123",
  "organization_id": "org_01XYZ",
  "type": "admin_api_key_created"
}

Anthropic Admin API Key Deleted

#
Severity
medium
Group by
actor.email_address
Log types
Anthropic.Activity
Tags
Anthropic, Credential Access
Source
github.com/panther-labs/panther-analysis

Detects when an admin API key is deleted. Unauthorized deletion could indicate an attacker revoking legitimate credentials to disrupt operations or covering tracks after using a compromised key.

MITRE ATT&CK coverage

Detection logic

from panther_anthropic_helpers import anthropic_actor_id, anthropic_alert_context


def rule(event):
    return event.get("type") == "admin_api_key_deleted"


def title(event):
    actor_email = anthropic_actor_id(event)
    return f"Anthropic: Admin API key deleted by [{actor_email}]"


def dedup(event):
    return anthropic_actor_id(event)


def alert_context(event):
    return anthropic_alert_context(event)

Rule specification

AnalysisType: rule
RuleID: Anthropic.Activity.Admin.API.Key.Deleted
DisplayName: "Anthropic Admin API Key Deleted"
Enabled: true
Filename: anthropic_admin_api_key_deleted.py
LogTypes:
  - Anthropic.Activity
Severity: Medium
Description: >
  Detects when an admin API key is deleted. Unauthorized deletion could
  indicate an attacker revoking legitimate credentials to disrupt operations
  or covering tracks after using a compromised key.
Runbook: |
  1. Find all Anthropic.Activity events by actor:email_address in the 6 hours before and after the alert to determine if this is part of routine key rotation
  2. Check if an admin_api_key_created event occurred near this deletion to determine if this is a key rotation or a standalone deletion
  3. Check if actor:ip_address is associated with known VPN/proxy services or matches previously seen IP addresses for this actor
Tags:
  - Anthropic
  - Credential Access
Reports:
  MITRE ATT&CK:
    - TA0006:T1098.001  # Account Manipulation: Additional Cloud Credentials

Stages and Predicates

Fires on Anthropic.Activity events when the condition below holds.

Condition

  • type is admin_api_key_deleted

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
typeeq
  • admin_api_key_deleted
field:"type" kind:eq value:"admin_api_key_deleted"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
event_typetype
actor_typeactor.type
actor_emailactor.email_address
actor_user_idactor.user_id
ip_addressactor.ip_address
user_agentactor.user_agent
api_key_idactor.api_key_id
organization_id
ipsp_any_ip_addresses

Response runbook

1. Find all Anthropic.Activity events by actor:email_address in the 6 hours before and after the alert to determine if this is part of routine key rotation

2. Check if an admin_api_key_created event occurred near this deletion to determine if this is a key rotation or a standalone deletion

3. Check if actor:ip_address is associated with known VPN/proxy services or matches previously seen IP addresses for this actor

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "email_address": "admin@example.com",
    "ip_address": "10.0.0.1",
    "type": "user_actor",
    "user_agent": "Mozilla/5.0",
    "user_id": "user_01ABC"
  },
  "created_at": "2026-05-07T10:00:00Z",
  "id": "activity_01ABC123",
  "organization_id": "org_01XYZ",
  "type": "admin_api_key_deleted"
}

Anthropic Artifact Shared Publicly

#
Severity
medium
Group by
actor.email_address
Log types
Anthropic.Activity
Tags
Anthropic, Data Loss Prevention
Source
github.com/panther-labs/panther-analysis

Detects when an artifact's sharing audience is changed to public. Public artifacts are accessible to anyone with the link, which could expose sensitive content outside the organization.

MITRE ATT&CK coverage

TacticTechniques
Exfiltration

Detection logic

from panther_anthropic_helpers import anthropic_actor_id, anthropic_alert_context


def rule(event):
    if event.get("type") != "claude_artifact_sharing_updated":
        return False
    audience = event.get("audience")
    if audience is None:
        return False
    # Panther's event wrapper intercepts .get("type") and ["type"] on nested
    # objects, returning the parent event's type. String matching on the
    # serialized audience is the only reliable approach in the test framework.
    # In production, audience entries only have a "type" key, so matching
    # "'public'" or '"public"' is equivalent to checking entry.type == "public".
    audience_str = str(audience)
    return "'public'" in audience_str or '"public"' in audience_str


def title(event):
    actor_email = anthropic_actor_id(event)
    artifact_id = event.get("claude_artifact_id", "<UNKNOWN_ARTIFACT>")
    return f"Anthropic: Artifact [{artifact_id}] shared publicly by [{actor_email}]"


def dedup(event):
    return anthropic_actor_id(event)


def alert_context(event):
    return anthropic_alert_context(event)

Rule specification

AnalysisType: rule
RuleID: Anthropic.Activity.Artifact.Shared.Publicly
DisplayName: "Anthropic Artifact Shared Publicly"
Enabled: true
Filename: anthropic_artifact_shared_publicly.py
LogTypes:
  - Anthropic.Activity
Severity: Medium
Description: >
  Detects when an artifact's sharing audience is changed to public. Public
  artifacts are accessible to anyone with the link, which could expose
  sensitive content outside the organization.
Runbook: |
  1. Find all Anthropic.Activity events by actor:email_address in the 1 hour before and after the alert to understand the context of the sharing change
  2. Check if the claude_artifact_id has been viewed or accessed by external users in the 24 hours after the sharing change
  3. Check if actor:email_address has shared other artifacts publicly in the past 30 days to determine if this is a pattern
Tags:
  - Anthropic
  - Data Loss Prevention
Reports:
  MITRE ATT&CK:
    - TA0010:T1567  # Exfiltration Over Web Service

Stages and Predicates

Fires on Anthropic.Activity events when all of the conditions below hold.

Condition

  • type is claude_artifact_sharing_updated
  • audience is present
  • any of:
    • audience contains 'public'
    • audience contains "public"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
audiencecontains
  • "public"
  • 'public'
field:"audience" kind:contains
audienceis_not_null
  • (no value, null check)
field:"audience" kind:is_not_null
typeeq
  • claude_artifact_sharing_updated
field:"type" kind:eq value:"claude_artifact_sharing_updated"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
event_typetype
actor_typeactor.type
actor_emailactor.email_address
actor_user_idactor.user_id
ip_addressactor.ip_address
user_agentactor.user_agent
api_key_idactor.api_key_id
organization_id
ipsp_any_ip_addresses
claude_artifact_id

Response runbook

1. Find all Anthropic.Activity events by actor:email_address in the 1 hour before and after the alert to understand the context of the sharing change

2. Check if the claude_artifact_id has been viewed or accessed by external users in the 24 hours after the sharing change

3. Check if actor:email_address has shared other artifacts publicly in the past 30 days to determine if this is a pattern

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "email_address": "user@example.com",
    "ip_address": "10.0.0.1",
    "type": "user_actor",
    "user_agent": "Mozilla/5.0",
    "user_id": "user_01ABC"
  },
  "audience": [
    {
      "type": "public"
    }
  ],
  "claude_artifact_id": "claude_artifact_01ABC",
  "created_at": "2026-05-07T09:10:01Z",
  "id": "activity_01ABC123",
  "organization_id": "org_01XYZ",
  "type": "claude_artifact_sharing_updated"
}

Anthropic Excessive Chat Access Failures

#
Severity
medium
Group by
actor.email_address
Log types
Anthropic.Activity
Tags
Anthropic, Access Control, Enumeration
Source
github.com/panther-labs/panther-analysis

Detects when a single actor generates more than 50 chat access failures within a 10-minute window. Could indicate automated chat enumeration or unauthorized bulk access attempts. The claude_chat_id field identifies which chats were targeted — sequential or patterned IDs suggest scripted enumeration, while scattered IDs suggest shared-link browsing.

MITRE ATT&CK coverage

TacticTechniques
Discovery

Detection logic

from panther_anthropic_helpers import anthropic_actor_id, anthropic_alert_context


def rule(event):
    return event.get("type") == "claude_chat_access_failed"


def title(event):
    return f"Anthropic: Excessive chat access failures from [{anthropic_actor_id(event)}]"


def dedup(event):
    return anthropic_actor_id(event)


def alert_context(event):
    return anthropic_alert_context(event)

Rule specification

AnalysisType: rule
RuleID: Anthropic.Activity.Excessive.Chat.Access.Failures
DisplayName: "Anthropic Excessive Chat Access Failures"
Enabled: true
Filename: anthropic_excessive_chat_access_failures.py
LogTypes:
  - Anthropic.Activity
Severity: Medium
Threshold: 50
DedupPeriodMinutes: 10
Description: >
  Detects when a single actor generates more than 50 chat access failures
  within a 10-minute window. Could indicate automated chat enumeration
  or unauthorized bulk access attempts. The claude_chat_id field identifies
  which chats were targeted — sequential or patterned IDs suggest scripted
  enumeration, while scattered IDs suggest shared-link browsing.
Runbook: |
  1. Find all Anthropic.Activity events by actor:email_address in the 1 hour before and after the alert to establish whether this is part of normal browsing or an isolated burst
  2. Compare the actor's claude_chat_access_failed count to their claude_chat_viewed count in the same window — a high failure-to-success ratio suggests enumeration rather than shared-link browsing
  3. Check if actor:ip_address appears in threat intelligence feeds or is associated with known VPN/proxy services
Tags:
  - Anthropic
  - Access Control
  - Enumeration
Reports:
  MITRE ATT&CK:
    - TA0007:T1087  # Account Discovery

Stages and Predicates

Fires on Anthropic.Activity events when the condition below holds.

Condition

  • type is claude_chat_access_failed
Alert cadence
alerts after 50 matches within 10m

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
typeeq
  • claude_chat_access_failed
field:"type" kind:eq value:"claude_chat_access_failed"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
event_typetype
actor_typeactor.type
actor_emailactor.email_address
actor_user_idactor.user_id
ip_addressactor.ip_address
user_agentactor.user_agent
api_key_idactor.api_key_id
organization_id
ipsp_any_ip_addresses

Response runbook

1. Find all Anthropic.Activity events by actor:email_address in the 1 hour before and after the alert to establish whether this is part of normal browsing or an isolated burst

2. Compare the actor's claude_chat_access_failed count to their claude_chat_viewed count in the same window — a high failure-to-success ratio suggests enumeration rather than shared-link browsing

3. Check if actor:ip_address appears in threat intelligence feeds or is associated with known VPN/proxy services

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "email_address": "user@example.com",
    "ip_address": "192.168.1.1",
    "type": "user_actor",
    "user_agent": "Mozilla/5.0",
    "user_id": "user_01XYZ"
  },
  "claude_chat_id": "chat_01ABC",
  "created_at": "2026-04-28T08:00:00Z",
  "id": "evt_01ABC123",
  "organization_id": "org_123",
  "type": "claude_chat_access_failed"
}

Anthropic Integration Connected

#
Severity
informational
Group by
actor.email_address
Log types
Anthropic.Activity
Tags
Anthropic, Compliance, Integrations
Source
github.com/panther-labs/panther-analysis

Tracks when a user connects an external integration (e.g., GitHub, Google Drive) to their Anthropic account. Logged for compliance visibility into external data pathways. The integration_type field identifies which service was connected.

MITRE ATT&CK coverage

TacticTechniques
Collection

Detection logic

from panther_anthropic_helpers import anthropic_actor_id, anthropic_alert_context


def rule(event):
    return event.get("type") == "integration_user_connected"


def title(event):
    actor_email = anthropic_actor_id(event)
    integration_type = event.get("integration_type", "<UNKNOWN_TYPE>")
    return f"Anthropic: User [{actor_email}] connected [{integration_type}] integration"


def dedup(event):
    return anthropic_actor_id(event)


def alert_context(event):
    return anthropic_alert_context(event)

Rule specification

AnalysisType: rule
RuleID: Anthropic.Activity.Integration.Connected
DisplayName: "Anthropic Integration Connected"
Enabled: true
Filename: anthropic_integration_connected.py
LogTypes:
  - Anthropic.Activity
Severity: Info
Description: >
  Tracks when a user connects an external integration (e.g., GitHub, Google Drive)
  to their Anthropic account. Logged for compliance visibility into external data
  pathways. The integration_type field identifies which service was connected.
Runbook: |
  1. Find all Anthropic.Activity events by actor:email_address in the 1 hour before and after the alert to understand the context of the integration connection
  2. Check if actor:email_address has connected other integrations in the past 30 days to identify unusual patterns
  3. Check if actor:ip_address matches previously seen IP addresses for this actor
Tags:
  - Anthropic
  - Compliance
  - Integrations
Reports:
  MITRE ATT&CK:
    - TA0009:T1530  # Data from Cloud Storage

Stages and Predicates

Fires on Anthropic.Activity events when the condition below holds.

Condition

  • type is integration_user_connected

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
typeeq
  • integration_user_connected
field:"type" kind:eq value:"integration_user_connected"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
event_typetype
actor_typeactor.type
actor_emailactor.email_address
actor_user_idactor.user_id
ip_addressactor.ip_address
user_agentactor.user_agent
api_key_idactor.api_key_id
organization_id
ipsp_any_ip_addresses
integration_type

Response runbook

1. Find all Anthropic.Activity events by actor:email_address in the 1 hour before and after the alert to understand the context of the integration connection

2. Check if actor:email_address has connected other integrations in the past 30 days to identify unusual patterns

3. Check if actor:ip_address matches previously seen IP addresses for this actor

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "email_address": "user@example.com",
    "ip_address": "10.0.0.1",
    "type": "user_actor",
    "user_agent": "Mozilla/5.0",
    "user_id": "user_01ABC"
  },
  "created_at": "2026-05-06T17:38:28Z",
  "id": "activity_01ABC123",
  "integration_type": "github",
  "organization_id": "org_01XYZ",
  "type": "integration_user_connected"
}

Anthropic IP Restriction Deleted

#
Severity
high
Group by
actor.email_address
Log types
Anthropic.Activity
Tags
Anthropic, Network Security, Defense Evasion
Source
github.com/panther-labs/panther-analysis

Detects when an organization IP restriction is deleted. IP restrictions are a critical network-level access control — removing them allows access from any IP address, which could indicate an attacker widening the attack surface after gaining admin access.

MITRE ATT&CK coverage

TacticTechniques
Defense Impairment

Detection logic

from panther_anthropic_helpers import anthropic_actor_id, anthropic_alert_context


def rule(event):
    return event.get("type") == "org_ip_restriction_deleted"


def title(event):
    actor_email = anthropic_actor_id(event)
    return f"Anthropic: IP restriction deleted by [{actor_email}]"


def dedup(event):
    return anthropic_actor_id(event)


def alert_context(event):
    return anthropic_alert_context(event)

Rule specification

AnalysisType: rule
RuleID: Anthropic.Activity.IP.Restriction.Deleted
DisplayName: "Anthropic IP Restriction Deleted"
Enabled: true
Filename: anthropic_ip_restriction_deleted.py
LogTypes:
  - Anthropic.Activity
Severity: High
Description: >
  Detects when an organization IP restriction is deleted. IP restrictions
  are a critical network-level access control — removing them allows access
  from any IP address, which could indicate an attacker widening the attack
  surface after gaining admin access.
Runbook: |
  1. Find all Anthropic.Activity events by actor:email_address in the 24 hours before the alert to identify any suspicious activity leading up to the IP restriction change
  2. Check if actor:ip_address matches previously seen IP addresses for this actor in the past 30 days to detect potential account compromise
  3. Check if other org_ip_restriction events (created, updated) occurred in the 1 hour around the alert to determine if this is a policy replacement or a standalone deletion
Tags:
  - Anthropic
  - Network Security
  - Defense Evasion
Reports:
  MITRE ATT&CK:
    - TA0005:T1562.001  # Impair Defenses: Disable or Modify Tools

Stages and Predicates

Fires on Anthropic.Activity events when the condition below holds.

Condition

  • type is org_ip_restriction_deleted

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
typeeq
  • org_ip_restriction_deleted
field:"type" kind:eq value:"org_ip_restriction_deleted"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
event_typetype
actor_typeactor.type
actor_emailactor.email_address
actor_user_idactor.user_id
ip_addressactor.ip_address
user_agentactor.user_agent
api_key_idactor.api_key_id
organization_id
ipsp_any_ip_addresses

Response runbook

1. Find all Anthropic.Activity events by actor:email_address in the 24 hours before the alert to identify any suspicious activity leading up to the IP restriction change

2. Check if actor:ip_address matches previously seen IP addresses for this actor in the past 30 days to detect potential account compromise

3. Check if other org_ip_restriction events (created, updated) occurred in the 1 hour around the alert to determine if this is a policy replacement or a standalone deletion

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "email_address": "admin@example.com",
    "ip_address": "10.0.0.1",
    "type": "user_actor",
    "user_agent": "Mozilla/5.0",
    "user_id": "user_01ABC"
  },
  "created_at": "2026-05-07T10:00:00Z",
  "id": "activity_01ABC123",
  "organization_id": "org_01XYZ",
  "type": "org_ip_restriction_deleted"
}

Anthropic MCP Server Created

#
Severity
medium
Group by
actor.email_address
Log types
Anthropic.Activity
Tags
Anthropic, Configuration, Supply Chain
Source
github.com/panther-labs/panther-analysis

Detects when a new MCP (Model Context Protocol) server integration is created. Each MCP server is a new external data pathway that could be used for data exfiltration. Every new integration should be verified as approved, especially when created by external contractors or service accounts.

MITRE ATT&CK coverage

TacticTechniques
Exfiltration

Detection logic

from panther_anthropic_helpers import anthropic_actor_id, anthropic_alert_context


def rule(event):
    return event.get("type") == "mcp_server_created"


def title(event):
    actor_email = anthropic_actor_id(event)
    server_name = event.get("mcp_server_name", "<UNKNOWN_SERVER>")
    return f"Anthropic: MCP server [{server_name}] created by [{actor_email}]"


def dedup(event):
    return anthropic_actor_id(event)


def alert_context(event):
    return anthropic_alert_context(event)

Rule specification

AnalysisType: rule
RuleID: Anthropic.Activity.MCP.Server.Created
DisplayName: "Anthropic MCP Server Created"
Enabled: true
Filename: anthropic_mcp_server_created.py
LogTypes:
  - Anthropic.Activity
Severity: Medium
Description: >
  Detects when a new MCP (Model Context Protocol) server integration is created.
  Each MCP server is a new external data pathway that could be used for data
  exfiltration. Every new integration should be verified as approved, especially
  when created by external contractors or service accounts.
Runbook: |
  1. Find all Anthropic.Activity events by actor:email_address in the 1 hour before and after the alert to understand the context of the MCP server creation
  2. Check if actor:email_address is an external contractor (ext. domain) or internal employee, and whether they have created MCP servers in the past 90 days
  3. Check if actor:ip_address is associated with known VPN/proxy services or matches previously seen IP addresses for this actor
Tags:
  - Anthropic
  - Configuration
  - Supply Chain
Reports:
  MITRE ATT&CK:
    - TA0010:T1567  # Exfiltration Over Web Service

Stages and Predicates

Fires on Anthropic.Activity events when the condition below holds.

Condition

  • type is mcp_server_created

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
typeeq
  • mcp_server_created
field:"type" kind:eq value:"mcp_server_created"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
event_typetype
actor_typeactor.type
actor_emailactor.email_address
actor_user_idactor.user_id
ip_addressactor.ip_address
user_agentactor.user_agent
api_key_idactor.api_key_id
organization_id
ipsp_any_ip_addresses
mcp_server_name

Response runbook

1. Find all Anthropic.Activity events by actor:email_address in the 1 hour before and after the alert to understand the context of the MCP server creation

2. Check if actor:email_address is an external contractor (ext. domain) or internal employee, and whether they have created MCP servers in the past 90 days

3. Check if actor:ip_address is associated with known VPN/proxy services or matches previously seen IP addresses for this actor

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "email_address": "contractor@ext.example.com",
    "ip_address": "10.0.0.1",
    "type": "user_actor",
    "user_agent": "Mozilla/5.0",
    "user_id": "user_01ABC"
  },
  "created_at": "2026-04-28T19:26:58Z",
  "id": "activity_01ABC123",
  "mcp_server_id": "mcpsrv_01ABC",
  "mcp_server_name": "Snowflake",
  "organization_id": "org_01XYZ",
  "type": "mcp_server_created"
}

Anthropic MCP Server Deleted

#
Severity
low
Group by
actor.email_address
Log types
Anthropic.Activity
Tags
Anthropic, Configuration
Source
github.com/panther-labs/panther-analysis

Detects when an MCP server integration is deleted from the organization. Removing an approved integration could indicate an attacker covering tracks or unauthorized configuration changes. The mcp_server_name and mcp_server_id fields identify which integration was removed.

MITRE ATT&CK coverage

TacticTechniques
Defense Impairment

Detection logic

from panther_anthropic_helpers import anthropic_actor_id, anthropic_alert_context


def rule(event):
    return event.get("type") == "mcp_server_deleted"


def title(event):
    actor_email = anthropic_actor_id(event)
    server_name = event.get("mcp_server_name", "<UNKNOWN_SERVER>")
    return f"Anthropic: MCP server [{server_name}] deleted by [{actor_email}]"


def dedup(event):
    return anthropic_actor_id(event)


def alert_context(event):
    return anthropic_alert_context(event)

Rule specification

AnalysisType: rule
RuleID: Anthropic.Activity.MCP.Server.Deleted
DisplayName: "Anthropic MCP Server Deleted"
Enabled: true
Filename: anthropic_mcp_server_deleted.py
LogTypes:
  - Anthropic.Activity
Severity: Low
Description: >
  Detects when an MCP server integration is deleted from the organization.
  Removing an approved integration could indicate an attacker covering tracks
  or unauthorized configuration changes. The mcp_server_name and mcp_server_id
  fields identify which integration was removed.
Runbook: |
  1. Find all Anthropic.Activity events with type mcp_server_created by actor:email_address in the 10 minutes after the alert to determine if this was a delete-then-recreate (config fix) or a standalone deletion
  2. Check if actor:email_address has performed other administrative actions (claude_organization_settings_updated, mcp_server_created) in the 6 hours around the alert to assess if this is part of routine admin work
  3. Find all alerts for actor:email_address in the past 7 days to check for signs of account compromise preceding this action
Tags:
  - Anthropic
  - Configuration
Reports:
  MITRE ATT&CK:
    - TA0005:T1562  # Impair Defenses

Stages and Predicates

Fires on Anthropic.Activity events when the condition below holds.

Condition

  • type is mcp_server_deleted

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
typeeq
  • mcp_server_deleted
field:"type" kind:eq value:"mcp_server_deleted"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
event_typetype
actor_typeactor.type
actor_emailactor.email_address
actor_user_idactor.user_id
ip_addressactor.ip_address
user_agentactor.user_agent
api_key_idactor.api_key_id
organization_id
ipsp_any_ip_addresses
mcp_server_name

Response runbook

1. Find all Anthropic.Activity events with type mcp_server_created by actor:email_address in the 10 minutes after the alert to determine if this was a delete-then-recreate (config fix) or a standalone deletion

2. Check if actor:email_address has performed other administrative actions (claude_organization_settings_updated, mcp_server_created) in the 6 hours around the alert to assess if this is part of routine admin work

3. Find all alerts for actor:email_address in the past 7 days to check for signs of account compromise preceding this action

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "email_address": "admin@example.com",
    "ip_address": "10.0.0.1",
    "type": "user_actor",
    "user_agent": "Mozilla/5.0",
    "user_id": "user_01ABC"
  },
  "created_at": "2026-05-05T21:46:28Z",
  "id": "activity_01ABC123",
  "mcp_server_id": "mcpsrv_01ABC",
  "mcp_server_name": "Snowflake",
  "organization_id": "org_01XYZ",
  "type": "mcp_server_deleted"
}

Anthropic Organization Settings Updated

#
Severity
medium
Group by
actor.email_address
Log types
Anthropic.Activity
Tags
Anthropic, Configuration
Source
github.com/panther-labs/panther-analysis

Detects when organization-wide settings are modified in Anthropic. These changes can affect security posture for all users (e.g., SSO configuration, data retention, access controls). The updates field identifies which settings were changed.

MITRE ATT&CK coverage

TacticTechniques
Defense Impairment

Detection logic

import re

from panther_anthropic_helpers import anthropic_actor_id, anthropic_alert_context

PARENT_EVENT_TYPE = "claude_organization_settings_updated"


def rule(event):
    return event.get("type") == PARENT_EVENT_TYPE


def _extract_update_type(entry_str):
    """Extract the first type value from a single serialized update entry."""
    match = re.search(r"'type':\s*'([^']+)'", entry_str)
    if not match:
        match = re.search(r'"type":\s*"([^"]+)"', entry_str)
    return match.group(1) if match else None


def _extract_update_types(updates):
    """Extract top-level update type values from the updates list.

    Serializes each entry individually to avoid capturing type values
    from nested objects. Uses string parsing because Panther's event
    wrapper intercepts .get("type") on nested objects.
    """
    result = []
    for entry in updates:
        update_type = _extract_update_type(str(entry))
        if update_type and update_type != PARENT_EVENT_TYPE:
            result.append(update_type)
    return result


def title(event):
    actor_email = anthropic_actor_id(event)
    updates = event.get("updates", [])
    if updates:
        update_types = _extract_update_types(updates)
        if update_types:
            types_str = ", ".join(update_types)
            return f"Anthropic: Organization settings updated by" f" [{actor_email}]: {types_str}"
    return f"Anthropic: Organization settings updated by [{actor_email}]"


def dedup(event):
    return anthropic_actor_id(event)


def alert_context(event):
    return anthropic_alert_context(event)

Rule specification

AnalysisType: rule
RuleID: Anthropic.Activity.Organization.Settings.Updated
DisplayName: "Anthropic Organization Settings Updated"
Enabled: true
Filename: anthropic_org_settings_updated.py
LogTypes:
  - Anthropic.Activity
Severity: Medium
Description: >
  Detects when organization-wide settings are modified in Anthropic. These changes
  can affect security posture for all users (e.g., SSO configuration, data retention,
  access controls). The updates field identifies which settings were changed.
Runbook: |
  1. Find all Anthropic.Activity events by actor:email_address in the 6 hours before and after the alert to understand what other administrative actions they performed
  2. Check if actor:email_address has performed claude_organization_settings_updated events in the past 90 days to determine if this is routine admin activity or a first-time action
  3. Check if actor:ip_address is associated with known VPN/proxy services or matches previously seen IP addresses for this actor
Tags:
  - Anthropic
  - Configuration
Reports:
  MITRE ATT&CK:
    - TA0005:T1562  # Impair Defenses

Stages and Predicates

Fires on Anthropic.Activity events when the condition below holds.

Condition

  • type is claude_organization_settings_updated

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
typeeq
  • claude_organization_settings_updated
field:"type" kind:eq value:"claude_organization_settings_updated"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
event_typetype
actor_typeactor.type
actor_emailactor.email_address
actor_user_idactor.user_id
ip_addressactor.ip_address
user_agentactor.user_agent
api_key_idactor.api_key_id
organization_id
ipsp_any_ip_addresses

Response runbook

1. Find all Anthropic.Activity events by actor:email_address in the 6 hours before and after the alert to understand what other administrative actions they performed

2. Check if actor:email_address has performed claude_organization_settings_updated events in the past 90 days to determine if this is routine admin activity or a first-time action

3. Check if actor:ip_address is associated with known VPN/proxy services or matches previously seen IP addresses for this actor

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "email_address": "admin@example.com",
    "ip_address": "10.0.0.1",
    "type": "user_actor",
    "user_agent": "Mozilla/5.0",
    "user_id": "user_01ABC"
  },
  "created_at": "2026-04-29T09:14:15Z",
  "id": "activity_01ABC123",
  "organization_id": "org_01XYZ",
  "type": "claude_organization_settings_updated",
  "updates": [
    {
      "current_value": [
        {
          "org_name": "example-org",
          "type": "github"
        }
      ],
      "type": "vcs_connections"
    }
  ]
}

Anthropic Organization User Deleted

#
Severity
informational
Group by
actor.email_address
Log types
Anthropic.Activity
Tags
Anthropic, Compliance, User Lifecycle
Source
github.com/panther-labs/panther-analysis

Tracks when a user is removed from the Anthropic organization. Logged for compliance visibility into user lifecycle changes. The deleted_user_id and deleted_user_email fields identify who was removed.

MITRE ATT&CK coverage

TacticTechniques
Impact

Detection logic

from panther_anthropic_helpers import anthropic_actor_id, anthropic_alert_context


def rule(event):
    return event.get("type") == "org_user_deleted"


def title(event):
    actor_email = anthropic_actor_id(event)
    deleted_user = event.get("deleted_user_email") or event.get("deleted_user_id", "<UNKNOWN_USER>")
    return f"Anthropic: User [{deleted_user}] deleted from org by [{actor_email}]"


def dedup(event):
    return anthropic_actor_id(event)


def alert_context(event):
    return anthropic_alert_context(event)

Rule specification

AnalysisType: rule
RuleID: Anthropic.Activity.Org.User.Deleted
DisplayName: "Anthropic Organization User Deleted"
Enabled: true
Filename: anthropic_org_user_deleted.py
LogTypes:
  - Anthropic.Activity
Severity: Info
Description: >
  Tracks when a user is removed from the Anthropic organization. Logged
  for compliance visibility into user lifecycle changes. The deleted_user_id
  and deleted_user_email fields identify who was removed.
Runbook: |
  1. Find all Anthropic.Activity events by actor:email_address in the 6 hours before and after the alert to determine if this is part of routine offboarding or an isolated deletion
  2. Check if the deleted user had any unusual activity (claude_chat_access_failed, claude_organization_settings_updated) in the 7 days before removal
  3. Check if actor:email_address has deleted other users in the past 7 days to identify potential bulk unauthorized removals
Tags:
  - Anthropic
  - Compliance
  - User Lifecycle
Reports:
  MITRE ATT&CK:
    - TA0040:T1531  # Account Access Removal

Stages and Predicates

Fires on Anthropic.Activity events when the condition below holds.

Condition

  • type is org_user_deleted

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
typeeq
  • org_user_deleted
field:"type" kind:eq value:"org_user_deleted"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
event_typetype
actor_typeactor.type
actor_emailactor.email_address
actor_user_idactor.user_id
ip_addressactor.ip_address
user_agentactor.user_agent
api_key_idactor.api_key_id
organization_id
ipsp_any_ip_addresses
deleted_user_email

Response runbook

1. Find all Anthropic.Activity events by actor:email_address in the 6 hours before and after the alert to determine if this is part of routine offboarding or an isolated deletion

2. Check if the deleted user had any unusual activity (claude_chat_access_failed, claude_organization_settings_updated) in the 7 days before removal

3. Check if actor:email_address has deleted other users in the past 7 days to identify potential bulk unauthorized removals

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "email_address": "admin@example.com",
    "ip_address": "10.0.0.1",
    "type": "user_actor",
    "user_agent": "Mozilla/5.0",
    "user_id": "user_01ABC"
  },
  "created_at": "2026-05-07T10:00:00Z",
  "deleted_user_email": "deleted-user@example.com",
  "deleted_user_id": "user_01DEF",
  "id": "activity_01ABC123",
  "organization_id": "org_01XYZ",
  "type": "org_user_deleted"
}

Anthropic Primary Owner Transferred

#
Severity
high
Group by
actor.email_address
Log types
Anthropic.Activity
Tags
Anthropic, Privilege Escalation
Source
github.com/panther-labs/panther-analysis

Detects when the primary owner role of the Anthropic organization is transferred to another member. This is an extremely high-privilege action that gives full control of the organization. The previous_owner_id and new_owner_id fields identify who gave up and received ownership.

MITRE ATT&CK coverage

Detection logic

from panther_anthropic_helpers import anthropic_actor_id, anthropic_alert_context


def rule(event):
    return event.get("type") == "primary_owner_transferred"


def title(event):
    actor_email = anthropic_actor_id(event)
    return f"Anthropic: Primary owner transferred by [{actor_email}]"


def dedup(event):
    return anthropic_actor_id(event)


def alert_context(event):
    return anthropic_alert_context(event)

Rule specification

AnalysisType: rule
RuleID: Anthropic.Activity.Primary.Owner.Transferred
DisplayName: "Anthropic Primary Owner Transferred"
Enabled: true
Filename: anthropic_primary_owner_transferred.py
LogTypes:
  - Anthropic.Activity
Severity: High
Description: >
  Detects when the primary owner role of the Anthropic organization is
  transferred to another member. This is an extremely high-privilege action
  that gives full control of the organization. The previous_owner_id and
  new_owner_id fields identify who gave up and received ownership.
Runbook: |
  1. Find all Anthropic.Activity events by actor:email_address in the 24 hours before the alert to identify any suspicious activity leading up to the ownership transfer
  2. Check if actor:ip_address matches previously seen IP addresses for this actor in the past 30 days to detect potential account compromise
  3. Find all alerts for actor:email_address in the past 7 days to check for signs of account compromise preceding this action
Tags:
  - Anthropic
  - Privilege Escalation
Reports:
  MITRE ATT&CK:
    - TA0003:T1098.003  # Account Manipulation: Additional Cloud Roles

Stages and Predicates

Fires on Anthropic.Activity events when the condition below holds.

Condition

  • type is primary_owner_transferred

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
typeeq
  • primary_owner_transferred
field:"type" kind:eq value:"primary_owner_transferred"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
event_typetype
actor_typeactor.type
actor_emailactor.email_address
actor_user_idactor.user_id
ip_addressactor.ip_address
user_agentactor.user_agent
api_key_idactor.api_key_id
organization_id
ipsp_any_ip_addresses

Response runbook

1. Find all Anthropic.Activity events by actor:email_address in the 24 hours before the alert to identify any suspicious activity leading up to the ownership transfer

2. Check if actor:ip_address matches previously seen IP addresses for this actor in the past 30 days to detect potential account compromise

3. Find all alerts for actor:email_address in the past 7 days to check for signs of account compromise preceding this action

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "email_address": "owner@example.com",
    "ip_address": "10.0.0.1",
    "type": "user_actor",
    "user_agent": "Mozilla/5.0",
    "user_id": "user_01ABC"
  },
  "created_at": "2026-05-07T10:00:00Z",
  "id": "activity_01ABC123",
  "organization_id": "org_01XYZ",
  "type": "primary_owner_transferred"
}

Anthropic Role Granted

#
Severity
informational
Group by
actor.email_address
Log types
Anthropic.Activity
Tags
Anthropic, Access Control
Source
github.com/panther-labs/panther-analysis

Tracks all role grants in the Anthropic organization. Currently used to build visibility into the role taxonomy as the log source matures. Once sufficient data is collected on org-level vs project-level role patterns, this rule can be refined to alert at higher severity for elevated roles.

MITRE ATT&CK coverage

TacticTechniques
Privilege Escalation

Detection logic

from panther_anthropic_helpers import anthropic_actor_id, anthropic_alert_context


def rule(event):
    return event.get("type") == "role_assignment_granted"


def title(event):
    actor_email = anthropic_actor_id(event)
    role = event.get("role", "<UNKNOWN_ROLE>")
    target_id = event.get("target_id", "<UNKNOWN_TARGET>")
    return f"Anthropic: Role [{role}] granted to [{target_id}] by [{actor_email}]"


def dedup(event):
    return anthropic_actor_id(event)


def alert_context(event):
    return anthropic_alert_context(event)

Rule specification

AnalysisType: rule
RuleID: Anthropic.Activity.Role.Granted
DisplayName: "Anthropic Role Granted"
Enabled: true
Filename: anthropic_role_granted.py
LogTypes:
  - Anthropic.Activity
Severity: Info
Description: >
  Tracks all role grants in the Anthropic organization. Currently used to
  build visibility into the role taxonomy as the log source matures. Once
  sufficient data is collected on org-level vs project-level role patterns,
  this rule can be refined to alert at higher severity for elevated roles.
Runbook: |
  1. Find all Anthropic.Activity events by actor:email_address in the 6 hours before and after the alert to determine if this is part of routine project creation or an isolated privilege grant
  2. Check if target_id has been granted other roles in the past 7 days to identify potential privilege accumulation
  3. Check if actor:ip_address is associated with known VPN/proxy services or matches previously seen IP addresses for this actor
Tags:
  - Anthropic
  - Access Control
Reports:
  MITRE ATT&CK:
    - TA0004:T1098  # Account Manipulation

Stages and Predicates

Fires on Anthropic.Activity events when the condition below holds.

Condition

  • type is role_assignment_granted

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
typeeq
  • role_assignment_granted
field:"type" kind:eq value:"role_assignment_granted"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
event_typetype
actor_typeactor.type
actor_emailactor.email_address
actor_user_idactor.user_id
ip_addressactor.ip_address
user_agentactor.user_agent
api_key_idactor.api_key_id
organization_id
ipsp_any_ip_addresses
role
target_id

Response runbook

1. Find all Anthropic.Activity events by actor:email_address in the 6 hours before and after the alert to determine if this is part of routine project creation or an isolated privilege grant

2. Check if target_id has been granted other roles in the past 7 days to identify potential privilege accumulation

3. Check if actor:ip_address is associated with known VPN/proxy services or matches previously seen IP addresses for this actor

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "email_address": "admin@example.com",
    "ip_address": "10.0.0.1",
    "type": "user_actor",
    "user_agent": "Mozilla/5.0",
    "user_id": "user_01ABC"
  },
  "created_at": "2026-05-07T13:02:42Z",
  "id": "activity_01ABC123",
  "organization_id": "org_01XYZ",
  "resource_id": "claude_proj_01ABC",
  "resource_type": "chat_project",
  "role": "chat_project:viewer",
  "target_id": "user_01DEF",
  "target_type": "organization_member",
  "type": "role_assignment_granted"
}

Anthropic Service Key Created

#
Severity
medium
Group by
actor.email_address
Log types
Anthropic.Activity
Tags
Anthropic, Credential Access
Source
github.com/panther-labs/panther-analysis

Detects when a new service key is created. Service keys provide programmatic access and their creation should be verified as authorized. The service_key_id, service_name, key_name, and scopes fields identify the key and its permissions.

MITRE ATT&CK coverage

Detection logic

from panther_anthropic_helpers import anthropic_actor_id, anthropic_alert_context


def rule(event):
    return event.get("type") == "service_key_created"


def title(event):
    actor_email = anthropic_actor_id(event)
    return f"Anthropic: Service key created by [{actor_email}]"


def dedup(event):
    return anthropic_actor_id(event)


def alert_context(event):
    return anthropic_alert_context(event)

Rule specification

AnalysisType: rule
RuleID: Anthropic.Activity.Service.Key.Created
DisplayName: "Anthropic Service Key Created"
Enabled: true
Filename: anthropic_service_key_created.py
LogTypes:
  - Anthropic.Activity
Severity: Medium
Description: >
  Detects when a new service key is created. Service keys provide
  programmatic access and their creation should be verified as authorized.
  The service_key_id, service_name, key_name, and scopes fields identify
  the key and its permissions.
Runbook: |
  1. Find all Anthropic.Activity events by actor:email_address in the 6 hours before and after the alert to determine if this is part of routine service account setup
  2. Check if actor:email_address has created service keys in the past 90 days to determine if this is a first-time action
  3. Check if actor:ip_address is associated with known VPN/proxy services or matches previously seen IP addresses for this actor
Tags:
  - Anthropic
  - Credential Access
Reports:
  MITRE ATT&CK:
    - TA0006:T1098.001  # Account Manipulation: Additional Cloud Credentials

Stages and Predicates

Fires on Anthropic.Activity events when the condition below holds.

Condition

  • type is service_key_created

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
typeeq
  • service_key_created
field:"type" kind:eq value:"service_key_created"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
event_typetype
actor_typeactor.type
actor_emailactor.email_address
actor_user_idactor.user_id
ip_addressactor.ip_address
user_agentactor.user_agent
api_key_idactor.api_key_id
organization_id
ipsp_any_ip_addresses

Response runbook

1. Find all Anthropic.Activity events by actor:email_address in the 6 hours before and after the alert to determine if this is part of routine service account setup

2. Check if actor:email_address has created service keys in the past 90 days to determine if this is a first-time action

3. Check if actor:ip_address is associated with known VPN/proxy services or matches previously seen IP addresses for this actor

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "email_address": "admin@example.com",
    "ip_address": "10.0.0.1",
    "type": "user_actor",
    "user_agent": "Mozilla/5.0",
    "user_id": "user_01ABC"
  },
  "created_at": "2026-05-07T10:00:00Z",
  "id": "activity_01ABC123",
  "organization_id": "org_01XYZ",
  "type": "service_key_created"
}

Anthropic Service Key Revoked

#
Severity
medium
Group by
actor.email_address
Log types
Anthropic.Activity
Tags
Anthropic, Credential Access
Source
github.com/panther-labs/panther-analysis

Detects when a service key is revoked. Unauthorized revocation could indicate an attacker disrupting integrations or covering tracks after using a compromised key. The service_key_id and service_name fields identify which key was revoked.

MITRE ATT&CK coverage

Detection logic

from panther_anthropic_helpers import anthropic_actor_id, anthropic_alert_context


def rule(event):
    return event.get("type") == "service_key_revoked"


def title(event):
    actor_email = anthropic_actor_id(event)
    return f"Anthropic: Service key revoked by [{actor_email}]"


def dedup(event):
    return anthropic_actor_id(event)


def alert_context(event):
    return anthropic_alert_context(event)

Rule specification

AnalysisType: rule
RuleID: Anthropic.Activity.Service.Key.Revoked
DisplayName: "Anthropic Service Key Revoked"
Enabled: true
Filename: anthropic_service_key_revoked.py
LogTypes:
  - Anthropic.Activity
Severity: Medium
Description: >
  Detects when a service key is revoked. Unauthorized revocation could
  indicate an attacker disrupting integrations or covering tracks after
  using a compromised key. The service_key_id and service_name fields
  identify which key was revoked.
Runbook: |
  1. Find all Anthropic.Activity events by actor:email_address in the 6 hours before and after the alert to determine if this is part of routine key rotation or incident response
  2. Check if a service_key_created event occurred near this revocation to determine if this is a key rotation or a standalone revocation
  3. Check if actor:ip_address is associated with known VPN/proxy services or matches previously seen IP addresses for this actor
Tags:
  - Anthropic
  - Credential Access
Reports:
  MITRE ATT&CK:
    - TA0006:T1098.001  # Account Manipulation: Additional Cloud Credentials

Stages and Predicates

Fires on Anthropic.Activity events when the condition below holds.

Condition

  • type is service_key_revoked

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
typeeq
  • service_key_revoked
field:"type" kind:eq value:"service_key_revoked"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
event_typetype
actor_typeactor.type
actor_emailactor.email_address
actor_user_idactor.user_id
ip_addressactor.ip_address
user_agentactor.user_agent
api_key_idactor.api_key_id
organization_id
ipsp_any_ip_addresses

Response runbook

1. Find all Anthropic.Activity events by actor:email_address in the 6 hours before and after the alert to determine if this is part of routine key rotation or incident response

2. Check if a service_key_created event occurred near this revocation to determine if this is a key rotation or a standalone revocation

3. Check if actor:ip_address is associated with known VPN/proxy services or matches previously seen IP addresses for this actor

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "email_address": "admin@example.com",
    "ip_address": "10.0.0.1",
    "type": "user_actor",
    "user_agent": "Mozilla/5.0",
    "user_id": "user_01ABC"
  },
  "created_at": "2026-05-07T10:00:00Z",
  "id": "activity_01ABC123",
  "organization_id": "org_01XYZ",
  "type": "service_key_revoked"
}

Anthropic Spend Limit Deleted

#
Severity
medium
Group by
actor.email_address
Log types
Anthropic.Activity
Tags
Anthropic, Financial Controls
Source
github.com/panther-labs/panther-analysis

Detects when a platform spend limit is deleted. A deleted spend limit without a subsequent recreate could indicate an attacker removing financial guardrails to enable large-scale API usage or data exfiltration. Note that normal admin workflow often involves a delete immediately followed by a create (editing a limit).

MITRE ATT&CK coverage

TacticTechniques
Impact

Detection logic

from panther_anthropic_helpers import anthropic_actor_id, anthropic_alert_context


def rule(event):
    return event.get("type") == "platform_spend_limit_deleted"


def title(event):
    actor_email = anthropic_actor_id(event)
    return f"Anthropic: Platform spend limit deleted by [{actor_email}]"


def dedup(event):
    return anthropic_actor_id(event)


def alert_context(event):
    return anthropic_alert_context(event)

Rule specification

AnalysisType: rule
RuleID: Anthropic.Activity.Spend.Limit.Deleted
DisplayName: "Anthropic Spend Limit Deleted"
Enabled: true
Filename: anthropic_spend_limit_deleted.py
LogTypes:
  - Anthropic.Activity
Severity: Medium
Description: >
  Detects when a platform spend limit is deleted. A deleted spend limit without
  a subsequent recreate could indicate an attacker removing financial guardrails
  to enable large-scale API usage or data exfiltration. Note that normal admin
  workflow often involves a delete immediately followed by a create (editing a limit).
Runbook: |
  1. Find all Anthropic.Activity events with type platform_spend_limit_created by actor:email_address in the 10 minutes after the alert to determine if this was a delete-then-recreate (normal edit) or a standalone deletion
  2. Check if actor:email_address has performed other administrative actions (claude_organization_settings_updated, role_assignment_granted) in the 6 hours around the alert to assess if this is part of routine admin work
  3. Find all alerts for actor:email_address in the past 7 days to check for signs of account compromise preceding this action
Tags:
  - Anthropic
  - Financial Controls
Reports:
  MITRE ATT&CK:
    - TA0040:T1496  # Resource Hijacking

Stages and Predicates

Fires on Anthropic.Activity events when the condition below holds.

Condition

  • type is platform_spend_limit_deleted

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
typeeq
  • platform_spend_limit_deleted
field:"type" kind:eq value:"platform_spend_limit_deleted"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
event_typetype
actor_typeactor.type
actor_emailactor.email_address
actor_user_idactor.user_id
ip_addressactor.ip_address
user_agentactor.user_agent
api_key_idactor.api_key_id
organization_id
ipsp_any_ip_addresses

Response runbook

1. Find all Anthropic.Activity events with type platform_spend_limit_created by actor:email_address in the 10 minutes after the alert to determine if this was a delete-then-recreate (normal edit) or a standalone deletion

2. Check if actor:email_address has performed other administrative actions (claude_organization_settings_updated, role_assignment_granted) in the 6 hours around the alert to assess if this is part of routine admin work

3. Find all alerts for actor:email_address in the past 7 days to check for signs of account compromise preceding this action

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "email_address": "admin@example.com",
    "ip_address": "10.0.0.1",
    "type": "user_actor",
    "user_agent": "Mozilla/5.0",
    "user_id": "user_01ABC"
  },
  "created_at": "2026-04-30T09:46:26Z",
  "id": "activity_01ABC123",
  "organization_id": "org_01XYZ",
  "type": "platform_spend_limit_deleted"
}

Anthropic SSO Disabled

#
Severity
high
Group by
actor.email_address
Log types
Anthropic.Activity
Tags
Anthropic, Authentication, Defense Evasion
Source
github.com/panther-labs/panther-analysis

Detects when SSO is disabled or an SSO connection is deactivated for the organization. Disabling SSO allows users to bypass the identity provider and use weaker authentication methods. This is a critical security posture change that could indicate an attacker attempting to maintain access without IdP visibility.

MITRE ATT&CK coverage

TacticTechniques
Defense Impairment

Detection logic

from panther_anthropic_helpers import anthropic_actor_id, anthropic_alert_context


def rule(event):
    event_type = event.get("type")
    if event_type == "org_sso_toggled":
        return event.get("is_enabled") in (False, "false")
    if event_type == "org_sso_connection_deactivated":
        return True
    return False


def title(event):
    actor_email = anthropic_actor_id(event)
    event_type = event.get("type")
    if event_type == "org_sso_toggled":
        return f"Anthropic: SSO disabled by [{actor_email}]"
    return f"Anthropic: SSO connection deactivated by [{actor_email}]"


def dedup(event):
    return anthropic_actor_id(event)


def alert_context(event):
    return anthropic_alert_context(event)

Rule specification

AnalysisType: rule
RuleID: Anthropic.Activity.SSO.Disabled
DisplayName: "Anthropic SSO Disabled"
Enabled: true
Filename: anthropic_sso_disabled.py
LogTypes:
  - Anthropic.Activity
Severity: High
Description: >
  Detects when SSO is disabled or an SSO connection is deactivated for the
  organization. Disabling SSO allows users to bypass the identity provider
  and use weaker authentication methods. This is a critical security posture
  change that could indicate an attacker attempting to maintain access
  without IdP visibility.
Runbook: |
  1. Find all Anthropic.Activity events by actor:email_address in the 24 hours before the alert to identify any suspicious activity leading up to the SSO change
  2. Check if actor:ip_address matches previously seen IP addresses for this actor in the past 30 days to detect potential account compromise
  3. Find all SSO-related events (sso_login_failed, sso_login_initiated, sso_login_succeeded) in the 1 hour before and after the alert to understand the authentication context
Tags:
  - Anthropic
  - Authentication
  - Defense Evasion
Reports:
  MITRE ATT&CK:
    - TA0005:T1562.001  # Impair Defenses: Disable or Modify Tools

Stages and Predicates

Fires on Anthropic.Activity events when any of the conditions below holds.

Condition

  • any of:
    • type is org_sso_toggled
    • all of:
      • type is not org_sso_toggled
      • type is org_sso_connection_deactivated

This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
typeeq
  • org_sso_connection_deactivated
  • org_sso_toggled
field:"type" kind:eq
typene
  • org_sso_toggled
field:"type" kind:ne value:"org_sso_toggled"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
event_typetype
actor_typeactor.type
actor_emailactor.email_address
actor_user_idactor.user_id
ip_addressactor.ip_address
user_agentactor.user_agent
api_key_idactor.api_key_id
organization_id
ipsp_any_ip_addresses

Response runbook

1. Find all Anthropic.Activity events by actor:email_address in the 24 hours before the alert to identify any suspicious activity leading up to the SSO change

2. Check if actor:ip_address matches previously seen IP addresses for this actor in the past 30 days to detect potential account compromise

3. Find all SSO-related events (sso_login_failed, sso_login_initiated, sso_login_succeeded) in the 1 hour before and after the alert to understand the authentication context

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "email_address": "admin@example.com",
    "ip_address": "10.0.0.1",
    "type": "user_actor",
    "user_agent": "Mozilla/5.0",
    "user_id": "user_01ABC"
  },
  "created_at": "2026-05-07T10:00:00Z",
  "id": "activity_01ABC123",
  "is_enabled": false,
  "organization_id": "org_01XYZ",
  "type": "org_sso_toggled"
}

Anthropic SSO Login Failed

#
Severity
medium
Group by
actor.email_address
Log types
Anthropic.Activity
Tags
Anthropic, Authentication
Source
github.com/panther-labs/panther-analysis

Detects failed SSO login attempts to the Anthropic organization. The actor is unauthenticated so no email is available — only the source IP. Every failure is alerted on as SSO failures should be rare in normal operation.

MITRE ATT&CK coverage

TacticTechniques
Credential Access

Detection logic

from panther_anthropic_helpers import anthropic_actor_id, anthropic_alert_context


def rule(event):
    return event.get("type") == "sso_login_failed"


def title(event):
    actor = anthropic_actor_id(event)
    return f"Anthropic: SSO login failed from [{actor}]"


def dedup(event):
    return anthropic_actor_id(event)


def alert_context(event):
    return anthropic_alert_context(event)

Rule specification

AnalysisType: rule
RuleID: Anthropic.Activity.SSO.Login.Failed
DisplayName: "Anthropic SSO Login Failed"
Enabled: true
Filename: anthropic_sso_login_failed.py
LogTypes:
  - Anthropic.Activity
Severity: Medium
Description: >
  Detects failed SSO login attempts to the Anthropic organization. The actor
  is unauthenticated so no email is available — only the source IP. Every
  failure is alerted on as SSO failures should be rare in normal operation.
Runbook: |
  1. Find all Anthropic.Activity SSO events (sso_login_initiated, sso_login_succeeded, sso_login_failed) from actor:ip_address in the 1 hour before and after the alert to determine if this was a one-off or part of a burst
  2. Check if actor:ip_address appears in threat intelligence feeds or is associated with known VPN/proxy services
  3. Check if actor:ip_address has been seen in successful sso_login_succeeded events in the past 30 days to determine if this is a known user IP
Tags:
  - Anthropic
  - Authentication
Reports:
  MITRE ATT&CK:
    - TA0006:T1110  # Brute Force

Stages and Predicates

Fires on Anthropic.Activity events when the condition below holds.

Condition

  • type is sso_login_failed

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
typeeq
  • sso_login_failed
field:"type" kind:eq value:"sso_login_failed"

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
event_typetype
actor_typeactor.type
actor_emailactor.email_address
actor_user_idactor.user_id
ip_addressactor.ip_address
user_agentactor.user_agent
api_key_idactor.api_key_id
organization_id
ipsp_any_ip_addresses

Response runbook

1. Find all Anthropic.Activity SSO events (sso_login_initiated, sso_login_succeeded, sso_login_failed) from actor:ip_address in the 1 hour before and after the alert to determine if this was a one-off or part of a burst

2. Check if actor:ip_address appears in threat intelligence feeds or is associated with known VPN/proxy services

3. Check if actor:ip_address has been seen in successful sso_login_succeeded events in the past 30 days to determine if this is a known user IP

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "actor": {
    "ip_address": "192.168.1.1",
    "type": "unauthenticated_user_actor",
    "user_agent": "Mozilla/5.0"
  },
  "created_at": "2026-05-05T21:33:29Z",
  "id": "activity_01ABC123",
  "organization_id": "org_01XYZ",
  "type": "sso_login_failed"
}