๐ Recipe ยท SharePoint & OneDrive
Audit SharePoint Files with Public or Anonymous Sharing Links
Scan every SharePoint site and document library to identify files exposed via anonymous (public) sharing links and produce a remediation-ready report.
Complexity
Intermediate
Impact
security + compliance + data-governance + access-review
Context
Why This Matters
Anonymous sharing links in SharePoint (also called "Anyone" links) allow access to files without authentication โ anyone with the URL can view or edit the content. While convenient for external collaboration, these links are one of the most common sources of data leakage in Microsoft 365 tenants.
Run this audit when you need to:
- Respond to a compliance review (SOC 2, ISO 27001, HIPAA, GDPR)
- Investigate a suspected data exposure incident
- Perform a quarterly or post-acquisition data governance review
- Validate external sharing policy changes after tightening tenant-level settings
- Prepare for a tenant-to-tenant migration or M&A due diligence
The recipe walks every SharePoint site collection, enumerates each document library, inspects file-level sharing permissions, and flags items where the sharing scope is anonymous (and, optionally, organization for a broader posture review).
Expected Outcomes
What you'll have when you're done
- A complete inventory of files with anonymous (public internet) sharing links across all SharePoint sites
- A secondary list of files with organization-wide links (optional but recommended)
- A CSV report with site, file path, link type, permission scope, and direct URL โ suitable for import into a GRC tool or ticketing system
- Clear remediation targets: each flagged file can be revoked or re-shared with specific users
- A repeatable script you can schedule monthly to catch new exposures
Risks & Considerations
Warnings and gotchas
- Read-only audit: The audit itself does not change any permissions. Never auto-revoke sharing links without a review โ you may break legitimate external workflows (partners, contractors, customers).
- Throttling: Large tenants (hundreds of sites, millions of files) will hit Graph API throttling (HTTP 429). Honor
Retry-Afterheaders and paginate with@odata.nextLink. - Permission inspection is per-item: The
sharedproperty on adriveItemonly indicates that it is shared, not how. You must callGET /drives/{id}/items/{id}/permissionsto confirm a link is truly anonymous. - Nested folders:
/root/childrenonly returns top-level items. Use/root/search(q=' ')or recurse into folders to catch every file. - OneDrive is separate: This recipe targets SharePoint sites. OneDrive personal libraries require scanning user drives via
/users/{id}/drive. - Data handling: The output report contains file paths and URLs that may themselves be sensitive. Store it in a restricted location and delete after remediation.
- Don't confuse scopes:
anonymous= public internet;organization= anyone in the tenant with the link;users= specific named users. Onlyanonymousis a true public exposure.
Required Permissions
| Permission | Why It's Needed |
|---|---|
| Sites.Read.All | Enumerate all SharePoint sites and read site metadata |
| Files.Read.All | List drive items across all document libraries |
| Sites.FullControl.All | Required to read detailed sharing permissions on every item (Files.Read.All alone is insufficient for /permissions on some items) |
The fastest way to get this done: just ask Dex. Copy the prompt below and paste it into your Dex conversation.
For IT Admins
Paste into Dex Pro
Audit via the SharePoint Admin Center and Microsoft Purview
Microsoft provides two GUI-based paths. The Purview path is the most comprehensive; the SharePoint admin center is faster for a smaller tenant.
Option A โ SharePoint Admin Center (per-site review)
- Sign in to the SharePoint admin center at
https://<tenant>-admin.sharepoint.comas a Global Admin or SharePoint Admin. - Navigate to .
- For each site, click the site name, then open to confirm the site allows Anyone links. If disabled, the site cannot have public links.
- Open the site itself in a new tab. For each document library, select .
- Click Manage access requests or use Advanced โ Check Permissions on individual files. Files with an "Anyone" link will show a sharing link entry with no grantee.
Option B โ Microsoft Purview Content Search (tenant-wide)
- Open Microsoft Purview at
https://purview.microsoft.com. - Go to (or depending on your license).
- Click + New search. Give it a name like
Public SharePoint Files Audit. - Under Locations, choose SharePoint sites โ All.
- In the query box, enter KQL:
SharedWithUsersOWSUser:"Everyone" OR ViewableByExternalUsers:true OR IsAnonymousAccess:true. - Run the search and wait for it to complete.
- Click Export results โ Reports only to download a CSV of matching items.
Option C โ SharePoint Sharing Report (built-in, per-site)
- Open any SharePoint site as a site owner.
- Go to .
- Scroll to Shared with external users and click Run sharing report.
- Choose a target library to save the CSV into and click Run report. The CSV lists every externally shared item, including anonymous links.
- Repeat for each site โ this is why the API/script approach is recommended for tenants with more than ~10 sites.
Audit via Microsoft Graph API
There is no single endpoint that returns "all publicly shared files tenant-wide." You must walk the hierarchy: sites โ drives โ items โ permissions, and filter on link.scope == 'anonymous'.
Step 1 โ List all SharePoint sites
GET https://graph.microsoft.com/v1.0/sites?search=*&$select=id,displayName,webUrl&$top=999
Authorization: Bearer <token>Paginate with @odata.nextLink until exhausted.
Step 2 โ List document libraries (drives) for each site
GET https://graph.microsoft.com/v1.0/sites/{site-id}/drives?$select=id,nameStep 3 โ Enumerate all files in each drive (including subfolders)
Use the search endpoint with an empty-ish query to return every item:
GET https://graph.microsoft.com/v1.0/drives/{drive-id}/root/search(q=' ')?$select=id,name,webUrl,shared,file,parentReference&$top=200Items with a shared property are candidates. But shared.scope on the driveItem can be anonymous, organization, or users โ or absent even when an anonymous link exists โ so you must verify via /permissions.
Step 4 โ Inspect sharing permissions on each candidate item
GET https://graph.microsoft.com/v1.0/drives/{drive-id}/items/{item-id}/permissionsExample response fragment for an anonymous link:
{
"id": "aTowIy5mfG1lbWJlcnNoaXB...",
"roles": ["read"],
"link": {
"scope": "anonymous",
"type": "view",
"webUrl": "https://tenant.sharepoint.com/:b:/s/Site/Ab12...",
"preventsDownload": false
}
}Any permission object where link.scope == "anonymous" is a public sharing link and should be included in the report.
Step 5 โ (Optional) Remove an anonymous link
Once reviewed:
DELETE https://graph.microsoft.com/v1.0/drives/{drive-id}/items/{item-id}/permissions/{permission-id}Rate limits
Graph throttles at roughly 10,000 requests per 10 minutes per app per tenant. For large tenants, batch with $batch (up to 20 requests) and respect Retry-After on 429 responses.
PowerShell with Microsoft Graph SDK
The script below uses the Microsoft.Graph PowerShell module to run the complete audit and emit a CSV report. It handles pagination, throttling, and folder recursion.
Prerequisites
- PowerShell 7+ recommended (works on 5.1 with minor tweaks)
- Install the Graph SDK:
Install-Module Microsoft.Graph -Scope CurrentUser - Connect with the required scopes (see permissions table above)
How it works
Connect-MgGraphauthenticates with delegated or app-only credentials.Get-MgSite -Search '*'enumerates every SharePoint site.- For each site,
Get-MgSiteDrivelists document libraries. - For each drive, the script calls the
search(q=' ')endpoint directly to recurse every item. - For every item with a
sharedhint, it pulls/permissionsand keeps only those wherelink.scope == 'anonymous'. - Results are written to a timestamped CSV.
Running the script
# Audit only anonymous links (default)
.\Audit-SharePointPublicFiles.ps1 -OutputPath .\public-files-audit.csv
# Include organization-wide links for a broader review
.\Audit-SharePointPublicFiles.ps1 -IncludeOrganizationScope -OutputPath .\all-shared.csv
# Target a single site for faster runs during testing
.\Audit-SharePointPublicFiles.ps1 -SiteFilter 'Finance' -OutputPath .\finance-audit.csvOn completion, the script prints a summary (sites scanned, files checked, public links found) and writes the CSV to the path specified.
Next steps