Microsoft 365 External Sharing Audit and Restriction: How to Find What Is Shared Outside Your Tenant and Lock It Down

Retool's new app builder is where AI-generated code ships safely
Building apps with AI is easy. Getting them to production safely is another story.
External sharing in M365 is controlled at three levels: the Entra ID tenant (who can be invited as guests), the SharePoint tenant admin center (sharing modes from Anyone to Specific people only), and individual SharePoint sites or OneDrive accounts. Each level can restrict but not expand what the level above permits. The audit process starts at the most permissive sharing settings and works down to identify where over-sharing is occurring.
Auditing the Tenant-Level Sharing Configuration
The SharePoint admin center's tenant sharing setting is the ceiling for all external sharing:
# Connect to SharePoint Online
Connect-SPOService -Url https://contoso-admin.sharepoint.com
# Check current tenant-level sharing settings
Get-SPOTenant | Select-Object SharingCapability, DefaultSharingLinkType, `
DefaultLinkPermission, RequireAnonymousLinksExpireInDays, `
ExternalUserExpirationRequired, ExternalUserExpireInDays
Sharing capability levels (from most to least permissive):
ExternalUserAndGuestSharing(Anyone): anyone links allowed, new guest invitations allowedExternalUserSharingOnly: anyone links blocked, new guest invitations allowedExistingExternalUserSharingOnly: no new guests, existing guests can still accessDisabled: no external sharing at all
For most organizations, the recommended minimum is ExternalUserSharingOnly (guests require an account to access), with anyone links disabled or strictly expiring:
# Set tenant to block anonymous anyone links, require guest sign-in
Set-SPOTenant -SharingCapability ExternalUserSharingOnly
# Or keep anyone links but enforce 14-day expiration
Set-SPOTenant -RequireAnonymousLinksExpireInDays 14
# Set default link type to specific people (instead of anyone)
Set-SPOTenant -DefaultSharingLinkType Direct
Finding All Active Anyone Links and External Shares
Audit current external sharing activity across all sites:
# List all SharePoint sites with external sharing enabled
Get-SPOSite -Limit All | Where-Object {$_.SharingCapability -ne "Disabled"} |
Select-Object Url, SharingCapability, StorageUsageCurrent |
Sort-Object SharingCapability | Format-Table -AutoSize
# List all external users currently with access to any site
Get-SPOExternalUser -PageSize 50 -SiteUrl https://contoso.sharepoint.com/sites/project |
Select-Object DisplayName, Email, AcceptedAs, WhenCreated, ExpirationTime
# Find all sites with guest users
Get-SPOSite -Limit All -IncludePersonalSite $false | ForEach-Object {
$site = $_
$externals = Get-SPOExternalUser -SiteUrl $site.Url -PageSize 10 -ErrorAction SilentlyContinue
if ($externals) {
[PSCustomObject]@{
Site = $site.Url
ExternalUserCount = $externals.Count
OldestAccess = ($externals | Sort-Object WhenCreated | Select-Object -First 1).WhenCreated
}
}
} | Sort-Object ExternalUserCount -Descending
For anyone link discovery via the Unified Audit Log:
# Find anyone link creation events in the last 30 days
Connect-IPPSSession
$anyoneLinks = Search-UnifiedAuditLog -StartDate (Get-Date).AddDays(-30) -EndDate (Get-Date) `
-Operations "AnonymousLinkCreated","AnonymousLinkUpdated" `
-ResultSize 5000
$anyoneLinks | ForEach-Object {
$data = $_.AuditData | ConvertFrom-Json
[PSCustomObject]@{
Time = $_.CreationDate
User = $_.UserIds
File = $data.SourceFileName
Site = $data.SiteUrl
Expiry = $data.ExpirationTime
}
} | Export-Csv anyone-links-audit.csv -NoTypeInformation
Briefings like this, every morning before 9am.
Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.
Per-Site Sharing Restrictions and Allowlisted Domains
Individual SharePoint sites can be more restrictive than the tenant level (but not more permissive). For sites containing sensitive data, restrict sharing to internal users only or to a specific external domain allowlist:
# Restrict a specific site to internal users only
Set-SPOSite -Identity https://contoso.sharepoint.com/sites/finance `
-SharingCapability Disabled
# Restrict to specific domains only (for partner collaboration sites)
Set-SPOSite -Identity https://contoso.sharepoint.com/sites/partner-project `
-SharingCapability ExternalUserSharingOnly `
-SharingAllowedDomainList "partnercompany.com" `
-SharingDomainRestrictionMode AllowList
# Audit all sites with domain restrictions currently configured
Get-SPOSite -Limit All | Where-Object {$_.SharingDomainRestrictionMode -ne "None"} |
Select-Object Url, SharingCapability, SharingAllowedDomainList, SharingBlockedDomainList
For high-sensitivity site classes (HR, Legal, Finance, Board), apply a mandatory sharing restriction via sensitivity labels:
- Create a sensitivity label in Microsoft Purview compliance portal: Labels > Create a label
- Under 'Sites & Groups settings', set 'External sharing from SharePoint sites' to 'Only people in your organization'
- Apply the label to the site: Get-SPOSite > Set-SPOSite -SensitivityLabel "{label-GUID}"
Sensitivity-label-enforced restrictions cannot be overridden by site owners, providing stronger governance than site-level settings that owners can change.
Guest Lifecycle Management and Access Reviews
Guest user accounts in Entra ID persist indefinitely unless explicitly managed. Implement guest lifecycle controls:
# Find guest users who have not signed in for more than 90 days
Get-MgUser -Filter "userType eq 'Guest'" -All |
Where-Object { $_.SignInActivity.LastSignInDateTime -lt (Get-Date).AddDays(-90) -or
$_.SignInActivity.LastSignInDateTime -eq $null } |
Select-Object DisplayName, UserPrincipalName, CreatedDateTime, `
@{N='LastSignIn';E={$_.SignInActivity.LastSignInDateTime}} |
Sort-Object LastSignIn
For automated lifecycle management, configure Entra ID access reviews:
- Entra ID admin center > Identity Governance > Access reviews > New access review
- Review type: Teams + Groups (for M365 group and Teams guest access)
- Scope: Guest users only
- Reviewers: Group owners
- Frequency: Quarterly
- If reviewer does not respond: Remove access
- Apply results automatically: Yes
This creates a quarterly review where each site/team owner confirms or removes each guest. Guests whose access is not confirmed are automatically removed after the review period.
Teams External Access Versus Guest Access Configuration
Teams has two distinct external sharing mechanisms that administrators often conflate:
External access (federation): Allows Teams users to find, call, and message users in other Entra ID tenants and Skype consumer accounts. No shared channels, no file access. Configured at the Teams admin center org-wide level.
Guest access: Invites external users as guests into specific Teams, giving them access to channels, files, meetings, and apps in that Team. Configured both at Teams admin center org-wide level and per-Team by the team owner.
Audit current Teams guest access:
# Connect to Microsoft Teams PowerShell
Connect-MicrosoftTeams
# List all Teams with external/guest access enabled
Get-Team -NumberOfThreads 20 | Where-Object {$_.GuestSettings -eq 'True'} |
Select-Object DisplayName, Description, Visibility, GuestSettings
# List all guest members across all Teams
Get-Team | ForEach-Object {
Get-TeamUser -GroupId $_.GroupId | Where-Object {$_.Role -eq "Guest"} | ForEach-Object {
[PSCustomObject]@{
Team = $_.Team
GuestEmail = $_.User
Role = $_.Role
}
}
} | Export-Csv teams-guests.csv -NoTypeInformation
For Teams with no active collaboration (no messages in last 90 days), archive or delete the Team rather than allowing guests to retain access to potentially sensitive historical files.
The bottom line
M365 external sharing audit starts with the SharePoint tenant sharing setting, then per-site restrictions, then active external user and anyone link inventory. The highest-risk items to address first are anyone links with no expiration (set mandatory 14-day expiration), guest accounts not reviewed in 90+ days (implement quarterly Entra ID access reviews), and SharePoint sites with sensitive data that have tenant-default sharing enabled rather than explicitly restricted. Sensitivity labels provide the strongest governance because they enforce sharing restrictions that site owners cannot override.
Frequently asked questions
What is the difference between a guest user and an external user in M365?
In M365 terminology, a 'guest user' has an account in your Entra ID tenant with userType = Guest. They sign in with their own Microsoft account or a one-time passcode and appear in your Entra ID user list. An 'external user' who accesses content via an anyone link does not have an account in your tenant and is completely anonymous from a directory perspective. The risk profiles differ: guest users can be audited, reviewed, and have their access scoped via groups; anyone link users are invisible in your directory.
Can I prevent specific SharePoint site owners from enabling external sharing?
Yes, via two mechanisms. First, the tenant sharing setting acts as a ceiling -- if the tenant is set to 'Existing external users only', no site owner can enable anyone links regardless of their site settings. Second, sensitivity labels applied to sites enforce sharing restrictions that owners cannot change via the UI. For a programmatic approach, use a PowerShell scheduled task or Logic App that queries Get-SPOSite daily and resets any site with an overly permissive sharing setting back to the approved level.
How do I identify which files have been accessed by external users?
Query the SharePoint audit log in the Unified Audit Log for FileAccessed events filtered to external users. Run: `Search-UnifiedAuditLog -Operations FileAccessed -ResultSize 5000 | Where-Object {($_.AuditData | ConvertFrom-Json).UserType -eq 3}`. UserType 3 indicates an external or anonymous user. For SharePoint site-level access reporting, also use the SharePoint admin center > Active sites > [site] > Permissions > External users to see all guests and their last access date.
What happens to files in a Teams channel when a guest is removed from the Team?
When a guest is removed from a Team, they immediately lose access to all channel files stored in the Team's SharePoint site. Files they were shared with directly via OneDrive are not affected by Team membership changes -- those shares must be revoked separately. Any files the guest uploaded to the channel remain in SharePoint and are accessible to remaining team members. Run a file audit of the Team's SharePoint site after removing a guest to identify any files they may have uploaded that need review.
How do I prevent users from sharing SharePoint files with anyone who has the link (anonymous links)?
At the tenant level: in the SharePoint admin center under Policies > Sharing, set the tenant-level sharing to 'Existing guests' or 'Only people in your organization'. This removes the 'Anyone with the link' option from all sites unless individually overridden. To prevent site-level overrides, set the tenant restriction and then use a sensitivity label policy to enforce a lower sharing setting on labeled sites. For high-sensitivity sites that already exist, run: `Set-SPOSite -Identity https://tenant.sharepoint.com/sites/HR -SharingCapability ExternalUserSharingOnly` to set the maximum sharing to authenticated guests, blocking anonymous links for that specific site.
How do I run an access review to identify stale external guests in Microsoft 365?
Use Entra ID Access Reviews (requires P2 license) to create a recurring review for guest users across all Microsoft 365 groups or specific high-risk groups. Go to Entra ID > Identity Governance > Access reviews > New access review, select Teams + Groups as the scope, add all M365 groups with guests or specific groups, set reviewers to group owners, and configure the review frequency (quarterly is common for guest access). When the review runs, owners receive an email prompting them to confirm or deny each guest's continued access. At review completion, configure automatic remediation to remove access for guests whose access was denied or left unreviewed. For guest accounts that have been inactive beyond a threshold, use the Entra ID guest access review's inactivity filter or run: `Get-AzureADUser -Filter "UserType eq 'Guest'" | Where-Object {$_.SignInActivity.LastSignInDateTime -lt (Get-Date).AddDays(-90)}`.
Sources & references
Free resources
Critical CVE Reference Card 2025–2026
25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.
Ransomware Incident Response Playbook
Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.
Get threat intel before your inbox does.
50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.
Unsubscribe anytime. We never sell your data.

Founder & Cybersecurity Evangelist, Decryption Digest
Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.
Win a $2,495 Black Hat pass.
Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.
