← Back to SOC feed Coverage →

AI Agents - Instructions changed on previously published agent

kql MEDIUM Azure-Sentinel
T1565.001
IdentityInfo
huntingmicrosoftofficial
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-20T23:00:00Z · Confidence: medium

Hunt Hypothesis

This hypothesis posits that adversaries are modifying instructions on previously published AI agents to inject malicious prompts or alter logic flow, leveraging MITRE technique T1565.001 (Search for Information). A proactive hunt is essential in Azure Sentinel because unauthorized prompt changes can silently compromise data integrity and decision-making processes before traditional security controls detect the deviation.

KQL Query

let lookback = 14d;
let recent = 2d;
let IdentityIdtoUPN = materialize(
    IdentityInfo
    | extend ResolvedAccountUpn = tostring(column_ifexists("AccountUpn", column_ifexists("AccountUPN", ""))),
             IdentityTimestamp = todatetime(column_ifexists("Timestamp", column_ifexists("TimeGenerated", datetime(null))))
    | where IdentityTimestamp >= ago(lookback)
    | where isnotempty(AccountObjectId) and isnotempty(ResolvedAccountUpn)
    | summarize arg_max(IdentityTimestamp, ResolvedAccountUpn) by AccountObjectId
    | project AccountObjectId = tostring(AccountObjectId), AccountUpn = ResolvedAccountUpn);
let CurrentState =
    AgentsInfo
    | where Timestamp > ago(recent)
    | summarize arg_max(Timestamp, *) by AgentId
    | where LifecycleStatus != "Deleted"
    | where PublishedStatus == "Published"
    | where isnotempty(Instructions) and Instructions != "N/A"
    | project AgentId, Timestamp, Name, Platform, CreatedDateTime, Owners,
              CurrentInstructions = Instructions;
let BaselineState =
    AgentsInfo
    | where Timestamp between (ago(lookback) .. ago(recent))
    | where LifecycleStatus != "Deleted"
    | summarize arg_max(Timestamp, *) by AgentId
    | where PublishedStatus == "Published"
    | where isnotempty(Instructions) and Instructions != "N/A"
    | project AgentId, PreviousTimestamp = Timestamp,
              PreviousInstructions = Instructions;
CurrentState
| join kind=inner BaselineState on AgentId
| where CurrentInstructions != PreviousInstructions
| extend PreviousInstructionsHash = hash_sha256(PreviousInstructions),
         CurrentInstructionsHash = hash_sha256(CurrentInstructions),
         InstructionsLengthDelta = strlen(CurrentInstructions) - strlen(PreviousInstructions)
| extend OwnerIds = iff(array_length(coalesce(Owners, dynamic([]))) > 0, Owners, dynamic([""]))
| mv-expand OwnerId = OwnerIds to typeof(string)
| join kind=leftouter IdentityIdtoUPN on $left.OwnerId == $right.AccountObjectId
| project-rename OwnerUpn = AccountUpn
| extend OwnerAccountName = tostring(split(OwnerUpn, "@")[0]),
         OwnerAccountUPNSuffix = tostring(split(OwnerUpn, "@")[1])
| project Timestamp, PreviousTimestamp, AgentId, Name, Platform, CreatedDateTime,
         PreviousInstructionsHash, CurrentInstructionsHash, InstructionsLengthDelta,
         OwnerId, OwnerUpn, OwnerAccountName, OwnerAccountUPNSuffix
| sort by Timestamp desc

Analytic Rule Definition

id: 662eae7f-494f-41a8-bfef-23dd80361795
name: AI Agents - Instructions changed on previously published agent
description: |
  Identifies instruction changes on AI agents that were published in both current and baseline snapshots. Review the changed prompt and audit records to confirm whether the update was authorized. Run within 2 days of a change to retain coverage.
requiredDataConnectors: []
tactics:
  - Impact
relevantTechniques:
  - T1565.001
query: |
  let lookback = 14d;
  let recent = 2d;
  let IdentityIdtoUPN = materialize(
      IdentityInfo
      | extend ResolvedAccountUpn = tostring(column_ifexists("AccountUpn", column_ifexists("AccountUPN", ""))),
               IdentityTimestamp = todatetime(column_ifexists("Timestamp", column_ifexists("TimeGenerated", datetime(null))))
      | where IdentityTimestamp >= ago(lookback)
      | where isnotempty(AccountObjectId) and isnotempty(ResolvedAccountUpn)
      | summarize arg_max(IdentityTimestamp, ResolvedAccountUpn) by AccountObjectId
      | project AccountObjectId = tostring(AccountObjectId), AccountUpn = ResolvedAccountUpn);
  let CurrentState =
      AgentsInfo
      | where Timestamp > ago(recent)
      | summarize arg_max(Timestamp, *) by AgentId
      | where LifecycleStatus != "Deleted"
      | where PublishedStatus == "Published"
      | where isnotempty(Instructions) and Instructions != "N/A"
      | project AgentId, Timestamp, Name, Platform, CreatedDateTime, Owners,
                CurrentInstructions = Instructions;
  let BaselineState =
      AgentsInfo
      | where Timestamp between (ago(lookback) .. ago(recent))
      | where LifecycleStatus != "Deleted"
      | summarize arg_max(Timestamp, *) by AgentId
      | where PublishedStatus == "Published"
      | where isnotempty(Instructions) and Instructions != "N/A"
      | project AgentId, PreviousTimestamp = Timestamp,
                PreviousInstructions = Instructions;
  CurrentState
  | join kind=inner BaselineState on AgentId
  | where CurrentInstructions != PreviousInstructions
  | extend PreviousInstructionsHash = hash_sha256(PreviousInstructions),
           CurrentInstructionsHash = hash_sha256(CurrentInstructions),
           InstructionsLengthDelta = strlen(CurrentInstructions) - strlen(PreviousInstructions)
  | extend OwnerIds = iff(array_length(coalesce(Owners, dynamic([]))) > 0, Owners, dynamic([""]))
  | mv-expand OwnerId = OwnerIds to typeof(string)
  | join kind=leftouter IdentityIdtoUPN on $left.OwnerId == $right.AccountObjectId
  | project-rename OwnerUpn = AccountUpn
  | extend OwnerAccountName = tostring(split(OwnerUpn, "@")[0]),
           OwnerAccountUPNSuffix = tostring(split(OwnerUpn, "@")[1])
  | project Timestamp, PreviousTimestamp, AgentId, Name, Platform, CreatedDateTime,
           PreviousInstructionsHash, CurrentInstructionsHash, InstructionsLengthDelta,
           OwnerId, OwnerUpn, OwnerAccountName, OwnerAccountUPNSuffix
  | sort by Timestamp desc
entityMappings:
  - entityType: Account
    fi

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 - Instructions changed on previously published agent detection rule, tailored for an enterprise environment:

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