← Back to SOC feed Coverage →

A365 AI Agents - Hard-coded credentials in Tools or Actions

kql MEDIUM Azure-Sentinel
T1552T1078
IdentityInfo
credential-thefthuntingmicrosoftofficial
This rule was pulled from an open-source repository and enriched with AI. Validate in a test environment before deploying to production.
View original rule at Azure-Sentinel →
Retrieved: 2026-04-20T09:00:00Z · Confidence: medium

Hunt Hypothesis

Adversaries may embed hard-coded credentials in A365 AI agents to maintain persistent access and exfiltrate data undetected. Proactively hunting for this behavior in Azure Sentinel helps identify potential credential theft and unauthorized access vectors before they lead to data breaches.

KQL Query

let suspicious_patterns = @"(AKIA[0-9A-Z]{16})|(AIza[0-9A-Za-z_\-]{35})|(xox[baprs]-[0-9a-zA-Z]{10,48})|(ghp_[A-Za-z0-9]{36,59})|(sk_(live|test)_[A-Za-z0-9]{24})|(SG\.[A-Za-z0-9]{22}\.[A-Za-z0-9]{43})|(\d{8}:[\w\-]{35})|(eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+)|(Authorization\s*:\s*Basic\s+[A-Za-z0-9=:+]+)|([A-Za-z]+:\/\/[^\/\s]+:[^\/\s]+@[^\/\s]+)";  
let IdentityIdtoUPN = materialize (
IdentityInfo
| distinct AccountObjectId, AccountUpn
| extend AccountObjectId = tostring(AccountObjectId)
| where isnotempty(AccountObjectId) and isnotempty(AccountUpn)); 
AIAgentsInfo 
| summarize arg_max(Timestamp, *) by AIAgentId  
| where RegistrySource == "A365"
| extend RawAgentInfoJson = parse_json(RawAgentInfo)
| extend DeclarativeCopilotMetadata = RawAgentInfoJson.declarativeCopilotMetadata[0]
| extend DeveloperName = RawAgentInfoJson.developerName
| 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
| where 
  AgentActionTriggers matches regex suspicious_patterns 
  or AgentToolsDetails matches regex suspicious_patterns 
  or DeclarativeCopilotMetadata matches regex suspicious_patterns
| project-away RawAgentInfoJson, OwnerId, CreatorId,  AccountObjectId, AccountObjectId1
| project-reorder AgentCreationTime, AIAgentId, AIAgentName, AgentActionTriggers, AgentToolsDetails, DeclarativeCopilotMetadata, OwnerUpn, CreatorUpn, DeveloperName

Analytic Rule Definition

id: 1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d
name: A365 AI Agents - Hard-coded credentials in Tools or Actions
description: |
  This query identifies A365 AI agents that contain hard-coded credentials in their tools or actions. 
  Storing credentials in clear text within agent logic creates a security risk because these secrets can be exposed to unintended users or attackers. 
  If compromised, credentials could allow unauthorized access to external systems, APIs, or sensitive data.
  Recommended Action: Avoid embedding credentials directly in Tools or Actions. Use secure alternatives 
  such as Azure Key Vault with environment variables or enable secured input options for sensitive fields. 
  Regularly audit agents for hard-coded secrets and rotate any exposed credentials immediately.
requiredDataConnectors: []
tactics:
  - CredentialAccess
  - InitialAccess
relevantTechniques:
  - T1552
  - T1078
query: |
  let suspicious_patterns = @"(AKIA[0-9A-Z]{16})|(AIza[0-9A-Za-z_\-]{35})|(xox[baprs]-[0-9a-zA-Z]{10,48})|(ghp_[A-Za-z0-9]{36,59})|(sk_(live|test)_[A-Za-z0-9]{24})|(SG\.[A-Za-z0-9]{22}\.[A-Za-z0-9]{43})|(\d{8}:[\w\-]{35})|(eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+)|(Authorization\s*:\s*Basic\s+[A-Za-z0-9=:+]+)|([A-Za-z]+:\/\/[^\/\s]+:[^\/\s]+@[^\/\s]+)";  
  let IdentityIdtoUPN = materialize (
  IdentityInfo
  | distinct AccountObjectId, AccountUpn
  | extend AccountObjectId = tostring(AccountObjectId)
  | where isnotempty(AccountObjectId) and isnotempty(AccountUpn)); 
  AIAgentsInfo 
  | summarize arg_max(Timestamp, *) by AIAgentId  
  | where RegistrySource == "A365"
  | extend RawAgentInfoJson = parse_json(RawAgentInfo)
  | extend DeclarativeCopilotMetadata = RawAgentInfoJson.declarativeCopilotMetadata[0]
  | extend DeveloperName = RawAgentInfoJson.developerName
  | 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
  | where 
    AgentActionTriggers matches regex suspicious_patterns 
    or AgentToolsDetails matches regex suspicious_patterns 
    or DeclarativeCopilotMetadata matches regex suspicious_patterns
  | project-away RawAgentInfoJson, OwnerId, CreatorId,  AccountObjectId, AccountObjectId1
  | project-reorder AgentCreationTime, AIAgentId, AIAgentName, AgentActionTriggers, AgentToolsDetails, DeclarativeCopilotMetadata, OwnerUpn, CreatorUpn, DeveloperName
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: CreatorUpn
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: AIAgentName
version: 1.0.0

Required Data Sources

Sentinel TableNotes
IdentityInfoEnsure this data connector is enabled

MITRE ATT&CK Context

References

False Positive Guidance

Original source: https://github.com/Azure/Azure-Sentinel/blob/main/Hunting Queries/AI Agents/A365 Connector/AIAgentsHardCodedCredentials.yaml