Query Details

Foundry Threat Intel Url Match

Query

id: 4d5e6f70-1313-4312-9212-0123456789e2
name: Foundry - URL / domain / IP matched against threat intelligence
description: |
  Extracts URLs (and their hosts / IPs) from Foundry / Agent Service
  conversation content - both user input (gen_ai.input.messages) and agent
  output (gen_ai.output.messages) - and correlates them against active
  Microsoft Sentinel threat-intelligence indicators. A match means the
  agent either received or emitted a known malicious / suspicious URL,
  domain or IP, which can indicate a phishing lure fed to the agent, a
  poisoned RAG / knowledge source, or a corrupted agent surfacing attacker
  infrastructure. This is the high-fidelity companion to
  FoundrySuspiciousUrlInContent (which is heuristic): here the verdict
  comes from the TI feed.

  Joins against the modern ThreatIntelIndicators table (network observable
  types url:value / domain-name:value / ipv4-addr:value / ipv6-addr:value)
  and only considers active, non-revoked, in-date indicators. Reads agent
  text from AppDependencies (requires
  AZURE_TRACING_GEN_AI_CONTENT_RECORDING_ENABLED).
severity: High
requiredDataConnectors:
- connectorId: ApplicationInsights
  dataTypes:
  - AppDependencies
- connectorId: ThreatIntelligence
  dataTypes:
  - ThreatIntelIndicators
queryFrequency: PT1H
queryPeriod: P14D
triggerOperator: gt
triggerThreshold: 0
enabled: true
tactics:
- CommandAndControl
- InitialAccess
relevantTechniques:
- T1071
- T1566
query: |
  let dt_lookBack = 1h;
  let ioc_lookBack = 14d;
  let networkIocTypes = dynamic(["url:value", "domain-name:value", "ipv4-addr:value", "ipv6-addr:value"]);
  let TI =
      ThreatIntelIndicators
      | where TimeGenerated > ago(ioc_lookBack)
      | where IsActive == true and Revoked == false
      | where ObservableKey in (networkIocTypes)
      | where isempty(ValidUntil) or ValidUntil > now()
      | summarize arg_max(TimeGenerated, *) by IndicatorId = Id
      | extend IOC = tolower(ObservableValue)
      | where isnotempty(IOC);
  let Spans =
      AppDependencies
      | where TimeGenerated > ago(dt_lookBack)
      | where isnotempty(Properties["gen_ai.input.messages"]) or isnotempty(Properties["gen_ai.output.messages"])
      | extend
          Agent     = tostring(Properties["gen_ai.agent.name"]),
          Model     = tostring(Properties["gen_ai.request.model"]),
          ConvId    = tostring(Properties["gen_ai.conversation.id"]),
          ProjectId = tostring(Properties["microsoft.foundry.project.id"]),
          Input     = tostring(Properties["gen_ai.input.messages"]),
          Output    = tostring(Properties["gen_ai.output.messages"]),
          SrcIp     = tostring(column_ifexists("ClientIP", ""));
  let FromInput  = Spans | where isnotempty(Input)  | extend Direction = "UserPrompt",    Text = Input;
  let FromOutput = Spans | where isnotempty(Output) | extend Direction = "AgentResponse", Text = Output;
  let Content =
      union FromInput, FromOutput
      | mv-expand Url = extract_all(@"(https?://[^\s\)\]\}""'<>]+)", Text) to typeof(string)
      | extend
          Url  = tolower(Url),
          Host = tolower(tostring(extract(@"https?://([^/:\s]+)", 1, Url)))
      | mv-expand IOC = pack_array(Url, Host) to typeof(string)
      | where isnotempty(IOC);
  Content
  | join kind=inner TI on IOC
  | extend AccountName = iff(isempty(Agent), "unknown-agent", Agent)
  | project
      TimeGenerated, Direction, AccountName, Agent, Model, ProjectId, ConvId,
      MatchedIOC = IOC, ObservableKey, Confidence,
      ThreatType  = tostring(todynamic(Data).indicator_types[0]),
      Description = tostring(todynamic(Data).description),
      Url, Host, SrcIp
  | order by TimeGenerated desc
entityMappings:
- entityType: Account
  fieldMappings:
  - identifier: Name
    columnName: AccountName
- entityType: CloudApplication
  fieldMappings:
  - identifier: Name
    columnName: Model
- entityType: URL
  fieldMappings:
  - identifier: Url
    columnName: Url
- entityType: IP
  fieldMappings:
  - identifier: Address
    columnName: SrcIp
eventGroupingSettings:
  aggregationKind: SingleAlert
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: PT6H
    matchingMethod: Selected
    groupByEntities:
    - Account
    - URL
    groupByAlertDetails: []
    groupByCustomDetails: []
version: 1.0.0
kind: Scheduled
tags:
- Sentinel-As-Code
- Custom
- Foundry
- AI
- ThreatIntelligence
- MaliciousUrl

Explanation

This query is designed to detect potentially malicious URLs, domains, or IP addresses that are involved in interactions with an AI agent. Here's a simplified breakdown of what it does:

  1. Purpose: The query checks if any URLs, domains, or IPs extracted from AI agent conversations match known threat intelligence indicators. This helps identify if the AI agent is interacting with or being targeted by malicious entities.

  2. Data Sources: It uses data from two main sources:

    • AppDependencies: Contains conversation content from the AI agent, including user inputs and agent responses.
    • ThreatIntelIndicators: Contains threat intelligence data with known malicious URLs, domains, and IPs.
  3. Process:

    • Extract URLs: It extracts URLs from both user inputs and agent outputs.
    • Match with Threat Intelligence: It compares these URLs against active threat intelligence indicators to find matches.
    • Filter Criteria: Only considers indicators that are active, not revoked, and within a valid date range.
  4. Output: If a match is found, it provides details such as the time of the event, the direction of the conversation (user input or agent response), the agent's name, the model used, and the matched threat intelligence data.

  5. Severity and Alerts: The severity of the alert is marked as high, and it triggers an alert if any matches are found. It also creates incidents for further investigation.

  6. Frequency: The query runs every hour and looks back over the past 14 days for threat intelligence data.

  7. Use Case: This is useful for identifying potential security threats like phishing attempts or compromised AI agents interacting with malicious infrastructure.

Overall, this query helps in monitoring and securing AI agent interactions by leveraging threat intelligence data to detect and alert on suspicious activities.

Details

David Alonso profile picture

David Alonso

Released: June 8, 2026

Tables

ThreatIntelIndicatorsAppDependencies

Keywords

ThreatIntelligenceDevicesURLIPAccountCloudApplication

Operators

letdynamicagowhereinisemptyorsummarizearg_maxbyextendtolowerisnotemptytostringcolumn_ifexistsunionmv-expandextract_allextractpack_arrayjoinkind=inneriffprojectorder bydesctostringtodynamic

Actions