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.

Query · kql

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
Raw source AI Agents - Hard-coded credentials in Tools or Configuration · KQL
Esc
Published by Azure/Azure-Sentinel ↗, licensed under MIT ↗. Reproduced here unmodified.
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

Detection rules belong to the projects that publish them and remain under their own licenses. This site indexes and links to them; it claims no rights in them.