Query Details

Microsoft 365 Copilot - Config change followed by abuse signal

Copilot Config To Abuse Chain

Query

let configRecordTypes = dynamic([
    "UpdateCopilotSettings",
    "CreateCopilotPlugin", "UpdateCopilotPlugin",
    "EnableCopilotPlugin", "DisableCopilotPlugin",
    "CreateCopilotPromptBook", "UpdateCopilotPromptBook",
    "DeleteCopilotPromptBook"
]);
let window = 1d;
let recentWindow = 1h;
let configEvents =
    CopilotActivity
    | where TimeGenerated > ago(window)
    | where RecordType in (configRecordTypes)
    | project
        ConfigTime = TimeGenerated,
        ConfigKind = RecordType,
        ConfigAgentId = AgentId,
        ConfigAgentName = AgentName,
        ConfigActor = ActorName,
        ConfigActorUserId = ActorUserId,
        TenantId;
let abuseEvents =
    CopilotActivity
    | where TimeGenerated > ago(recentWindow)
    | where RecordType == "CopilotInteraction"
    | extend
        ThreadId = tostring(LLMEventData.ThreadId),
        DlpDeferred = tobool(LLMEventData.DLPEvaluationDeferred)
    | mv-expand r = LLMEventData.AccessedResources, m = LLMEventData.Messages
    | extend
        XpiaHit = tobool(r.XPIADetected),
        DlpHit = (isnotempty(tostring(r.PolicyDetails))
                  and tostring(r.PolicyDetails) !in ("[]", "{}", "null"))
                  or DlpDeferred,
        JbHit = tobool(m.JailbreakDetected)
    | where XpiaHit or DlpHit or JbHit
    | summarize
        AbuseTime = max(TimeGenerated),
        AbuseKinds = make_set(case(XpiaHit, "XPIA", DlpHit, "DLP", JbHit, "Jailbreak", ""), 4),
        AbuseThreads = make_set(ThreadId, 8),
        AbuseSites = make_set(tostring(r.SiteUrl), 16)
        by AgentId, AgentName, ActorName, ActorUserId, TenantId;
abuseEvents
| join kind=inner (
    configEvents
    | project-rename
        ConfigAgentIdJ = ConfigAgentId,
        ConfigActorUserIdJ = ConfigActorUserId
) on $left.TenantId == $right.TenantId
| where ConfigTime <= AbuseTime
    and AbuseTime - ConfigTime <= window
    and (
        (isnotempty(AgentId) and AgentId == ConfigAgentIdJ)
        or (isnotempty(ActorUserId) and ActorUserId == ConfigActorUserIdJ)
    )
| extend ChainGapMin = datetime_diff('minute', AbuseTime, ConfigTime)
| project
    ConfigTime, ConfigKind, ConfigActor, ConfigAgentName,
    AbuseTime, AbuseKinds, AbuseThreads, AbuseSites,
    AgentId, AgentName, ActorName, ActorUserId,
    ChainGapMin, TenantId
| order by AbuseTime desc, ChainGapMin asc

Explanation

This query is designed to detect potential security threats related to Microsoft 365 Copilot by identifying a sequence of events that could indicate misuse. Here's a simplified breakdown:

  1. Purpose: The query looks for a pattern where an administrative change to Copilot's configuration (like settings, plugins, or prompt-books) is followed by suspicious activities within a 24-hour period. These activities could include attempts to bypass security measures, inject unauthorized prompts, or trigger data loss prevention (DLP) policies.

  2. How it Works:

    • It first identifies configuration changes made by an admin or a potentially compromised account.
    • Then, it checks for any abuse signals, such as jailbreak attempts, prompt injections, or DLP policy hits, that occur after these changes.
    • The query correlates these events if they happen on the same agent or are initiated by the same user.
  3. Limitations: The correlation is based on the agent ID or user ID. If a plugin is installed across the entire tenant and misused by a different user on another agent, the query might not link these events.

  4. Severity and Response: The rule is set to a high severity level, indicating a significant threat. If the pattern is detected, an alert is generated, and an incident is created for further investigation.

  5. Technical Details:

    • The query runs every hour and looks back over the past day.
    • It uses specific data types and connectors related to Microsoft Copilot activities.
    • The results are ordered by the time of the abuse event and the time gap between the configuration change and the abuse.
  6. Entity Mapping and Incident Management: The query maps relevant entities like cloud applications and user accounts for better context and groups related alerts into a single incident for efficient management.

Overall, this query helps security teams quickly identify and respond to potential security incidents involving Microsoft 365 Copilot by highlighting suspicious sequences of configuration changes followed by misuse.

Details

David Alonso profile picture

David Alonso

Released: May 20, 2026

Tables

CopilotActivity

Keywords

MicrosoftCopilotActivityAgentActorTenantCloudApplicationAccountSentinelAsCodeCustomAI

Operators

letdynamicagoinprojectwhereextendmv-expandtoboolisnotemptytostringcasesummarizemake_setbyjoinonproject-rename==<=-andordatetime_difforder by

Severity

High

Tactics

PersistenceDefenseEvasionExecution

MITRE Techniques

Frequency: PT1H

Period: P1D

Actions

GitHub