← Back to SOC feed Coverage →

AI Agents - Hard-coded credentials in Tools or Configuration

kql MEDIUM Azure-Sentinel
T1552T1078
IdentityInfo
backdoorcredential-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-07-02T23:00:00Z · Confidence: medium

Hunt Hypothesis

This hunt targets adversaries exploiting AI agents with exposed hard-coded credentials to facilitate unauthorized access and lateral movement via MITRE techniques T1552 and T1078. Proactively identifying these static secrets within Azure Sentinel is critical because compromised agent configurations often serve as persistent entry points for attackers seeking to pivot across cloud environments without triggering standard authentication alerts.

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
    | where isnotempty(AccountObjectId) and isnotempty(AccountUpn)
    | summarize arg_max(Timestamp, AccountUpn) by AccountObjectId
    | project AccountObjectId = tostring(AccountObjectId), AccountUpn);
AgentsInfo
| summarize arg_max(Timestamp, *) by AgentId
| where LifecycleStatus != "Deleted"
| extend ToolsStr = tostring(DeclaredTools), TriggersStr = tostring(Triggers), McpStr = tostring(McpServers), SkillsStr = tostring(Skills), CapsStr = tostring(Capabilities), RawStr = tostring(RawAgentInfo)
| where ToolsStr matches regex suspicious_patterns
    or TriggersStr matches regex suspicious_patterns
    or McpStr matches regex suspicious_patterns
    or SkillsStr matches regex suspicious_patterns
    or CapsStr matches regex suspicious_patterns
    or RawStr matches regex suspicious_patterns
    or Instructions matches regex suspicious_patterns
| extend OwnerId = tostring(Owners[0])
| join kind=leftouter IdentityIdtoUPN on $left.OwnerId == $right.AccountObjectId
| project-rename OwnerUpn = AccountUpn
| project-away OwnerId, AccountObjectId, RawStr
| project-reorder CreatedDateTime, AgentId, Name, Platform,Instructions, ToolsStr, TriggersStr, McpStr, SkillsStr,CapsStr, OwnerUpn

Analytic Rule Definition

id: fdc8a7ec-586d-4021-a78a-d27544986178
name: AI Agents - Hard-coded credentials in Tools or Configuration
description: |
  This query identifies AI agents that contain hard-coded credentials in their declared tools, triggers, MCP servers, skills, capabilities, or raw agent configuration.
  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 configuration. 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
      | where isnotempty(AccountObjectId) and isnotempty(AccountUpn)
      | summarize arg_max(Timestamp, AccountUpn) by AccountObjectId
      | project AccountObjectId = tostring(AccountObjectId), AccountUpn);
  AgentsInfo
  | summarize arg_max(Timestamp, *) by AgentId
  | where LifecycleStatus != "Deleted"
  | extend ToolsStr = tostring(DeclaredTools), TriggersStr = tostring(Triggers), McpStr = tostring(McpServers), SkillsStr = tostring(Skills), CapsStr = tostring(Capabilities), RawStr = tostring(RawAgentInfo)
  | where ToolsStr matches regex suspicious_patterns
      or TriggersStr matches regex suspicious_patterns
      or McpStr matches regex suspicious_patterns
      or SkillsStr matches regex suspicious_patterns
      or CapsStr matches regex suspicious_patterns
      or RawStr matches regex suspicious_patterns
      or Instructions matches regex suspicious_patterns
  | extend OwnerId = tostring(Owners[0])
  | join kind=leftouter IdentityIdtoUPN on $left.OwnerId == $right.AccountObjectId
  | project-rename OwnerUpn = AccountUpn
  | project-away OwnerId, AccountObjectId, RawStr
  | project-reorder CreatedDateTime, AgentId, Name, Platform,Instructions, ToolsStr, TriggersStr, McpStr, SkillsStr,CapsStr, OwnerUpn
  
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: OwnerUpn
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: Name
version: 1.0.0

Required Data Sources

Sentinel TableNotes
IdentityInfoEnsure this data connector is enabled

MITRE ATT&CK Context

References

False Positive Guidance

Here are 4 specific false positive scenarios for the AI Agents - Hard-coded credentials rule, including suggested filters and exclusions:

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