Query Details

Copilot Studio - URL / domain / IP matched against threat intelligence

Copilot Studio Threat Intel Url Match

Query

let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let networkIocTypes = dynamic(["url:value", "domain-name:value", "ipv4-addr:value", "ipv6-addr:value"]);
let TI =
    ThreatIntelIndicators
    | where TimeGenerated > ago(ioc_lookBack)
    | where IsActive == true and Revoked == false
    | where ObservableKey in (networkIocTypes)
    | where isempty(ValidUntil) or ValidUntil > now()
    | summarize arg_max(TimeGenerated, *) by IndicatorId = Id
    | extend IOC = tolower(ObservableValue)
    | where isnotempty(IOC);
let Content =
    AppEvents
    | where TimeGenerated > ago(dt_lookBack)
    | where Name in ("BotMessageReceived", "BotMessageSend")
    | extend
        ConvId    = tostring(Properties["conversationId"]),
        ChannelId = tostring(Properties["channelId"]),
        Direction = iff(Name == "BotMessageReceived", "UserPrompt", "AgentResponse"),
        Text      = tostring(Properties["text"])
    | where isnotempty(Text)
    | mv-expand Url = extract_all(@"(https?://[^\s\)\]\}""'<>]+)", Text) to typeof(string)
    | extend
        Url  = tolower(Url),
        Host = tolower(tostring(extract(@"https?://([^/:\s]+)", 1, Url)))
    | mv-expand IOC = pack_array(Url, Host) to typeof(string)
    | where isnotempty(IOC);
Content
| join kind=inner TI on IOC
| extend AccountName = iff(isempty(UserId), "unknown-agent", UserId)
| project
    TimeGenerated, Direction, AccountName, ConvId, ChannelId,
    MatchedIOC = IOC, ObservableKey, Confidence,
    ThreatType  = tostring(todynamic(Data).indicator_types[0]),
    Description = tostring(todynamic(Data).description),
    Url, Host, ClientIP, SessionId, AppVersion
| order by TimeGenerated desc

Explanation

This query is designed to monitor and identify potentially malicious URLs, domains, or IP addresses that appear in conversations involving Copilot Studio, a chatbot or virtual assistant platform. Here's a simplified breakdown of what the query does:

  1. Data Sources: It uses data from two sources:

    • Application Insights (AppEvents): This captures the text content of conversations, both incoming user prompts and outgoing agent responses.
    • Threat Intelligence (ThreatIntelIndicators): This provides a list of known malicious or suspicious URLs, domains, and IP addresses.
  2. Time Frame:

    • The query checks conversation data from the last hour.
    • It compares this data against threat intelligence indicators from the last 14 days.
  3. Process:

    • Extracts URLs and their hosts/IPs from the conversation content.
    • Converts these to lowercase for consistent matching.
    • Compares these extracted URLs/hosts/IPs against the active threat intelligence indicators.
  4. Matching:

    • If a match is found, it indicates that the conversation involved a known malicious or suspicious URL, domain, or IP.
    • This could suggest a phishing attempt, compromised information source, or exposure to attacker infrastructure.
  5. Output:

    • For each match, it provides details such as the time of the event, the direction of the message (user prompt or agent response), account name, conversation ID, channel ID, matched indicator, threat type, and description.
  6. Severity and Alerts:

    • The severity of these findings is marked as high.
    • If any matches are found, an alert is triggered, and an incident is created in Microsoft Sentinel.
  7. Additional Features:

    • The query is scheduled to run every hour.
    • It supports incident grouping based on accounts and URLs to manage alerts efficiently.

Overall, this query helps in proactively identifying and responding to potential security threats within the Copilot Studio environment by leveraging threat intelligence data.

Details

David Alonso profile picture

David Alonso

Released: June 8, 2026

Tables

AppEventsThreatIntelIndicators

Keywords

ThreatIntelIndicatorsAppEventsAccountNameUrlHostClientIPSessionIdAppVersionTimeGeneratedDirectionConvIdChannelIdObservableKeyConfidenceThreatTypeDescription

Operators

letdynamicagoisactiveandisemptynowsummarizearg_maxbyextendtolowerisnotemptytostringiffextract_allmv-expandextractpack_arrayjoinonprojectorder bydesctdynamic

Severity

High

Tactics

CommandAndControlInitialAccess

MITRE Techniques

Frequency: PT1H

Period: P14D

Actions

GitHub