Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions src/powershell/tests/Test-Assessment.35039.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
Communication Compliance policies with Copilot content detection enable organizations to monitor and investigate how users interact with Microsoft Copilot in Teams, Outlook, and Microsoft 365 apps. Without Communication Compliance policies configured to capture Copilot interactions, organizations cannot detect when sensitive data is being exposed to AI services, how users are leveraging Copilot with confidential information, or detect potential policy violations involving AI-assisted data processing.

Copilot interaction capture through Communication Compliance enables organizations to implement governance and oversight of AI usage while maintaining user communication privacy controls. Users may unknowingly expose sensitive data (customer records, financial information, source code, trade secrets) to Copilot, creating a data spillage risk that becomes invisible without activity monitoring. Organizations must enable Communication Compliance policies targeting Copilot interactions to maintain visibility into how AI features are being used with sensitive data and ensure compliance with data governance policies.

**Remediation action**

To create and enable Communication Compliance policies for Copilot interaction capture:

Sign in as a Global Administrator or Compliance Administrator to the Microsoft Purview portal
Navigate to Communication Compliance > Policies
Select "+ Create policy" to start the policy creation workflow
Choose the "Monitor for sensitive content" template or create a custom policy
Name the policy (e.g., "Copilot Data Protection")
Configure the scope (all users or specific groups)
On the Conditions page, add conditions to detect:
Sensitive information types (credit cards, SSN, financial data)
Keywords related to confidential data
Custom patterns for your organization's sensitive data
On the Review settings page, configure:
Reviewers (compliance team members)
Alert volume preference
Review mailbox for alerts
Enable the policy
Verify rule creation via PowerShell using Query 1 and 2
Via PowerShell (creation requires portal, but verification via cmdlets):

Connect-ExchangeOnline
Get-SupervisoryReviewRule -IncludeDetails | Select-Object Name, Policy
Get-SupervisoryReviewPolicyV2 | Select-Object Name, Enabled, ReviewMailbox
For more information:

Create Communication Compliance policies
Communication Compliance message classes
SupervisoryReview cmdlet reference
<!--- Results --->
%TestResult%
246 changes: 246 additions & 0 deletions src/powershell/tests/Test-Assessment.35039.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
<#
.SYNOPSIS
Validates that Communication Compliance rules are configured to detect and monitor Copilot content.

.DESCRIPTION
This test verifies that Communication Compliance rules targeting Copilot interactions are properly
configured and enabled. It checks that supervisory review policies with Copilot-targeting rules
are active and have configured review mailboxes for processing alerts.

.NOTES
Test ID: 35039
Category: Communication Compliance
Pillar: Data
Required Module: ExchangeOnlineManagement
Required Connection: Security & Compliance PowerShell
#>

function Test-Assessment-35039 {
[ZtTest(
Category = 'Communication Compliance',
ImplementationCost = 'Medium',
MinimumLicense = ('Microsoft 365 E5 Compliance'),
Pillar = 'Data',
RiskLevel = 'Medium',
SfiPillar = 'Protect tenants and production systems',
TenantType = ('Workforce'),
TestId = 35039,
Title = 'Communication Compliance Rules Targeting Copilot Content',
UserImpact = 'Medium'
)]
[CmdletBinding()]
param()

#region Data Collection
Write-PSFMessage '🟦 Start' -Tag Test -Level VeryVerbose

$activity = 'Checking Communication Compliance Rules for Copilot Content'
Write-ZtProgress -Activity $activity -Status 'Getting supervisory review rules'

# Q1: Find Communication Compliance rules targeting Copilot content
$copilotRules = $null
$errorMsg = $null

try {
$allRules = @(Get-SupervisoryReviewRule -IncludeRuleXml -ErrorAction Stop)

$copilotRules = @(foreach ($rule in $allRules) {
if (-not [string]::IsNullOrWhiteSpace($rule.RuleXml)) {
try {
# Wrap RuleXml in a root element to handle multiple rule elements
$wrappedXml = "<root>$($rule.RuleXml)</root>"
$ruleXml = [xml]$wrappedXml
$hasCopilotConfig = $false

# Check for Copilot in multiple possible locations in the XML structure
if ($ruleXml.root) {
$valueElements = $ruleXml.root.GetElementsByTagName('value')
foreach ($valueElement in $valueElements) {
if ($valueElement.'#text' -match 'IPM\.SkypeTeams\.Message\.Copilot') {
$hasCopilotConfig = $true
break
}
}
}

if ($hasCopilotConfig) {
$rule
}
}
catch {
Write-PSFMessage "Error parsing RuleXml for rule '$($rule.Name)': $_" -Level Warning
}
}
})
}
catch {
$errorMsg = $_
Write-PSFMessage "Failed to retrieve supervisory review rules: $_" -Tag Test -Level Warning
}

# Q2: Resolve Copilot-targeting policies and verify enabled status
$enabledCopilotPolicies = @()
if ($copilotRules -and -not $errorMsg) {
#Write-ZtProgress -Activity $activity -Status 'Verifying policy enabled status'

try {
$copilotPolicyIdentities = @($copilotRules | Select-Object -ExpandProperty Policy -Unique)
$policies = foreach ($id in $copilotPolicyIdentities.Guid) {
Get-SupervisoryReviewPolicyV2 -Identity $id -ErrorAction SilentlyContinue
}
$enabledCopilotPolicies = @($policies | Where-Object { $_ -and $_.Enabled -eq $true })
}
catch {
Write-PSFMessage "Failed to retrieve supervisory review policies: $_" -Tag Test -Level Warning
}
}

# Q3: Verify Copilot capture is active by checking audit logs (optional)
$policyHits = $null
if ($enabledCopilotPolicies) {
Write-ZtProgress -Activity $activity -Status 'Checking audit logs'

try {
$startDate = (Get-Date).AddDays(-30)
$endDate = Get-Date
$hits = @(Search-UnifiedAuditLog -StartDate $startDate -EndDate $endDate -Operations SupervisionRuleMatch -ErrorAction Stop)

if ($hits) {
$policyNamePattern = ($enabledCopilotPolicies.Name | ForEach-Object { [regex]::Escape($_) }) -join '|'
$policyHits = @($hits | Where-Object { $_.AuditData -match $policyNamePattern -and ($_.AuditData -match $copilotItemClassRegex -or $_.AuditData -match 'Copilot') })
}
}
catch {
Write-PSFMessage "Failed to check audit logs: $_" -Tag Test -Level Warning
}
}
#endregion Data Collection

#region Assessment Logic
$passed = $false
$customStatus = $null

if ($errorMsg) {
# Investigate: Cannot query supervisory review rules (Query 1 failed)
$passed = $false
$customStatus = 'Investigate'
}
elseif ($copilotRules.Count -eq 0) {
# Fail: Query 1 returns no rules matching the Copilot item class regex
$passed = $false
}
elseif ($enabledCopilotPolicies.Count -eq 0) {
# Fail: Query 2 returns no enabled policies
$passed = $false
}
else {
# Verify all enabled policies have ReviewMailbox configured (Query 2 requirement)
$hasValidPolicies = @($enabledCopilotPolicies | Where-Object { $_.ReviewMailbox }).Count -gt 0

if ($hasValidPolicies) {
# Pass: Query 1 returns at least 1 rule AND Query 2 returns at least 1 enabled policy with ReviewMailbox
$passed = $true
}
else {
# Fail: Enabled policies exist but none have ReviewMailbox configured
$passed = $false
}
}
#endregion Assessment Logic

#region Report Generation
$testResultMarkdown = ''

if ($customStatus -eq 'Investigate') {
$testResultMarkdown = "### Investigate`n`n"
$testResultMarkdown += "Unable to determine Communication Compliance configuration status due to permissions issues or service connection failure."
}
elseif ($passed) {
$testResultMarkdown = "✅ **Status: Pass**`n`n"
$testResultMarkdown += "Communication Compliance rules targeting Copilot content are properly configured and enabled.`n`n"
}
else {
$testResultMarkdown = "❌ **Status: Fail**`n`n"
$testResultMarkdown += "Communication Compliance rules targeting Copilot content are not properly configured or enabled.`n`n"
}

# Copilot-Targeting Rules section
if ($copilotRules -and $copilotRules.Count -gt 0) {
$testResultMarkdown += "## Copilot-Targeting Rules`n`n"
$testResultMarkdown += "| Rule Name | Associated Policy |`n"
$testResultMarkdown += "| :--- | :--- |`n"

foreach ($rule in $copilotRules | Sort-Object Name) {
$safeRuleName = Get-SafeMarkdown $rule.Name
$safePolicyName = Get-SafeMarkdown $rule.Policy

$testResultMarkdown += "| $safeRuleName | $safePolicyName |`n"
}
$testResultMarkdown += "`n"
}
else {
$testResultMarkdown += "## Copilot-Targeting Rules`n`n"
$testResultMarkdown += "No Copilot-targeting rules found.`n`n"
}

# Enabled Policies section
if ($enabledCopilotPolicies -and $enabledCopilotPolicies.Count -gt 0) {
$testResultMarkdown += "## Enabled Policies`n`n"
$testResultMarkdown += "| Policy Name | Enabled | Review Mailbox |`n"
$testResultMarkdown += "| :--- | :--- | :--- |`n"

foreach ($policy in $enabledCopilotPolicies | Sort-Object Name) {
$safePolicyName = Get-SafeMarkdown $policy.Name
$reviewMailbox = if ($policy.ReviewMailbox) { Get-SafeMarkdown $policy.ReviewMailbox } else { 'Not configured' }
$enabledStatus = if ($policy.Enabled -eq $true) { 'True' } else { 'False' }

$testResultMarkdown += "| $safePolicyName | $enabledStatus | $reviewMailbox |`n"
}
$testResultMarkdown += "`n"
}
else {
$testResultMarkdown += "## Enabled Policies`n`n"
$testResultMarkdown += "No enabled policies with Copilot rules found.`n`n"
}

# Activity Evidence section (Optional)
$testResultMarkdown += "## Activity Evidence (Optional)`n`n"
if ($policyHits -and $policyHits.Count -gt 0) {
$testResultMarkdown += "**Recent Copilot Matches (30 days):** $($policyHits.Count)`n`n"
}
elseif ($enabledCopilotPolicies -and $enabledCopilotPolicies.Count -gt 0) {
$testResultMarkdown += "**Recent Copilot Matches (30 days):** 0`n`n"
}
else {
$testResultMarkdown += "**Recent Copilot Matches (30 days):** No policies configured for audit review.`n`n"
}

# Summary section
# Summary section
$testResultMarkdown += "## Summary`n`n"
$testResultMarkdown += "* **Total Copilot Rules Found:** $($copilotRules.Count)`n"
$testResultMarkdown += "* **Enabled Policies with Copilot Rules:** $($enabledCopilotPolicies.Count)`n"

if ($customStatus -eq 'Investigate') {
$testResultMarkdown += "* **Status:** Investigate`n"
}
elseif ($passed) {
$testResultMarkdown += "* **Status:** Pass`n"
}
else {
$testResultMarkdown += "* **Status:** Fail`n"
}

#endregion Report Generation

$params = @{
TestId = '35039'
Title = 'Communication Compliance Rules Targeting Copilot Content'
Status = $passed
Result = $testResultMarkdown
}
if ($customStatus) {
$params.CustomStatus = $customStatus
}
Add-ZtTestResultDetail @params
}