When managing Windows file permissions through scripts, many administrators encounter a frustrating limitation with ICACLS: the command doesn't recursively remove user permissions from subfolders when using the basic /remove parameter. The current implementation only removes the specified permission from the top-level directory while leaving inherited permissions intact in child items.
Windows NTFS permissions operate on an inheritance model where child objects (files and subfolders) automatically inherit permissions from their parent container. When we run:
ICACLS "E:\\Home Directories\\%userDir%" /remove "MYDOMAIN\\%username%"
This only affects the explicit ACE (Access Control Entry) at the root level. Any inherited permissions from parent folders or previously set permissions on child items remain unchanged.
To achieve true recursive permission removal, we need to combine several ICACLS parameters:
ICACLS "E:\\Home Directories\\%userDir%" /remove:d "MYDOMAIN\\%username%" /T /C /Q
Let's break down these parameters:
- /T: Traverse all subfolders
- /remove:d: Remove all occurrences of the specified user (both explicit and inherited)
- /C: Continue operation despite any file errors
- /Q: Quiet mode (suppress success messages)
Here's an enhanced version of the original script that properly handles recursive permission removal:
@echo off
set /p userDir=Enter the login of the user's directory you're modifying permissions for. (i.e. jDoe)
:: Take ownership recursively
TAKEOWN /f "E:\Home Directories\%userDir%" /r /d y
:: Reset all permissions to inherited defaults
ICACLS "E:\Home Directories\%userDir%" /reset /T /C /Q
:: Apply new permissions
ICACLS "E:\Home Directories\%userDir%" /grant:r "MYDOMAIN\%userDir%":(OI)(CI)F /grant:r "SYSTEM":(OI)(CI)F /T /C /Q
:: Break inheritance while copying existing permissions
ICACLS "E:\Home Directories\%userDir%" /inheritance:r /T /C /Q
:: Set proper ownership recursively
ICACLS "E:\Home Directories\%userDir%" /setowner "MYDOMAIN\%userDir%" /T /C /Q
:: Remove admin permissions recursively from all files and subfolders
ICACLS "E:\Home Directories\%userDir%" /remove:d "MYDOMAIN\%username%" /T /C /Q
For more complex permission scenarios, PowerShell provides better control:
$userDir = Read-Host "Enter user directory name"
$path = "E:\Home Directories\$userDir"
$user = "MYDOMAIN\$userDir"
$admin = "MYDOMAIN\$env:USERNAME"
Takeown /f $path /r /d y
icacls $path /reset /T /C /Q
# Remove all ACLs including inherited ones
Get-ChildItem $path -Recurse | ForEach-Object {
$acl = Get-Acl $_.FullName
$acl.SetAccessRuleProtection($true, $false)
$acl.Access | Where-Object {$_.IdentityReference -eq $admin} | ForEach-Object {
$acl.RemoveAccessRule($_) | Out-Null
}
Set-Acl $_.FullName $acl
}
# Apply new permissions
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule($user, "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")
Get-ChildItem $path -Recurse | ForEach-Object {
$acl = Get-Acl $_.FullName
$acl.AddAccessRule($rule)
Set-Acl $_.FullName $acl
}
- Always test permission changes in a non-production environment first
- Consider using the /save and /restore parameters to backup ACLs before making changes
- For very large directories, the operation may take significant time to complete
- The /C (continue) parameter may mask important permission errors - review carefully
When managing Windows file permissions at scale, many administrators encounter this exact scenario: You need to completely remove a specific user's access from an entire directory tree, including all nested files and subfolders. The standard ICACLS command appears to only remove permissions from the top-level directory while leaving inherited permissions intact in child items.
ICACLS "E:\Home Directories\jDoe" /remove "MYDOMAIN\adminUser"
This command only removes the explicit ACE (Access Control Entry) at the root level. Any permissions inherited from parent folders or explicitly set on child items remain untouched. This creates a security risk where users retain access through inheritance.
To achieve true recursive permission removal, we need to combine several ICACLS operations with proper inheritance handling:
:: Take ownership first (required for permission changes)
TAKEOWN /f "E:\Home Directories\%userDir%" /r /d y
:: Reset all permissions completely
ICACLS "E:\Home Directories\%userDir%" /reset /T
:: Set new permissions (including required SYSTEM access)
ICACLS "E:\Home Directories\%userDir%" /grant:r "MYDOMAIN\%userDir%":(OI)(CI)F /grant:r "SYSTEM":(OI)(CI)F
:: Disable inheritance and copy existing permissions
ICACLS "E:\Home Directories\%userDir%" /inheritance:d
:: Remove the admin user from ALL files and folders
ICACLS "E:\Home Directories\%userDir%" /remove:g "MYDOMAIN\%username%" /T
:: Restore original owner
ICACLS "E:\Home Directories\%userDir%" /setowner "MYDOMAIN\%userDir%" /T
The critical changes from the original approach are:
- Using
/remove:g
instead of just/remove
to ensure recursive processing - Applying the
/T
flag to operate through all subfolders - Disabling inheritance before permission removal
For those preferring PowerShell, here's an equivalent solution:
$path = "E:\Home Directories\jDoe"
$userToRemove = "MYDOMAIN\adminUser"
# Reset permissions recursively
Get-ChildItem $path -Recurse | ForEach-Object {
$acl = Get-Acl $_.FullName
$acl.SetAccessRuleProtection($true, $false)
$accessRules = $acl.Access | Where-Object { $_.IdentityReference -ne $userToRemove }
$acl.SetAccessRule($accessRules)
Set-Acl $_.FullName $acl
}