Adversaries may configure AI agents with tools that are not referenced in their instructions to obscure malicious activities or evade detection. SOC teams should proactively hunt for this behavior in Azure Sentinel to identify potential misuse of AI agents and uncover covert command and control mechanisms.
KQL Query
let IdentityIdtoUPN = materialize (
IdentityInfo
| distinct AccountObjectId, AccountUpn
| extend AccountObjectId = tostring(AccountObjectId)
| where isnotempty(AccountObjectId) and isnotempty(AccountUpn));
let AgentFunctions =
AIAgentsInfo
| where RegistrySource == "A365"
| where isnotempty(AgentActionTriggers)
| extend Triggers = parse_json(AgentActionTriggers)
| mv-expand Trigger = Triggers
| extend AIAgentId = tostring(AIAgentId),
FunctionName = tostring(Trigger.name)
| where isnotempty(AIAgentId) and isnotempty(FunctionName)
| summarize FunctionNames = make_set(FunctionName) by AIAgentId;
AIAgentsInfo
| where RegistrySource == "A365"
| summarize arg_max(Timestamp, *) by AIAgentId
| extend AIAgentId = tostring(AIAgentId)
| extend RawAgentInfoJson = parse_json(RawAgentInfo)
| extend DeveloperName = RawAgentInfoJson.developerName
| where isnotempty(AgentActionTriggers)
| join kind=leftouter AgentFunctions on $left.AIAgentId == $right.AIAgentId
| where array_length(FunctionNames) > 0
| where Instructions !contains tostring(FunctionNames)
| extend OwnerId = tostring(RawAgentInfoJson.owners[0].entityId)
| extend CreatorId = tostring(RawAgentInfoJson.creatorId)
| join kind=leftouter IdentityIdtoUPN on $left.OwnerId == $right.AccountObjectId
| project-rename OwnerUpn = AccountUpn
| join kind=leftouter IdentityIdtoUPN on $left.CreatorId == $right.AccountObjectId
| project-rename CreatorUpn = AccountUpn
| project-away RawAgentInfoJson, OwnerId, CreatorId, AccountObjectId, AccountObjectId1
| project-reorder AgentCreationTime, AIAgentId, AIAgentName, Instructions, FunctionNames, OwnerUpn, CreatorUpn, DeveloperName
id: 7d8e9f0a-1b2c-3d4e-5f6a-7b8c9d0e1f2a
name: A365 AI Agents - Missing Tools in Instructions
description: |
This query identifies A365 AI agents that have tools configured but they are not mentioned in instructions.
This query identifies A365 AI agents that have tools configured but are not mentioned in instructions.
When tools are enabled without being explicitly referenced, the agent may use capabilities that are not clearly governed or expected, increasing the risk of unintended behavior or misuse.
Recommended Action: Ensure all configured tools are clearly documented in the agent's instructions, including their purpose and usage constraints. Regularly review instructions and tool configurations to maintain alignment and reduce security risks.
requiredDataConnectors: []
tactics:
- Impact
- DefenseEvasion
relevantTechniques:
- T1499
- T1562
query: |
let IdentityIdtoUPN = materialize (
IdentityInfo
| distinct AccountObjectId, AccountUpn
| extend AccountObjectId = tostring(AccountObjectId)
| where isnotempty(AccountObjectId) and isnotempty(AccountUpn));
let AgentFunctions =
AIAgentsInfo
| where RegistrySource == "A365"
| where isnotempty(AgentActionTriggers)
| extend Triggers = parse_json(AgentActionTriggers)
| mv-expand Trigger = Triggers
| extend AIAgentId = tostring(AIAgentId),
FunctionName = tostring(Trigger.name)
| where isnotempty(AIAgentId) and isnotempty(FunctionName)
| summarize FunctionNames = make_set(FunctionName) by AIAgentId;
AIAgentsInfo
| where RegistrySource == "A365"
| summarize arg_max(Timestamp, *) by AIAgentId
| extend AIAgentId = tostring(AIAgentId)
| extend RawAgentInfoJson = parse_json(RawAgentInfo)
| extend DeveloperName = RawAgentInfoJson.developerName
| where isnotempty(AgentActionTriggers)
| join kind=leftouter AgentFunctions on $left.AIAgentId == $right.AIAgentId
| where array_length(FunctionNames) > 0
| where Instructions !contains tostring(FunctionNames)
| extend OwnerId = tostring(RawAgentInfoJson.owners[0].entityId)
| extend CreatorId = tostring(RawAgentInfoJson.creatorId)
| join kind=leftouter IdentityIdtoUPN on $left.OwnerId == $right.AccountObjectId
| project-rename OwnerUpn = AccountUpn
| join kind=leftouter IdentityIdtoUPN on $left.CreatorId == $right.AccountObjectId
| project-rename CreatorUpn = AccountUpn
| project-away RawAgentInfoJson, OwnerId, CreatorId, AccountObjectId, AccountObjectId1
| project-reorder AgentCreationTime, AIAgentId, AIAgentName, Instructions, FunctionNames, OwnerUpn, CreatorUpn, DeveloperName
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: CreatorUpn
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: AIAgentName
version: 1.0.0
| Sentinel Table | Notes |
|---|---|
IdentityInfo | Ensure this data connector is enabled |
Scenario: A365 AI agent is configured with the Microsoft Teams tool but the instruction does not mention it.
Filter/Exclusion: where InstructionText not like '%Microsoft Teams%' or where InstructionText not like '%Teams%'
Scenario: An AI agent is set up with the Power Automate tool, but the instruction text does not reference it.
Filter/Exclusion: where InstructionText not like '%Power Automate%' or where InstructionText not like '%Power Automate%'
Scenario: A scheduled job is configured using the Azure DevOps tool, but the instruction text does not include a reference to it.
Filter/Exclusion: where InstructionText not like '%Azure DevOps%' or where InstructionText not like '%DevOps%'
Scenario: An admin task is assigned to an AI agent using the Exchange Online tool, but the instruction does not mention it.
Filter/Exclusion: where InstructionText not like '%Exchange Online%' or where InstructionText not like '%Exchange%'
Scenario: An AI agent is configured with the SharePoint Online tool, but the instruction text does not reference it.
Filter/Exclusion: where InstructionText not like '%SharePoint Online%' or where InstructionText not like '%SharePoint%'