SharePoint Online: Delete Unique Permissions for All Items in a List using PowerShell

Requirement: Reset all customized permissions in all documents of a SharePoint Online document library.

By default, Permissions are inherited from their parents in all levels of SharePoint. E.g., Subsites inherit permissions from their parent site collection (or parent site), lists and libraries inherit permissions from the site, and items in the list inherit permissions from the list. So, If you make any change in permissions at the parent level, any child underneath automatically inherits the permission changes you made in the parent unless the child is using its own unique permissions.

At times, you may have to set up unique permissions at a granular level, and of course, you may have to reset the broken permissions as well.

How to Delete Unique Permissions in SharePoint?

To reset custom permissions on SharePoint list items or documents, follow these steps:

  1. Navigate to the SharePoint library in the web browser, where your documents are stored.
  2. Right-click on the document and choose “Manage Access” from the menu.Reset Unique Permissions for All files in a Document Library
  3. Click on the “Advanced” link at the bottom of the “Manage Access” Pane >> and click on the “Delete Unique Permissions” button from the ribbon. Confirm the prompt once!
    delete unique permissions in sharepoint online using powershell

Alright, now the permissions are set to Inherited from the parent library of the document. But wait, picking every individual document and repeating these steps to remove unique permissions is tedious, wouldn’t you agree? So, I wrote this PowerShell script to Reset Broken Inheritance on all items in a SharePoint List.

How do I get rid of limited access in SharePoint online?
Limited Access means the user has access to an underlying object. E.g. If you provide unique permission to a document, at the document library level, the specific user will have “Limited Access”. It provides the user limited permission to get to the item he has access. If you want to remove the limited access, you need to remove the unique permission on the items the user has access.

PowerShell to Remove Unique Permissions from a SharePoint Online List Item:

You need SharePoint Online Client SDK installed on your client machine to use this code: https://www.microsoft.com/en-us/download/details.aspx?id=42038. Here is how to remove all unique permissions in the SharePoint Online list item

#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"

#Function to remove unique permissions and inherit from the parent
Function Remove-ListItemUniquePermissions
{
param
    (
        [Parameter(Mandatory=$true)] [string] $SiteURL,
        [Parameter(Mandatory=$true)] [string] $ListName,
        [Parameter(Mandatory=$true)] [string] $ItemID        
    )

    Try {
        $Cred= Get-Credential
        $Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)

        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
        $Ctx.Credentials = $Credentials

        #Remove unique permissions and reset inheritance
        $List=$Ctx.Web.Lists.GetByTitle($ListName)
        $ListItem=$List.GetItemByID($ItemID)
        $ListItem.ResetRoleInheritance()
        $Ctx.ExecuteQuery()

        Write-Host -f green "Unique Permissions are removed and inherited from the Parent!"
    }

    Catch {
        write-host -f Red "Error Deleting Unique Permissions!" $_.Exception.Message
    } 
}

#Parameters
$SiteURL="https://crescent.sharepoint.com"
$ListName="Projects"
$ItemID="25"

#Call the function to remove unique permissions from a list
Remove-ListItemUniquePermissions -SiteURL $SiteURL -ListName $ListName -ItemID $ItemID 

PowerShell Script to Delete Unique Permissions for All List Items in SharePoint Online

Here is the SharePoint Online PowerShell to reset unique permissions:

#Load SharePoint Online Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
  
##Variables for Processing
$SiteUrl = "https://crescent.sharepoint.com/sites/Sales/"
$ListName= "Documents"
$UserName= "Salaudeen@crescent.com"
$Password ="Password goes here"
 
#Setup Credentials to connect
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName,(ConvertTo-SecureString $Password -AsPlainText -Force))
 
#Set up the context
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteUrl) 
$Context.Credentials = $credentials
  
#Get the List
$List = $Context.web.Lists.GetByTitle($ListName)
 
#Get All List Items
$Query = New-Object Microsoft.SharePoint.Client.CamlQuery
$ListItems = $List.GetItems($Query)
$Context.Load($ListItems)
$Context.ExecuteQuery()

Write-host "Total Items Found:"$ListItems.Count
#Iterate through each list item
 $ListItems |  foreach {
    #Delete Unique Permission
    $_.ResetRoleInheritance()
 }
$Context.ExecuteQuery()

Write-host "Broken Permissions are Deleted on All Items!" -ForegroundColor Green

We can make two improvements to the above script:

  1. The above script doesn’t handle large lists with > 5000 items. 
  2. The above script simply resets inheritance without checking if the list item has unique permissions.

So, let us resolve the above issues, and here is the updated script:

Delete Unique Permissions in SharePoint Online using PowerShell

Here is the PowerShell to reset unique permissions in large lists or document libraries (with more than 5000 items!)

#Load SharePoint Online Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"

##Variables for Processing
$SiteUrl = "https://crescent.sharepoint.com"
$ListName= "Documents"
  
#Get Credentials to connect
$Cred= Get-Credential
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)
  
#Set up the context
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteUrl) 
$Context.Credentials = $Credentials
   
#Get the List
$List = $Context.web.Lists.GetByTitle($ListName)

$Query = New-Object Microsoft.SharePoint.Client.CamlQuery
$Query.ViewXml = "<View Scope='RecursiveAll'><RowLimit>2000</RowLimit></View>"

#Batch process list items - to mitigate list threshold issue on larger lists
Do {  
    #Get items from the list in batches
    $ListItems = $List.GetItems($Query)
    $Context.Load($ListItems)
    $Context.ExecuteQuery()
          
    $Query.ListItemCollectionPosition = $ListItems.ListItemCollectionPosition
 
    #Loop through each List item
    ForEach($ListItem in $ListItems)
    {
        $ListItem.Retrieve("HasUniqueRoleAssignments")
        $Context.ExecuteQuery()
        if ($ListItem.HasUniqueRoleAssignments -eq $true)
        {
            #Reset Permission Inheritance
            $ListItem.ResetRoleInheritance()
            Write-host  -ForegroundColor Yellow "Inheritence Restored on Item:" $ListItem.ID
        }
    }
    $Context.ExecuteQuery()
} While ($Query.ListItemCollectionPosition -ne $null)
 
Write-host "Broken Permissions are Deleted on All Items!" -ForegroundColor Green

PnP PowerShell to Remove Unique Permissions from all Items in a List

To reset permissions on a list item, we can use the Set-PnPListItemPermission cmdlet with the “InheritPermissions” switch.

#Set Variables
$SiteURL = "https://crescent.sharepoint.com/sites/Marketing"
$ListName = "Documents"
 
#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Credentials (Get-Credential)

#Get all list items in batches
$ListItems = Get-PnPListItem -List $ListName -PageSize 500

#Iterate through each list item
ForEach($ListItem in $ListItems)
{
    #Check if the Item has unique permissions
    $HasUniquePermissions = Get-PnPProperty -ClientObject $ListItem -Property "HasUniqueRoleAssignments"
    If($HasUniquePermissions)
    {        
        $Msg = "Deleting Unique Permissions on {0} '{1}' at {2} " -f $ListItem.FileSystemObjectType,$ListItem.FieldValues["FileLeafRef"],$ListItem.FieldValues["FileRef"]
        Write-host $Msg
        #Delete unique permissions on the list item
        Set-PnPListItemPermission -List $ListName -Identity $ListItem.ID -InheritPermissions 
    }
}

Reset Unique Permissions for All files in a Folder using PnP PowerShell

This time, let’s use PnP PowerShell to reset unique permissions on all files stored in a SharePoint Online Folder:

#Parameters
$SiteURL = "https://crescent.sharepoint.com/sites/Marketing"
$FolderServerRelativeURL = "/sites/Marketing/Branding/2018"

#Connect to the site
Connect-PnPOnline -Url $SiteURL -Interactive

#Get the Folder from given URL
$Folder = Get-PnPFolder -Url $FolderServerRelativeURL -Includes ListItemAllFields.ParentList
$ParentList = $Folder.ListItemAllFields.ParentList.Title

#Get All Files from the Folder
$Files = Get-PnPListItem -List $ParentList -FolderServerRelativeUrl $Folder.ServerRelativeUrl | Where {$_.FileSystemObjectType -eq "File"}

#Traverse through each file in the folder
ForEach ($File in $Files)
{
    #Check If File has Unique Permissions
    $HasUniquePermissions = Get-PnPProperty -ClientObject $File -Property HasUniqueRoleAssignments
    If($HasUniquePermissions)
    {
        #Reset Broken Inheritance
        $File.ResetRoleInheritance()
        $File.update()
        Invoke-PnPQuery
        Write-Host "Reset Unique Permissions on File $($File.FieldValues["FileRef"])" -ForegroundColor Green
    }
}

Similarly, you can reset unique permissions in SharePoint Online sites, lists, and folders with PowerShell as:

Conclusion

In summary, unique permissions can quickly accumulate in SharePoint sites, lists, and items over time. This leads to permission management headaches and complex webs of access that are difficult to untangle. Deleting unique permissions and restoring inherited roles simplifies the permissions structure and makes managing content easier. Once you confirm which unique permissions to remove, choose the best deletion method. The interface works well for individual sites, lists or items. PowerShell automation helps mass delete unique roles across all site content and restore inheritance in one sweep.

Salaudeen Rajack

Salaudeen Rajack - Information Technology Expert with Two-decades of hands-on experience, specializing in SharePoint, PowerShell, Microsoft 365, and related products. He has held various positions including SharePoint Architect, Administrator, Developer and consultant, has helped many organizations to implement and optimize SharePoint solutions. Known for his deep technical expertise, He's passionate about sharing the knowledge and insights to help others, through the real-world articles!

34 thoughts on “SharePoint Online: Delete Unique Permissions for All Items in a List using PowerShell

  • Quick update: you do not need to call Update() after ResetRoleInheritance(). It messes with the Modified Timestamp

    https://learn.microsoft.com/en-us/answers/questions/136741/do-i-need-to-issue-listitem-update()-when-i-am-exe

    Reply
  • Hey Salaudeen, I frequent your site for SP related PS scripts. I was looking for a way to reset inheritance across an entire library with PNP (all folders, subfolders, files) and I couldn’t find that you had something to do this.

    I used a couple of your examples (this post, along with another post where you describe resetting inheritance of all subfolders) to create a single simple script that does it all. I thought you might find it handy to update your post. It’s 90% your work anyways 🙂

    (note, I know it’s probably not optimized, but using the -recursive option and other stuff like that often fails with larger sets of data, so while this method is slower it usually doesn’t choke on too much data)

    #Set Variables
    $SiteURL = "https://crescent.sharepoint.com/sites/Marketing"
    $FolderURL = "/Shared Documents" #Document Library Site Relative URL
     
    #Connect to PnP Online
    Connect-PnPOnline -Url $SiteURL -Interactive  #-Credentials (Get-Credential)
     
    #Function to reset permissions of all Sub-Folders
    Function Reset-SubFolderPermissions($FolderURL)
    {
        #Get all files from the parent folder as folder items
        $Files = Get-PnPFolderItem -FolderSiteRelativeUrl $FolderURL -ItemType File
    
        #Loop through each file in the folder
        ForEach($File in $Files)
        {
            #Retrieve the file as a list item as we cannot use Get-PnPProperty on a folder item
            $FileURL = $FolderURL+"/"+$File.Name
            $FileItem = Get-PnPFile $FileURL -AsListItem
            
            #Check if the file has unique permissions
            $HasUniquePermissions = Get-PnPProperty -ClientObject $FileItem -Property HasUniqueRoleAssignments
            If($HasUniquePermissions)
            {
                #Reset inheritance
                $FileItem.ResetRoleInheritance()
                $FileItem.update()
                Invoke-PnPQuery
                Write-Host "Reset unique permissions on file $($FileItem.FieldValues["FileRef"])"
            }
        }
        
        #Get all sub-folders of the Folder - Exclude system folders
        $SubFolders = Get-PnPFolderItem -FolderSiteRelativeUrl $FolderURL -ItemType Folder | Where {$_.Name -ne "Forms" -and $_.Name -ne "Document"}
     
        #Loop through each sub-folder
        ForEach($SubFolder in $SubFolders)
        {
            $SubFolderURL = $FolderUrl+"/"+$SubFolder.Name
            Write-host -ForegroundColor Green "Processing Folder '$($SubFolder.Name)' at $SubFolderURL"
     
            #Get the Folder Object - with HasUniqueAssignments and ParentList properties
            $Folder = Get-PnPFolder -Url $SubFolderURL -Includes ListItemAllFields.HasUniqueRoleAssignments, ListItemAllFields.ParentList, ListItemAllFields.ID
     
            #Get the List Item of the Folder
            $FolderItem = $Folder.ListItemAllFields
     
            #Check if the Folder has unique permissions
            If($FolderItem.HasUniqueRoleAssignments)
            {
                #Reset permission inheritance
                Set-PnPListItemPermission -List $FolderItem.ParentList -Identity $FolderItem.ID -InheritPermissions
                Write-host "`tUnique Permissions are removed from the Folder!"
            }
     
            #Call the function recursively
            Reset-SubFolderPermissions $SubFolderURL
        }
    }
       
    #Call the function
    Reset-SubFolderPermissions $FolderURL
    
    Reply
    • Matthew,

      I found your script very helpful in for addressing permissions in sites with hundreds of thousands of objects.

      I modified it slightly to provide additional user feedback, but otthwise used it as is to one with with 400k of objects and another with over 500k of objects,

      Can I ask if there is way to also check for sharing links and to remove them whilst resetting the file/folder permissions?

      Les

      Reply
    • I tried this but after running if I go into any folder I get “The specified list is invalid
      The specified list might have been deleted or you might not have permission to view it. Contact the site owner for more information”

      Reply
    • Thank you Matthew!
      The File.ResetRoleInheritance() method didn’t work, but yours did.
      It’s indeed very slow, but as long as it get’s the job done I’m happy!

      Reply
  • @Salaudeen Rajack,
    Great script if runs though…
    Getting Exception calling “ExecuteQuery” with “0” argument(s): “The remote server returned an error: (429).”

    Any idea how to fix this issue? Thanks!

    Reply
  • I ran this successfully against a Library, but the top level library itself still has unique permissions from the site. Am I missing something here? Thanks for all your work!

    Reply
  • Note that this is much easier than listed. You can just use the switch “-interactive” instead of -credential.

    Reply
  • any updates on this?

    Reply
  • Do you have a script for on prem?

    Reply
  • sooo… is there a way to use the “Delete Unique Permissions in SharePoint Online using PowerShell” script with MFA enbalded account?

    Reply
  • Thank you, thank you, thank you! You made fixing a serious issue into a 20 minute job.

    Reply
  • Getting Exception calling “ExecuteQuery” with “0” argument(s): “The remote server returned an error: (429).” Assume its do do with the number of requests?

    Reply
  • for “PnP PowerShell to Remove Unique Permissions from all Items in a List” worked great. I added a few tweaks, progress and counters because the first time I ran it, the library had almost 8k item and I Could not tell it was running. also added the $credential = Import-CliXml -Path so no need to login. great job

    Reply
  • This is an excellent solution and worked very well. As another user mentioned, it is especially useful when using Sharegate or other migration tool to migrate files where the NTFS file permissions are preserved. Thank you very much for sharing, you prob saved me days really dumb work.

    Reply
  • This script worked perfectly! We migrated 100k files from onsite to SharePoint using the migration tool and kept unique permissions. It took awhile but it removed all unique permissions and enabled inheritance again. Thank you!

    Reply
  • Hi, thank you very much for the script, works well.
    Can this script be modified so that it goes through all document libraries and deletes all unique permissions (i have less than 5000 items within the site bit have 43 libraries which have inherited permissions during migration from file servers)? Thank you in advance

    Reply
  • Thank you for the scripts.
    I kept getting the message: The sign-in name or password does not match one in the Microsoft account system
    Turns out I had to use an account that did not have MFA enabled.

    Reply
    • is there a way to adjust the get-credential to support MFA?

      Reply
    • If MFA is enabled, You can’t hard-code credentials! You can use App Passwords, however.

      Reply
  • Is there a way to change the Listname into a subfolder name? So I can process just a part of my list.

    Reply
  • Found an issue with the script. Line 41 needs to come out of the DO loop. Otherwise it will just keep iterating over the same items over and over, and won’t go inside any folders properly. If you bring 41 out of the DO loop it then iterates recursively like it is supposed to. Great script!

    Reply
    • Seriously? The “Do” loop executes for the first time, gets 2000 list items and the “while” part takes care of next execution or exit from the loop.

      Reply
  • Would this work for the sharepoint sites behind Microsoft teams?

    Reply
  • Great code, it worked a treat! I did strike an issue where SP Online has an unchangeable list view limit of 5000. To get around this I replace the CAML row limit with a query on the Item Id as per below

    5000

    to

    600010000

    Reply
    • Could you expand on this a little more?
      Thanks!

      Reply
  • This was very usable. I noticed when running the code on a library with more than 1000 items that I got an error message complaining about not enough resources in SPO to complete the request. I changed the foreach to the following:
    # Start with 100 items
    $Counter = 100

    #Iterate through each list item
    $ListItems | foreach {
    if ($Counter > 0) {
    #Delete Unique Permission
    $_.ResetRoleInheritance()
    $Counter = $Counter – 1
    }
    else {
    $_.ResetRoleInheritance()
    $Context.ExecuteQuery()
    $Counter = 100
    }
    }
    $Context.ExecuteQuery()

    This way the changes are made on every 100 items and then for the last items at the end. I’ve used it on three different libraries without errors.

    Reply

Leave a Reply

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