Share via

icacls command line refuses to remove ACLs

Rob Stevens 5 Reputation points
2026-03-18T16:20:27.6333333+00:00

I have many files which seem to have ACLs containing old, unknown SIDs.
They look like this:

S-1-5-21-xxxxxxxx-yyyyyyyy-zzzzzzzz-513:(RX)
xxxxxxxx-yyyyyyyy-zzzzzzzz is the identifier of some unknown machine, and is an orphan
due probably to some old ancient upgrade of the computer

I want to remove all these since that SID belongs to an unknown user. Icacls should, according to its documentation, be able to do this. But it does not work. I try it on just a regular file, say x.txt:

 **icacls x.txt /remove S-1-5-21-xxxxxxxx-yyyyyyyy-zzzzzzzz-513:(RX)**

and it reports: "Successfully processed 0 files.." and indeed when I look, I find that nothing changed.

The graphical interface, accessed by the Properties of x.txt, is able to delete this ACL without trouble.

I am running windows11 professional latest build 24H2, all patches installed.

Why is icacls not working? It will take me forever to delete these ACLs by hand

Sysinternals
Sysinternals

Advanced system utilities to manage, troubleshoot, and diagnose Windows and Linux systems and applications.


2 answers

Sort by: Most helpful
  1. MotoX80 37,676 Reputation points
    2026-03-21T00:14:57.59+00:00

    Based on the dates in this question, it would appear that icacls has never worked with dead sids.

    https://serverfault.com/questions/165531/remove-sid-with-icacls

    Years ago I used Microsoft's Subinacl.exe to clean up sids. For some reason they have killed that utility.

    I do have some scripts that might help you. The first I named FindUnInheritedPerms.ps1. It examines a directory and it's subfolders and looks for folders/files that do not inherit permissions from their parent folder. That can help you identify where there are permission differences.

    FindUnInheritedPerms.ps1 -target c:\temp -all $true
    

    See https://learn.microsoft.com/en-us/answers/questions/1118931/powershell-on-modifying-permissions

    With Subinacl no longer available to download, I wrote a ReplaceAcl.ps1 script to search for uninherited ACL's and and replace one account with another. To just remove an ACL, like you want to do, you simply don't provide a -grant switch with a second account.

    I strongly recommend that you test this on a small folder structure to verify that it sets permissions as desired. Especially if you are dealing with cygwin.

    Use the -whatif switch during your first test.

    ReplaceAcl.ps1 -Path c:\temp -Remove S-1-5-21-142060798-3261728243-3662720503-1012 -whatif
    

    Here is the script. I wrote it a while ago, so I highly recommend testing it on a subset of your data files.

    <#
    
    .SYNOPSIS
    Microsoft has decommisioned the Subinacl tool. 
    Ths script replaces one group/user with another on a given folder structure (or just removes the ACL).   
    
    .DESCRIPTION
    Find files/folder where admins/owners have been tweaking security permissions. 
    
    Whatever permissions the -Remove account has will be copied for the -Grant account. 
     
    
    This script accepts these parameters.
    -path      The path to the folder to be analyzed.
    -remove    The account to look for.  
    -depth     How many subfolders to analyze (To reduce the run time on file systems with thousands of folders.) 
    -grant     Replace the Remove account with the Grant account. 
    -whatif    Do not perform the update, add the whatif switch to see which folders would be updated
    
    .EXAMPLE
    
    ./ReplaceAcl.ps1 -path c:\temp -remove everyone 
    
    ./ReplaceAcl.ps1 -path c:\temp -remove everyone -grant "authenticated users"
    
    ./ReplaceAcl.ps1 -path c:\temp -remove everyone -depth 5 -verbose -whatif 
    
    
    .NOTES
    
    Author: MotoX80 on Microsoft Q&A Forums 
    Version: 2024-07-26
    #>
    
    param (
        [string]$Path = '',                            # analyze this folder
        [string]$Remove = '',                          # the account to remove. 
        [string]$Grant = '',                           # the account to add (can be blank to remove 
        [string]$Depth = '9999999',                     # folder depth to analyze (not yet implemented)  
        [switch]$Verbose,                                  # Show what we are doing  
        [switch]$Whatif                                  # Don't do the update  
    
     )
    
    if ($path -eq '') {
        "Please specify a path to a folder to analyze."
        return 
    }
    
    if ($Remove -eq '') {
        "Please specify an account to look for."
        return 
    }
    
    
    if ($Grant -eq '') {
        "The account $remove will be removed. "
    }
    if ($verbose) { 
    	$VerbosePreference = "continue"
    }
    
    $AllDirs = @()                                                   # Empty array    
    $AllDirs += Get-Item -Path $Path                                 # Add the root directory 
    $AllDirs += Get-Childitem  -Path $Path -recurse -depth $depth      # Add in all of the subfolders and files, use -Depth switch to limit how deep we analyze 
    
                                                                     # if you have hundreds of subfolders
    write-verbose "Verbose mode."			
    
    Foreach ($dir in $AllDirs) {
        write-verbose $dir.fullname                                                # Comment out to reduce output 
        $acl = get-acl $dir.FullName  
        $OldAces = $acl.Access                                       # Who has access?
        $UpdateAcl = $false                                          # Default to not update 
        foreach ($OldAce in $OldAces) {
                if ($OldAce.IsInherited -eq $FALSE) {                # There is no need to touch inherited aces 
    				"  Found uninherited ACE: {0} " -f $OldAce.IdentityReference | write-verbose 
                    if ($OldAce.IdentityReference -match $Remove) {         # Did we find the guy we're looking for? 
                        write-verbose "  It's a match."     
                        if ($grant -ne "") {
    						# Create new rule with the old rights 
    						$ArgList = $Grant, $OldAce.fileSystemRights, $OldAce.InheritanceFlags, $OldAce.PropagationFlags, $OldAce.AccessControlType
    						$NewAce = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $ArgList
    							   
    						# Remove old rule, add in new one                
    						$Acl.SetAccessRule($NewAce)
    						write-verbose "  Added $grant"
    					}
    					$Acl.RemoveAccessRule($OldAce) | Out-Null
                        $UpdateAcl = $true                              # Set flag to do the update 
                    }
                }
         }
    
         if ($UpdateAcl) {
            "   *** Update ***   {0}" -f $dir.FullName
    		if ($whatif) {
    			Set-Acl  $dir.FullName $acl   -WhatIf                  # Update the permissions 
    		} else {
    			Set-Acl  $dir.FullName $acl                        # Update the permissions
    		}
         }
    }
    
    
    

  2. Q&A Assist
    2026-03-18T16:22:32.5366667+00:00
    AI generated content. This question contains an answer created with AI from Q&A Assist. Learn more

    icacls is not removing the ACEs because the /remove parameter is being used with an invalid syntax.

    The string

    S-1-5-21-xxxxxxxx-yyyyyyyy-zzzzzzzz-513:(RX)
    

    is the display format that icacls uses when showing an ACE. The part :(RX) is not accepted as part of the SID when using /remove.

    Per the documented syntax, /remove only accepts a SID (optionally scoped to granted or denied ACEs), not a SID plus permissions:

    • /remove <sid> – remove all ACEs (grant and deny) for that SID
    • /remove:g <sid> – remove only granted ACEs for that SID
    • /remove:d <sid> – remove only denied ACEs for that SID

    So this command:

    icacls x.txt /remove S-1-5-21-xxxxxxxx-yyyyyyyy-zzzzzzzz-513:(RX)
    

    matches no ACEs, which is why icacls reports:

    Successfully processed 0 files
    

    Use the SID alone instead:

    icacls x.txt /remove S-1-5-21-xxxxxxxx-yyyyyyyy-zzzzzzzz-513
    

    If the ACE is a grant ACE and you want to be explicit:

    icacls x.txt /remove:g S-1-5-21-xxxxxxxx-yyyyyyyy-zzzzzzzz-513
    

    To clean up the orphaned SID recursively under a folder:

    icacls C:\path\to\root /t /c /remove S-1-5-21-xxxxxxxx-yyyyyyyy-zzzzzzzz-513
    
    • /t processes all files and subfolders
    • /c continues on errors

    The graphical ACL editor works because it manipulates the ACE objects directly and does not require the textual :(RX) portion; icacls requires only the SID token for removal.


    References:

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.