Copilot Studio - Session context contamination across a conversation
Copilot Studio Session Context Contamination
Query
let injectionMarkers = dynamic([
"ignore previous instructions","disregard previous","you are now",
"developer mode","do anything now","reveal your system prompt",
"bypass your rules","forget the previous","new instructions",
"from now on you","store this and remember","next time the user asks"
]);
let sensitiveConnectors = dynamic([
"office365","sendemail","sendmail","outlook","exchange",
"http","webhook","azuread","azure","sql","dataverse",
"sharepoint","onedrive","powershell","function","automate",
"logicapp","graph","keyvault","blob","storage"
]);
let safeHostSuffixes = dynamic([
"microsoft.com","office.com","office365.com","sharepoint.com",
"microsoftonline.com","windows.net","azure.com","azureedge.net",
"live.com","bing.com","msn.com","dynamics.com","powerplatform.com"
]);
let turns =
AppEvents
| where TimeGenerated > ago(2h)
| where Name == "BotMessageReceived"
| extend ConvId = tostring(Properties["conversationId"]),
Text = tolower(tostring(Properties["text"])),
ChannelId = tostring(Properties["channelId"])
| where isnotempty(Text);
let convBounds =
turns
| summarize Turns = count(),
Start = min(TimeGenerated),
End = max(TimeGenerated),
AnyUser = take_any(UserId),
AnyIp = take_any(ClientIP),
AnyChannel = take_any(ChannelId)
by ConvId
| where Turns >= 5;
let early =
turns
| join kind=inner convBounds on ConvId
| extend RangeMs = max_of(datetime_diff('millisecond', End, Start), 1)
| extend OffMs = datetime_diff('millisecond', TimeGenerated, Start)
| extend Quartile = min_of(toint(OffMs * 4 / RangeMs), 3)
| where Quartile == 0
| extend Host = tolower(extract(@"https?://([A-Za-z0-9.\-]+)", 1, Text))
| extend HasInjection = Text has_any (injectionMarkers);
let earlyUrl =
early
| where isnotempty(Host)
| where not(Host has_any (safeHostSuffixes))
| summarize UrlHits = count(), UntrustedHosts = make_set(Host, 16) by ConvId;
let earlyInj =
early
| summarize InjHits = countif(HasInjection) by ConvId;
let lateActs =
AppDependencies
| where TimeGenerated > ago(2h)
| where AppRoleName == "Microsoft Copilot Studio" or DependencyType == "Connector"
| extend ConvId = tostring(Properties["conversationId"]),
MatchKey = tolower(strcat(Name, " ", Target))
| where MatchKey has_any (sensitiveConnectors)
| summarize SensitiveCalls = count(),
Connectors = make_set(Name, 8),
Targets = make_set(Target, 16),
LastSeen = max(TimeGenerated),
FirstSensitive = min(TimeGenerated)
by ConvId;
earlyUrl
| join kind=fullouter earlyInj on ConvId
| extend ConvId = coalesce(ConvId, ConvId1)
| extend Contamination = coalesce(UrlHits, 0) + coalesce(InjHits, 0)
| where Contamination >= 1
| join kind=inner lateActs on ConvId
| join kind=leftouter convBounds on ConvId
| where SensitiveCalls >= 1
| extend AccountName = iff(isempty(AnyUser), "unknown-agent", AnyUser)
| project LastSeen, AccountName, UserId = AnyUser, ConvId, AnyChannel, AnyIp,
Contamination, UntrustedHosts, SensitiveCalls, Connectors, Targets, FirstSensitive
| order by Contamination desc, SensitiveCalls descExplanation
This query is designed to detect a specific type of security threat in conversations with Microsoft Copilot Studio. Here's a simplified breakdown:
-
Objective: The query identifies cases where an attacker might manipulate a conversation to trigger sensitive actions later. This is done by planting misleading data early in the conversation, which affects the system's behavior in later stages.
-
Conversation Analysis:
- The query examines conversations with at least five user interactions (turns).
- It splits each conversation into four time segments (quartiles).
-
Detection Criteria:
- Early Contamination: In the first segment of the conversation, it looks for:
- External URLs that are not from trusted Microsoft domains.
- Specific phrases that might indicate an attempt to manipulate the system (injection markers).
- Late Actions: In the last segment, it checks if any sensitive actions are triggered, such as calls to email, HTTP, SQL, Azure, SharePoint, etc.
- Early Contamination: In the first segment of the conversation, it looks for:
-
Data Sources: The query uses data from Application Insights, specifically looking at application events and dependencies.
-
Alerting:
- If both early contamination and late sensitive actions are detected, an alert is generated.
- The alert includes details like the last time the issue was seen, the user involved, the conversation ID, and any untrusted hosts or sensitive actions detected.
-
Severity and Frequency:
- The severity of the alert is set to medium.
- The query runs every hour and looks back over the past two hours.
-
Additional Details:
- The query includes lists of known injection markers and sensitive connectors.
- It also maintains a list of safe Microsoft domains to filter out trusted URLs.
-
Incident Management:
- If an incident is detected, it is configured to create an alert and group related alerts by account.
Overall, this query is part of a security monitoring strategy to detect and alert on potential session context contamination in conversations with Microsoft Copilot Studio.
Details

David Alonso
Released: June 8, 2026
Tables
Keywords
Operators
Severity
MediumTactics
Frequency: PT1H
Period: PT2H