Detection rules › Panther

Panther rules: databricks

RuleSeverity
Databricks Access to Multiple Workspacesmedium
Databricks Access Token Revokedinformational
Databricks Account Admin Privileged Role Assignmentmedium
Databricks Account-Level Configuration Changesinformational
Databricks Attempted Logon From Denied IPinformational
Databricks Data Downloads From Control Planemedium
Databricks Data Movement with Explicit Credentialsinformational
Databricks Delta Sharing IP Access Failuresmedium
Databricks Delta Sharing Recipient Without IP ACLsmedium
Databricks Destructive Activitiesmedium
Databricks Employee Logoninformational
Databricks Global Init Script Changesinformational
Databricks Group Createdinformational
Databricks Group Deletedlow
Databricks High Priority Configuration Changesmedium
Databricks Install Library on All Clustersmedium
Databricks Long-Lifetime Token Generatedlow
Databricks Metastore Admin Privilege Grantedmedium
Databricks MFA Key Changeinformational
Databricks Mount Point Creationinformational
Databricks Non-SSO Login Detectedinformational
Databricks Potential Privilege Escalationhigh
Databricks Principal Removed From Groupinformational
Databricks Repeated Access to Secretsmedium
Databricks Repeated Failed Login Attemptsmedium
Databricks Repeated Unauthorized UC Data Requestshigh
Databricks Repeated Unauthorized Unity Catalog Requestsmedium
Databricks SSO Configuration Changedlow
Databricks Terms of Service Changesinformational
Databricks TruffleHog Scan Detectedmedium
Databricks User Account Createdinformational
Databricks User Account Deletedlow
Databricks User Password Changedinformational
Databricks User Role Modifiedinformational
Databricks Verbose Audit Logging Disabledhigh
Databricks Workspace Admin Privileged Role Assignmentmedium
Databricks Workspace-Level Configuration Changesinformational

Databricks Access to Multiple Workspaces

#
Status
Experimental
Severity
medium
Group by
userIdentity.email
Log types
Databricks.Audit
Tags
Databricks, Lateral Movement, Reconnaissance
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects users accessing 5 or more distinct workspaces within 24 hours, which may indicate lateral movement, reconnaissance, or compromised credentials.

MITRE ATT&CK coverage

TacticTechniques
Lateral Movement

Detection logic

from panther_databricks_helpers import SYSTEM_USERS, databricks_alert_context


def rule(event):
    # Filter out system users and unknown
    user = event.deep_get("userIdentity", "email", default="")
    if user in SYSTEM_USERS or user in ("", "unknown"):
        return False

    # Must have workspace context
    return event.get("workspaceId") is not None


def dedup(event):
    user = event.deep_get("userIdentity", "email", default="unknown")
    return user


def unique(event):
    workspace = event.get("workspaceId", "unknown")
    return workspace


def title(event):
    user = event.deep_get("userIdentity", "email", default="Unknown User")
    return f"User accessing multiple workspaces: {user} (≥5 workspaces/day)"


def alert_context(event):
    return databricks_alert_context(event)

Rule specification

AnalysisType: rule
Filename: databricks_access_to_multiple_workspaces.py
RuleID: "Databricks.Audit.AccessToMultipleWorkspaces"
DisplayName: "Databricks Access to Multiple Workspaces"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Lateral Movement
  - Reconnaissance
Reports:
  MITRE ATT&CK:
    - TA0008:T1021 # Remote Services
Severity: Medium
Threshold: 5
DedupPeriodMinutes: 1440
Description: >
  Detects users accessing 5 or more distinct workspaces within 24 hours, which may indicate
  lateral movement, reconnaissance, or compromised credentials.
Runbook: |
  1. Query audit logs for all workspace access by this user in the past 7 days to establish normal patterns
  2. Check if the user performed unusual actions (data downloads, permission changes) across multiple workspaces
  3. Find all users accessing multiple workspaces in the past 30 days to establish baseline
Reference: https://github.com/andyweaves/system-tables-audit-logs/blob/main/resources/queries_and_alerts.json
SummaryAttributes:
  - actor

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • userIdentity.email is not one of System-User
  • userIdentity.email is not one of "", unknown
  • workspaceId is present
Alert cadence
alerts after 5 matches within 1d

Exclusions

The rule actively suppresses these predicates.

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
workspaceIdis_not_null
  • (no value, null check)
field:"workspaceId" kind:is_not_null

Output fields

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

FieldSource
emailuserIdentity.email

Response runbook

1. Query audit logs for all workspace access by this user in the past 7 days to establish normal patterns

2. Check if the user performed unusual actions (data downloads, permission changes) across multiple workspaces

3. Find all users accessing multiple workspaces in the past 30 days to establish baseline

Worked example

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

Sample Test Event
{
  "actionName": "login",
  "response": {
    "statusCode": 200
  },
  "serviceName": "accounts",
  "timestamp": 1704067200000,
  "userIdentity": {
    "email": "user@example.com"
  },
  "workspaceId": "1234567890123456"
}

Databricks Access Token Revoked

#
Status
Experimental
Severity
informational
Group by
requestParams.tokenId
Log types
Databricks.Audit
Tags
Databricks, Defense Evasion
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects revocation of Databricks access tokens. Token revocation may be routine credential rotation or could indicate an attacker covering their tracks after using a compromised token.

MITRE ATT&CK coverage

TacticTechniques
Stealth

Detection logic

from panther_databricks_helpers import databricks_alert_context


def rule(event):
    if event.get("serviceName") != "accounts":
        return False

    return event.get("actionName") == "revokeDbToken"


def title(event):
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    token_id = event.deep_get("requestParams", "tokenId", default="Unknown Token")
    return f"Access token revoked: {token_id} by {actor}"


def dedup(event):
    token_id = event.deep_get("requestParams", "tokenId", default="unknown")
    return f"token_revoked_{token_id}"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={
            "token_id": event.deep_get("requestParams", "tokenId"),
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_access_token_revoked.py
RuleID: "Databricks.Audit.AccessTokenRevoked"
DisplayName: "Databricks Access Token Revoked"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Defense Evasion
Reports:
  MITRE ATT&CK:
    - TA0005:T1070 # Indicator Removal
Severity: Info
Description: >
  Detects revocation of Databricks access tokens. Token revocation may be routine
  credential rotation or could indicate an attacker covering their tracks after
  using a compromised token.
Runbook: |
  1. Verify the token revocation was intentional and authorized
  2. Check if the token was recently created or used from unusual IPs
  3. Look for preceding suspicious activity associated with this token
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/tree/main/base/detections/behavioral

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • serviceName is accounts
  • actionName is revokeDbToken

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
tokenIdrequestParams.tokenId
emailuserIdentity.email

Response runbook

1. Verify the token revocation was intentional and authorized

2. Check if the token was recently created or used from unusual IPs

3. Look for preceding suspicious activity associated with this token

Worked example

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

Sample Test Event
{
  "actionName": "revokeDbToken",
  "requestParams": {
    "tokenId": "dapi-abc123def456"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "accounts",
  "userIdentity": {
    "email": "user@example.com"
  }
}

Databricks Account Admin Privileged Role Assignment

#
Status
Experimental
Severity
medium
Log types
Databricks.Audit
Tags
Databricks, Privilege Escalation, Persistence
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects when account-level admin privileges are granted in Databricks through direct role assignments or administrative group membership. Account admins have extensive control across all workspaces and should be carefully monitored. Successful grants are elevated to HIGH severity.

MITRE ATT&CK coverage

Detection logic

from panther_databricks_helpers import (
    ADMIN_PRIVILEGE_ACTIONS,
    databricks_alert_context,
    extract_group_identifier,
    extract_target_principal,
    get_principal_type,
    is_admin_privilege_action,
)

REMOVAL_ACTIONS = ["removeAdmin", "removePrincipalFromGroup"]


def rule(event):
    # Must be account-level event
    if event.get("auditLevel") != "ACCOUNT_LEVEL":
        return False

    # Exclude privilege removals — this rule detects grants only
    if event.get("actionName") in REMOVAL_ACTIONS:
        return False

    return is_admin_privilege_action(event)


def severity(event):
    status_code = event.deep_get("response", "statusCode")
    return "HIGH" if status_code == 200 else "MEDIUM"


def title(event):
    action = event.get("actionName", "Unknown Action")
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    target = extract_target_principal(event) or "Unknown Principal"
    status_code = event.deep_get("response", "statusCode")
    status = "Granted" if status_code == 200 else "Attempted to grant"

    # Check if it's direct admin action or group-based
    if action in ADMIN_PRIVILEGE_ACTIONS["direct"]:
        return f"{status} account admin privileges to {target} by {actor}"
    group = extract_group_identifier(event)
    return f"{status} admin group membership ({group}) to {target} by {actor}"


def dedup(event):
    target_principal = extract_target_principal(event) or "unknown"
    return f"account_admin_privilege_assignment_{target_principal}"


def alert_context(event):
    target_principal = extract_target_principal(event)
    principal_type = get_principal_type(target_principal) if target_principal else "Unknown"

    return databricks_alert_context(
        event,
        additional_fields={
            "privilege_scope": "ACCOUNT_LEVEL",
            "target_principal": target_principal,
            "principal_type": principal_type,
            "target_group": extract_group_identifier(event),
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_account_admin_privileged_role_assignment.py
RuleID: "Databricks.Audit.AccountAdminPrivilegedRoleAssignment"
DisplayName: "Databricks Account Admin Privileged Role Assignment"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Privilege Escalation
  - Persistence
Reports:
  MITRE ATT&CK:
    - TA0004:T1098 # Account Manipulation
    - TA0003:T1136 # Create Account
Severity: Medium
Description: >
  Detects when account-level admin privileges are granted in Databricks through direct role
  assignments or administrative group membership. Account admins have extensive control across
  all workspaces and should be carefully monitored. Successful grants are elevated to HIGH severity.
Runbook: |
  1. Query audit logs for all account-level administrative actions by the target principal in the 24 hours after this privilege grant
  2. Check if the target principal accessed multiple workspaces or performed bulk operations in the 6 hours after receiving admin rights
  3. Find all account admin grants in the past 90 days to identify unusual patterns or privilege escalation chains
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/blob/main/base/detections/event-based/account_admin_privileged_role_assignment.py
SummaryAttributes:
  - actor
  - target_principal
  - principal_type

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • auditLevel is ACCOUNT_LEVEL
  • actionName is not one of removeAdmin, removePrincipalFromGroup

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

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
actionNameinremoveAdmin, removePrincipalFromGroupexcludes:actionName field:"actionName" value:"removeAdmin" field:"actionName" value:"removePrincipalFromGroup"

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
emailuserIdentity.email

Response runbook

1. Query audit logs for all account-level administrative actions by the target principal in the 24 hours after this privilege grant

2. Check if the target principal accessed multiple workspaces or performed bulk operations in the 6 hours after receiving admin rights

3. Find all account admin grants in the past 90 days to identify unusual patterns or privilege escalation chains

Worked example

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

Sample Test Event
{
  "accountId": "12345678-1234-1234-1234-123456789012",
  "actionName": "setAccountAdmin",
  "auditLevel": "ACCOUNT_LEVEL",
  "requestParams": {
    "targetUserName": "newadmin@example.com"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "accounts",
  "sourceIPAddress": "198.51.100.1",
  "timestamp": 1234567890000,
  "userIdentity": {
    "email": "superadmin@example.com"
  }
}

Databricks Account-Level Configuration Changes

#
Status
Experimental
Severity
informational
Group by
actionName, serviceName
Log types
Databricks.Audit
Tags
Databricks, Persistence
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects configuration changes at the Databricks account level, including account settings, metastore configurations, and SSO settings. Account-level changes affect all workspaces and should be monitored for unauthorized modifications.

MITRE ATT&CK coverage

TacticTechniques
Persistence

Detection logic

from panther_databricks_helpers import databricks_alert_context, is_config_change


def rule(event):
    # Must be account-level audit event
    if event.get("auditLevel") != "ACCOUNT_LEVEL":
        return False

    # Account settings changes
    if is_config_change(event, config_category="account"):
        return True

    # SSO configuration changes
    if is_config_change(event, config_category="sso"):
        return True

    return False


def title(event):
    action = event.get("actionName", "Unknown Action")
    service = event.get("serviceName", "Unknown Service")
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    status_code = event.deep_get("response", "statusCode")
    status = "Success" if status_code == 200 else "Failed"

    return f"Account-level configuration change ({service}.{action}) by {actor} - {status}"


def dedup(event):
    service = event.get("serviceName", "unknown")
    action = event.get("actionName", "unknown")
    return f"account_config_change_{service}_{action}"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={
            "change_scope": "ACCOUNT_LEVEL",
            "request_params": event.get("requestParams"),
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_config_changes_account_level.py
RuleID: "Databricks.Audit.ConfigChangesAccountLevel"
DisplayName: "Databricks Account-Level Configuration Changes"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Persistence
Reports:
  MITRE ATT&CK:
    - TA0003:T1098 # Account Manipulation
Severity: Info
Description: >
  Detects configuration changes at the Databricks account level, including account settings,
  metastore configurations, and SSO settings. Account-level changes affect all workspaces and
  should be monitored for unauthorized modifications.
Runbook: |
  1. Query audit logs for all account-level changes by the actor in the 24 hours around this event
  2. Check if this configuration change affected multiple workspaces based on activity in the 6 hours after the change
  3. Find all account-level configuration changes in the past 30 days to identify patterns
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/blob/main/base/detections/event-based/configuration_changes_account_level.py

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • auditLevel is ACCOUNT_LEVEL
  • any of:
    • serviceName is workspace
    • all of:
      • serviceName is not workspace
      • serviceName is accounts
    • all of:
      • serviceName is not workspace
      • serviceName is not accounts
      • serviceName is ssoConfigBackend
    • serviceName is workspace
    • all of:
      • serviceName is not workspace
      • serviceName is accounts
    • all of:
      • serviceName is not workspace
      • serviceName is not accounts
      • serviceName is ssoConfigBackend

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
auditLeveleq
  • ACCOUNT_LEVEL
field:"auditLevel" kind:eq value:"ACCOUNT_LEVEL"
serviceNameeq
  • accounts
  • ssoConfigBackend
  • workspace
field:"serviceName" kind:eq

Output fields

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

FieldSource
serviceName
actionName
emailuserIdentity.email

Response runbook

1. Query audit logs for all account-level changes by the actor in the 24 hours around this event

2. Check if this configuration change affected multiple workspaces based on activity in the 6 hours after the change

3. Find all account-level configuration changes in the past 30 days to identify patterns

Worked example

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

Sample Test Event
{
  "actionName": "updateAccountSettings",
  "auditLevel": "ACCOUNT_LEVEL",
  "requestParams": {
    "setting": "defaultWorkspaceRegion",
    "value": "us-west-2"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "accounts",
  "sourceIPAddress": "198.51.100.1",
  "timestamp": 1234567890000,
  "userIdentity": {
    "email": "admin@example.com"
  }
}

Databricks Attempted Logon From Denied IP

#
Status
Experimental
Severity
informational
Group by
sourceIPAddress, workspaceId
Log types
Databricks.Audit
Tags
Databricks, Initial Access, Reconnaissance
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects blocked login attempts from IP addresses explicitly denied by workspace IP access control policies. This excludes known service agents and telemetry operations. While these attempts were successfully blocked, they may indicate reconnaissance or unauthorized access attempts.

MITRE ATT&CK coverage

TacticTechniques
Initial Access

Detection logic

from panther_databricks_helpers import databricks_alert_context, filter_noise


def rule(event):
    if event.get("serviceName") != "accounts":
        return False

    if event.get("actionName") != "IpAccessDenied":
        return False

    # Filter out system noise using helper
    if filter_noise(event):
        return False

    return True


def title(event):
    user = event.deep_get("userIdentity", "email", default="Unknown User")
    source_ip = event.get("sourceIPAddress", "Unknown IP")
    workspace = event.get("workspaceId", "Unknown Workspace")
    return (
        f"Blocked login attempt from denied IP {source_ip} for user {user} to workspace {workspace}"
    )


def dedup(event):
    source_ip = event.get("sourceIPAddress", "unknown")
    workspace = event.get("workspaceId", "unknown")
    return f"denied_ip_login_{workspace}_{source_ip}"


def alert_context(event):
    return databricks_alert_context(
        event, additional_fields={"path": event.deep_get("requestParams", "path")}
    )

Rule specification

AnalysisType: rule
Filename: databricks_attempted_logon_from_denied_ip.py
RuleID: "Databricks.Audit.AttemptedLogonFromDeniedIP"
DisplayName: "Databricks Attempted Logon From Denied IP"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Initial Access
  - Reconnaissance
Reports:
  MITRE ATT&CK:
    - TA0001:T1078 # Valid Accounts
Severity: Info
Description: >
  Detects blocked login attempts from IP addresses explicitly denied by workspace IP access
  control policies. This excludes known service agents and telemetry operations. While these
  attempts were successfully blocked, they may indicate reconnaissance or unauthorized access attempts.
Runbook: |
  1. Count all login attempts from the source IP (sourceIPAddress) in the 1 hour before and after this blocked attempt
  2. Check if the source IP is associated with known VPN services, cloud providers, or threat intelligence feeds
  3. Find all successful and failed login attempts for this user in the 24 hours around the alert to identify credential stuffing patterns
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/blob/main/base/detections/event-based/attempted_logon_from_denied_ip.py

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • serviceName is accounts
  • actionName is IpAccessDenied
  • userAgent does not contain Databricks-Service/driver
  • userAgent does not contain Databricks-Runtime
  • userAgent does not contain Delta-Sharing-SparkStructuredStreaming
  • userAgent does not contain RawDBHttpClient
  • userAgent does not contain mlflow-python
  • userAgent does not contain obsSDK-scala
  • userAgent does not contain wsfs
  • userAgent does not contain feature-store
  • requestParams.path does not contain /telemetry
  • requestParams.path does not contain /delta-commit
  • requestParams.path does not contain /health
  • requestParams.path does not contain /metrics
  • requestParams.path does not contain /status

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

Exclusions

The rule actively suppresses these predicates.

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
sourceIPAddress
emailuserIdentity.email
workspaceId

Response runbook

1. Count all login attempts from the source IP (sourceIPAddress) in the 1 hour before and after this blocked attempt

2. Check if the source IP is associated with known VPN services, cloud providers, or threat intelligence feeds

3. Find all successful and failed login attempts for this user in the 24 hours around the alert to identify credential stuffing patterns

Worked example

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

Sample Test Event
{
  "actionName": "IpAccessDenied",
  "requestParams": {
    "path": "/login"
  },
  "response": {
    "statusCode": 403
  },
  "serviceName": "accounts",
  "sourceIPAddress": "192.0.2.100",
  "timestamp": 1234567890000,
  "userAgent": "Mozilla/5.0",
  "userIdentity": {
    "email": "user@example.com"
  },
  "workspaceId": "1234567890123456"
}

Databricks Data Downloads From Control Plane

#
Status
Experimental
Severity
medium
Group by
userIdentity.email
Log types
Databricks.Audit
Tags
Databricks, Exfiltration
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects high volume data downloads from the control plane which may indicate data exfiltration. Monitors download actions including query results, notebooks, and models.

MITRE ATT&CK coverage

TacticTechniques
Exfiltration

Detection logic

from panther_databricks_helpers import DOWNLOAD_ACTIONS, databricks_alert_context


def rule(event):
    action = event.get("actionName")
    if action not in DOWNLOAD_ACTIONS:
        return False

    # Exclude source exports
    if action == "workspaceExport":
        export_format = event.deep_get("requestParams", "workspaceExportFormat")
        if export_format == "SOURCE":
            return False

    # Exclude arrows format
    if action == "downloadQueryResult":
        file_type = event.deep_get("requestParams", "fileType")
        if file_type == "arrows":
            return False

    return True


def dedup(event):
    user = event.deep_get("userIdentity", "email", default="unknown")
    return f"data_download_{user}"


def title(event):
    user = event.deep_get("userIdentity", "email", default="Unknown User")
    action = event.get("actionName", "download")
    return f"High volume data downloads by {user} ({action})"


def alert_context(event):
    return databricks_alert_context(event)

Rule specification

AnalysisType: rule
Filename: databricks_data_downloads_from_control_plane.py
RuleID: "Databricks.Audit.DataDownloadsFromControlPlane"
DisplayName: "Databricks Data Downloads From Control Plane"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Exfiltration
Reports:
  MITRE ATT&CK:
    - TA0010:T1567 # Exfiltration Over Web Service
Severity: Medium
Threshold: 21
DedupPeriodMinutes: 60
Description: >
  Detects high volume data downloads from the control plane which may indicate
  data exfiltration. Monitors download actions including query results, notebooks, and models.
Runbook: |
  1. Query audit logs for all download actions by this user in the past 24 hours to calculate total volume
  2. Check if the downloaded data contains sensitive classifications or PII in the 6 hours around this alert
  3. Find all users with high download rates in the past 30 days to establish baseline
Reference: https://github.com/andyweaves/system-tables-audit-logs/blob/main/resources/queries_and_alerts.json

SummaryAttributes:
  - actor

Stages and Predicates

Fires on Databricks.Audit events when the condition below holds.

Condition

  • actionName is one of downloadPreviewResults, downloadLargeResults, filesGet, getModelVersionDownloadUri, getModelVersionSignedDownloadUri (+2 more values, see Indicators below)

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

Alert cadence
alerts after 21 matches within 1h

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
actionNamein
  • downloadLargeResults
  • downloadPreviewResults
  • downloadQueryResult
  • filesGet
  • getModelVersionDownloadUri
  • getModelVersionSignedDownloadUri
  • workspaceExport
field:"actionName" kind:in

Output fields

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

FieldSource
emailuserIdentity.email
actionName

Response runbook

1. Query audit logs for all download actions by this user in the past 24 hours to calculate total volume

2. Check if the downloaded data contains sensitive classifications or PII in the 6 hours around this alert

3. Find all users with high download rates in the past 30 days to establish baseline

Worked example

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

Sample Test Event
{
  "actionName": "downloadPreviewResults",
  "response": {
    "statusCode": 200
  },
  "serviceName": "sql",
  "timestamp": 1704067200000,
  "userIdentity": {
    "email": "user@example.com"
  }
}

Databricks Data Movement with Explicit Credentials

#
Status
Experimental
Severity
informational
Group by
actionName, userIdentity.email
Log types
Databricks.Audit
Tags
Databricks, Exfiltration
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects creation or modification of storage credentials, connections, and external locations that could facilitate data exfiltration. These operations establish direct paths to external storage and may indicate data movement preparation. Mount point creation is covered separately by Databricks.Audit.MountPointCreation.

MITRE ATT&CK coverage

TacticTechniques
Exfiltration

Detection logic

from panther_databricks_helpers import DATA_MOVEMENT_CREDENTIAL_ACTIONS, databricks_alert_context


def rule(event):
    action = event.get("actionName")
    # mount is covered by databricks_mount_point_creation; skip it here
    return action in DATA_MOVEMENT_CREDENTIAL_ACTIONS and action != "mount"


def title(event):
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    action = event.get("actionName", "unknown")
    workspace = event.get("workspaceId", "Unknown Workspace")
    return f"Data movement credential operation: {action} in workspace {workspace} by {actor}"


def dedup(event):
    actor = event.deep_get("userIdentity", "email", default="unknown")
    action = event.get("actionName", "unknown")
    return f"data_movement_cred_{actor}_{action}"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={
            "request_params": event.get("requestParams"),
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_data_movement_explicit_credentials.py
RuleID: "Databricks.Audit.DataMovementExplicitCredentials"
DisplayName: "Databricks Data Movement with Explicit Credentials"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Exfiltration
Reports:
  MITRE ATT&CK:
    - TA0010:T1537 # Transfer Data to Cloud Account
Severity: Info
Description: >
  Detects creation or modification of storage credentials, connections, and external
  locations that could facilitate data exfiltration. These operations establish direct
  paths to external storage and may indicate data movement preparation. Mount point
  creation is covered separately by Databricks.Audit.MountPointCreation.
Runbook: |
  1. Verify the credential/connection creation was part of an approved workflow
  2. Check the target storage location for sensitivity
  3. Monitor for subsequent data access through the new credential
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/tree/main/base/detections/behavioral

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • actionName is one of mount, createStorageCredential, updateStorageCredential, createConnection, updateConnection
  • actionName is not mount

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
actionNamein
  • createConnection
  • createStorageCredential
  • mount
  • updateConnection
  • updateStorageCredential
field:"actionName" kind:in
actionNamene
  • mount
field:"actionName" kind:ne value:"mount"

Output fields

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

FieldSource
actionName
workspaceId
emailuserIdentity.email

Response runbook

1. Verify the credential/connection creation was part of an approved workflow

2. Check the target storage location for sensitivity

3. Monitor for subsequent data access through the new credential

Worked example

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

Sample Test Event
{
  "actionName": "createStorageCredential",
  "requestParams": {
    "name": "external-s3-cred"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "unityCatalog",
  "userIdentity": {
    "email": "admin@example.com"
  }
}

Databricks Delta Sharing IP Access Failures

#
Status
Experimental
Severity
medium
Log types
Databricks.Audit
Tags
Databricks, Delta Sharing, Initial Access
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects blocked Delta Sharing access attempts due to IP access list restrictions, which may indicate unauthorized access attempts from unexpected locations.

MITRE ATT&CK coverage

TacticTechniques
Initial Access

Detection logic

from panther_databricks_helpers import databricks_alert_context

# Keywords that indicate IP-based access denials
IP_DENIAL_KEYWORDS = ["address", "network", "cidr", "allowlist", "blocklist"]


def rule(event):
    if event.get("serviceName") != "deltaSharingAccess":
        return False

    status_code = event.deep_get("response", "statusCode")
    if status_code not in [403, 401]:
        return False

    error_message = event.deep_get("response", "errorMessage", default="").lower()
    return any(keyword in error_message for keyword in IP_DENIAL_KEYWORDS)


def title(event):
    recipient = event.deep_get("requestParams", "recipientName", default="Unknown Recipient")
    source_ip = event.get("sourceIPAddress", "Unknown IP")
    return f"Delta Sharing access blocked from {source_ip} for recipient {recipient}"


def alert_context(event):
    return databricks_alert_context(event)

Rule specification

AnalysisType: rule
Filename: databricks_delta_sharing_ip_access_failures.py
RuleID: "Databricks.Audit.DeltaSharingIPAccessFailures"
DisplayName: "Databricks Delta Sharing IP Access Failures"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Delta Sharing
  - Initial Access
Reports:
  MITRE ATT&CK:
    - TA0001:T1078 # Valid Accounts
Severity: Medium
Description: >
  Detects blocked Delta Sharing access attempts due to IP access list restrictions,
  which may indicate unauthorized access attempts from unexpected locations.
Runbook: |
  1. Query audit logs for all Delta Sharing access attempts from this IP in the past 24 hours
  2. Check if the source IP is associated with known threats or unexpected geographic locations
  3. Find all Delta Sharing access failures in the past 7 days to identify patterns
Reference: https://github.com/andyweaves/system-tables-audit-logs/blob/main/resources/queries_and_alerts.json

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • serviceName is deltaSharingAccess
  • response.statusCode is one of 403, 401
  • any of:
    • response.errorMessage contains address
    • response.errorMessage contains network
    • response.errorMessage contains cidr
    • response.errorMessage contains allowlist
    • response.errorMessage contains blocklist

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
response.errorMessagecontains
  • address
  • allowlist
  • blocklist
  • cidr
  • network
field:"response.errorMessage" kind:contains
response.statusCodein
  • 401 transforms: number
  • 403 transforms: number
field:"response.statusCode" kind:in
serviceNameeq
  • deltaSharingAccess
field:"serviceName" kind:eq value:"deltaSharingAccess"

Output fields

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

FieldSource
sourceIPAddress
recipientNamerequestParams.recipientName

Response runbook

1. Query audit logs for all Delta Sharing access attempts from this IP in the past 24 hours

2. Check if the source IP is associated with known threats or unexpected geographic locations

3. Find all Delta Sharing access failures in the past 7 days to identify patterns

Worked example

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

Sample Test Event
{
  "actionName": "getShare",
  "response": {
    "errorMessage": "IP address not allowed",
    "statusCode": 403
  },
  "serviceName": "deltaSharingAccess",
  "sourceIPAddress": "203.0.113.50",
  "timestamp": 1704067200000
}

Databricks Delta Sharing Recipient Without IP ACLs

#
Status
Experimental
Severity
medium
Log types
Databricks.Audit
Tags
Databricks, Delta Sharing, Defense Evasion
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects creation of Delta Sharing recipients without IP access list restrictions, which could allow unauthorized data access from any location.

MITRE ATT&CK coverage

TacticTechniques
Defense Impairment

Detection logic

from panther_databricks_helpers import databricks_alert_context


def rule(event):
    if event.get("actionName") != "createRecipient":
        return False

    # Check if IP access list is configured
    # Alert if IP ACL is missing, empty string, or empty list (all falsy)
    ip_access_list = event.deep_get("requestParams", "ipAccessList")
    return not ip_access_list


def title(event):
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    recipient = event.deep_get("requestParams", "name", default="Unknown Recipient")
    return f"Delta Sharing recipient created without IP ACLs: {recipient} by {actor}"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={"recipient_name": event.deep_get("requestParams", "name")},
    )

Rule specification

AnalysisType: rule
Filename: databricks_delta_sharing_recipient_without_ip_acls.py
RuleID: "Databricks.Audit.DeltaSharingRecipientWithoutIPACLs"
DisplayName: "Databricks Delta Sharing Recipient Without IP ACLs"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Delta Sharing
  - Defense Evasion
Reports:
  MITRE ATT&CK:
    - TA0005:T1562 # Impair Defenses
Severity: Medium
Description: >
  Detects creation of Delta Sharing recipients without IP access list restrictions,
  which could allow unauthorized data access from any location.
Runbook: |
  1. Query audit logs for all Delta Sharing recipient creations in the past 30 days
  2. Check if this recipient has accessed shared data in the 24 hours after creation
  3. Find all recipients without IP ACLs to establish security posture
Reference: https://github.com/andyweaves/system-tables-audit-logs/blob/main/resources/queries_and_alerts.json

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • actionName is createRecipient
  • requestParams.ipAccessList is empty

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
namerequestParams.name
emailuserIdentity.email

Response runbook

1. Query audit logs for all Delta Sharing recipient creations in the past 30 days

2. Check if this recipient has accessed shared data in the 24 hours after creation

3. Find all recipients without IP ACLs to establish security posture

Worked example

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

Sample Test Event
{
  "actionName": "createRecipient",
  "requestParams": {
    "name": "external-partner"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "deltaSharingControl",
  "timestamp": 1704067200000,
  "userIdentity": {
    "email": "admin@example.com"
  }
}

Databricks Destructive Activities

#
Status
Experimental
Severity
medium
Group by
userIdentity.email
Log types
Databricks.Audit
Tags
Databricks, Impact
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects high volume destructive activities by a single user which may indicate malicious data destruction, ransomware, or insider threats.

MITRE ATT&CK coverage

TacticTechniques
Impact

Detection logic

from panther_databricks_helpers import SYSTEM_USERS, databricks_alert_context

# Destructive action prefixes/names to match
DESTRUCTIVE_PREFIXES = ["delete", "drop", "trash", "destroy", "purge"]


def rule(event):
    action = event.get("actionName", "").lower()

    # Exclude system users
    user = event.deep_get("userIdentity", "email", default="")
    if user in SYSTEM_USERS:
        return False

    # Exclude non-destructive actions that contain "delete" as substring
    if action.startswith("undelete") or action.startswith("restore"):
        return False

    # Check for destructive action prefixes
    return any(action.startswith(prefix) for prefix in DESTRUCTIVE_PREFIXES)


def dedup(event):
    user = event.deep_get("userIdentity", "email", default="unknown")
    return f"destructive_{user}"


def title(event):
    user = event.deep_get("userIdentity", "email", default="Unknown User")
    action = event.get("actionName", "delete")
    return f"High volume destructive activities by {user} (>50/day, action: {action})"


def alert_context(event):
    return databricks_alert_context(event)

Rule specification

AnalysisType: rule
Filename: databricks_destructive_activities.py
RuleID: "Databricks.Audit.DestructiveActivities"
DisplayName: "Databricks Destructive Activities"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Impact
Reports:
  MITRE ATT&CK:
    - TA0040:T1485 # Data Destruction
Severity: Medium
Threshold: 50
DedupPeriodMinutes: 1440
Description: >
  Detects high volume destructive activities by a single user which may indicate
  malicious data destruction, ransomware, or insider threats.
Runbook: |
  1. Query audit logs for all delete actions by this user in the past 7 days to identify patterns
  2. Check if deleted resources can be recovered or if backups exist
  3. Find all users with high deletion rates in the past 30 days to establish baseline
Reference: https://github.com/andyweaves/system-tables-audit-logs/blob/main/resources/queries_and_alerts.json
SummaryAttributes:
  - actor

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • userIdentity.email is not one of System-User
  • actionName does not start with undelete
  • actionName does not start with restore
  • any of:
    • actionName starts with delete
    • actionName starts with drop
    • actionName starts with trash
    • actionName starts with destroy
    • actionName starts with purge
Alert cadence
alerts after 50 matches within 1d

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
actionNamestarts_withrestoreexcludes:actionName field:"actionName" value:"restore"
actionNamestarts_withundeleteexcludes:actionName field:"actionName" value:"undelete"
userIdentity.emaileqSystem-Userexcludes:userIdentity.email field:"userIdentity.email" value:"System-User"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
actionNamestarts_with
  • delete
  • destroy
  • drop
  • purge
  • trash
field:"actionName" kind:starts_with

Output fields

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

FieldSource
emailuserIdentity.email
actionName

Response runbook

1. Query audit logs for all delete actions by this user in the past 7 days to identify patterns

2. Check if deleted resources can be recovered or if backups exist

3. Find all users with high deletion rates in the past 30 days to establish baseline

Worked example

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

Sample Test Event
{
  "actionName": "deleteTable",
  "response": {
    "statusCode": 200
  },
  "serviceName": "unityCatalog",
  "timestamp": 1704067200000,
  "userIdentity": {
    "email": "user@example.com"
  }
}

Databricks Employee Logon

#
Status
Experimental
Severity
informational
Log types
Databricks.Audit
Tags
Databricks, Initial Access
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects when a Databricks employee successfully logs into a workspace using GENIE_AUTH authentication. This is typically for legitimate support purposes but should be tracked for awareness.

MITRE ATT&CK coverage

TacticTechniques
Initial Access

Detection logic

from panther_databricks_helpers import (
    databricks_alert_context,
    is_databricks_employee_auth,
    is_login_action,
)


def rule(event):
    if event.get("serviceName") != "accounts":
        return False

    if not is_login_action(event):
        return False

    if not is_databricks_employee_auth(event):
        return False

    # Check for successful response
    status_code = event.deep_get("response", "statusCode")
    if status_code != 200:
        return False

    # Check for workspace-level audit
    if event.get("auditLevel") != "WORKSPACE_LEVEL":
        return False

    return True


def title(event):
    user = event.deep_get("userIdentity", "email", default="Unknown User")
    workspace = event.get("workspaceId", "Unknown Workspace")
    return f"Databricks employee logged into workspace {workspace} as {user}"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={"auth_method": event.deep_get("requestParams", "authentication_method")},
    )

Rule specification

AnalysisType: rule
Filename: databricks_employee_logon.py
RuleID: "Databricks.Audit.EmployeeLogon"
DisplayName: "Databricks Employee Logon"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Initial Access
Reports:
  MITRE ATT&CK:
    - TA0001:T1078 # Valid Accounts
Severity: Info
Description: >
  Detects when a Databricks employee successfully logs into a workspace using GENIE_AUTH authentication.
  This is typically for legitimate support purposes but should be tracked for awareness.
Runbook: |
  1. Query Databricks audit logs for all actions by this Databricks employee (userIdentity.email) in the 24 hours before and after the alert
  2. Check if there are open support cases or authorized maintenance windows that would explain this employee access
  3. Find all other Databricks employee logins to this workspace in the past 30 days to identify patterns
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/blob/main/base/detections/event-based/databricks_employee_logon.py

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • serviceName is accounts
  • actionName is one of aadBrowserLogin, aadTokenLogin, certLogin, jwtLogin, login (+5 more values, see Indicators below)
  • requestParams.authentication_method is GENIE_AUTH
  • response.statusCode is 200
  • auditLevel is WORKSPACE_LEVEL

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
workspaceId
emailuserIdentity.email

Response runbook

1. Query Databricks audit logs for all actions by this Databricks employee (userIdentity.email) in the 24 hours before and after the alert

2. Check if there are open support cases or authorized maintenance windows that would explain this employee access

3. Find all other Databricks employee logins to this workspace in the past 30 days to identify patterns

Worked example

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

Sample Test Event
{
  "accountId": "12345678-1234-1234-1234-123456789012",
  "actionName": "login",
  "auditLevel": "WORKSPACE_LEVEL",
  "requestId": "req-123",
  "requestParams": {
    "authentication_method": "GENIE_AUTH"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "accounts",
  "sessionId": "session-123",
  "sourceIPAddress": "198.51.100.1",
  "timestamp": 1234567890000,
  "userAgent": "Mozilla/5.0",
  "userIdentity": {
    "email": "support@databricks.com"
  },
  "version": "2.0",
  "workspaceId": "1234567890123456"
}

Databricks Global Init Script Changes

#
Status
Experimental
Severity
informational
Group by
requestParams.name, requestParams.script_id
Log types
Databricks.Audit
Tags
Databricks, Persistence, Execution
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects modifications to global initialization scripts which run on all clusters at startup. These scripts can be used for persistence or to execute malicious code across the environment. All script creations, updates, and deletions are monitored.

MITRE ATT&CK coverage

Detection logic

from panther_databricks_helpers import databricks_alert_context


def rule(event):
    return event.get("serviceName") == "globalInitScripts"


def title(event):
    action = event.get("actionName", "Unknown Action")
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    script_name = event.deep_get("requestParams", "name", default="Unknown Script")
    return f"Global init script {action}: {script_name} by {actor}"


def dedup(event):
    script_name = event.deep_get("requestParams", "name", default="unknown")
    script_id = event.deep_get("requestParams", "script_id", default="unknown")
    return f"global_init_script_{script_id}_{script_name}"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={
            "script_name": event.deep_get("requestParams", "name"),
            "script_id": event.deep_get("requestParams", "script_id"),
            "script_enabled": event.deep_get("requestParams", "enabled"),
            "script_sha256": event.deep_get("requestParams", "script-SHA256"),
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_global_init_script_changes.py
RuleID: "Databricks.Audit.GlobalInitScriptChanges"
DisplayName: "Databricks Global Init Script Changes"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Persistence
  - Execution
Reports:
  MITRE ATT&CK:
    - TA0003:T1037 # Boot or Logon Initialization Scripts
    - TA0002:T1059 # Command and Scripting Interpreter
Severity: Info
Description: >
  Detects modifications to global initialization scripts which run on all clusters at startup.
  These scripts can be used for persistence or to execute malicious code across the environment.
  All script creations, updates, and deletions are monitored.
Runbook: |
  1. Query audit logs for all global init script changes by this actor in the past 30 days
  2. Check if new clusters were created shortly after the script modification in the 6 hours after this change
  3. Find all script modifications across all workspaces in the past 7 days to identify coordinated changes
Reference: https://github.com/andyweaves/system-tables-audit-logs/blob/main/resources/queries_and_alerts.json
SummaryAttributes:
  - actor
  - script_name
  - action

Stages and Predicates

Fires on Databricks.Audit events when the condition below holds.

Condition

  • serviceName is globalInitScripts

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
actionName
namerequestParams.name
emailuserIdentity.email

Response runbook

1. Query audit logs for all global init script changes by this actor in the past 30 days

2. Check if new clusters were created shortly after the script modification in the 6 hours after this change

3. Find all script modifications across all workspaces in the past 7 days to identify coordinated changes

Worked example

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

Sample Test Event
{
  "actionName": "create",
  "requestParams": {
    "enabled": "true",
    "name": "security-monitoring",
    "script-SHA256": "abc123def456",
    "script_id": "script-123"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "globalInitScripts",
  "sourceIPAddress": "198.51.100.1",
  "timestamp": 1704067200000,
  "userIdentity": {
    "email": "admin@example.com"
  },
  "workspaceId": "1234567890123456"
}

Databricks Group Created

#
Status
Experimental
Severity
informational
Log types
Databricks.Audit
Tags
Databricks, Persistence
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects creation of user groups in Databricks. Group creation may be part of normal administration or could indicate privilege escalation preparation by creating a group that will later receive elevated permissions.

MITRE ATT&CK coverage

TacticTechniques
Persistence

Detection logic

from panther_databricks_helpers import databricks_alert_context, extract_group_identifier


def rule(event):
    if event.get("serviceName") != "accounts":
        return False

    return event.get("actionName") == "createGroup"


def title(event):
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    group = extract_group_identifier(event) or event.deep_get(
        "requestParams", "groupName", default="Unknown Group"
    )
    return f"Group created: {group} by {actor}"


def dedup(event):
    group = extract_group_identifier(event) or "unknown"
    return f"group_created_{group}"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={
            "group_name": extract_group_identifier(event),
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_group_created.py
RuleID: "Databricks.Audit.GroupCreated"
DisplayName: "Databricks Group Created"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Persistence
Reports:
  MITRE ATT&CK:
    - TA0003:T1136 # Create Account
Severity: Info
Description: >
  Detects creation of user groups in Databricks. Group creation may be part of normal
  administration or could indicate privilege escalation preparation by creating a group
  that will later receive elevated permissions.
Runbook: |
  1. Verify the group creation was part of an approved workflow
  2. Check if the group was subsequently granted admin or elevated permissions
  3. Review group membership additions following creation
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/tree/main/base/detections/behavioral

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • serviceName is accounts
  • actionName is createGroup

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
emailuserIdentity.email

Response runbook

1. Verify the group creation was part of an approved workflow

2. Check if the group was subsequently granted admin or elevated permissions

3. Review group membership additions following creation

Worked example

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

Sample Test Event
{
  "actionName": "createGroup",
  "requestParams": {
    "targetGroupName": "data-engineers"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "accounts",
  "userIdentity": {
    "email": "admin@example.com"
  }
}

Databricks Group Deleted

#
Status
Experimental
Severity
low
Log types
Databricks.Audit
Tags
Databricks, Impact
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects group deletions in Databricks accounts. While often part of normal cleanup processes, unauthorized group deletions could indicate access control dismantling. Successful deletions are elevated to HIGH severity.

MITRE ATT&CK coverage

TacticTechniques
Impact

Detection logic

from panther_databricks_helpers import (
    databricks_alert_context,
    extract_group_identifier,
    should_alert_on_group_change,
)


def rule(event):
    return should_alert_on_group_change(event, change_type="delete")


def severity(event):
    status_code = event.deep_get("response", "statusCode")
    return "HIGH" if status_code == 200 else "LOW"


def title(event):
    group_id = extract_group_identifier(event) or "Unknown Group"
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    status_code = event.deep_get("response", "statusCode")
    status = "Success" if status_code == 200 else "Failed"
    return f"Group deletion {status}: {group_id} by {actor}"


def dedup(event):
    group_id = extract_group_identifier(event) or "unknown"
    return f"group_deleted_{group_id}"


def alert_context(event):
    group_id = extract_group_identifier(event)
    return databricks_alert_context(event, additional_fields={"group_id": group_id})

Rule specification

AnalysisType: rule
Filename: databricks_group_deleted.py
RuleID: "Databricks.Audit.GroupDeleted"
DisplayName: "Databricks Group Deleted"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Impact
Reports:
  MITRE ATT&CK:
    - TA0040:T1531 # Account Access Removal
Severity: Low
Description: >
  Detects group deletions in Databricks accounts. While often part of normal cleanup processes,
  unauthorized group deletions could indicate access control dismantling. Successful deletions
  are elevated to HIGH severity.
Runbook: |
  1. Query audit logs for all members who were in this group in the 24 hours before deletion
  2. Check if this group had admin privileges or access to sensitive resources based on past 30 days of activity
  3. Find all group deletions by this actor in the past 30 days to identify bulk deletion patterns
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/blob/main/base/detections/event-based/group_deleted.py

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • userAgent does not contain Databricks-Service/driver
  • userAgent does not contain Databricks-Runtime
  • userAgent does not contain Delta-Sharing-SparkStructuredStreaming
  • userAgent does not contain RawDBHttpClient
  • userAgent does not contain mlflow-python
  • userAgent does not contain obsSDK-scala
  • userAgent does not contain wsfs
  • userAgent does not contain feature-store
  • requestParams.path does not contain /telemetry
  • requestParams.path does not contain /delta-commit
  • requestParams.path does not contain /health
  • requestParams.path does not contain /metrics
  • requestParams.path does not contain /status
  • serviceName is accounts

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

Exclusions

The rule actively suppresses these predicates.

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
emailuserIdentity.email

Response runbook

1. Query audit logs for all members who were in this group in the 24 hours before deletion

2. Check if this group had admin privileges or access to sensitive resources based on past 30 days of activity

3. Find all group deletions by this actor in the past 30 days to identify bulk deletion patterns

Worked example

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

Sample Test Event
{
  "actionName": "removeGroup",
  "requestParams": {
    "targetGroupId": "group-123"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "accounts",
  "sourceIPAddress": "198.51.100.1",
  "timestamp": 1234567890000,
  "userIdentity": {
    "email": "admin@example.com"
  }
}

Databricks High Priority Configuration Changes

#
Status
Experimental
Severity
medium
Log types
Databricks.Audit
Tags
Databricks, Defense Evasion, Persistence
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects high-priority security configuration changes including audit logging modifications, IP access list changes, and security-critical workspace settings. Severity is elevated for successful changes to high-risk settings.

MITRE ATT&CK coverage

Detection logic

from panther_databricks_helpers import (
    databricks_alert_context,
    get_config_key_value,
    is_critical_config_change,
)


def rule(event):
    if not is_critical_config_change(event):
        return False

    # Verbose audit logging disabled is handled by a dedicated rule
    config_key, config_value = get_config_key_value(event)
    if config_key == "enableVerboseAuditLogs" and config_value == "false":
        return False

    return True


def severity(event):
    status_code = event.deep_get("response", "statusCode")
    success = status_code == 200
    action = event.get("actionName", "Unknown Action")

    # Determine severity from action type
    #                        Success    Failure
    # IP access list deleted HIGH       MEDIUM
    # Other critical configs MEDIUM     LOW
    if action == "deleteIpAccessList":
        return "HIGH" if success else "MEDIUM"
    return "MEDIUM" if success else "LOW"


def title(event):
    action = event.get("actionName", "Unknown Action")
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    status_code = event.deep_get("response", "statusCode")
    status = "Successfully" if status_code == 200 else "Attempted to"

    # IP access list changes
    if "IpAccessList" in action:
        return f"{status} {action} by {actor}"

    # Workspace configuration edits
    config_key, config_value = get_config_key_value(event)
    if config_key:
        return f"{status} modify {config_key} to {config_value} by {actor}"

    return f"Critical configuration change by {actor}"


def dedup(event):
    config_key, _ = get_config_key_value(event)
    # IP access list events don't have workspaceConfKeys, so fall back to actionName
    key = config_key or event.get("actionName", "unknown")
    return f"critical_config_change_{key}"


def alert_context(event):
    config_key, config_value = get_config_key_value(event)
    return databricks_alert_context(
        event,
        additional_fields={
            "config_key": config_key,
            "config_value": config_value,
            "change_category": (
                "IP Access List"
                if "IpAccessList" in event.get("actionName", "")
                else "Workspace Configuration"
            ),
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_config_changes_high_priority.py
RuleID: "Databricks.Audit.ConfigChangesHighPriority"
DisplayName: "Databricks High Priority Configuration Changes"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Defense Evasion
  - Persistence
Reports:
  MITRE ATT&CK:
    - TA0005:T1562.008 # Impair Defenses: Disable Cloud Logs
    - TA0003:T1098 # Account Manipulation
Severity: Medium
Description: >
  Detects high-priority security configuration changes including audit logging modifications,
  IP access list changes, and security-critical workspace settings. Severity is elevated for
  successful changes to high-risk settings.
Runbook: |
  1. Query audit logs for all configuration changes by the actor in the 24 hours before and after this critical change
  2. Check if this configuration change has been performed by this actor in the past 90 days to establish legitimacy
  3. Find all other high-risk configuration changes (IP access lists, audit settings) across all workspaces in the past 7 days
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/blob/main/base/detections/event-based/configuration_changes_high_priority.py
SummaryAttributes:
  - actor
  - config_key
  - change_category

Stages and Predicates

Fires on Databricks.Audit events when the condition below holds.

Condition

  • actionName is one of createIpAccessList, updateIpAccessList, deleteIpAccessList

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
actionNamein
  • createIpAccessList
  • deleteIpAccessList
  • updateIpAccessList
field:"actionName" kind:in

Output fields

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

FieldSource
actionName
emailuserIdentity.email

Response runbook

1. Query audit logs for all configuration changes by the actor in the 24 hours before and after this critical change

2. Check if this configuration change has been performed by this actor in the past 90 days to establish legitimacy

3. Find all other high-risk configuration changes (IP access lists, audit settings) across all workspaces in the past 7 days

Worked example

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

Sample Test Event
{
  "actionName": "workspaceConfEdit",
  "requestParams": {
    "workspaceConfKeys": "enableVerboseAuditLogs",
    "workspaceConfValues": "true"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "workspace",
  "sourceIPAddress": "198.51.100.1",
  "timestamp": 1234567890000,
  "userIdentity": {
    "email": "admin@example.com"
  }
}

Databricks Install Library on All Clusters

#
Status
Experimental
Severity
medium
Log types
Databricks.Audit
Tags
Databricks, Execution, Persistence
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects use of the deprecated installLibraryOnAllClusters action. This anti-pattern can introduce security risks by installing potentially malicious libraries across the entire environment without proper review or controls.

MITRE ATT&CK coverage

Detection logic

from panther_databricks_helpers import databricks_alert_context


def rule(event):
    return event.get("actionName") == "installLibraryOnAllClusters"


def title(event):
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    workspace = event.get("workspaceId", "Unknown Workspace")
    return f"Library installed on all clusters in workspace {workspace} by {actor}"


def alert_context(event):
    return databricks_alert_context(
        event, additional_fields={"library_config": event.get("requestParams")}
    )

Rule specification

AnalysisType: rule
Filename: databricks_install_library_all_clusters.py
RuleID: "Databricks.Audit.InstallLibraryAllClusters"
DisplayName: "Databricks Install Library on All Clusters"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Execution
  - Persistence
Reports:
  MITRE ATT&CK:
    - TA0002:T1203 # Exploitation for Client Execution
    - TA0003:T1543 # Create or Modify System Process
Severity: Medium
Description: >
  Detects use of the deprecated installLibraryOnAllClusters action. This anti-pattern can
  introduce security risks by installing potentially malicious libraries across the entire
  environment without proper review or controls.
Runbook: |
  1. Query audit logs for the library installation details and identify what library was installed
  2. Check if this library has been used in notebook or job execution in the 24 hours after installation
  3. Find all library installations by this user in the past 30 days to identify patterns
Reference: https://github.com/andyweaves/system-tables-audit-logs/blob/main/resources/queries_and_alerts.json
SummaryAttributes:
  - actor
  - workspace_id

Stages and Predicates

Fires on Databricks.Audit events when the condition below holds.

Condition

  • actionName is installLibraryOnAllClusters

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
actionNameeq
  • installLibraryOnAllClusters
field:"actionName" kind:eq value:"installLibraryOnAllClusters"

Output fields

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

FieldSource
workspaceId
emailuserIdentity.email

Response runbook

1. Query audit logs for the library installation details and identify what library was installed

2. Check if this library has been used in notebook or job execution in the 24 hours after installation

3. Find all library installations by this user in the past 30 days to identify patterns

Worked example

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

Sample Test Event
{
  "actionName": "installLibraryOnAllClusters",
  "requestParams": {
    "library": {
      "pypi": {
        "package": "suspicious-package"
      }
    }
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "clusters",
  "sourceIPAddress": "198.51.100.1",
  "timestamp": 1704067200000,
  "userIdentity": {
    "email": "developer@example.com"
  },
  "workspaceId": "1234567890123456"
}

Databricks Long-Lifetime Token Generated

#
Status
Experimental
Severity
low
Log types
Databricks.Audit
Tags
Databricks, Credential Access, Persistence
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects generation of personal access tokens (PATs) with lifetime exceeding 72 hours. Long-lived tokens increase the risk of credential theft and unauthorized access if compromised. Tokens with lifetime >90 days are elevated to MEDIUM, >1 year to HIGH severity.

MITRE ATT&CK coverage

Detection logic

from panther_databricks_helpers import databricks_alert_context


def _token_duration_hours(event):
    """Calculate token lifetime in hours, or None if not determinable."""
    try:
        token_expiration = int(event.deep_get("requestParams", "tokenExpirationTime", default=0))
        event_time_ms = event.get("timestamp", 0)
        if not token_expiration or not event_time_ms:
            return None
        return (token_expiration - event_time_ms) / (1000 * 3600)
    except (ValueError, TypeError):
        return None


def rule(event):
    if event.get("actionName") != "generateDbToken":
        return False

    duration = _token_duration_hours(event)
    return duration is not None and duration > 72


def severity(event):
    duration = _token_duration_hours(event)
    if duration is None:
        return "LOW"

    #                    Severity
    # >1 year (8760h)   HIGH
    # >90 days (2160h)  MEDIUM
    # otherwise         LOW
    if duration > 8760:
        return "HIGH"
    if duration > 2160:
        return "MEDIUM"
    return "LOW"


def title(event):
    actor = event.deep_get("userIdentity", "email", default="Unknown User")
    duration = _token_duration_hours(event)
    if duration is not None:
        return f"Long-lifetime token ({int(duration / 24)} days) generated by {actor}"
    return f"Long-lifetime token generated by {actor}"


def alert_context(event):
    duration = _token_duration_hours(event)
    duration_days = duration / 24 if duration is not None else None

    return databricks_alert_context(
        event,
        additional_fields={
            "token_expiration_time": event.deep_get("requestParams", "tokenExpirationTime"),
            "token_hash": event.deep_get("requestParams", "tokenHash"),
            "token_duration_hours": duration,
            "token_duration_days": duration_days,
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_long_lifetime_token_generated.py
RuleID: "Databricks.Audit.LongLifetimeTokenGenerated"
DisplayName: "Databricks Long-Lifetime Token Generated"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Credential Access
  - Persistence
Reports:
  MITRE ATT&CK:
    - TA0006:T1550 # Use Alternate Authentication Material
    - TA0003:T1098 # Account Manipulation
Severity: Low
Description: >
  Detects generation of personal access tokens (PATs) with lifetime exceeding 72 hours.
  Long-lived tokens increase the risk of credential theft and unauthorized access if compromised.
  Tokens with lifetime >90 days are elevated to MEDIUM, >1 year to HIGH severity.
Runbook: |
  1. Query audit logs for all token generation by this user in the past 30 days to identify patterns
  2. Check if the generated token has been used for API calls in the 24 hours after creation
  3. Find all other long-lifetime tokens (>72 hours) created in the past 90 days to establish baseline
Reference: https://github.com/andyweaves/system-tables-audit-logs/blob/main/resources/queries_and_alerts.json
SummaryAttributes:
  - actor
  - token_duration_days

Stages and Predicates

Fires on Databricks.Audit events when the condition below holds.

Condition

  • actionName is generateDbToken

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.

Output fields

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

FieldSource
emailuserIdentity.email

Response runbook

1. Query audit logs for all token generation by this user in the past 30 days to identify patterns

2. Check if the generated token has been used for API calls in the 24 hours after creation

3. Find all other long-lifetime tokens (>72 hours) created in the past 90 days to establish baseline

Worked example

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

Sample Test Event
{
  "actionName": "generateDbToken",
  "requestParams": {
    "tokenExpirationTime": "1704672000000",
    "tokenHash": "abc123def456"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "accounts",
  "sourceIPAddress": "198.51.100.1",
  "timestamp": 1704067200000,
  "userIdentity": {
    "email": "user@example.com"
  },
  "workspaceId": "1234567890123456"
}

Databricks Metastore Admin Privilege Granted

#
Status
Experimental
Severity
medium
Group by
requestParams.metastoreId, requestParams.principal
Log types
Databricks.Audit
Tags
Databricks, Privilege Escalation, Unity Catalog
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects when metastore admin privileges are granted in Databricks through direct metastore ownership changes or addition to metastore admin groups. Metastore admins have extensive control over data access and governance policies in Unity Catalog.

MITRE ATT&CK coverage

TacticTechniques
Privilege Escalation

Detection logic

from panther_databricks_helpers import databricks_alert_context, is_metastore_admin_action


def rule(event):
    # Use helper to check for metastore admin actions
    if not is_metastore_admin_action(event):
        return False

    action = event.get("actionName", "")

    # For group membership changes, only alert on additions (not removals)
    # and ensure it's at the account level
    if action != "updateMetastore":
        # Exclude removals
        if action == "removePrincipalFromGroup":
            return False
        # Must be account-level event
        if event.get("serviceName") != "accounts":
            return False

    return True


def title(event):
    action = event.get("actionName", "Unknown Action")
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")

    if action == "updateMetastore":
        new_owner = event.deep_get("requestParams", "owner", default="Unknown Owner")
        return f"Metastore ownership changed to {new_owner} by {actor}"
    target_group = event.deep_get("requestParams", "targetGroupName", default="Unknown Group")
    principal = event.deep_get("requestParams", "principal") or event.deep_get(
        "requestParams", "targetUserName", default="Unknown Principal"
    )
    return f"Principal {principal} added to metastore admin group {target_group} by {actor}"


def dedup(event):
    action = event.get("actionName", "unknown")
    if action == "updateMetastore":
        metastore_id = event.deep_get("requestParams", "metastoreId", default="unknown")
        return f"metastore_admin_{metastore_id}"
    principal = event.deep_get("requestParams", "principal") or event.deep_get(
        "requestParams", "targetUserName", default="unknown"
    )
    return f"metastore_admin_group_{principal}"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={
            "new_owner": event.deep_get("requestParams", "owner"),
            "target_group": event.deep_get("requestParams", "targetGroupName"),
            "principal": event.deep_get("requestParams", "principal")
            or event.deep_get("requestParams", "targetUserName"),
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_metastore_admin_privilege_granted.py
RuleID: "Databricks.Audit.MetastoreAdminPrivilegeGranted"
DisplayName: "Databricks Metastore Admin Privilege Granted"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Privilege Escalation
  - Unity Catalog
Reports:
  MITRE ATT&CK:
    - TA0004:T1098 # Account Manipulation
Severity: Medium
Description: >
  Detects when metastore admin privileges are granted in Databricks through direct metastore
  ownership changes or addition to metastore admin groups. Metastore admins have extensive
  control over data access and governance policies in Unity Catalog.
Runbook: |
  1. Query Unity Catalog audit logs for all metastore operations by the target principal in the 24 hours after this privilege grant
  2. Check if the target principal accessed sensitive catalogs or tables in the 6 hours after receiving admin rights
  3. Find all metastore admin grants in the past 90 days to identify unusual patterns
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/blob/main/base/detections/event-based/metastore_admin_privilege_granted.py

Stages and Predicates

Fires on Databricks.Audit events when any of the conditions below holds.

Condition

  • any of:
    • all of:
      • actionName is updateMetastore
      • requestParams contains owner
    • actionName is not updateMetastore

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.

Output fields

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

FieldSource
ownerrequestParams.owner
emailuserIdentity.email
principalrequestParams.principal
targetGroupNamerequestParams.targetGroupName

Response runbook

1. Query Unity Catalog audit logs for all metastore operations by the target principal in the 24 hours after this privilege grant

2. Check if the target principal accessed sensitive catalogs or tables in the 6 hours after receiving admin rights

3. Find all metastore admin grants in the past 90 days to identify unusual patterns

Worked example

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

Sample Test Event
{
  "actionName": "updateMetastore",
  "requestParams": {
    "metastoreId": "metastore-123",
    "owner": "newadmin@example.com"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "unityCatalog",
  "sourceIPAddress": "198.51.100.1",
  "timestamp": 1234567890000,
  "userIdentity": {
    "email": "admin@example.com"
  }
}

Databricks MFA Key Change

#
Status
Experimental
Severity
informational
Group by
actionName, userIdentity.email
Log types
Databricks.Audit
Tags
Databricks, Credential Access
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects addition or deletion of MFA keys on Databricks accounts. MFA key deletion may indicate an attacker weakening account security, while unexpected additions may indicate enrollment of attacker-controlled authenticators.

MITRE ATT&CK coverage

TacticTechniques
Credential Access

Detection logic

from panther_databricks_helpers import MFA_ACTIONS, databricks_alert_context


def rule(event):
    if event.get("serviceName") != "accounts":
        return False

    action = event.get("actionName")
    return action in MFA_ACTIONS["add"] or action in MFA_ACTIONS["delete"]


def title(event):
    action = event.get("actionName", "unknown")
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    change_type = "added" if action in MFA_ACTIONS["add"] else "deleted"
    return f"MFA key {change_type} by {actor}"


def dedup(event):
    actor = event.deep_get("userIdentity", "email", default="unknown")
    action = event.get("actionName", "unknown")
    return f"mfa_key_change_{actor}_{action}"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={
            "change_type": "add" if event.get("actionName") in MFA_ACTIONS["add"] else "delete",
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_mfa_key_change.py
RuleID: "Databricks.Audit.MFAKeyChange"
DisplayName: "Databricks MFA Key Change"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Credential Access
Reports:
  MITRE ATT&CK:
    - TA0006:T1556 # Modify Authentication Process
Severity: Info
Description: >
  Detects addition or deletion of MFA keys on Databricks accounts. MFA key deletion
  may indicate an attacker weakening account security, while unexpected additions may
  indicate enrollment of attacker-controlled authenticators.
Runbook: |
  1. Verify the actor intended to modify their MFA settings
  2. For deletions, check if a replacement key was added
  3. For additions, verify the new key was enrolled by the legitimate user
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/tree/main/base/detections/behavioral

Stages and Predicates

Fires on Databricks.Audit events when the condition below holds.

Condition

  • serviceName is accounts

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.

Output fields

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

FieldSource
emailuserIdentity.email

Response runbook

1. Verify the actor intended to modify their MFA settings

2. For deletions, check if a replacement key was added

3. For additions, verify the new key was enrolled by the legitimate user

Worked example

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

Sample Test Event
{
  "actionName": "mfaAddKey",
  "response": {
    "statusCode": 200
  },
  "serviceName": "accounts",
  "userIdentity": {
    "email": "user@example.com"
  }
}

Databricks Mount Point Creation

#
Status
Experimental
Severity
informational
Group by
requestParams.mountPoint, workspaceId
Log types
Databricks.Audit
Tags
Databricks, Collection, Lateral Movement
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects creation of legacy mount points in Databricks. Mount points are deprecated in favor of Unity Catalog external locations and can pose security risks by bypassing access controls. This anti-pattern should be avoided in modern Databricks deployments.

MITRE ATT&CK coverage

TacticTechniques
Lateral Movement
Collection

Detection logic

from panther_databricks_helpers import databricks_alert_context


def rule(event):
    return event.get("actionName") == "mount"


def title(event):
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    mount_point = event.deep_get("requestParams", "mountPoint", default="Unknown Mount")
    workspace = event.get("workspaceId", "Unknown Workspace")
    return f"Mount point created: {mount_point} in workspace {workspace} by {actor}"


def dedup(event):
    mount_point = event.deep_get("requestParams", "mountPoint", default="unknown")
    workspace = event.get("workspaceId", "unknown")
    return f"mount_point_{workspace}_{mount_point}"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={
            "mount_point": event.deep_get("requestParams", "mountPoint"),
            "mount_config": event.get("requestParams"),
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_mount_point_creation.py
RuleID: "Databricks.Audit.MountPointCreation"
DisplayName: "Databricks Mount Point Creation"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Collection
  - Lateral Movement
Reports:
  MITRE ATT&CK:
    - TA0009:T1074 # Data Staged
    - TA0008:T1021 # Remote Services
Severity: Info
Description: >
  Detects creation of legacy mount points in Databricks. Mount points are deprecated in favor
  of Unity Catalog external locations and can pose security risks by bypassing access controls.
  This anti-pattern should be avoided in modern Databricks deployments.
Runbook: |
  1. Query audit logs for all mount operations by this user in the past 30 days to identify patterns
  2. Check if data was accessed through this mount point in the 24 hours after creation
  3. Find all mount point creations across workspaces in the past 90 days to establish baseline
Reference: https://github.com/andyweaves/system-tables-audit-logs/blob/main/resources/queries_and_alerts.json
SummaryAttributes:
  - actor
  - mount_point
  - workspace_id

Stages and Predicates

Fires on Databricks.Audit events when the condition below holds.

Condition

  • actionName is mount

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
mountPointrequestParams.mountPoint
workspaceId
emailuserIdentity.email

Response runbook

1. Query audit logs for all mount operations by this user in the past 30 days to identify patterns

2. Check if data was accessed through this mount point in the 24 hours after creation

3. Find all mount point creations across workspaces in the past 90 days to establish baseline

Worked example

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

Sample Test Event
{
  "actionName": "mount",
  "requestParams": {
    "mountPoint": "/mnt/data-lake",
    "source": "s3://my-bucket/data"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "dbfs",
  "sourceIPAddress": "198.51.100.1",
  "timestamp": 1704067200000,
  "userIdentity": {
    "email": "user@example.com"
  },
  "workspaceId": "1234567890123456"
}

Databricks Non-SSO Login Detected

#
Status
Experimental
Severity
informational
Group by
userIdentity.email
Log types
Databricks.Audit
Tags
Databricks, Initial Access
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects successful logins that bypass SSO (SAML). In organizations that enforce SSO, non-SAML logins may indicate credential compromise, misconfigured service accounts, or unauthorized access methods.

MITRE ATT&CK coverage

TacticTechniques
Initial Access

Detection logic

from panther_databricks_helpers import databricks_alert_context, is_login_action


def rule(event):
    if not is_login_action(event):
        return False

    if event.deep_get("response", "statusCode") != 200:
        return False

    # Alert on logins that bypass SSO (SAML).
    # If authentication_method is missing, fall back to checking the action name.
    auth_method = event.deep_get("requestParams", "authentication_method", default="")
    if auth_method:
        return auth_method != "BROWSER_BYO_IDP_SAML"

    # No auth_method field: treat non-SAML login actions as non-SSO
    return event.get("actionName") not in ("samlLogin",)


def title(event):
    user = event.deep_get("userIdentity", "email", default="Unknown User")
    auth_method = event.deep_get("requestParams", "authentication_method", default="Unknown")
    action = event.get("actionName", "login")
    return f"Non-SSO login by {user} via {auth_method} ({action})"


def dedup(event):
    user = event.deep_get("userIdentity", "email", default="unknown")
    return f"non_sso_login_{user}"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={
            "authentication_method": event.deep_get("requestParams", "authentication_method"),
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_non_sso_login.py
RuleID: "Databricks.Audit.NonSSOLogin"
DisplayName: "Databricks Non-SSO Login Detected"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Initial Access
Reports:
  MITRE ATT&CK:
    - TA0001:T1078 # Valid Accounts
Severity: Info
Description: >
  Detects successful logins that bypass SSO (SAML). In organizations that enforce SSO,
  non-SAML logins may indicate credential compromise, misconfigured service accounts,
  or unauthorized access methods.
Runbook: |
  1. Verify whether the user is expected to use non-SSO authentication
  2. Check if this is a service account or automation that legitimately bypasses SSO
  3. Review the authentication_method in alert context
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/tree/main/base/detections/behavioral

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • actionName is one of aadBrowserLogin, aadTokenLogin, certLogin, jwtLogin, login (+5 more values, see Indicators below)
  • response.statusCode is 200
  • any of:
    • all of:
      • requestParams.authentication_method is present
      • requestParams.authentication_method is not BROWSER_BYO_IDP_SAML
    • all of:
      • requestParams.authentication_method is empty
      • actionName is not one of samlLogin

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
emailuserIdentity.email
authentication_methodrequestParams.authentication_method
actionName

Response runbook

1. Verify whether the user is expected to use non-SSO authentication

2. Check if this is a service account or automation that legitimately bypasses SSO

3. Review the authentication_method in alert context

Worked example

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

Sample Test Event
{
  "actionName": "tokenLogin",
  "requestParams": {
    "authentication_method": "TOKEN"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "accounts",
  "userIdentity": {
    "email": "user@example.com"
  }
}

Databricks Potential Privilege Escalation

#
Status
Experimental
Severity
high
Group by
userIdentity.email
Log types
Databricks.Audit
Tags
Databricks, Privilege Escalation
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects potential privilege escalation through high volume permission modifications (≥25 per hour) by the same user. Monitors various permission-related actions across account, workspace, and Unity Catalog.

MITRE ATT&CK coverage

TacticTechniques
Privilege Escalation

Detection logic

from panther_databricks_helpers import PRIVILEGE_MODIFICATION_ACTIONS, databricks_alert_context


def rule(event):
    return event.get("actionName") in PRIVILEGE_MODIFICATION_ACTIONS


def dedup(event):
    user = event.deep_get("userIdentity", "email", default="unknown")
    return f"priv_escalation_{user}"


def title(event):
    user = event.deep_get("userIdentity", "email", default="Unknown User")
    return f"Potential privilege escalation by {user} (>25 permission changes/hour)"


def alert_context(event):
    return databricks_alert_context(event)

Rule specification

AnalysisType: rule
Filename: databricks_potential_privilege_escalation.py
RuleID: "Databricks.Audit.PotentialPrivilegeEscalation"
DisplayName: "Databricks Potential Privilege Escalation"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Privilege Escalation
Reports:
  MITRE ATT&CK:
    - TA0004:T1078 # Valid Accounts
Severity: High
Threshold: 25
DedupPeriodMinutes: 60
Description: >
  Detects potential privilege escalation through high volume permission modifications (≥25 per hour) by the same user.
  Monitors various permission-related actions across account, workspace, and Unity Catalog.
Runbook: |
  1. Query audit logs for all permission modifications by this user in the past 24 hours
  2. Check if the user performed high-privilege actions immediately after the permission changes
  3. Find all users with high permission modification rates in the past 7 days
Reference: https://github.com/andyweaves/system-tables-audit-logs/blob/main/resources/queries_and_alerts.json
SummaryAttributes:
  - actor

Stages and Predicates

Fires on Databricks.Audit events when the condition below holds.

Condition

  • actionName is one of addPrincipalToGroup, removePrincipalFromGroup, addPrincipalsToGroup, setAdmin, removeAdmin (+22 more values, see Indicators below)
Alert cadence
alerts after 25 matches within 1h

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
actionNamein
  • addPrincipalToGroup
  • addPrincipalsToGroup
  • assignRole
  • changeAccountOwner
  • changeOwner
  • createRole
  • createRoleAssignment
  • deleteRole
  • deleteRoleAssignment
  • grant
  • removeAdmin
  • removePrincipalFromGroup
  • revoke
  • setAccountAdmin
  • setAdmin
  • setPermissions
  • unassignRole
  • updateCatalog
  • updateConnection
  • updateFunction
  • updateMetastore
  • updatePermissions
  • updateRole
  • updateSchema
  • updateTable
  • updateVolume
  • updateWorkspaceAssignment
field:"actionName" kind:in

Output fields

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

FieldSource
emailuserIdentity.email

Response runbook

1. Query audit logs for all permission modifications by this user in the past 24 hours

2. Check if the user performed high-privilege actions immediately after the permission changes

3. Find all users with high permission modification rates in the past 7 days

Worked example

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

Sample Test Event
{
  "actionName": "addPrincipalToGroup",
  "requestParams": {
    "targetGroupName": "developers"
  },
  "serviceName": "accounts",
  "timestamp": 1704067200000,
  "userIdentity": {
    "email": "admin@example.com"
  }
}

Databricks Principal Removed From Group

#
Status
Experimental
Severity
informational
Group by
requestParams.targetGroupName, requestParams.targetUserName
Log types
Databricks.Audit
Tags
Databricks, Persistence
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects when principals (users or service principals) are removed from groups in Databricks accounts. This is often legitimate administrative activity but should be monitored for unauthorized membership changes.

MITRE ATT&CK coverage

TacticTechniques
Persistence

Detection logic

from panther_databricks_helpers import databricks_alert_context


def rule(event):
    if event.get("serviceName") != "accounts":
        return False

    return event.get("actionName") == "removePrincipalFromGroup"


def title(event):
    target_user = event.deep_get("requestParams", "targetUserName", default="Unknown User")
    target_group = event.deep_get("requestParams", "targetGroupName", default="Unknown Group")
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    return f"Principal {target_user} removed from group {target_group} by {actor}"


def dedup(event):
    target_user = event.deep_get("requestParams", "targetUserName", default="unknown")
    target_group = event.deep_get("requestParams", "targetGroupName", default="unknown")
    return f"principal_removed_{target_group}_{target_user}"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={
            "target_user": event.deep_get("requestParams", "targetUserName"),
            "target_group": event.deep_get("requestParams", "targetGroupName"),
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_principal_removed_from_group.py
RuleID: "Databricks.Audit.PrincipalRemovedFromGroup"
DisplayName: "Databricks Principal Removed From Group"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Persistence
Reports:
  MITRE ATT&CK:
    - TA0003:T1098 # Account Manipulation
Severity: Info
Description: >
  Detects when principals (users or service principals) are removed from groups in Databricks accounts.
  This is often legitimate administrative activity but should be monitored for unauthorized membership changes.
Runbook: |
  1. Query audit logs for all group membership changes by the actor in the 24 hours around this event
  2. Check if the removed principal had active sessions or API calls in the 1 hour before removal
  3. Find all group membership removals for this group in the past 30 days to identify patterns
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/blob/main/base/detections/event-based/principal_removed_from_group.py

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • serviceName is accounts
  • actionName is removePrincipalFromGroup

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
targetUserNamerequestParams.targetUserName
targetGroupNamerequestParams.targetGroupName
emailuserIdentity.email

Response runbook

1. Query audit logs for all group membership changes by the actor in the 24 hours around this event

2. Check if the removed principal had active sessions or API calls in the 1 hour before removal

3. Find all group membership removals for this group in the past 30 days to identify patterns

Worked example

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

Sample Test Event
{
  "actionName": "removePrincipalFromGroup",
  "requestParams": {
    "targetGroupName": "developers",
    "targetUserName": "user@example.com"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "accounts",
  "sourceIPAddress": "198.51.100.1",
  "timestamp": 1234567890000,
  "userIdentity": {
    "email": "admin@example.com"
  }
}

Databricks Repeated Access to Secrets

#
Status
Experimental
Severity
medium
Group by
userIdentity.email
Log types
Databricks.Audit
Tags
Databricks, Credential Access, Collection
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects repeated secret access (≥10 times in 60 minutes) which may indicate credential harvesting or unauthorized secret enumeration.

MITRE ATT&CK coverage

TacticTechniques
Credential Access

Detection logic

from panther_databricks_helpers import SYSTEM_USERS, databricks_alert_context


def rule(event):
    if event.get("actionName") != "getSecret":
        return False

    # Filter out system users
    user = event.deep_get("userIdentity", "email", default="")
    return user not in SYSTEM_USERS


def dedup(event):
    user = event.deep_get("userIdentity", "email", default="unknown")
    return f"secret_access_{user}"


def title(event):
    user = event.deep_get("userIdentity", "email", default="Unknown User")
    scope = event.deep_get("requestParams", "scope", default="Unknown Scope")
    return f"Repeated secret access by {user} in scope {scope}"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={
            "secret_scope": event.deep_get("requestParams", "scope"),
            "secret_key": event.deep_get("requestParams", "key"),
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_repeated_access_to_secrets.py
RuleID: "Databricks.Audit.RepeatedAccessToSecrets"
DisplayName: "Databricks Repeated Access to Secrets"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Credential Access
  - Collection
Reports:
  MITRE ATT&CK:
    - TA0006:T1555 # Credentials from Password Stores
Severity: Medium
Threshold: 10
DedupPeriodMinutes: 60
Description: >
  Detects repeated secret access (≥10 times in 60 minutes) which may indicate credential
  harvesting or unauthorized secret enumeration.
Runbook: |
  1. Query audit logs for all secret access by this user in the past 24 hours to identify patterns
  2. Check if the accessed secrets were used in API calls or notebook execution in the 6 hours after access
  3. Find all users with high secret access rates in the past 7 days to establish baseline
Reference: https://github.com/andyweaves/system-tables-audit-logs/blob/main/resources/queries_and_alerts.json
SummaryAttributes:
  - actor
  - secret_scope

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • actionName is getSecret
  • userIdentity.email is not one of System-User
Alert cadence
alerts after 10 matches within 1h

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
userIdentity.emaileqSystem-Userexcludes:userIdentity.email field:"userIdentity.email" value:"System-User"

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
emailuserIdentity.email
scoperequestParams.scope

Response runbook

1. Query audit logs for all secret access by this user in the past 24 hours to identify patterns

2. Check if the accessed secrets were used in API calls or notebook execution in the 6 hours after access

3. Find all users with high secret access rates in the past 7 days to establish baseline

Worked example

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

Sample Test Event
{
  "actionName": "getSecret",
  "requestParams": {
    "key": "api-token",
    "scope": "production-keys"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "secrets",
  "timestamp": 1704067200000,
  "userIdentity": {
    "email": "user@example.com"
  }
}

Databricks Repeated Failed Login Attempts

#
Status
Experimental
Severity
medium
Group by
userIdentity.email
Log types
Databricks.Audit
Tags
Databricks, Credential Access, Initial Access
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects repeated failed login attempts within a 60-minute window, which may indicate credential stuffing, brute force attacks, or compromised credentials.

MITRE ATT&CK coverage

TacticTechniques
Initial Access
Credential Access

Detection logic

from panther_databricks_helpers import databricks_alert_context, is_login_action


def rule(event):
    if not is_login_action(event):
        return False

    # Check for failure status codes
    status_code = event.deep_get("response", "statusCode")
    return status_code in [401, 403]


def title(event):
    user = event.deep_get("userIdentity", "email") or event.deep_get(
        "requestParams", "user", default="Unknown User"
    )
    source_ip = event.get("sourceIPAddress", "Unknown IP")
    action = event.get("actionName", "login")
    return f"Repeated failed login attempts: {user} from {source_ip} ({action})"


def dedup(event):
    user = (
        event.deep_get("userIdentity", "email")
        or event.deep_get("requestParams", "user")
        or "unknown"
    )
    return f"failed_login_{user}"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={
            "login_user": event.deep_get("userIdentity", "email")
            or event.deep_get("requestParams", "user"),
            "login_action": event.get("actionName"),
            "error_message": event.deep_get("response", "errorMessage"),
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_repeated_failed_login_attempts.py
RuleID: "Databricks.Audit.RepeatedFailedLoginAttempts"
DisplayName: "Databricks Repeated Failed Login Attempts"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Credential Access
  - Initial Access
Reports:
  MITRE ATT&CK:
    - TA0006:T1110 # Brute Force
    - TA0001:T1078 # Valid Accounts
Severity: Medium
Threshold: 5
DedupPeriodMinutes: 60
Description: >
  Detects repeated failed login attempts within a 60-minute window, which may indicate
  credential stuffing, brute force attacks, or compromised credentials.
Runbook: |
  1. Count all failed and successful login attempts for this user in the 6 hours around this alert
  2. Check if the source IPs match known VPNs, proxies, or are from unexpected geographic locations
  3. Find if there were successful logins from different IPs immediately after the failed attempts
Reference: https://github.com/andyweaves/system-tables-audit-logs/blob/main/resources/queries_and_alerts.json
SummaryAttributes:
  - login_user
  - source_ip
  - login_action

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • actionName is one of aadBrowserLogin, aadTokenLogin, certLogin, jwtLogin, login (+5 more values, see Indicators below)
  • response.statusCode is one of 401, 403
Alert cadence
alerts after 5 matches within 1h

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
actionNamein
  • aadBrowserLogin
  • aadTokenLogin
  • certLogin
  • jwtLogin
  • login
  • mfaLogin
  • oidcBrowserLogin
  • passwordVerifyAuthentication
  • samlLogin
  • tokenLogin
field:"actionName" kind:in
response.statusCodein
  • 401 transforms: number
  • 403 transforms: number
field:"response.statusCode" kind:in

Output fields

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

FieldSource
emailuserIdentity.email
sourceIPAddress
actionName

Response runbook

1. Count all failed and successful login attempts for this user in the 6 hours around this alert

2. Check if the source IPs match known VPNs, proxies, or are from unexpected geographic locations

3. Find if there were successful logins from different IPs immediately after the failed attempts

Worked example

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

Sample Test Event
{
  "actionName": "samlLogin",
  "response": {
    "errorMessage": "Invalid credentials",
    "statusCode": 401
  },
  "serviceName": "accounts",
  "sourceIPAddress": "203.0.113.50",
  "timestamp": 1704067200000,
  "userIdentity": {
    "email": "user@example.com"
  }
}

Databricks Repeated Unauthorized UC Data Requests

#
Status
Experimental
Severity
high
Group by
userIdentity.email
Log types
Databricks.Audit
Tags
Databricks, Collection, Unity Catalog
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects repeated unauthorized Unity Catalog data access attempts (>15 per hour) including credential generation failures and Delta Sharing access denials.

MITRE ATT&CK coverage

TacticTechniques
Collection

Detection logic

from panther_databricks_helpers import TEMP_CREDENTIAL_ACTIONS, databricks_alert_context


def rule(event):
    action = event.get("actionName", "")
    status_code = event.deep_get("response", "statusCode")

    # Check for credential generation failures (exact match)
    if action in TEMP_CREDENTIAL_ACTIONS:
        return status_code in [401, 403]

    # Check for Delta Sharing access failures
    if event.get("serviceName") == "deltaSharingAccess":
        return status_code in [401, 403]

    return False


def dedup(event):
    user = event.deep_get("userIdentity", "email", default="unknown")
    return f"uc_data_unauthorized_{user}"


def title(event):
    user = event.deep_get("userIdentity", "email", default="Unknown User")
    return f"Repeated unauthorized UC data access attempts by {user}"


def alert_context(event):
    return databricks_alert_context(event)

Rule specification

AnalysisType: rule
Filename: databricks_repeated_unauthorized_uc_data_requests.py
RuleID: "Databricks.Audit.RepeatedUnauthorizedUCDataRequests"
DisplayName: "Databricks Repeated Unauthorized UC Data Requests"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Collection
  - Unity Catalog
Reports:
  MITRE ATT&CK:
    - TA0009:T1530 # Data from Cloud Storage Object
Severity: High
Threshold: 16
DedupPeriodMinutes: 60
Description: >
  Detects repeated unauthorized Unity Catalog data access attempts (>15 per hour) including
  credential generation failures and Delta Sharing access denials.
Runbook: |
  1. Query Unity Catalog audit logs for all data access attempts by this user in the past 24 hours
  2. Check which specific tables, volumes, or shares the user attempted to access
  3. Find all users with high unauthorized data request rates in the past 7 days
Reference: https://github.com/andyweaves/system-tables-audit-logs/blob/main/resources/queries_and_alerts.json
SummaryAttributes:
  - actor

Stages and Predicates

Fires on Databricks.Audit events when any of the conditions below holds.

Condition

  • any of:
    • all of:
      • actionName is one of generateTemporaryTableCredential, generateTemporaryVolumeCredential, generateTemporaryPathCredential
      • response.statusCode is one of 401, 403
    • all of:
      • actionName is not one of generateTemporaryTableCredential, generateTemporaryVolumeCredential, generateTemporaryPathCredential
      • serviceName is deltaSharingAccess
      • response.statusCode is one of 401, 403
Alert cadence
alerts after 16 matches within 1h

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
actionNamein
  • generateTemporaryPathCredential
  • generateTemporaryTableCredential
  • generateTemporaryVolumeCredential
field:"actionName" kind:in
response.statusCodein
  • 401 transforms: number
  • 403 transforms: number
field:"response.statusCode" kind:in
serviceNameeq
  • deltaSharingAccess
field:"serviceName" kind:eq value:"deltaSharingAccess"

Output fields

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

FieldSource
emailuserIdentity.email

Response runbook

1. Query Unity Catalog audit logs for all data access attempts by this user in the past 24 hours

2. Check which specific tables, volumes, or shares the user attempted to access

3. Find all users with high unauthorized data request rates in the past 7 days

Worked example

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

Sample Test Event
{
  "actionName": "generateTemporaryTableCredential",
  "response": {
    "statusCode": 403
  },
  "serviceName": "unityCatalog",
  "timestamp": 1704067200000,
  "userIdentity": {
    "email": "user@example.com"
  }
}

Databricks Repeated Unauthorized Unity Catalog Requests

#
Status
Experimental
Severity
medium
Group by
userIdentity.email
Log types
Databricks.Audit
Tags
Databricks, Discovery, Unity Catalog
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects repeated unauthorized Unity Catalog API requests (>25 per hour) which may indicate reconnaissance, privilege enumeration, or unauthorized data access attempts.

MITRE ATT&CK coverage

TacticTechniques
Discovery

Detection logic

from panther_databricks_helpers import databricks_alert_context


def rule(event):
    # Must be Unity Catalog service
    if event.get("serviceName") != "unityCatalog":
        return False

    # Check for unauthorized status codes
    status_code = event.deep_get("response", "statusCode")
    return status_code in [401, 403]


def dedup(event):
    user = event.deep_get("userIdentity", "email", default="unknown")
    return f"uc_unauthorized_{user}"


def title(event):
    user = event.deep_get("userIdentity", "email", default="Unknown User")
    action = event.get("actionName", "Unknown Action")
    return f"Repeated unauthorized Unity Catalog requests by {user} ({action})"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={"uc_action": event.get("actionName")},
    )

Rule specification

AnalysisType: rule
Filename: databricks_repeated_unauthorized_uc_requests.py
RuleID: "Databricks.Audit.RepeatedUnauthorizedUCRequests"
DisplayName: "Databricks Repeated Unauthorized Unity Catalog Requests"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Discovery
  - Unity Catalog
Reports:
  MITRE ATT&CK:
    - TA0007:T1087 # Account Discovery
Severity: Medium
Threshold: 26
DedupPeriodMinutes: 60
Description: >
  Detects repeated unauthorized Unity Catalog API requests (>25 per hour) which may indicate
  reconnaissance, privilege enumeration, or unauthorized data access attempts.
Runbook: |
  1. Query Unity Catalog audit logs for all unauthorized attempts by this user in the past 24 hours
  2. Check if the user attempted to access specific catalogs, schemas, or tables repeatedly
  3. Find all users with high unauthorized request rates in the past 7 days
Reference: https://github.com/andyweaves/system-tables-audit-logs/blob/main/resources/queries_and_alerts.json
SummaryAttributes:
  - actor
  - uc_action

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • serviceName is unityCatalog
  • response.statusCode is one of 401, 403
Alert cadence
alerts after 26 matches within 1h

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
response.statusCodein
  • 401 transforms: number
  • 403 transforms: number
field:"response.statusCode" kind:in
serviceNameeq
  • unityCatalog
field:"serviceName" kind:eq value:"unityCatalog"

Output fields

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

FieldSource
emailuserIdentity.email
actionName

Response runbook

1. Query Unity Catalog audit logs for all unauthorized attempts by this user in the past 24 hours

2. Check if the user attempted to access specific catalogs, schemas, or tables repeatedly

3. Find all users with high unauthorized request rates in the past 7 days

Worked example

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

Sample Test Event
{
  "actionName": "getCatalog",
  "response": {
    "errorMessage": "Access denied",
    "statusCode": 403
  },
  "serviceName": "unityCatalog",
  "timestamp": 1704067200000,
  "userIdentity": {
    "email": "user@example.com"
  }
}

Databricks SSO Configuration Changed

#
Status
Experimental
Severity
low
Group by
actionName
Log types
Databricks.Audit
Tags
Databricks, Credential Access
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects modifications to single sign-on (SSO) configurations in Databricks. While SSO changes may be part of planned identity provider updates, unauthorized modifications could indicate attempts to tamper with authentication mechanisms. Successful changes are elevated to MEDIUM severity.

MITRE ATT&CK coverage

TacticTechniques
Credential Access

Detection logic

from panther_databricks_helpers import databricks_alert_context


def rule(event):
    if event.get("serviceName") != "ssoConfigBackend":
        return False

    return event.get("actionName") in ["create", "update"]


def severity(event):
    status_code = event.deep_get("response", "statusCode")
    return "MEDIUM" if status_code == 200 else "LOW"


def title(event):
    action = event.get("actionName", "Unknown Action")
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    sso_status = event.deep_get("requestParams", "status", default="Unknown Status")
    return f"SSO configuration {action}d by {actor} - Status: {sso_status}"


def dedup(event):
    action = event.get("actionName", "unknown")
    return f"sso_config_{action}"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={
            "sso_status": event.deep_get("requestParams", "status"),
            "sso_config": event.deep_get("requestParams", "config"),
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_sso_config_changed.py
RuleID: "Databricks.Audit.SSOConfigChanged"
DisplayName: "Databricks SSO Configuration Changed"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Credential Access
Reports:
  MITRE ATT&CK:
    - TA0006:T1556 # Modify Authentication Process
Severity: Low
Description: >
  Detects modifications to single sign-on (SSO) configurations in Databricks. While SSO changes
  may be part of planned identity provider updates, unauthorized modifications could indicate
  attempts to tamper with authentication mechanisms. Successful changes are elevated to MEDIUM severity.
Runbook: |
  1. Query audit logs for all SSO configuration changes in the 48 hours before and after this event
  2. Check if there were successful logins using the new SSO configuration in the 6 hours after the change
  3. Find all authentication failures or unusual login patterns in the 24 hours after the SSO change
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/blob/main/base/detections/event-based/sso_config_changed.py

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • serviceName is ssoConfigBackend
  • actionName is one of create, update

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
actionName
emailuserIdentity.email
statusrequestParams.status

Response runbook

1. Query audit logs for all SSO configuration changes in the 48 hours before and after this event

2. Check if there were successful logins using the new SSO configuration in the 6 hours after the change

3. Find all authentication failures or unusual login patterns in the 24 hours after the SSO change

Worked example

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

Sample Test Event
{
  "actionName": "create",
  "requestParams": {
    "config": {
      "provider": "okta"
    },
    "status": "enabled"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "ssoConfigBackend",
  "sourceIPAddress": "198.51.100.1",
  "timestamp": 1234567890000,
  "userIdentity": {
    "email": "admin@example.com"
  }
}

Databricks Terms of Service Changes

#
Status
Experimental
Severity
informational
Log types
Databricks.Audit
Tags
Databricks, Compliance
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects Terms of Service acceptance or distribution events for compliance tracking. These events should be monitored for audit and governance purposes.

Detection logic

from panther_databricks_helpers import databricks_alert_context


def rule(event):
    return event.get("actionName") in ["acceptTos", "sendTos"]


def title(event):
    action = event.get("actionName", "Unknown Action")
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")

    if action == "acceptTos":
        return f"Terms of Service accepted by {actor}"
    return f"Terms of Service distributed by {actor}"


def alert_context(event):
    return databricks_alert_context(event)

Rule specification

AnalysisType: rule
Filename: databricks_terms_of_service_changes.py
RuleID: "Databricks.Audit.TermsOfServiceChanges"
DisplayName: "Databricks Terms of Service Changes"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Compliance
Severity: Info
Description: >
  Detects Terms of Service acceptance or distribution events for compliance tracking.
  These events should be monitored for audit and governance purposes.
Runbook: |
  1. Query audit logs for all TOS-related events in the past 90 days to establish baseline
  2. Check if this TOS acceptance aligns with expected onboarding or policy update timelines
  3. Find all TOS events for this user to verify compliance history
Reference: https://github.com/andyweaves/system-tables-audit-logs/blob/main/resources/queries_and_alerts.json

Stages and Predicates

Fires on Databricks.Audit events when the condition below holds.

Condition

  • actionName is one of acceptTos, sendTos

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
actionNamein
  • acceptTos
  • sendTos
field:"actionName" kind:in

Output fields

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

FieldSource
emailuserIdentity.email

Response runbook

1. Query audit logs for all TOS-related events in the past 90 days to establish baseline

2. Check if this TOS acceptance aligns with expected onboarding or policy update timelines

3. Find all TOS events for this user to verify compliance history

Worked example

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

Sample Test Event
{
  "actionName": "acceptTos",
  "response": {
    "statusCode": 200
  },
  "serviceName": "accounts",
  "sourceIPAddress": "198.51.100.1",
  "timestamp": 1704067200000,
  "userIdentity": {
    "email": "newuser@example.com"
  }
}

Databricks TruffleHog Scan Detected

#
Status
Experimental
Severity
medium
Log types
Databricks.Audit
Tags
Databricks, Collection, Credential Access
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects TruffleHog secret scanning activity in Databricks. TruffleHog is a tool used to scan repositories and systems for exposed credentials and secrets. While it can be used legitimately for security audits, unauthorized scanning may indicate credential harvesting attempts. External IP sources are elevated to HIGH severity.

MITRE ATT&CK coverage

Detection logic

import ipaddress

from panther_databricks_helpers import databricks_alert_context, filter_noise


def rule(event):
    # Filter out system noise
    if filter_noise(event):
        return False

    # Check user agent for TruffleHog signature
    user_agent = event.get("userAgent", "")
    return "TruffleHog" in user_agent


def title(event):
    source_ip = event.get("sourceIPAddress", "Unknown IP")
    user = event.deep_get("userIdentity", "email", default="Unknown User")
    return f"TruffleHog secret scan detected from {source_ip} (User: {user})"


def severity(event):
    source_ip = event.get("sourceIPAddress", "")
    # Lower severity for scans from private IPs (internal testing)
    if source_ip:
        try:
            if ipaddress.ip_address(source_ip).is_private:
                return "MEDIUM"
        except ValueError:
            # Invalid IP format, treat as public (HIGH severity)
            pass
    return "HIGH"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={
            "token_id": event.deep_get("requestParams", "tokenId"),
            "user_agent_full": event.get("userAgent"),
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_trufflehog_scan_detected.py
RuleID: "Databricks.Audit.TrufflehogScanDetected"
DisplayName: "Databricks TruffleHog Scan Detected"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Collection
  - Credential Access
Reports:
  MITRE ATT&CK:
    - TA0006:T1552 # Unsecured Credentials
    - TA0009:T1213 # Data from Information Repositories
Severity: Medium
Description: >
  Detects TruffleHog secret scanning activity in Databricks. TruffleHog is a tool used to scan
  repositories and systems for exposed credentials and secrets. While it can be used legitimately
  for security audits, unauthorized scanning may indicate credential harvesting attempts. External
  IP sources are elevated to HIGH severity.
Runbook: |
  1. Query audit logs for all secret access attempts (getSecret action) by this user in the 24 hours before and after the TruffleHog scan
  2. Check if the source IP (sourceIPAddress) matches known security scanning tools or is from an unexpected geographic location
  3. Find all other unusual secret access patterns from this IP or user in the past 7 days
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/blob/main/base/detections/event-based/trufflehog_scan_detected.py

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • userAgent does not contain Databricks-Service/driver
  • userAgent does not contain Databricks-Runtime
  • userAgent does not contain Delta-Sharing-SparkStructuredStreaming
  • userAgent does not contain RawDBHttpClient
  • userAgent does not contain mlflow-python
  • userAgent does not contain obsSDK-scala
  • userAgent does not contain wsfs
  • userAgent does not contain feature-store
  • requestParams.path does not contain /telemetry
  • requestParams.path does not contain /delta-commit
  • requestParams.path does not contain /health
  • requestParams.path does not contain /metrics
  • requestParams.path does not contain /status
  • userAgent contains TruffleHog

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

Exclusions

The rule actively suppresses these predicates.

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
sourceIPAddress
emailuserIdentity.email

Response runbook

1. Query audit logs for all secret access attempts (getSecret action) by this user in the 24 hours before and after the TruffleHog scan

2. Check if the source IP (sourceIPAddress) matches known security scanning tools or is from an unexpected geographic location

3. Find all other unusual secret access patterns from this IP or user in the past 7 days

Worked example

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

Sample Test Event
{
  "actionName": "login",
  "requestParams": {
    "tokenId": "token-123"
  },
  "serviceName": "accounts",
  "sourceIPAddress": "203.0.113.50",
  "timestamp": 1234567890000,
  "userAgent": "TruffleHog/3.0",
  "userIdentity": {
    "email": "scanner@external.com"
  }
}

Databricks User Account Created

#
Status
Experimental
Severity
informational
Group by
requestParams.targetUserName
Log types
Databricks.Audit
Tags
Databricks, Persistence
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects creation of new user accounts in Databricks. Account creation may be part of normal onboarding or could indicate an attacker establishing persistence.

MITRE ATT&CK coverage

TacticTechniques
Persistence

Detection logic

from panther_databricks_helpers import databricks_alert_context


def rule(event):
    if event.get("serviceName") != "accounts":
        return False

    action = event.get("actionName")
    return action in ("createUser", "addUser")


def title(event):
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    target = event.deep_get("requestParams", "targetUserName", default="Unknown User")
    endpoint = event.deep_get("requestParams", "endpoint", default="")
    source = f" via {endpoint}" if endpoint else ""
    return f"User account created: {target} by {actor}{source}"


def dedup(event):
    target = event.deep_get("requestParams", "targetUserName", default="unknown")
    return f"user_created_{target}"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={
            "target_user": event.deep_get("requestParams", "targetUserName"),
            "endpoint": event.deep_get("requestParams", "endpoint"),
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_user_account_created.py
RuleID: "Databricks.Audit.UserAccountCreated"
DisplayName: "Databricks User Account Created"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Persistence
Reports:
  MITRE ATT&CK:
    - TA0003:T1136 # Create Account
Severity: Info
Description: >
  Detects creation of new user accounts in Databricks. Account creation may be part of
  normal onboarding or could indicate an attacker establishing persistence.
Runbook: |
  1. Verify the account creation was part of an approved onboarding workflow
  2. Check if the new account was immediately granted elevated privileges
  3. Review the actor who created the account
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/tree/main/base/detections/behavioral

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • serviceName is accounts
  • actionName is one of createUser, addUser

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
targetUserNamerequestParams.targetUserName
emailuserIdentity.email

Response runbook

1. Verify the account creation was part of an approved onboarding workflow

2. Check if the new account was immediately granted elevated privileges

3. Review the actor who created the account

Worked example

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

Sample Test Event
{
  "actionName": "createUser",
  "requestParams": {
    "targetUserName": "newuser@example.com"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "accounts",
  "userIdentity": {
    "email": "admin@example.com"
  }
}

Databricks User Account Deleted

#
Status
Experimental
Severity
low
Group by
requestParams.targetUserName
Log types
Databricks.Audit
Tags
Databricks, Impact
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects user account deletions in Databricks. While often part of normal offboarding processes, unauthorized deletions could indicate malicious activity or insider threats. Successful deletions are elevated to HIGH severity.

MITRE ATT&CK coverage

TacticTechniques
Impact

Detection logic

from panther_databricks_helpers import databricks_alert_context


def rule(event):
    if event.get("serviceName") != "accounts":
        return False

    if event.get("actionName") != "delete":
        return False

    # Only match user deletions, not other account-level deletes
    # Primary check: targetUserName field exists
    # Fallback: endpoint contains "/users/" or starts with "users"
    if event.deep_get("requestParams", "targetUserName") is not None:
        return True

    endpoint = event.deep_get("requestParams", "endpoint", default="").lower()
    return "/users/" in endpoint or endpoint.startswith("users")


def severity(event):
    status_code = event.deep_get("response", "statusCode")
    return "HIGH" if status_code == 200 else "LOW"


def title(event):
    target_user = event.deep_get("requestParams", "targetUserName", default="Unknown User")
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    status_code = event.deep_get("response", "statusCode")
    status = "Success" if status_code == 200 else "Failed"
    return f"User account deletion {status}: {target_user} by {actor}"


def dedup(event):
    target_user = event.deep_get("requestParams", "targetUserName", default="unknown")
    return f"user_deleted_{target_user}"


def alert_context(event):
    return databricks_alert_context(
        event,
        additional_fields={
            "target_user": event.deep_get("requestParams", "targetUserName"),
            "endpoint": event.deep_get("requestParams", "endpoint"),
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_user_account_deleted.py
RuleID: "Databricks.Audit.UserAccountDeleted"
DisplayName: "Databricks User Account Deleted"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Impact
Reports:
  MITRE ATT&CK:
    - TA0040:T1531 # Account Access Removal
Severity: Low
Description: >
  Detects user account deletions in Databricks. While often part of normal offboarding processes,
  unauthorized deletions could indicate malicious activity or insider threats. Successful deletions
  are elevated to HIGH severity.
Runbook: |
  1. Query audit logs for all actions performed by the deleted user (requestParams.targetUserName) in the 48 hours before deletion
  2. Check if there were any privilege escalation or suspicious actions by this user in the 7 days before deletion
  3. Find all user deletions by this actor in the past 30 days to identify bulk deletion patterns
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/blob/main/base/detections/event-based/user_account_deleted.py

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • serviceName is accounts
  • actionName is delete
  • any of:
    • requestParams.targetUserName is present
    • requestParams.endpoint contains /users/
    • requestParams.endpoint starts with users

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
targetUserNamerequestParams.targetUserName
emailuserIdentity.email

Response runbook

1. Query audit logs for all actions performed by the deleted user (requestParams.targetUserName) in the 48 hours before deletion

2. Check if there were any privilege escalation or suspicious actions by this user in the 7 days before deletion

3. Find all user deletions by this actor in the past 30 days to identify bulk deletion patterns

Worked example

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

Sample Test Event
{
  "actionName": "delete",
  "requestParams": {
    "endpoint": "/users",
    "targetUserName": "user@example.com"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "accounts",
  "sourceIPAddress": "198.51.100.1",
  "timestamp": 1234567890000,
  "userIdentity": {
    "email": "admin@example.com"
  }
}

Databricks User Password Changed

#
Status
Experimental
Severity
informational
Group by
userIdentity.email
Log types
Databricks.Audit
Tags
Databricks, Credential Access
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects password change events on Databricks accounts. May indicate legitimate password rotation or an unauthorized reset following account compromise.

MITRE ATT&CK coverage

TacticTechniques
Persistence
Privilege Escalation

Detection logic

from panther_databricks_helpers import databricks_alert_context


def rule(event):
    if event.get("serviceName") != "accounts":
        return False

    return event.get("actionName") == "changePassword"


def title(event):
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    status_code = event.deep_get("response", "statusCode")
    status = "Success" if status_code == 200 else "Failed"
    return f"Password changed by {actor} - {status}"


def dedup(event):
    actor = event.deep_get("userIdentity", "email", default="unknown")
    return f"password_changed_{actor}"


def alert_context(event):
    return databricks_alert_context(event)

Rule specification

AnalysisType: rule
Filename: databricks_user_password_changed.py
RuleID: "Databricks.Audit.UserPasswordChanged"
DisplayName: "Databricks User Password Changed"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Credential Access
Reports:
  MITRE ATT&CK:
    - TA0006:T1098 # Account Manipulation
Severity: Info
Description: >
  Detects password change events on Databricks accounts. May indicate legitimate
  password rotation or an unauthorized reset following account compromise.
Runbook: |
  1. Verify the password change was initiated by the legitimate account owner
  2. Check for preceding suspicious activity (failed logins, MFA changes)
  3. If unauthorized, force password reset and revoke active sessions
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/tree/main/base/detections/behavioral

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • serviceName is accounts
  • actionName is changePassword

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
emailuserIdentity.email

Response runbook

1. Verify the password change was initiated by the legitimate account owner

2. Check for preceding suspicious activity (failed logins, MFA changes)

3. If unauthorized, force password reset and revoke active sessions

Worked example

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

Sample Test Event
{
  "actionName": "changePassword",
  "response": {
    "statusCode": 200
  },
  "serviceName": "accounts",
  "userIdentity": {
    "email": "user@example.com"
  }
}

Databricks User Role Modified

#
Status
Experimental
Severity
informational
Log types
Databricks.Audit
Tags
Databricks, Privilege Escalation
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects when user roles are modified or users are added to administrative groups in Databricks. This is often legitimate administrative activity but should be monitored for unauthorized changes.

MITRE ATT&CK coverage

TacticTechniques
Privilege Escalation

Detection logic

from panther_databricks_helpers import databricks_alert_context


def rule(event):
    if event.get("serviceName") != "accounts":
        return False

    return event.get("actionName") in ["addUserToAdminGroup", "modifyUserRole"]


def title(event):
    action = event.get("actionName", "Unknown Action")
    actor = event.deep_get("userIdentity", "email", default="Unknown User")
    return f"User role modified: {action} by {actor}"


def alert_context(event):
    return databricks_alert_context(
        event, additional_fields={"request_params": event.get("requestParams")}
    )

Rule specification

AnalysisType: rule
Filename: databricks_user_role_modified.py
RuleID: "Databricks.Audit.UserRoleModified"
DisplayName: "Databricks User Role Modified"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Privilege Escalation
Reports:
  MITRE ATT&CK:
    - TA0004:T1098 # Account Manipulation
Severity: Info
Description: >
  Detects when user roles are modified or users are added to administrative groups in Databricks.
  This is often legitimate administrative activity but should be monitored for unauthorized changes.
Runbook: |
  1. Query audit logs for all role modifications by the actor (userIdentity.email) in the 24 hours before and after this change
  2. Check if the target user has performed new actions using the modified role in the 6 hours after the change
  3. Find all role modifications for this target user in the past 90 days to establish baseline
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/blob/main/base/detections/event-based/user_role_modified.py

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • serviceName is accounts
  • actionName is one of addUserToAdminGroup, modifyUserRole

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
actionNamein
  • addUserToAdminGroup
  • modifyUserRole
field:"actionName" kind:in
serviceNameeq
  • accounts
field:"serviceName" kind:eq value:"accounts"

Output fields

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

FieldSource
actionName
emailuserIdentity.email

Response runbook

1. Query audit logs for all role modifications by the actor (userIdentity.email) in the 24 hours before and after this change

2. Check if the target user has performed new actions using the modified role in the 6 hours after the change

3. Find all role modifications for this target user in the past 90 days to establish baseline

Worked example

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

Sample Test Event
{
  "actionName": "addUserToAdminGroup",
  "requestParams": {
    "targetGroupName": "admins",
    "targetUserName": "user@example.com"
  },
  "serviceName": "accounts",
  "sourceIPAddress": "198.51.100.1",
  "timestamp": 1234567890000,
  "userIdentity": {
    "email": "admin@example.com"
  }
}

Databricks Verbose Audit Logging Disabled

#
Status
Experimental
Severity
high
Log types
Databricks.Audit
Tags
Databricks, Defense Evasion
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects when verbose audit logging is disabled in a Databricks workspace. Disabling verbose audit logging significantly reduces the visibility of security-relevant events and is a common technique used by attackers to hide malicious activity. Successful disabling is elevated to CRITICAL severity.

MITRE ATT&CK coverage

Detection logic

from panther_databricks_helpers import databricks_alert_context


def rule(event):
    if event.get("serviceName") != "workspace":
        return False

    if event.get("actionName") != "workspaceConfEdit":
        return False

    # Check if the configuration key is for verbose audit logs
    conf_key = event.deep_get("requestParams", "workspaceConfKeys")
    if conf_key != "enableVerboseAuditLogs":
        return False

    # Check if verbose logging is being disabled
    conf_value = event.deep_get("requestParams", "workspaceConfValues")
    return conf_value == "false"


def severity(event):
    status_code = event.deep_get("response", "statusCode")
    return "CRITICAL" if status_code == 200 else "HIGH"


def title(event):
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    status_code = event.deep_get("response", "statusCode")
    status = "Successfully disabled" if status_code == 200 else "Attempted to disable"
    return f"Verbose audit logging {status} by {actor}"


def alert_context(event):
    conf_value = event.deep_get("requestParams", "workspaceConfValues")
    return databricks_alert_context(
        event,
        additional_fields={
            "config_key": event.deep_get("requestParams", "workspaceConfKeys"),
            "config_value": conf_value,
            "config_status": "Disabled" if conf_value == "false" else "Enabled",
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_verbose_audit_logging_disabled.py
RuleID: "Databricks.Audit.VerboseAuditLoggingDisabled"
DisplayName: "Databricks Verbose Audit Logging Disabled"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Defense Evasion
Reports:
  MITRE ATT&CK:
    - TA0005:T1562.008 # Impair Defenses: Disable or Modify Cloud Logs
Severity: High
Description: >
  Detects when verbose audit logging is disabled in a Databricks workspace. Disabling verbose
  audit logging significantly reduces the visibility of security-relevant events and is a common
  technique used by attackers to hide malicious activity. Successful disabling is elevated to
  CRITICAL severity.
Runbook: |
  1. Query audit logs for all actions by the actor (userIdentity.email) in the 6 hours before and after disabling audit logging
  2. Check if there were suspicious data access, deletion, or privilege escalation actions in the 24 hours around this change
  3. Find all other high-risk configuration changes by this actor in the past 7 days
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/blob/main/base/detections/event-based/verbose_audit_logging_disabled.py
SummaryAttributes:
  - actor
  - source_ip
  - config_status

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • serviceName is workspace
  • actionName is workspaceConfEdit
  • requestParams.workspaceConfKeys is enableVerboseAuditLogs
  • requestParams.workspaceConfValues is false

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
emailuserIdentity.email

Response runbook

1. Query audit logs for all actions by the actor (userIdentity.email) in the 6 hours before and after disabling audit logging

2. Check if there were suspicious data access, deletion, or privilege escalation actions in the 24 hours around this change

3. Find all other high-risk configuration changes by this actor in the past 7 days

Worked example

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

Sample Test Event
{
  "actionName": "workspaceConfEdit",
  "auditLevel": "WORKSPACE_LEVEL",
  "requestParams": {
    "workspaceConfKeys": "enableVerboseAuditLogs",
    "workspaceConfValues": "false"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "workspace",
  "sourceIPAddress": "198.51.100.1",
  "timestamp": 1234567890000,
  "userAgent": "Mozilla/5.0",
  "userIdentity": {
    "email": "admin@example.com"
  }
}

Databricks Workspace Admin Privileged Role Assignment

#
Status
Experimental
Severity
medium
Group by
workspaceId
Log types
Databricks.Audit
Tags
Databricks, Privilege Escalation, Persistence
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects when workspace-level admin privileges are granted in Databricks through direct role assignments or administrative group membership. This simplified version detects direct admin grants and additions to admin groups. For nested group resolution (detecting when groups are added to admin groups), consider implementing a correlation rule. Successful grants to the system 'admins' group are elevated to HIGH severity.

MITRE ATT&CK coverage

Detection logic

from panther_databricks_helpers import (
    databricks_alert_context,
    extract_group_identifier,
    extract_target_principal,
    get_principal_type,
    is_admin_privilege_action,
)

REMOVAL_ACTIONS = ["removeAdmin", "removePrincipalFromGroup"]


def rule(event):
    # Only match workspace-level events to avoid overlap with the
    # account-level admin privilege rule
    if event.get("auditLevel") != "WORKSPACE_LEVEL":
        return False

    # Exclude privilege removals — this rule detects grants only
    if event.get("actionName") in REMOVAL_ACTIONS:
        return False

    return is_admin_privilege_action(event)


def severity(event):
    status_code = event.deep_get("response", "statusCode")
    return "HIGH" if status_code == 200 else "MEDIUM"


def title(event):
    action = event.get("actionName", "Unknown Action")
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    target = extract_target_principal(event) or "Unknown Principal"
    workspace = event.get("workspaceId", "Unknown Workspace")
    status_code = event.deep_get("response", "statusCode")
    status = "Granted" if status_code == 200 else "Attempted to grant"

    # Check if it's direct admin action or group-based
    if action in ["setAdmin", "addAdmin"]:
        return (
            f"{status} workspace admin privileges to {target}"
            f" in workspace {workspace} by {actor}"
        )
    group = extract_group_identifier(event)
    return (
        f"{status} admin group membership ({group}) to {target}"
        f" in workspace {workspace} by {actor}"
    )


def dedup(event):
    target_principal = extract_target_principal(event) or "unknown"
    workspace = event.get("workspaceId", "unknown")
    return f"workspace_admin_privilege_{workspace}_{target_principal}"


def alert_context(event):
    target_principal = extract_target_principal(event)
    principal_type = get_principal_type(target_principal) if target_principal else "Unknown"
    group = extract_group_identifier(event)

    return databricks_alert_context(
        event,
        additional_fields={
            "privilege_scope": "WORKSPACE_LEVEL",
            "target_principal": target_principal,
            "principal_type": principal_type,
            "target_group": group,
            "is_system_admins_group": group.lower() == "admins" if group else False,
            "detection_note": (
                "Direct grants only - nested group resolution requires correlation rule"
            ),
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_workspace_admin_privileged_role_assignment.py
RuleID: "Databricks.Audit.WorkspaceAdminPrivilegedRoleAssignment"
DisplayName: "Databricks Workspace Admin Privileged Role Assignment"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Privilege Escalation
  - Persistence
Reports:
  MITRE ATT&CK:
    - TA0004:T1098 # Account Manipulation
    - TA0003:T1136 # Create Account
Severity: Medium
Description: >
  Detects when workspace-level admin privileges are granted in Databricks through direct role
  assignments or administrative group membership. This simplified version detects direct admin
  grants and additions to admin groups. For nested group resolution (detecting when groups are
  added to admin groups), consider implementing a correlation rule. Successful grants to the
  system 'admins' group are elevated to HIGH severity.
Runbook: |
  1. Query audit logs for all workspace administrative actions by the target principal in the 24 hours after this privilege grant
  2. Check if the target principal created clusters, modified notebooks, or accessed sensitive data in the 6 hours after receiving admin rights
  3. Find all workspace admin grants for this workspace in the past 90 days to establish baseline
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/blob/main/base/detections/event-based/workspace_admin_privileged_role_assignment.py
SummaryAttributes:
  - actor
  - target_principal
  - principal_type
  - target_group

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • auditLevel is WORKSPACE_LEVEL
  • actionName is not one of removeAdmin, removePrincipalFromGroup

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

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
actionNameinremoveAdmin, removePrincipalFromGroupexcludes:actionName field:"actionName" value:"removeAdmin" field:"actionName" value:"removePrincipalFromGroup"

Indicators

These rows show field, operator, and value matches.

Output fields

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

FieldSource
workspaceId
emailuserIdentity.email

Response runbook

1. Query audit logs for all workspace administrative actions by the target principal in the 24 hours after this privilege grant

2. Check if the target principal created clusters, modified notebooks, or accessed sensitive data in the 6 hours after receiving admin rights

3. Find all workspace admin grants for this workspace in the past 90 days to establish baseline

Worked example

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

Sample Test Event
{
  "actionName": "setAdmin",
  "auditLevel": "WORKSPACE_LEVEL",
  "requestParams": {
    "targetUserName": "newadmin@example.com"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "accounts",
  "sourceIPAddress": "198.51.100.1",
  "timestamp": 1234567890000,
  "userIdentity": {
    "email": "admin@example.com"
  },
  "workspaceId": "1234567890123456"
}

Databricks Workspace-Level Configuration Changes

#
Status
Experimental
Severity
informational
Group by
workspaceId
Log types
Databricks.Audit
Tags
Databricks, Persistence
Reference
github.com
Source
github.com/panther-labs/panther-analysis

Detects configuration changes at the Databricks workspace level. Workspace-level changes affect a single workspace and include settings like cluster configurations, notebook settings, and workspace-specific security controls.

MITRE ATT&CK coverage

TacticTechniques
Persistence

Detection logic

from panther_databricks_helpers import (
    databricks_alert_context,
    get_config_key_value,
    is_config_change,
)


def rule(event):
    # Must be workspace-level audit event
    if event.get("auditLevel") != "WORKSPACE_LEVEL":
        return False

    # Check if it's a workspace configuration change
    return is_config_change(event, config_category="workspace")


def title(event):
    action = event.get("actionName", "Unknown Action")
    actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
    workspace = event.get("workspaceId", "Unknown Workspace")
    status_code = event.deep_get("response", "statusCode")
    status = "Success" if status_code == 200 else "Failed"

    # Include the config key in the title when available
    config_key, _ = get_config_key_value(event)
    if config_key:
        return f"Workspace config change ({config_key}) in {workspace} by {actor} - {status}"

    return f"Workspace configuration change ({action}) in {workspace} by {actor} - {status}"


def dedup(event):
    workspace = event.get("workspaceId", "unknown")
    config_key, _ = get_config_key_value(event)
    return f"workspace_config_change_{workspace}_{config_key}"


def alert_context(event):
    config_key, config_value = get_config_key_value(event)
    return databricks_alert_context(
        event,
        additional_fields={
            "change_scope": "WORKSPACE_LEVEL",
            "config_key": config_key,
            "config_value": config_value,
        },
    )

Rule specification

AnalysisType: rule
Filename: databricks_config_changes_workspace_level.py
RuleID: "Databricks.Audit.ConfigChangesWorkspaceLevel"
DisplayName: "Databricks Workspace-Level Configuration Changes"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Persistence
Reports:
  MITRE ATT&CK:
    - TA0003:T1098 # Account Manipulation
Severity: Info
Description: >
  Detects configuration changes at the Databricks workspace level. Workspace-level changes
  affect a single workspace and include settings like cluster configurations, notebook
  settings, and workspace-specific security controls.
Runbook: |
  1. Query audit logs for all workspace configuration changes in the 24 hours around this event
  2. Check if the workspace behavior changed based on cluster activity or user actions in the 6 hours after the configuration change
  3. Find all configuration changes for this workspace in the past 30 days to establish baseline
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/blob/main/base/detections/event-based/configuration_changes_workspace_level.py

Stages and Predicates

Fires on Databricks.Audit events when all of the conditions below hold.

Condition

  • auditLevel is WORKSPACE_LEVEL
  • any of:
    • serviceName is workspace
    • all of:
      • serviceName is not workspace
      • serviceName is accounts
    • all of:
      • serviceName is not workspace
      • serviceName is not accounts
      • serviceName is ssoConfigBackend

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
auditLeveleq
  • WORKSPACE_LEVEL
field:"auditLevel" kind:eq value:"WORKSPACE_LEVEL"
serviceNameeq
  • accounts
  • ssoConfigBackend
  • workspace
field:"serviceName" kind:eq

Output fields

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

FieldSource
workspaceId
emailuserIdentity.email
actionName

Response runbook

1. Query audit logs for all workspace configuration changes in the 24 hours around this event

2. Check if the workspace behavior changed based on cluster activity or user actions in the 6 hours after the configuration change

3. Find all configuration changes for this workspace in the past 30 days to establish baseline

Worked example

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

Sample Test Event
{
  "actionName": "workspaceConfEdit",
  "auditLevel": "WORKSPACE_LEVEL",
  "requestParams": {
    "workspaceConfKeys": "defaultClusterVersion",
    "workspaceConfValues": "12.2.x-scala2.12"
  },
  "response": {
    "statusCode": 200
  },
  "serviceName": "workspace",
  "sourceIPAddress": "198.51.100.1",
  "timestamp": 1234567890000,
  "userIdentity": {
    "email": "admin@example.com"
  },
  "workspaceId": "1234567890123456"
}