Query Details

Copilot Exfiltration Pattern

Query

id: 4d6c9e3a-8b5f-4c7d-a1e2-9f8d7c6b5a41
name: Microsoft 365 Copilot - Exfiltration pattern (sensitive + cross-repo + large synthesis)
description: |
  Detects the classic data-exfiltration shape on a Microsoft 365 Copilot
  thread: a sensitive-resource hit (DLP PolicyDetails or
  DLPEvaluationDeferred), combined with cross-repository aggregation
  (many distinct grounding sites), combined with a large multi-document
  synthesis (high total message count on the thread).

  None of these signals on their own is necessarily malicious; the
  combination is. Tune the thresholds to match how your tenant uses
  Copilot - the defaults below assume a workforce that does not
  routinely synthesise 5+ document repositories in a single thread.

  Limitation: this rule only sees the structural fields exposed in
  LLMEventData. It cannot detect explicit export / send / forward
  intents because raw prompt and response text are not surfaced.
severity: High
requiredDataConnectors:
- connectorId: MicrosoftCopilot
  dataTypes:
  - CopilotActivity
queryFrequency: PT1H
queryPeriod: PT6H
triggerOperator: gt
triggerThreshold: 0
enabled: true
tactics:
- Collection
- Exfiltration
relevantTechniques:
- T1213
- T1530
- T1567
query: |
  // Per-thread combo: DLP hit + >=5 distinct sites + >=50 total messages.
  CopilotActivity
  | where TimeGenerated > ago(6h)
  | where RecordType == "CopilotInteraction"
  | extend
      ThreadId = tostring(LLMEventData.ThreadId),
      DlpDeferred = tobool(LLMEventData.DLPEvaluationDeferred),
      InteractionMessages = array_length(LLMEventData.Messages)
  | where isnotempty(ThreadId)
  | mv-expand r = LLMEventData.AccessedResources
  | extend
      SiteUrl = tostring(r.SiteUrl),
      ResourceType = tostring(r.Type),
      PolicyDetailsStr = tostring(r.PolicyDetails),
      HasPolicyHit = isnotempty(tostring(r.PolicyDetails))
          and tostring(r.PolicyDetails) !in ("[]", "{}", "null")
  | summarize
      DlpHits = countif(HasPolicyHit or DlpDeferred),
      DistinctSites = dcount(SiteUrl),
      DistinctTypes = dcount(ResourceType),
      TotalMessages = sum(InteractionMessages),
      Interactions = dcount(strcat(tostring(TimeGenerated))),
      Sites = make_set(SiteUrl, 32),
      ResourceTypes = make_set(ResourceType, 16),
      Policies = make_set(PolicyDetailsStr, 16),
      AgentIds = make_set(AgentId, 4),
      AgentNames = make_set(AgentName, 4),
      Actors = make_set(ActorName, 4),
      ActorUserIds = make_set(ActorUserId, 4),
      ClientIPs = make_set(SrcIpAddr, 16),
      FirstSeen = min(TimeGenerated),
      LastSeen = max(TimeGenerated)
      by ThreadId, TenantId
  | where DlpHits >= 1 and DistinctSites >= 5 and TotalMessages >= 50
  | extend
      AgentId = tostring(AgentIds[0]),
      AgentName = tostring(AgentNames[0]),
      ActorName = tostring(Actors[0]),
      ActorUserId = tostring(ActorUserIds[0]),
      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: PT12H
    matchingMethod: Selected
    groupByEntities:
    - Account
    groupByAlertDetails: []
    groupByCustomDetails: []
version: 1.0.0
kind: Scheduled
tags:
- Sentinel-As-Code
- Custom
- Copilot
- AI

Explanation

This query is designed to detect potential data exfiltration activities involving Microsoft 365 Copilot. Here's a simplified summary:

  1. Purpose: The query identifies suspicious patterns where sensitive data might be exfiltrated using Microsoft 365 Copilot. It looks for a combination of three specific signals:

    • A hit on a Data Loss Prevention (DLP) policy.
    • Access to multiple distinct repositories (at least 5 different sites).
    • A large number of messages (at least 50) in a single thread.
  2. How it Works:

    • The query examines Copilot activity over the past 6 hours.
    • It focuses on interactions where there is a DLP policy hit or evaluation is deferred.
    • It checks if the activity involves accessing resources from at least 5 different sites and involves at least 50 messages in total.
    • If these conditions are met, it flags the activity as potentially malicious.
  3. Limitations: The query only uses structural data from Copilot interactions and cannot detect explicit actions like exporting or forwarding data because it doesn't analyze the actual content of prompts or responses.

  4. Severity and Actions:

    • The severity of this detection is marked as high.
    • If the conditions are met, an incident is created for further investigation.
    • The query runs every hour and looks back at the past 6 hours of data.
  5. Configuration:

    • The query is enabled by default and is part of a scheduled task.
    • It groups incidents by account to help identify patterns related to specific users.

Overall, this query is a proactive measure to monitor and alert on potential data exfiltration activities using Microsoft 365 Copilot, helping organizations protect sensitive information.

Details

David Alonso profile picture

David Alonso

Released: May 20, 2026

Tables

CopilotActivity

Keywords

CopilotActivityThreadResourceSitePolicyMessageAgentActorUserIPAccountApplicationAlertIncident

Operators

ago==tostringtoboolarray_lengthisnotemptymv-expand!insummarizecountifdcountsumdcountmake_setminmaxby>=extend

Actions