Why SharePoint admins should not ignore Content Security Policy violations

Microsoft has been announcing since April that a new Content Security Policy (CSP) is coming to SharePoint. This is linked to the “Trusted script sources” page in the SharePoint admin center.

In web development, Content Security Policy (CSP) is a security feature that help prevent against various attack vectors including cross-site scripting (XSS), clickjacking, and other code injection attacks.

CSP enables a site to control which resources a page is allowed to load. It works though a series of instructions to the browser from the website that instruct the browser what the page is allowed to load.

Trusted script sources in SharePoint admin center
Trusted script sources in SharePoint admin center

Microsoft has also published the following warning for SharePoint admins:

Violations to content security policy are logged in Purview. Starting later this year, content security policy for script sources will also be enforced, blocking scripts from untrusted sources.

But there is no confirmation about an upcoming enforcement in the documentation.
Nevertheless, the CSP is currently in Report-only mode.

  • SharePoint admins can already choose to enforce this policy manually
  • Or Microsoft may enforce it in the future

You can manage CSP enforcement with the ContentSecurityPolicyEnforcement setting in your SharePoint tenant. The current default value is “False”.

ContentSecurityPolicyEnforcement
Controls whether content security policy is enabled: True or False

ContentSecurityPolicyEnforcement setting
ContentSecurityPolicyEnforcement setting

Neither option is ideal if you don’t know which script sources are affected. That’s why it’s important to analyze the violations as soon as possible.


Find untrusted script sources on a SharePoint site

I prepared a simple SPFx web part to subscribe to my Topedia Blog to simulate a content security violation. The web part uses a Mailjet source to load the form.

SPFx web part with an untrusted source
SPFx web part with an untrusted source

Open the browser developer tools (CTRL + Shift + I) while accessing a SharePoint site to check the Report-only mode, which appears if untrusted script sources are on the page.
Check the browser console for a “[Report Only]” section at the beginning. I found 51 reported sources in my case.

Report mode for untrusted script sources
Report mode for untrusted script sources

Even some Microsoft URLs appear in these reports.
It’s important to note that not all reported sources will be blocked once ContentSecurityPolicyEnforcement is enabled. The “[Report Only]” section appears if there is a single untrusted source. Microsoft has already predefined some trusted sources. You must run an audit report in Microsoft Purview to understand the actual impact.


Find Content Security Policy violations with Purview Audit Logs

CSP violations are logged in Purview Audit Logs.
As I often recommend, it’s faster and more flexible to build your audit queries with PowerShell and Microsoft Graph. Alternatively, you can use the Audit Logs in the Purview admin portal and manually set filters.

  1. Connect to Microsoft Graph with the scope AuditLogsQuery-SharePoint.Read.All.
PowerShell
Import-Module Microsoft.Graph.Authentication
Connect-MgGraph -Scopes AuditLogsQuery-SharePoint.Read.All

  1. Filter by the operation ContentSecurityPolicyViolated within the SharePoint workload.
    In my example, I searched the last 30 days, but you can adjust this value (up to 180 days for non-E5 customers).
    Keep in mind: more days = longer job processing time.
PowerShell
$StartDate = (Get-Date).AddDays(-30).ToString("yyyy-MM-ddT00:00:00Z")
$EndDate = (Get-Date).ToString("yyyy-MM-ddTHH:mm:ssZ")

$Body = 
@"
{
    "displayName": "MSGraphAuditlogQuery-SharePointCSP",
    "filterStartDateTime": "$StartDate",
    "filterEndDateTime": "$EndDate",
    "serviceFilters": ["SharePoint"],    
    "operationFilters": [
        "ContentSecurityPolicyViolated"
    ],
  }
"@

  1. Wait until the audit job has completed.
PowerShell
$AuditLogNewQueryID = $AuditLogNewQuery.id
$Url = "https://graph.microsoft.com/beta/security/auditLog/queries/$AuditLogNewQueryID"
$AuditLogNewQueryResult = Invoke-MgGraphRequest -Method Get -Uri $Url -ContentType "application/json"
$AuditLogNewQueryResult | select displayName,filterStartDateTime,filterEndDateTime,status,id

  1. Retrieve the results. My sample includes paging to make sure all audit records are captured.
PowerShell
# Get the results of the search job (paging included)
$Url = "https://graph.microsoft.com/beta/security/auditLog/queries/$AuditLogNewQueryID/records?`$top=1000"
$AuditLogNewQueryResultRecords = @()

While ( $null -ne $Url ) {
    $data = Invoke-MgGraphRequest -Method GET -Uri $Url -ContentType "application/json" 
    $AuditLogNewQueryResultRecords += $data.Value         
    $Url = $data.'@Odata.NextLink'
}


Analyzing Audit Logs and adding Trusted Sources in SharePoint

Once you’ve collected all CSP violation records, you’ll likely see multiple entries for the same source.
I only found 28 records in my test tenant. You can expect far more in a production environment.

Let’s look at one record more closely. The key information is BlockedUrl, which contains the blocked script source.
You can also check the operation (to confirm it’s a ContentSecurityPolicyViolated event), the affected SharePoint site (which may not be relevant if the same source appears across multiple sites), and the user who created the record (who is not aware of the issue). You can then work with site owners to decide if the script source should be trusted.

PowerShell
# Get the newest record and check the blocked URL
$Record1 = ($AuditLogNewQueryResultRecords.auditData | sort CreationTime -Descending)[0]
$Record1 | select Operation,CreationTime,UserId,DocumentUrl,BlockedUrl

PowerShell

Finally, filter the results for unique blocked URLs.
In my example, I identified 27 unique URLs. Most were related to Bing Maps, but the simulated Mailjet URL is also included, along with localhost sources from my web part preparation steps.

PowerShell
$AuditLogNewQueryResultRecords.auditData | sort BlockedUrl -Unique | select BlockedUrl


PowerShell

At this stage, review and decide which URLs are from a trusted source and add them to your SharePoint trusted script sources. You can add up to 1000 trusted sources. This configuration is for all of your sites.

The good news: wildcards are supported.
I added these three trusted sources for my test:

  • https://*.virtualearth.net
  • https://*.bing.com
  • https://app.mailjet.com/pas-nc-embedded-v1.js
Trusted script sources in SharePoint admin center
Trusted script sources in SharePoint admin center

After adding trusted sources, wait at least a few hours (or days) and run the audit job again.

  • Purview will stop logging new ContentSecurityPolicyViolated events for those trusted sources.
  • Alternatively, open the SharePoint site and check the browser developer tools. The “[Report Only]” section is no longer visible if all sources are trusted. This should work 15 minutes after you added the trusted source.

If you don’t find new CSP violations over the following weeks, you should be ready to safely enable the ContentSecurityPolicyEnforcement setting in your tenant. This change is active (or inactive) after a few minutes.

PowerShell
# Enable Content Security Policy (CSP) enforcement in your SharePoint tenant
Set-SPOTenant -ContentSecurityPolicyEnforcement $true


What happens when the Content Security Policy is enforced?

SharePoint will block untrusted scripts from loading if a SharePoint admin or Microsoft enables CSP enforcement.
For example, my SPFx web part rendered as empty without any error message. In the browser developer tools you can see that SharePoint explicitly refused to load the untrusted script. After adding this source to the trusted list in SharePoint the script started working again within a few minutes.

SharePoint refused to load the untrusted script
SharePoint refused to load the untrusted script

Share
Avatar photo

Tobias Asböck

Tobias is a Senior System Engineer with around ten years of professional experience with Microsoft 365 products such as SharePoint Online, SharePoint Premium, OneDrive for Business, Teams Collaboration, Entra ID, Information Protection, Universal Print, and Microsoft 365 Licensing. He also has 15+ years of experience planning, administering, and operating SharePoint Server environments. Tobias is a PowerShell Scripter with certifications for Microsoft 365 products. In his spare time, Tobias is busy with updates in the Microsoft 365 world or on the road with his road bike and other sports activities. If you have additional questions, please contact me via LinkedIn or [email protected].

Leave a Reply

Your email address will not be published. Required fields are marked *