Query Details

Agent Sensitive Response Content

Query

id: b2c3d4e5-2004-4b22-9d01-0123456789c4
name: Copilot Studio - Sensitive content in agent responses
description: |
  Scans Copilot Studio outbound responses for secret-like material and
  bulk PII (AWS keys, PEM private keys, JWTs, many email addresses, IBAN /
  card-like numbers). Broader, lower-threshold companion to the
  high-severity analytic rule - returns single-hit matches too, for
  proactive review and tuning. Requires "Log sensitive properties".
query: |
  let lookback = 1d;
  AppEvents
  | where TimeGenerated > ago(lookback)
  | where Name == "BotMessageSend"
  | extend
      ConvId    = tostring(Properties["conversationId"]),
      ChannelId = tostring(Properties["channelId"]),
      Output    = tostring(Properties["text"])
  | where isnotempty(Output)
  | extend
      AwsKey     = array_length(extract_all(@"(AKIA[0-9A-Z]{16})", Output)),
      PrivateKey = iff(Output contains "-----BEGIN" and Output contains "PRIVATE KEY-----", 1, 0),
      Jwt        = array_length(extract_all(@"(eyJ[A-Za-z0-9_\-]{10,}\.[A-Za-z0-9_\-]{10,}\.[A-Za-z0-9_\-]{10,})", Output)),
      Emails     = array_length(extract_all(@"([A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,})", Output)),
      CardLike   = array_length(extract_all(@"\b((?:\d[ \-]?){13,16})\b", Output))
  | extend HitScore = AwsKey + PrivateKey + Jwt + iff(Emails >= 5, 1, 0) + iff(CardLike >= 1, 1, 0)
  | where HitScore > 0
  | project
      TimeGenerated, UserId, ConvId, ChannelId,
      AwsKey, PrivateKey, Jwt, Emails, CardLike, HitScore,
      Output = substring(Output, 0, 1024)
  | order by HitScore desc, TimeGenerated desc
tactics:
  - Exfiltration
  - Collection
techniques:
  - T1567
  - T1213
tags:
  - Sentinel-As-Code
  - Custom
  - CopilotStudio
  - AI

Explanation

This query is designed to monitor and analyze outbound responses from Copilot Studio for potentially sensitive information. It looks for patterns that resemble secret keys, private keys, JWTs, multiple email addresses, and card-like numbers within the messages sent by the bot. Here's a simplified breakdown of what the query does:

  1. Time Frame: It examines events from the last day (lookback = 1d).

  2. Event Filtering: It focuses on events where the bot sends a message (Name == "BotMessageSend").

  3. Data Extraction: For each message, it extracts the conversation ID, channel ID, and the message text.

  4. Pattern Matching: It checks the message text for:

    • AWS keys
    • Private keys
    • JWTs (JSON Web Tokens)
    • Email addresses (counts if there are five or more)
    • Card-like numbers
  5. Scoring: It calculates a "HitScore" based on the presence of these patterns. A higher score indicates more potential sensitive content.

  6. Filtering: Only messages with a HitScore greater than 0 are considered, meaning they contain at least one type of sensitive information.

  7. Output: It displays the time the message was generated, user ID, conversation ID, channel ID, the count of each type of sensitive information found, the HitScore, and a truncated version of the message text (up to 1024 characters).

  8. Ordering: Results are sorted by HitScore and time, with the highest scores and most recent messages appearing first.

The query is tagged with tactics and techniques related to data exfiltration and collection, indicating its use in identifying potential data leaks or unauthorized data collection.

Details

David Alonso profile picture

David Alonso

Released: June 8, 2026

Tables

AppEvents

Keywords

AppEventsPropertiesOutputEmailsUserIdConvIdChannelIdAwsKeyPrivateKeyJwtCardLikeHitScoreTimeGenerated

Operators

letago|where==extendtostringisnotemptyarray_lengthextract_alliffcontainsprojectsubstringorder bydesc

Actions