Query Details

Copilot Access Drift Detection

Query

id: 1f6c2a5e-9c2f-4f4b-b1d3-3a7d5e8b9c01
name: Microsoft 365 Copilot - AI agent access drift outside baseline
description: |
  Detects when A Microsoft 365 Copilot agent suddenly invokes tools or accesses
  data sources that fall outside its 14-day behavioural baseline.

  Agent permissions tend to expand quietly as agents take on new
  tasks. An agent that has only ever read SharePoint documents
  unexpectedly invoking an Exchange or Graph data-write tool is a
  strong signal of access drift or scope abuse and should be
  reviewed by an analyst.
severity: Medium
requiredDataConnectors:
- connectorId: MicrosoftCopilot
  dataTypes:
  - CopilotActivity
queryFrequency: PT1H
queryPeriod: P14D
triggerOperator: gt
triggerThreshold: 0
enabled: true
tactics:
- PrivilegeEscalation
- Discovery
relevantTechniques:
- T1098
- T1087
query: |
  // Confirmed schema: LLMEventData.AccessedResources[].Type / .SiteUrl
  // Drift is computed on the resource-type set per user across a 14d window.
  let lookback = 14d;
  let recentWindow = 1h;
  let events =
      CopilotActivity
      | where TimeGenerated > ago(lookback)
      | where RecordType == "CopilotInteraction"
      | mv-expand r = LLMEventData.AccessedResources
      | extend
          ResourceType = tostring(r.Type),
          SiteUrl = tolower(tostring(r.SiteUrl)),
          ResourceAction = tostring(r.Action)
      | where isnotempty(ResourceType);
  let baseline =
      events
      | where TimeGenerated between (ago(lookback) .. ago(recentWindow))
      | summarize BaselineTypes = make_set(ResourceType, 64) by ActorUserId;
  let recent =
      events
      | where TimeGenerated > ago(recentWindow);
  recent
  | join kind=leftouter baseline on ActorUserId
  | extend BaselineTypes = coalesce(BaselineTypes, dynamic([]))
  | where array_index_of(BaselineTypes, ResourceType) < 0
  | summarize
      DriftCount = count(),
      NewResourceTypes = make_set(ResourceType, 16),
      SampleSites = make_set(SiteUrl, 16),
      SampleActions = make_set(ResourceAction, 8),
      AgentNames = make_set(AgentName, 8),
      AgentIds = make_set(AgentId, 8),
      AnyActor = take_any(ActorName),
      ClientIPs = make_set(SrcIpAddr, 16),
      FirstSeen = min(TimeGenerated),
      LastSeen = max(TimeGenerated)
      by ActorUserId, TenantId
  | extend
      AgentName = tostring(AgentNames[0]),
      AgentId = tostring(AgentIds[0]),
      ActorName = AnyActor,
      SrcIpAddr = tostring(ClientIPs[0])
entityMappings:
- entityType: CloudApplication
  fieldMappings:
  - identifier: Name
    columnName: AgentName
  - identifier: AppId
    columnName: AgentId
- entityType: Account
  fieldMappings:
  - identifier: Name
    columnName: ActorName
- entityType: IP
  fieldMappings:
  - identifier: Address
    columnName: SrcIpAddr
eventGroupingSettings:
  aggregationKind: SingleAlert
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: PT5H
    matchingMethod: Selected
    groupByEntities:
    - CloudApplication
    groupByAlertDetails: []
    groupByCustomDetails: []
version: 1.0.0
kind: Scheduled
tags:
- Sentinel-As-Code
- Custom
- Copilot
- AI

Explanation

This query is designed to monitor and detect unusual behavior by Microsoft 365 Copilot agents, specifically when they access tools or data sources that are not part of their usual activity over the past 14 days. Here's a simple breakdown:

  1. Purpose: The query identifies when a Microsoft 365 Copilot agent accesses resources outside its established 14-day baseline. This could indicate unauthorized access or misuse of permissions.

  2. Severity: The alert is marked as "Medium" severity, suggesting that while it's not critical, it still requires attention.

  3. Data Source: It uses data from the "MicrosoftCopilot" connector, specifically looking at "CopilotActivity" data.

  4. Frequency and Period: The query runs every hour and examines data from the past 14 days.

  5. Detection Logic:

    • It first collects all resource access events by Copilot agents over the last 14 days.
    • It establishes a baseline of resource types accessed by each agent during this period.
    • It then checks for any recent access (within the last hour) to resource types not in the baseline.
    • If such access is detected, it counts these occurrences and gathers additional details like the types of new resources accessed, sample sites, actions, agent names, and IP addresses.
  6. Alerting: If any access drift is detected, an alert is triggered. The alert includes details about the agent, the user involved, and the IP address from which the access occurred.

  7. Entity Mapping: The query maps detected entities to cloud applications, user accounts, and IP addresses for better context in alerts.

  8. Incident Management: When an alert is generated, it can create an incident in the system. Incidents are grouped by the cloud application to manage related alerts efficiently.

  9. Version and Tags: The query is versioned as 1.0.0 and tagged for easy identification and categorization within the system.

Overall, this query helps security analysts monitor for potential privilege escalation or unauthorized access by AI agents, ensuring that any deviation from normal behavior is promptly investigated.

Details

David Alonso profile picture

David Alonso

Released: May 20, 2026

Tables

CopilotActivity

Keywords

Microsoft365CopilotAIAgentAccessDataSourcesSharePointExchangeGraphResourceTypeUserActorTenantCloudApplicationAccountIPAddress

Operators

letmv-expandextendtostringtolowerisnotemptybetweenagosummarizemake_setjoinkind=leftoutercoalescedynamicarray_index_ofcounttake_anyminmax

Actions