A read-only PowerShell solution that evaluates governance, security, ownership, lifecycle, and operational controls across Microsoft 365 and highlights areas that require attention.
Tag Archives: Microsoft 365 Governance
Content Security Policy (CSP) in SharePoint Online
Microsoft enforces Content Security Policy (CSP) in SharePoint Online.
What does that mean to SharePoint Admins? Should we be concerned? What do we need to undertake? Before? After?
Generally, in web development – the policy (Content Security Policy – CSP) is needed to minimize the risk of security threats by controlling which resources, in particular JavaScript resources, a page/site is allowed to load.
In SharePoint web development is done via SPFx, so the CSP policy affect SPFx solutions. In a nutshell, from now on, for the SPFx solutions to work properly, admins should whitelist external domains. Admins can maintain allowed domains list via GUI in SharePoint admin center or via PowerShell:
# List current sources
Get-SPOContentSecurityPolicy
# Remove a source
Remove-SPOContentSecurityPolicy -Source "https://cdn.host.com/source/"
# Add a source
Add-SPOContentSecurityPolicy -Source "https://cdn.host.com/source/"
The CSP policy was enforced on March 1, 2026, but as per Microsoft, if clients need more time to review and update existing SPFx solutions, we can delay the enforcement by 90 days, until June 1, 2026, via
Set-SPOTenant -DelayContentSecurityPolicyEnforcement $true
# IMPORTANT: List the applied setting again as mandatory step to correctly persist the setting (will be fixed)
(Get-SPOTenant).DelayContentSecurityPolicyEnforcement
Admins can view the Content Security Policy Violations via Purview.
So there are cmdlets:
- Add-SPOContentSecurityPolicy
- Remove-SPOContentSecurityPolicy
- Set-SPOTenant
And for the Set-SPOTenant cmdlet there are options related to CSP:
- DelayContentSecurityPolicyEnforcement
- EnforceContentSecurityPolicyConfiguration
- ResyncContentSecurityPolicyConfigurationEntries
- ContentSecurityPolicyEnforcement
So the question I ask for myself is what exactly each command does and how are the options correlated to each other and affect SPFx solutions.
Content Security Policy (CSP) in SharePoint: My Findings
ContentSecurityPolicyEnforcement
It seems like using Set-SPOTenant with a ContentSecurityPolicyEnforcement parameter change nothing. I.e. “Set-SPOTenant -ContentSecurityPolicyEnforcement:$false” does not disable policy and vise versa
“Set-SPOTenant -ContentSecurityPolicyEnforcement:$true” does not enforce the CSP policy.
My guess it’s because this article is written in April 2026. Microsoft started Content Security Policy (CSP) enforcement since March 1, 2026. So probably before March 1, 2026 we could use ContentSecurityPolicyEnforcement to enable the policy, but since March 2026 the policy is enforced anyway and parameter ContentSecurityPolicyEnforcement is not needed (and probably will go away in the next versions of the Microsoft.Online.SharePoint.PowerShell Module).
DelayContentSecurityPolicyEnforcement
DelayContentSecurityPolicyEnforcement parameter effectively switches the policy on and off. It takes a few minutes for Microsoft to propagate the change across so you can start seeing the policy enforced or not. But this is true only during 90 days – in Mar, Apr and May 2026. Since June 1, 2026 the Content Security Policy (CSP) will be enforced in SharePoint Online.
Testing SPFx Solutions Before Enforcement
How do I know if my site compliant with CSP or not before CSP enforcement?
There are some good findings for developers in the article Preparing for SharePoint Online CSP Enforcement by Nello D’Andrea, MVP. But I will share some more.
Use browser’s dev tools (F12). Select console and filter/search output with “policy”. You can find something like:

“Loading the image ‘<URL>’ violates the following Content Security Policy directive” or
“Loading the script … violates the following Content Security Policy directive” or
“Executing inline script violates the following Content Security Policy directive” or
If the message is just informational (in white) and there is also “The policy is report-only, so the violation has been logged but no further action has been taken.” that means the policy is not enforced yet… and the site functionality should not be affected.
Otherwise – when you see the same “… violates the following Content Security Policy directive” in red – this would be an error message and the policy prevents something on your site due to the CSP policy so functionality will be broken.
References
- Content Security Policy (CSP) – MDN
- Support for Content Security Policy (CSP) in SharePoint Online (Microsoft)
- Set-SPOTenant cmdlet (SPO Management Shell, Microsoft)
- Preparing for SharePoint Online CSP Enforcement (Nello D’Andrea, MVP)
Orphaned Users Clean-Up in large Microsoft 365
This article address “Orphaned Users” in SharePoint and applies mostly to medium and large tenants.
The problem statement
Orphaned users are user accounts that no longer exist in Entra ID (Azure AD) but still appear inside Microsoft 365 SharePoint or OneDrive sites, specifically in the User Information List (UIL). A SharePoint User Information List (UIL) is a hidden system list that exists in every SharePoint site collection and stores cached profile information about users who have interacted with that site. In short about orphaned users and UIL: The identity is gone, but its footprint remains.
Why Orphaned Users Must Be Removed?
Orphaned users should be eliminated not only because their presence in sites confuses active users, but mostly because they cause “User ID Mismatch” issues when UPNs are reused.
What is a “User ID Mismatch” issue in SharePoint?
User ID Mismatch is a known problem in SharePoint. It happens usually when a user account is deleted from the directory, and then a new account is created with the same UPN (re-used user principal name). Symptoms are: a user is provided with the access to the site, but still cannot get access.
The reason behind it is that SharePoint caches users data in the UIL, including not only UPN, but also Entra Id user object Id. So when a re-used UPN tries to access the site – SharePoint does not allow access, because even if UPN is the same – Id is different – e.g. SharePoint treats user as a different one. So access needs to be re-provided. And this is where the actual issue happens. When a site owner shares the resource with a new user (or approves access request) – Microsoft does dot update the UIL with the new user ids. So for the user and for the site owner it looks like access was provided, but in fact it was not.
How do we remove Orphaned Users
Microsoft provides a “fix”, but this solution is really weak as it allows only to remove one orphaned user from one site reactively. Here are some more details: “Fixing SharePoint User ID Mismatch Issue“.
Can we address the issue proactively, tenant-wide (all users, all sites, before the issue happens)? Probably – yes, but it takes a lot. Here are some more details: “Preventing SharePoint User ID Mismatch: a Tenant‑Wide Approach“. In a nutshell solution is at the moment of an employee offboarding – when a user account is deleted from directory (Entra Id) – we need to remove that user from all sites UIL they had access to. But how? And the other question: is it safe?
How do we remove deleted Entra is users from all SharePoint sites? This is a huge problem, as there is no native (out-of-the-box) Microsoft’s tools or reports to get all sites a specific user has access to. But here is where a 3-rd party tools might help. E.g. SysKit Point – with it’s “Orphaned Users” policy or ShareGate.
Is it safe to remove all orphaned users from all sites in SharePoint? Though Microsoft did not publicly say “yes” (at least I have not seen it), a high-skilled SharePoint support engineers says yes, generally it’s safe if you do it correctly. My research on the question says the same – yes, it is safe (“Is It Safe to Remove a User from a SharePoint UIL?“).
Can we just turn the SysKit’s “Orphaned Users” policy on? In small tenants – yes, in new tenants – yes. But your tenant is not new and not small – you probably already have tens or hundreds of thousands of orphaned users. Unfortunately, in SysKit there is no options to implement the policy in chunks – so we do orphaned users clean-up against test sites, then pilot, then step-by-step all other sites. Also the “orphaned users” report just fails due to enormous amount of data.
So the idea is to do an initial clean-up in the environment – gracefully remove all existing orphaned users before implementing “Orphaned Users” policy. This is exactly the topic of this KBA.
Initial Clean-Up of Orphaned Users in large Microsoft 365 tenants
A controlled, script-based clean-up must be completed before the Orphaned Users policy can be safely enabled. PowerShell is identified as the primary tool for this effort.
Below is a draft (preliminary considerations) – to be tested/proved/updated.
Scale of the Problem (sample large Microsoft 365 tenant):
- Approximately 500,000 sites (~200k SharePoint + 300k OneDrive sites)
- Approximately 500,000 orphaned users
- Approximately 300,000 normal users
Key Constraints and Challenges
- No existing report that maps orphaned users to sites
- Full enumeration of sites and users is expensive and time-consuming
- Microsoft throttling limits must be respected
- Some sites have extremely large User Information Lists (UILs)
- Orphan detection must not rely on UPNs due to reuse
- Processing must be resumable and trackable
High-Level Strategy
The clean-up approach must:
- Support piloting and phased execution
- Reduce orphaned user count enough for SysKit reporting to function (no need in total “zero orphan” cleanup)
- Minimize tenant-wide risk
Recommended initial strategy:
- Exclude new sites and external sites
- Identify large sites and process them separately
- Begin with medium-sized sites
- Validate approach using small but active sites before scaling
Execution Model
For each site processed:
- Retrieve users from the site’s User Information List (UIL)
- Check each user to determine orphan status
- Remove orphaned users immediately
- Avoid report-only runs except for limited analysis
Deleting orphans immediately avoids duplicate scanning and unnecessary re-validation.
Orphan Detection Approach
Preferred identifier: Entra ID Object ID. UPNs must not be used to determine orphan status due to reuse.
Options considered:
- Query Entra ID for every user
- Accurate but expensive
- Repeats checks for the same users
- Maintain a cached list of existing users
- Risk of missing newly added users
- Large list reduces efficiency
Recommended technique:
- Maintain a list of orphaned users by Entra Object ID
- If Object ID is known orphaned, it is orphaned everywhere permanently
- Check UIL user Object ID against this list first
- If unavailable, fall back to Entra ID lookup
Note: UIL does not always store Entra Object ID directly; sometimes only login name (claim) is available.
Handling Large Sites
- Get-PnPUser does not support paging
- Direct access to the User Information List (UIL) with paging is required
- Large UILs can cause failures if not paged properly
Workers and Parallel Processing
The clean-up cannot be completed with a single script run.
Expected characteristics:
- Hundreds or thousands of executions
- Parallel workers required
- Throttling must be handled gracefully
- Processing must be resumable
Worker execution options:
- Manual runs from a VM (e.g., nightly)
- Scheduled Azure jobs (Function App or Automation Account)
With multiple workers, a global STOP flag should be supported.
Tracking and State Management
Tracking is mandatory to avoid reprocessing completed work.
Tracking by user-site pairs is not feasible due to scale.
Preferred approach: Tracking by site.
Minimum tracking fields per site:
- SiteUrl
- State (Pending | InProgress | Done | Failed)
- LastProcessedDateTime
- AttemptCount
- LastError
- Metrics:
- UsersScanned
- OrphansFound
- OrphansRemoved
- DurationSeconds
Tracking Storage Options
- SharePoint list: not suitable at scale
- CSV:
Pros: simple
Cons: slow, co-authoring issues - SQL:
Pros: fast, reliable
Cons: complex - Azure Table Storage or Cosmos Table API: viable option
Each worker:
- Takes a site
- Marks the site InProgress (with a lease)
- Scans UIL in pages
- Removes orphaned users
- Logs actions and metrics
- Marks site Done
Reused UPNs and User ID Mismatch
Because the tenant contains many reused UPNs:
- UPN must not be used to determine orphan status
- Entra ID Object ID must be used wherever possible
Deleting users by site user ID or login name is safe because reused UPNs are not added to UIL until the previous orphan entry is removed.
An alternative approach is to skip reused UPNs entirely:
- This is safe from a risk perspective
- But it misses an opportunity to fix User ID Mismatch issues
This tradeoff may be acceptable if performance gains are significant.
References
Is It Safe to Remove a User from a SharePoint UIL?
Actually, this article is more about “Is it safe to remove all deleted user accounts from all SharePoint sites UIL?”, as managing user lifecycle changes in Microsoft 365 goes far beyond deciding whether it’s safe to remove a single user from an individual SharePoint UIL. In large Microsoft 365 tenants, deleted or inactive accounts – sometimes called orphaned identities – can create clutter and confusion in permissions and UI elements affecting governance clarity, audit readiness. This KBA explains the broader tenant‑scale implications of cleaning up deleted user accounts across all SharePoint sites.
My immediate motivation was researching the ‘User ID Mismatch’ issue in SharePoint and figuring out how to address it proactively across the tenant. Why a dedicated KBA? Because, In isolated cases, it’s generally considered safe to remove a single user from a single SharePoint UI location after their Entra ID account has been disabled or deleted. However, there is no official guidance recommending a tenant‑wide cleanup of all UI entries for disabled or deleted accounts. In fact, when asked why such cleanup might be needed, Copilot typically responds that performing it tenant‑wide is not considered safe.
One of the reasons Copilot says it is not safe is

“Avoid removing UIL entries if you need historical metadata
For example, if you rely on “Created by” or “Modified by” or Version history tracking
In my personal experience, removing a user from the UIL does not affect item edit history — the removed user still appears correctly. Moreover, when a new user with the same UPN/email but a different display name is added to a site and begins working on the same document, SharePoint handles this correctly. But let’s test it to confirm or refute this.
I have created 3 new accounts in tenant and provided them with an m365 license:

Then created a test site, and all three users one-by-one were working on the site, creating documents, lists, providing permissions
Ensure that “Created by” or “Modified by” and Version history are tracking users correctly:


Now let us delicense, disable and delete all three users – John A Doe, John B Doe and John C Doe.
These does not change anything, as users are still in the UIL. Now let me remove all three users from the site UIL. Sources say that “Microsoft has a series jobs to clean-up users after deletion” and “never re-create users within days after deletion, wait at least 30 days.”
So let me check what is happening with “Created by”, “Modified by” and “Version history” after we delete users from the UIL and re-create users with the same UPN and provide access to the site…
| Event | Consequenses |
|---|---|
| User deleted from Entra Id and from UIL | all looks good |
| After a few minutes | all looks good |
| After a few hours | all looks good |
| User John A Dow is recreated with the same UPN (less than 24 hours since deletion), provided with permissions to the site and started working on documents | all looks good |
| After a few minutes | all looks good |
| After a few hours | all looks good |
| User John B Dow is recreated with the same UPN (less than 7 days since deletion), provided with permissions to the site and started working on documents | all looks good |
| After a few minutes, and after a few hours | all looks good |
| User John C Dow is recreated with the same UPN (less than 30 days since deletion), provided with permissions to the site and started working on documents | TBP |
| After a few minutes, and after a few hours | TBP |
So far all looks good, i.e. I’m not seeing any issues.
Proof is below (in the form of screenshots):
Users deleted from Entra Id and from UIL, after a few minutes:


After ~1-2 hours, I created a user with the same UPN “John.A.Doe@vladev.xyz” but with different display name – “John A2 Doe”. A new user requested access to the site, got approval and was able to access the site with no issues, then created a new document. Here is how it looks like:

Then a new user – John A2 Doe – updated Doc2. Again, all looks good. An old John.A.Doe and a new John.A.Doe are reflected correctly. Here is the version history:

Let us wait for 24+ hours…
After 10 days I undeleted “John B Dow”. Checked their access to site – permissions are here. Why? It turns out I did not remove the user from the associated Microsoft 365 group. So when I restored (undeleted) account from Entra Id – the account regain groups membership. And after some time the user was able to access the site correctly. I did not expect that, and I’m not sure is it OK. I need to keep this in mind.
Now let me try to undelete “John A Dow” (remember I already created another account with the same UPN). User accounts that you can find under “Deleted Users” have a username like “457be210d0344040a530dc99cfaa2ba6John.A.Doe@contoso.com”.
Admin center did not let me undelete this account. The message I got was “There was a problem” and “Conflicts occurred trying to restore user. Please resolve conflicts.”. So that is OK as well.

User Information List (UIL)
In short, User Information List (aka UIL) is a hidden system list that exists in every SharePoint site collection and stores cached profile information about users who have interacted with that site.
The UIL is normally hidden, but you can access it adding the following to the site URL: “/_catalogs/users/simple.aspx”, “/_catalogs/users/detail.aspx” or “/_layouts/15/people.aspx?MembershipGroupId=0”, e.g.
https://<site-collection-url>/_catalogs/users/simple.aspx
https://<site-collection-url>/_catalogs/users/detail.aspx
https://<site-collection-url>/_layouts/15/people.aspx?MembershipGroupId=0
References
- MS tech comm: What are best practices for orphaned users?
- Sharegate: Clean orphan users
- SysKit: Orphaned Users
Preventing SharePoint User ID Mismatch: a Tenant‑Wide Approach
There is a known problem in Microsoft 365 SharePoint called “User ID Mismatch”. It happens if a user account is deleted from the Entra Id directory, and then a new account is created with the same UPN (e.g. rehired person or a person with a popular name like John Smith). Symptoms are: a user is provided with the access to the resource, but still cannot open it and gets “Access denied” error or “Sorry, something went wrong” and “There is a legacy user account in this site with same email. Please ask site owner or administrator to remove the legacy user account from this site”.
The reason behind it is that SharePoint stores users data in it’s own database (accessible via hidden system list called User Information List – UIL). Properties include display name, title, UPN, and (!) AD SID and Entra Id user object id. So when a re-used UPN tries to access the SharePoint site – Microsoft 365 compares Ids and declines access. So access needs to be re-provided. And this is where the actual issue appears.
If the site was accessed by the “old” user in the past, site UIL contains information about that “old” user. When the site owner shares the site with the “new” user – Microsoft does dot update the UIL with the new user ids. Microsoft 365 behave “normally”, no error messages are displayed. So for the user and for the site owner it looks like access was provided, but in fact it’s not.
Existing fix
Microsoft knows about the issue. But instead of fixing the root cause – Microsoft recommends removing the old user from the UIL. Obviously this fix is a) reactive, b) for one specific user and c) for one specific site. In my previous article – Fixing SharePoint User ID Mismatch Issue – I explained the issue in details, outlined 3 options to fix the issue, including PowerShell script.
But the User ID Mismatch issue does not come for a one site and one user. Usually it impacts many sites, and the older your tenant is – the more reused UPNs you get. The bigger the tenant – the bigger the problem.
Moreover, the issue is tricky to recognize. From the user perspective it looks like “normal” permissions issue – so it takes some time for user and site admin to realize that something is wrong and reach support. So can we do it proactively? I mean, can we not only fix the issue for all impacted sites after the user hit the issue, but prevent the issue to appear?
Let us try to go deeper into the issue and find some more consistent solutions.
Fix the issue “everywhere” at once thoughts
Define terms
- Reactive – once we got a “user id mismatch” ticket – we can fix the issue for a site we got ticket for, and then try to find all sites with the user id mismatch issue for the same user
- Proactive – we’d fix the issue before the user hit Access Denied error due to User Id Mismatch issue. For this we need somehow
Fix all sites for one specific user reactively
Again, the issue is scoped with a specific site (site collection). The mentioned PowerShell-based solution and all Microsoft’s fixes are designed for one specific site, but in real life what is happening is the “old id user” had access to many sites, and “new id user” has access to many sites, so after a several “access denied” issues a user might be confused and ask SharePoint admins to fix the issue “everywhere”. We should not bother users with “please provide us list of site Url you are having issues with”… or saying to user “please create a new ticket when you hit the same issue again” also does not sound nice.
So how do we fix the User Id Mismatch Issue on all sites for a specific user (reactively)?
At first, the solution looks simple: we need to check all sites old user had access to and remove UPN from UIL. Well… yes… But how do we get a list of sites the old user present in the UIL?
So far – I’m not seeing a good solution.
Option 1: Brute force – scan all sites.
- Get list of all tenant sites
- For every site – check if the user is in the UIL
- If yes – check if this is a User Id Mismatch case
- If yes – remove the user from UIL
This option is comprehensive, i.e. it should fix the issue for all sites, so in case of reused UPN we should not have issues for any tenant site for the same user. But this is a really “heavy” solution and can work well for small tenants only. I do not think this option is feasible for medium or large tenants.
Option 2: Access report.
There are 3-rd party tools (I’m not aware if there is a built-in m365 tool for that) you can use to get report on all SharePoint resources user have access in tenant. So you’d export the list, select unique sites Urls and scan these sites. Possible issues – usually we no not know how the 3-rd party tool builds this report (if the UPN or object Id is used), would it be “old” user access report or “new” user access report?
Option 3: membership
We can use MS Graph “membership” and “people” API to get list of sites around. We can get our user membership – m365 groups and related sites. People API would return users related to our client – a collection of person objects based on their relevance to the user, which is determined by the user’s communication and collaboration patterns, and business relationships. We can get these people OD sites, we can get their groups memberships and sites. We can do the same for people related to people. NB: I know, this option would give us sites related to a new user, not old user.
Add-on to Option 3: common sites.
With Option 3 we’d get group-based and OD sites. How about standalone sites? Also there might be public teams…
Usually in any tenant number of group-based sites (teams sites) are much bigger than non-group-based sites. So we can simply scan all standalone sites. But, again, in large tenants this might not be a feasible option. But we can get list of “open” standalone sites and public teams and Yammer communities (i.e. “common sites” usually accessed by everyone in tenant). Additionally, over the time we can get “most popular impacted sites” form the fixing history to update our list of common sites.
Option 5: audit log
Reactively, we can use audit log to get AccessDenied sites for a new user
- Get audit log and filter it by user and select only “AccessDenied” pages
- Make a unique list of accessed sites
- For every site – check if this is a User Id Mismatch case
- If yes – remove the user id from site’s UIL
What I do not like here is getting audit log is a slow operation, and still re-active. I use it when I cannot reach impacted user and I need to know list of sites user already having issues with.
Practice
My personal experience.
Option 1. In my simple tests – it takes ~1 hour to scan ~500 sites (keep in mind, we need to scan all sites, including personals/OneDrive).
Options 2 and 3 helps, as allows to cover majority of impacted sites our re-used UPN user might have issues with. But we cannot guarantee we fixed all sites for the specific user.
Fix all sites for all users proactively
Obviously, for proactive solution, we need to start from Identity Management. Below are just thoughts so far…
No re-used UPNs.
Providing a unique UPN each time we create a user might help.
Know re-used UPN.
If we knew every reused UPN at the moment of account creation (an employee onboarding) – we could proactively apply Options 1,2,3 from our reactive approach.
Total clean-up
In theory – we could use our reactive Options 1, 2, 3 and 5 at the moment of the employee off-boarding to find all sites user had access to and just remove the terminated employee’s account from all sites UIL.
That would prevent user mismatch Id in the future. Removing a user from UIL should not impact edit history – i.e. user’s Name will still be populated correctly if you want to check versions history of documents created or updated by this user. Scanning all sites for every off-boarded employee could be an option for small tenants.
3-rd party tools
There are 3-rd party tools (e.g. SysKit Point).
SysKit’s Orphaned users governance policy currently is very simple, but new updates – i.e. Dec 16, 2025 – as advertised would allow to reove orphaned users automatically from sites. Once I got this update installed – I’ll test it and share here, as if all good – this might be the only real solution to a user id mismatch issue.
Bottom Line
Currently, there is no effective, tenant-wide, proactive solution that guarantees protection from user id mismatch issue. The bottleneck here is inability to quickly get list of sites a user had access to.
Custom PowerShell scripts would work only in small environment, but the “total scan” approach would hardly be realistic in large environments.
There are though 3-rd party tools that build it’s own database with all the permissions of all users, which could be the foundation for the “Prevent user id Mismatch” functionality.
Proactive SharePoint: Essential Initial Configurations for Every New Microsoft 365 Tenant
In this article I will share what I would recommend to configure on every new Microsoft 365 Tenant.
The Challenge: Why Many Microsoft 365 Tenants Become Unmanageable and Inefficient Over Time
Many organizations adopting Microsoft 365 quickly discover that while the platform offers immense power, its default configuration often leaves crucial features disabled. These “dormant” functionalities, designed to enhance data governance, search capabilities, content management, and user experience, remain untapped. The real problem arises when a tenant matures: as users populate SharePoint sites and OneDrive accounts with vast amounts of information, and as collaboration intensifies, attempts to enable these critical features become incredibly complex, disruptive, and even risky. Retrofitting governance, re-indexing content, or restructuring information architecture on an existing, data-rich tenant can lead to compliance headaches, data inconsistencies, user frustration, and significant administrative overhead. SharePoint administrators frequently struggle with the technical debt accrued from these missed initial configurations, spending countless hours trying to bring order to an environment that could have been optimally set up from day one.
Consider the following.
Ownerless resources
Having an owner for every Microsoft 365 resource should be enforced from day one.
Sensitivity labels
This step is an essential prerequisite for the other governance features. I have an article explaining ownerless Microsoft 365 groups policy in details and more KBAs regarding ownerless SharePoint resources.
Oversharing in SharePoint
Oversharing in SharePoint is a serious problem. The earlier you start addressing it – the easier you life as SharePoint engineer. Here are some thought: Control Oversharing in SharePoint Online: Smarter Access Management in Microsoft 365
User profiles to Term Store mapping
There is an OotB misconfiguration in Microsoft 365 User Profiles mapping to Term Store Metadata. Here is the KBA how to configure User Profiles correctly.
WIP
Why this approach?
- Relatability: It immediately speaks to the pain points experienced by many SharePoint admins (“unmanageable,” “inefficient,” “struggling with it,” “technical debt”).
- Highlights the “Why”: It explains why these features are off and why it’s a problem to turn them on later.
- Emphasizes Proactivity: It sets the stage for your solution, which is about proactive setup.
- Strong Call to Action (Implied): It makes the reader understand that your KBA will provide the solution to avoid these common pitfalls.
Controlling Oversharing in SharePoint Online: Smarter Access Management in Microsoft 365
Oversharing remains one of the most persistent challenges in SharePoint Online. With the introduction of Microsoft Copilot and its AI-powered search capabilities, the issue has become even more visible—and more urgent to address. Microsoft has acknowledged this by introducing the SharePoint Advanced Management suite, aimed at helping administrators to bolster content governance throughout the Microsoft Copilot deployment journey.
Why Does Oversharing Happen?
In most cases, oversharing is unintentional. Based on my experience, the root causes typically fall into four categories:
- Unaware Sharing: A user shares a site, library, or folder without realizing it contains sensitive information.
- Unaware Uploading: A user uploads sensitive content to a location that is already broadly shared.
- Human Error: Mistakes like selecting the wrong group or sharing a folder instead of a file.
- Convenience: Users opting to share with “Everyone” to avoid the hassle of managing individual permissions.
Why It’s a Bigger Problem Today
In the past, search in Microsoft 365 was content-driven—you had to know what you were looking for. Today, search is context-driven. Microsoft 365 proactively surfaces content with suggestions like “Here’s what might be interesting to you” or “Here’s what others are working on.” This increases the risk of oversharing content being exposed.
Separate issue, non-technical, but related to the subject – not every user knows that search in Microsoft 365 is security-trimmed, i.e. provides results from only what this specific user has access to. Sometimes people might think of Microsoft 365 search the same way as general internet search (If a can see it – then everyone can see it, or why my private documents appear under Bing search?).
The Admin Dilemma
As SharePoint administrators, we’re caught in a classic catch-22:
- Complex Microsoft products
- Users prone to mistakes
- Management demanding simple, fast solutions
What seemed like straightforward fixes for oversharing actually concealed the true issue, generating new problems, increasing admin burden, perplexing users, and ultimately hurting company productivity. Examples are (I would never do that):
- Exclude sites from search indexing (Set “Allow this site to appear in search results?” to No)
- Turn off Item insights, turn off People insights (turn off Delve)
- Truncate enterprise search with “official” sites only (via query)
Microsoft offers two solutions: “Restrict discovery of SharePoint sites and content” and “Restricted SharePoint search”. Both solutions aimed to exclude content from search and from Copilot. Microsoft: “Restricted SharePoint Search allows you to restrict both organization-wide search and Copilot experiences to a curated set of SharePoint sites of your choice… and content users own or that they have previously accessed in Copilot.”. “With Restricted Content Discovery, organizations can limit the ability of end users to search for files from specific SharePoint sites.”
Microsoft clearly says that “limit the ability of end users to search” is a temporary measure that “gives you time to review and audit site permissions”… “to help you maintain momentum with your Copilot deployment while you’re implementing comprehensive data security”. Also: “Sites identified with the highest risk of oversharing can use Restricted Content Discovery to protect content while taking time to ensure that permissions are accurate and well-managed”.
Microsoft highlights that “Overuse of Restricted Content Discovery can negatively affect performance across search, SharePoint, and Copilot. Removing sites or files from tenant-wide discovery means that there’s less content for search and Copilot to ground on, leading to inaccurate or incomplete results”.
And finally “Restricted Content Discovery doesn’t affect existing permissions on sites. Users with access can still open files on sites with Restricted Content Discovery toggled on.”. I.e. solutions “Restricted SharePoint Search” and “Restricted Content Discovery” do not solve the root cause of the problem (oversharing), but make the problem less visible.
With over 15 years of experience in SharePoint and more than a decade working with Microsoft 365 and Azure—including large-scale tenants—I’ve seen this problem evolve. Now, with Copilot in the mix, it’s more critical than ever to implement a robust access management strategy.

How to solve the real oversharing problem
(My Ideal “No-Oversharing” Tenant Configuration)
Here’s what I would recommend for minimizing oversharing in a Microsoft 365 environment (think of it as SharePoint Governance):
1. Remove “Everyone” and “Everyone Except External Users”
Disable these groups in the people picker to prevent broad, indiscriminate sharing. Instead, provide other options for sharing content with larger audiences (see below).
2. Implement Sensitivity Labels for Sites
- Enforce mandatory sensitivity labels for all sites.
- Labels should control site visibility (e.g., Private, Public) and be clearly named
The label is visible across all interfaces—Teams, SharePoint, libraries, lists, folders—so users always know how wide the content is shared from the sensitivity label.
3. Empower Users with Guardrails
- Allow users to create Teams and communities, but enforce sensitivity labels.
- Enable requests for standalone sites (Team or Communication) with required labels.
- Disallow private or shared channels under public Teams to avoid label mismatches (e.g., a private channel labeled “Public”).
Benefits of This Approach
Once implemented:
- Users will always know whether a site is private or public.
- Sharing with “Everyone” on private sites will be technically impossible.
- Users needing broad access can request public sites, e.g.
- Public Teams for collaboration with everyone (allows read/write access)
- Communication site for publishing information (allows read only access)
Yes, this may lead to more sites and Teams. Yes, this may lead to more tickets from users who at private site wanted to break permissions as usual and share list or library or folder with everyone. Yes, we would need to develop automation that can help manage the scale. But that’s a worthwhile trade-off for reducing oversharing!
More to consider
Large Custom Security Groups
There might be Large Custom Security Groups in tenant. What if the user wants to share site with one of these Large Custom Security Groups? What kind of site that would be? Private? Public?
Consider the following. When a team owner adds a security group to team members – it’s not a group added, but individual users. That makes sense – all team members can clearly see who are the other team members. That makes the team private. Private team should not be additionally shared at SharePoint site level. Only permissions should be provided through team.
Public team – as well as public standalone site – can be shared with EEEU. But what if the requirements are not to share the site with “Everyone…” but share with some other Large Custom Security Group – e.g. “All employee” or “All Central Office Users”? Can we do it? Should site be private or public in this case?
My opinion: site should be labelled as public. Site owner can request a public standalone site or create a team self-service, then site owner can remove “Everyone…” group from permissions and add a custom security group at any level.
Some orgs choose to recommend providing access to the standalone SharePoint sites via security groups vs SharePoint groups. So it is possible we have a private standalone site with access provided to security group (or m365 group). This is where an or should have their own policy – how big the group should be to be considered as large group and trigger site label as public. There are also dynamic security groups.
Automation Requirements
To support this model, we’ll need (at least) the following custom-designed solutions:
- Automated Site Provisioning: A request-and-approval process for creating labeled standalone sites.
- Channel Monitoring: A custom solution to detect and flag private/shared channels under public Teams, since there’s no out-of-the-box enforcement.
- Large Custom Security Groups Monitoring: make a list of large custom security groups users can share information with – and check on scheduled bases – if the site is shared with large custom security group – site must be labelled as public.
- Sharing site with “Everyone except external users” : If user accidentally removes “Everyone except external users” from public site – there must be an option for user to add “Everyone except external users” with permissions Read or Edit. Site can be shared with “Everyone except external users” only at the root site level and only if site labelled as Public.
Environment Clean-Up
To prevent oversharing, we should not only “from now on” follow the strategy described above, but also make sure our existing sites are compliant with our governance. This would be another challenge.
References
SharePoint Inactive Site Policies Deep Dive
SharePoint Advanced Management includes Inactive Site Policies under Site lifecycle management. Effective content lifecycle management is a key pillar of SharePoint governance. It plays a vital role in optimizing storage, preserving data integrity, and ensuring regulatory compliance. By systematically removing inactive or outdated sites, it also enhances security. Additionally, it supports successful Copilot implementation by ensuring that the information accessed is both accurate and current. So, how exactly this Inactive site policy works and what is the difference between Entra Id groups expiration policy and SharePoint Inactive Site Policy.
SharePoint Inactive Site Policy vs m365 Groups Expiration Policy
The Groups Expiration Policy has been a feature of Azure AD (Entra ID) for quite some time. It is included at no additional cost. This policy automatically notifies group owners about upcoming expirations and provides options to renew or delete the group. Since all self-created Teams teams and Viva Engage communities are backed by SharePoint sites and managed through Microsoft 365 Groups, this policy also plays a significant role in SharePoint governance ensuring that information stored in SharePoint remains current and properly maintained. I have an article Microsoft 365 group expiration policy deep dive.
Inactive Site Policy is a feature of SharePoint Advanced Management (SAM), which is an add-on and require premium SharePoint license. It also Identifies inactive sites, Sends notifications to site owners and can automatically archive or make sites read-only. Sound like very similar to to groups expiration policy.
Key differences
| Feature | Groups Expiration Policy | Inactive Site Policy |
|---|---|---|
| Where to configure Who can configure | Entra Id Groups Admin | SharePoint Admin center SharePoint Admin |
| Scope (policy is applied to) | Microsoft 365 Groups (including group-based sites, like teams, yammer) | SharePoint Sites (including both – group-based and non-group-based sites) |
| Who is notified | Group Owners | Site admin (group owner), site owners (*) TBC |
| Notifications come from email | msgroupsteam@microsoft.com | no-reply@sharepointonline.com |
| What if resource is active | group is automatically renewed, no emails sent | policy is not triggered against active sites |
| Can admin download report (list of inactive groups/sites) | No | Yes |
| Period of inactivity configuration | Configured in days, should be greater than or equal to 30 days | Options are: 1, 2, 3 or 6 months |
| Actions available (Options provided) to a resource owner | renew the group delete the group | certify site learn how to delete a site |
| What happens with resources owner did not take action (or with orphan resources). | Notifications is sent to a specific email address, group is deleted | site is archived or set to read-only or nothing |
Inactive site policy user experience
Here is how the email notification looks like:

Note that
The email subject includes “Action required” and site title (name).
It always says “… has been inactive for more than a month” even if the policy configured for “6 months”.
It shows SharePoint logo, which might mislead “teams-oriented” users.
Site title is not clickable, so site admin/owner cannot just click site link but have to navigate to site manually.
When user clicks button “Certify site” – a message “The action completed successfully” pops up at the bottom of the email for a few seconds and then disappears. The email itself does not change, so when a user opens the same email again – there is no visual evidences the action was taken.

At the bottom of the email Microsoft mentions tenant name.
The email template is the same for all kinds of policies – it does not matter if the policy action is configured configured as “do nothing”, or to automatically enforce archive site or set it to read-only. I.e. email just says “Select Certify site to confirm if it’s still in use, or consider deleting it if the site is no longer needed.”. Email does not inform users that site will be set to read-only or archived.
Also there is no link where a user can get more info on the subject, but Microsoft says that inactive sites policy email template will be customizable – in the Site lifecycle management policies v2 expected summer 2025.
Admin – Inactive sites report
You can download a csv report of inactive sites generated by policy.
Report includes fields:
Site name, URL, Template, Connected to Teams, Sensitivity label, Retention Policy, Site lock state, Last activity date (UTC), Site creation date (UTC), Storage used (GB), Number of site owners, Email address of site owners, Number of site admins, Email address of site admins, Action status, Total notifications count, Action taken on (UTC), Duration in Read-Only.
There is no GUI to see the list of inactive sites (you can only download a csv file), but there is a magic button “Get AI insights”.
Get AI insights
Here are insights I have seen so far:
- Inactive sites with significant storage usage
- Multiple sites owned by the same account
- Sites with Multiple Owners
- Sites inactive for over a year
Inactive sites policy behavior
Policy sends emails immediately after policy activation. That means if you have thousands of inactive sites you might hit a 10k exchange limit of daily emails sent.
If a user owns multiple inactive sites – he/she will get multiple emails.
You can scope the policy down by site template, sensitivity label and creation source if you want different behavior for different types of sites, e.g. if you want to setup longer period of inactivity for one type of sites and shorter for others… not sure when it makes sense…
Implementing an Inactive sites policy
First of all – It is highly recommended to take care of ownerless sites (find owners) before triggering an Inactive sites policy.
If you have a relatively new tenant – you probably have not much inactive sites, so turning the policy on should not be a problem. The older your tenant is the more inactive sites you have. For older tenants you probably already have a lot of inactive sites – ant that could be a problem. So we’d need to take care of initial policy implementation, and after some time it will just work so we could forget about it.
There is no way to pilot this policy with pre-selected scope of sites or users. You can scope the policy down by site template, sensitivity label and creation source, but you cannot scope the policy down the way only sites or uses you want to be a testers or pilot project members will be the target of the policy.
In small orgs there should be no problems implementing this policy. Still I would start from just getting a report. There is a “How long after the last activity should a site be considered inactive?” configuration, so I’d start from the longest – 6 months, then move to the shortest you need. Medium orgs could get some ideas from recommendations to large orgs below.
In large orgs you might
- trigger a spike in number of tickets submitted by users who needs help
- hit a maximum sending limit with Exchange Online which is 10,000 email recipients per day
So it would be crucial for enterprises to avoid an initial surge and start from smaller number of recipients, and gradually let the policy work at a full strength. One of the options to achieve that would be
- configure the policy for reports only, get inactive sites report
- select sites owner and admins in a separate list – then select only unique ones – so every user will get only one email, split this list into small chunks
- communicate to site owners (by chunks) – using enterprise-approved “send from” email and enterprise-branded email template saying that the policy is gonna be implemented, you might receive an email (like this one – screenshot), you can trust this email and click buttons. A list of site urls user owns must be included in the email, so user could visit these sites
(Optionally) you can instruct users how they can delete sites if site is no longer needed or archive sites if they are not sure if it is still needed or not
If so – it’d
- forewarn users so they would know to do and not be surprised and would create less tickets
- users might choose to delete or archive sites which would also
- users would visit their inactive sites and trigger sites activity, and that should dramatically decrease number of emails sent to users initially, on the day one of policy implementation
ideally – if users visit all sites – you’d have no inactive sites, so you’d just turn the policy on with no fear
then you’d wait for a couple of weeks, get new report to ensure that you have much less inactive sites – and you’d just enable the inactive sites policy (starting from the longest period – 6 month of inactivity)
References
Content Shared with Everyone: Access Review
This article is for SharePoint or Microsoft 365 admins focusing on governance and information protection. If you have SharePoint Advanced Management (SAM, aka SharePoint Premium) licensed or you got at least one Copilot for Microsoft 365 license (as having m365 Copilot license automatically enables SharePoint Advanced Management in tenant), then under reports – Data access governance (in SharePoint admin center) – you can not only get Content shared with ‘Everyone except external users’ (EEEU) reports, but also initiate access review. Let us look more closely at this functionality and discuss the pros and cons..
I’ll not repeat Microsoft documents:
– SharePoint Advanced Management
– Content shared with ‘Everyone except external users’ (EEEU) reports
– Site access reviews for Data access governance reports
but I’ll focus on what is not there and a real-world experience.
Reports
First of all, report does not provide you with all SharePoint content shared with “Everyone except external users”. Report helps you with what was shared with EEEU in the last 28 days. That drastically limits usage of this feature. I.e. you should first get initial report on the all content shared with EEEU, and somehow take care of it by other means (consider How to Find Content Shared with Everyone in SharePoint and Teams), and only then you can use this Microsoft’s content shared with EEEU report and access review.
You can share content with EEEU or directly – by adding EEEU to resource permissions directly or by including EEEU into SharePoint group. So content shared with EEEU reports come in two flavors – “Specific files, folders and lists” and “Site membership”

“Specific files, folders and lists” user experience
When you initiate access review from the “Specific files, folders and lists” type of report – users (site admins/owners) get email notification that says “You have sites with specific files, folders or lists shared with ‘Everyone except external users’. This means everyone in your organization has access to this content. Review the items shared for potential oversharing and manage their access.“

Scrolling down, in the email, site owner can see a list (table) of incompliant sites with the following columns: Site name, privacy, sensitivity, external sharing and “Items shared”. Site name is clickable and sends user to the root of the site.
Below the list of sites there is a button “View shared items” that sends user to the special system page –
“https://orgname.sharepoint.com/teams/site01/_layouts/15/siteaccessreview.aspx/<id>” where he/she can see list of SharePoint items shared with EEEU. Columns are: (item) Name, Shared on (date), Shared by (email), Action (manage access). Item name and manage access are clickable.

If an item is a library item – e.g. document or a folder – it is displayed correctly – with icon according to the doc type and doc name. Clicking on the doc name – an actual document opens so you can review it’s content.
If item is a list item – it is displayed incorrectly – no icon, no meaningful info about the item (it is displayed as “”). Clicking on the link – a warning icon and message “Can’t preview this file. Open the file or download it to view in your desktop app”. Buttons “Open” and “Download” are there but not helpful as well.
Clicking on “Manage access” opens almost standard “Manage access” dialogue you can have via “manage access” item context menu, but with no “…” more options at the top right:
which makes this dialogue screen useless, as you can only provide additional access to the item or remove all access. You cannot remove EEEU from access without three dots “More options”.
Manage Access from the Policy:

Regular Manage Access:

“Stop sharing” literally removes all permissions to the item except owners

Under the “Groups” tab – you’d see that the item is shared with “Everyone except external users” but you will not be able to remove just this group from access…

By clicking on a group name – site owner will be able to change this group permissions, but the option “No direct access” is not selectable…

“Site membership” user experience
In the case with a “Site membership” report, text would be slightly different: “You have sites where ‘Everyone except external users’ has been added to the site membership. This means everyone in your organization has access to this site. Review site permissions for potential oversharing and manage access.“, which makes sense.
Right after that, in the email, site owner can see a list of incompliant sites with the following columns: Site name, privacy, sensitivity, external sharing and “Groups with org-wide access”. Site name is clickable and sends user to the root of the site.

Then there is a button “View SharePoint groups” that sends user to the special system page –
“https://orgname.sharepoint.com/teams/site01/_layouts/15/siteaccessreview.aspx/<id>” where he/she can see list of SharePoint groups (clickable) with EEEU as members.

By clicking on a group name – admin opens standard SharePoint “People and Group” membership page:
/_layouts/15/people.aspx?MembershipGroupId=X, which is nice, because from this screed a site owner can simply remove this group from the access list using Actions-> Remove:

siteaccessreview.aspx page
User can navigate directly to the reviews page:
“https://orgname.sharepoint.com/teams/site01/_layouts/15/siteaccessreview.aspx” and if there were reviews initiated by SharePoint admins – and it’ll work – admin will see all access reviews initiated for this site – columns are: Review name, Description, Requested on (date), Status, reviewed by (email) and admin comment. In case no reviews were initiated against tie site – “You have no reviews to take action on” will be displayed. That’s good.
Complete review
On the bottom of the siteaccessreview.aspx page you’ll see “Complete review”

Click on it, add comment (optionally) and confirm:

SharePoint Admin is able to see the status of every site access review stats – pending or completed – in GUI and in the .CSV report saved.

Admin experience: GUI only
Once you got report – you can initiate access review. All must be done in GUI, click-click-click selecting sites… But what if you have thousands? There is no PowerShell cmdlets or API for this functionality, which really limits your ability to implement it gracefully, especially in large Microsoft 365 environments and automate it.
Download detailed report
Report “Specific files/folders/lists…” does not include files, folders, list – i.e. it does not include what exactly is shared with EEEU. Report includes site id, url, name, template, is it teams-connected, sensitivity (?), privacy, external sharing, primary admin name and email, and number of items (?) shared with EEEU.
So technically you can communicate to site owners, but you’d need to rely on them to figure out what content is shared with everyone.
Email template
When you initiate Site access review – an e-mail notification is send to site owners. This e-mail is not customizable at all. The only admin can do is to add a message (for every “initiate Site access review” action). But the email looks really similar to the site lifecycle policies email notification, and Microsoft is working on version 2 of the policies with a customizable email template.
This email comes from “SharePoint Online <no-reply@sharepointonline>” address (not customizable), so comes “from outside of your organization” and can be considered as scam.
Microsoft’s logos and other graphics are blocked by default and e-mail includes a button “View shared items” – enough red flags for users to consider it as spam. Keep this in mind.
The good news is e-mail contains site name – so site owner can recognize it at act accordingly.
Usage scenarios
Small tenants
In small Microsoft 365 environments – yes, this functionality probably can be used “as is” (and should be used). Especially for new tenants – I’d recommend enable reports and use this feature on a regular basis.
Medium-size tenants
I’m not sure. It depends on your governance rules and company culture.
Enterprises would not like it
I’m very pessimistic if this functionality is useful in large environments. Reasons are:
- In enterprises usually all the communication must follow approved templates, branding and so on. Currently SAM DAG does not support custom templates (though there are rumors Microsoft is working on it)
- User experience of “reviewing shares with everyone”… and “managing permissions” designed very poorly… You SharePoint users need clearness and simplicity. Existing UX makes everything wort. In enterprise you do not want to deal with thousands of tickets from site owners who could not figure it out
- In enterprises you’d think of automation. Currently all is just GUI.
- if your tenant is not new – you already have a lot of overshared content. This functionality covers only new shares, so you still need to come up with your custom solution (idk – PowerShell scripts?) to deal with oversharing. But once you designed your custom solution – why don’t you continue to use it?
SharePoint Advanced Management Deep Dive
SharePoint Advanced Management is an add-on to Microsoft 365 for admins. Microsoft says that it is a powerful suite of tools for IT admins to bolster content governance throughout the Microsoft Copilot deployment journey. Let us have a closer look at what SharePoint Advanced Management (SAM) is how exactly it helps with governance enforcement in the Copilot era.
Microsoft recently updated SAM features (this KBA is based on Oct 2025 features set). Now Advanced management page has a dashboard – “Overview” tab and “All features” tab.
Advanced management – Overview

On the “Overview” page Microsoft wants us to run assessment. “Start assessment” button starts assessment immediately. So let us click “Start assessment” button and see what it does exactly. Btw, it might take from days to weeks for your tenant – depending on the tenant size. While assessment is in progress – it’ll display “Assessment in progress. This might take some time. We’ll display the results as soon as they’re ready.”

It took 3-4 hours for my small dev tenant to assess Site lifecycle and find 62 sites require attention:

Advanced management – All features
Microsoft classifies SAM’s features as “Manage content sprawl”, “Manage content lifecycle”, “Manage permissions and access”. I’d put SAM’s tools into these buckets: Reports, Policies, Search, Features.
SAM Reports
SharePoint SAM reports provide structured, actionable data that you can analyze to optimize governance strategies and implement immediate improvements. Reports available are:
- Agent Insights – how agents are accessing the content on the sites
- App insights – review apps registered in Entra allowed access to SharePoint sites
- Change history reports – site actions or organization setting changes
you can choose org-wide or site-level settings, specify date range, sites and all or specific admins - Content services reports – Term store, term sets and terms
- Data Access Governance (4 different ones)
- Site permissions across your organization
- Sharing Links with 3 pre-configured reports:
Anyone links, People in your org links and Specific People links shared externally - Sensitivity labels applied to files: select label -> generate report
- Content Shared with Everyone Except External Users:
to discover specific sites whose content was made accessible for EEEU
you can choose from two types of report: where specific files/folders/lists are shared with EEEU or “Site membership” where EEEU was added as a member and initialize access review
(see Deep Dive into SAM DAG Content shared with EEEU access review)
- OneDrive Accounts report – about unlicensed OneDrive accounts
- Site policy comparison – control oversharing by identifying sites with similar files and different policies
SAM Policies
Policies in SharePoint SAM define governance rules that are enforced automatically, minimizing manual intervention and ensuring consistent compliance. SharePoint Advanced Management policies are:
- Site Lifecycle management: Inactive Site Policy. Allows:
- identify inactive sites
- send notifications to site owners and/or admins
- automatically archive or make sites read-only (or do nothing – just report)
(see Deep Dive in SharePoint Inactive Site Policies)
- Site Lifecycle management: Site Ownership Policy (went live June 2025)
(see my SharePoint Site Ownership Policies Deep Dive) - Access control – Site-level access restriction
- Access control – OneDrive access restriction
AI Insights – report feature that uses a language model to identify patterns and potential issues and provide actionable recommendations to solve issues
Features
Features are smaller that policies, more like an update to existing functionality.
- Conditional access to SharePoint site policy
This enhances existing conditional access Entra Id feature with the ability to apply the policy to SharePoint sites directly or via Site sensitivity label. - OneDrive access restriction
- SharePoint site-level access restrictions
- Block download policy
- Your recent actions
- Default sensitivity labels for document libraries
- Site access review
SAM for Search
I put it separately:
- restrict discovery of SharePoint sites and content
- Restricted SharePoint search
TBP