Adversaries may be using dormant Copilot Studio AI agents with stored author authentication credentials to maintain persistent access or exfiltrate data undetected. SOC teams should proactively hunt for these inactive agents in Azure Sentinel to identify potential long-term compromise and unauthorized credential usage.
KQL Query
let UsedAgents = CloudAppEvents
| where Timestamp > ago(30d)
| where ActionType == "CopilotInteraction"
| where RawEventData.AppIdentity startswith "Copilot.studio"
| extend AppIdentity = iff(isnotempty(RawEventData.CopilotEventData.AppIdentity), RawEventData.CopilotEventData.AppIdentity, RawEventData.AppIdentity)
| extend AgentName = extract(@"[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}-(.*)$", 1, tostring(AppIdentity))
| where isnotempty(AgentName)
| distinct tostring(AgentName);
let FirstFetch =
AIAgentsInfo
| where RegistrySource != "A365"
| summarize arg_max(Timestamp, *) by AIAgentId
| where AgentStatus != "Deleted"
| where AgentStatus == "Published"
| mv-expand tool = AgentToolsDetails
| where tool.action.connectionProperties.mode == "Maker"
| extend MatchType = "Tool", ConnectionReference = tostring(tool.action.connectionReference);
let SecondFetch =
AIAgentsInfo
| where RegistrySource != "A365"
| summarize arg_max(Timestamp, *) by AIAgentId
| where AgentStatus != "Deleted"
| where AgentStatus == "Published"
| mv-expand topic = AgentTopicsDetails
| mv-expand actionTopic = topic.beginDialog.actions
| where actionTopic.connectionProperties.mode == "Maker"
| extend MatchType = "Topic", ConnectionReference = tostring(actionTopic.connectionReference);
FirstFetch
| union SecondFetch
| extend schemaname = tostring(todynamic(RawAgentInfo)['Bot']['Attributes']['schemaname'])
| where schemaname !in (UsedAgents)
| project-reorder AgentCreationTime, AIAgentId, AIAgentName, AgentStatus, CreatorAccountUpn, OwnerAccountUpns, MatchType, ConnectionReference
id: 2a5b8c1d-4e7f-0a1b-2c3d-4e5f6a7b8c9d
name: Copilot Studio AI Agents - Dormant Author Authentication Connection
description: |
This query identifies Copilot Studio AI agents that are published and contain actions configured with Author Authentication (maker`s personal credentials) but have not been used or invoked in the last 30 days.
Dormant actions with elevated permissions pose a security risk because they retain access to resources even when inactive.
If these credentials remain valid, an attacker compromising the agent or its environment could exploit them for privilege escalation or unauthorized access.
Recommended Action: Review these agents and remove or reconfigure actions that use maker credentials. Replace personal credentials with secure alternatives such as managed identities or service principals.
If the agent is no longer needed, consider unpublishing or retiring it.
requiredDataConnectors: []
tactics: []
relevantTechniques: []
query: |
let UsedAgents = CloudAppEvents
| where Timestamp > ago(30d)
| where ActionType == "CopilotInteraction"
| where RawEventData.AppIdentity startswith "Copilot.studio"
| extend AppIdentity = iff(isnotempty(RawEventData.CopilotEventData.AppIdentity), RawEventData.CopilotEventData.AppIdentity, RawEventData.AppIdentity)
| extend AgentName = extract(@"[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}-(.*)$", 1, tostring(AppIdentity))
| where isnotempty(AgentName)
| distinct tostring(AgentName);
let FirstFetch =
AIAgentsInfo
| where RegistrySource != "A365"
| summarize arg_max(Timestamp, *) by AIAgentId
| where AgentStatus != "Deleted"
| where AgentStatus == "Published"
| mv-expand tool = AgentToolsDetails
| where tool.action.connectionProperties.mode == "Maker"
| extend MatchType = "Tool", ConnectionReference = tostring(tool.action.connectionReference);
let SecondFetch =
AIAgentsInfo
| where RegistrySource != "A365"
| summarize arg_max(Timestamp, *) by AIAgentId
| where AgentStatus != "Deleted"
| where AgentStatus == "Published"
| mv-expand topic = AgentTopicsDetails
| mv-expand actionTopic = topic.beginDialog.actions
| where actionTopic.connectionProperties.mode == "Maker"
| extend MatchType = "Topic", ConnectionReference = tostring(actionTopic.connectionReference);
FirstFetch
| union SecondFetch
| extend schemaname = tostring(todynamic(RawAgentInfo)['Bot']['Attributes']['schemaname'])
| where schemaname !in (UsedAgents)
| project-reorder AgentCreationTime, AIAgentId, AIAgentName, AgentStatus, CreatorAccountUpn, OwnerAccountUpns, MatchType, ConnectionReference
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: CreatorAccountUpn
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: AIAgentName
version: 1.0.0
| Sentinel Table | Notes |
|---|---|
CloudAppEvents | Ensure this data connector is enabled |
Scenario: Scheduled Job with Author Authentication
Description: A scheduled job in Azure DevOps or GitHub Actions is configured to use Author Authentication for accessing Copilot Studio AI agents, but the job hasn’t been executed in the last 30 days.
Filter/Exclusion: job_name:*scheduled_job* OR tool_name:azure_devops OR tool_name:github_actions
Scenario: Admin Task for Agent Configuration
Description: An admin is configuring an AI agent in Copilot Studio for future use, but the agent is not yet active or invoked.
Filter/Exclusion: user_role:admin OR action:configure_agent OR status:inactive
Scenario: Test Environment with Author Authentication
Description: A test environment (e.g., Azure DevOps test pipeline) uses Author Authentication to test an AI agent, but the test has not been run recently.
Filter/Exclusion: environment:test OR pipeline_name:*test_pipeline* OR tool_name:azure_devops
Scenario: Legacy Integration with Author Authentication
Description: A legacy integration (e.g., Power Automate) is set up to use Author Authentication with an AI agent, but the integration is not actively used.
Filter/Exclusion: tool_name:power_automate OR integration_type:legacy OR status:inactive
Scenario: User-Initiated Agent Setup
Description: A user has initiated the setup of an AI agent in Copilot Studio but has not yet completed the configuration or invoked the agent.
Filter/Exclusion: action:initiate_setup OR status:setup_pending OR user_role:standard_user