Fixing "This access control list is not in canonical form" errors from the command line
I was finally able to figure an automated fix for this. When you call PowerShell's Set-Acl
cmdlet, it will re-order the ACLs correctly:
$path = C:\Path\To\Item\With\Borked\ACL
$acl = Get-Acl $path
Set-Acl $path $acl
Of course, it could be a parent of the directory that is messed up, so you should do some traversing to find the culprit. Use icacls C:\Path\To\Item\With\Suspect\CL /verify
to figure out if something needs repair.
In our environment, Cygwin is the likely culprit: when it creates directories, it likes to give POSIX-style permissions on them, instead of relying on Windows to manage file system security.
You could try to use a simple PowerShell script to override the currupt files acl with the acl of another file: get-acl path_to_file_with_known_good_acl | set-acl -path path_to_corrupt_file
For me there was double trouble: non-canonical ACL + erroneous rule declared for NULL SID (WTH?). I suggest it was caused by cygwin version of git.
Anyway, in my case reapplying of the same ACL did not make any sense:
> Set-Acl $f.FullName (Get-Acl $f.FullName)
> (Get-Acl $f.FullName).AreAccessRulesCanonical
False
> (Get-Acl $f.FullName).GetAccessRules($True, $False, [System.Security.Principal.NTAccount]) | ? {$_.Identityeference.Value -eq "NULL SID" }
FileSystemRights : WriteExtendedAttributes, ExecuteFile, DeleteSubdirectoriesAndFiles, ReadPermissions
AccessControlType : Deny
IdentityReference : NULL SID
IsInherited : False
InheritanceFlags : None
PropagationFlags : None
So I've had to explicitly apply ACL from file having correct one, as mentioned by @mschneider