Public/Acl.ps1

using namespace System
using namespace System.IO
using namespace System.Security.Cryptography
using namespace System.Collections.Immutable

    #### # Get-AclItem
    function Get-AclItem {
        #### Return all ACEs for a path as structured objects. One row per ACE per target.
        ####
        #### **Parameters**
        #### - `[string]`: __Path__
        #### - *File or directory path. Accepts pipeline input.*
        #### - `[switch]`: __Recurse__ / __File__ / __Directory__
        #### - *Passed to `Get-AclPathTargets` for target scoping.*
        ####
        #### **Returns**
        #### - `[PSCustomObject[]]`
        #### - `[string]`: __Path__
        #### - *Absolute path of the item.*
        #### - `[string]`: __ItemType__
        #### - *`'File'` or `'Directory'`.*
        #### - `[string]`: __Owner__
        #### - *Current owner principal.*
        #### - `[string]`: __IdentityReference__
        #### - *Principal the ACE applies to.*
        #### - `[FileSystemRights]`: __FileSystemRights__
        #### - *Rights granted or denied.*
        #### - `[AccessControlType]`: __AccessControlType__
        #### - *`Allow` or `Deny`.*
        #### - `[bool]`: __IsInherited__
        #### - *`$true` if inherited from a parent container.*
        #### - `[InheritanceFlags]`: __InheritanceFlags__
        #### - *How inheritance propagates.*
        #### - `[PropagationFlags]`: __PropagationFlags__
        #### - *Inheritance propagation modifiers.*
        [CmdletBinding()]
        param(
            [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
            [ValidateNotNullOrEmpty()]
            [Alias('FullName')]
            [string]$Path,

            [Parameter()][switch]$Recurse,
            [Parameter()][switch]$File,
            [Parameter()][switch]$Directory
        )
        process {
            $targets = Get-AclPathTargets -Path $Path -Recurse:$Recurse -File:$File -Directory:$Directory
            foreach ($target in $targets) {
                $acl = Get-Acl -Path $target.FullName
                $itemType = if ($target -is [System.IO.DirectoryInfo]) { 'Directory' } else { 'File' }
                $acl.Access | ForEach-Object {
                    [PSCustomObject]@{
                        Path              = $target.FullName
                        ItemType          = $itemType
                        Owner             = $acl.Owner
                        IdentityReference = $_.IdentityReference.Value
                        FileSystemRights  = $_.FileSystemRights
                        AccessControlType = $_.AccessControlType
                        IsInherited       = $_.IsInherited
                        InheritanceFlags  = $_.InheritanceFlags
                        PropagationFlags  = $_.PropagationFlags
                    }
                }
            }
        }
    }

    #### # Show-AclItem
    function Show-AclItem {
        #### Format `Get-AclItem` output as an auto-sized table to the host.
        ####
        #### **Parameters**
        #### - `[string]`: __Path__
        #### - *File or directory path. Accepts pipeline input.*
        #### - `[switch]`: __Recurse__ / __File__ / __Directory__
        #### - *Passed through to `Get-AclItem`.*
        [CmdletBinding()]
        param(
            [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
            [ValidateNotNullOrEmpty()]
            [Alias('FullName')]
            [string]$Path,

            [Parameter()][switch]$Recurse,
            [Parameter()][switch]$File,
            [Parameter()][switch]$Directory
        )
        process {
            Get-AclItem -Path $Path -Recurse:$Recurse -File:$File -Directory:$Directory |
            Format-Table Path, ItemType, Owner, IdentityReference, FileSystemRights, AccessControlType, IsInherited -AutoSize
        }
    }

    #### # Get-AclItemOwner
    function Get-AclItemOwner {
        #### Return ownership information for each target: who owns it and whether the owner is SYSTEM, Administrators, or the current user.
        ####
        #### **Parameters**
        #### - `[string]`: __Path__
        #### - *File or directory path. Accepts pipeline input.*
        #### - `[switch]`: __Recurse__ / __File__ / __Directory__
        #### - *Passed to `Get-AclPathTargets`.*
        ####
        #### **Returns**
        #### - `[PSCustomObject[]]`
        #### - `[string]`: __Path__
        #### - *Absolute path of the item.*
        #### - `[string]`: __ItemType__
        #### - *`'File'` or `'Directory'`.*
        #### - `[string]`: __Owner__
        #### - *Current owner principal.*
        #### - `[bool]`: __IsAdminOwned__
        #### - *Owner matches `*Administrators*`.*
        #### - `[bool]`: __IsSystemOwned__
        #### - *Owner matches `*SYSTEM*`.*
        #### - `[bool]`: __IsCurrentUserOwned__
        #### - *Owner matches the current `$env:USERNAME`.*
        [CmdletBinding()]
        param(
            [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
            [ValidateNotNullOrEmpty()]
            [Alias('FullName')]
            [string]$Path,

            [Parameter()][switch]$Recurse,
            [Parameter()][switch]$File,
            [Parameter()][switch]$Directory
        )
        process {
            $targets = Get-AclPathTargets -Path $Path -Recurse:$Recurse -File:$File -Directory:$Directory
            foreach ($target in $targets) {
                $acl = Get-Acl -Path $target.FullName
                $owner = $acl.Owner
                $itemType = if ($target -is [System.IO.DirectoryInfo]) { 'Directory' } else { 'File' }
                [PSCustomObject]@{
                    Path               = $target.FullName
                    ItemType           = $itemType
                    Owner              = $owner
                    IsAdminOwned       = $owner -like '*Administrators*'
                    IsSystemOwned      = $owner -like '*SYSTEM*'
                    IsCurrentUserOwned = $owner -like "*$($env:USERNAME)*"
                }
            }
        }
    }

    #### # Set-AclItemOwner
    function Set-AclItemOwner {
        #### Change the owner of one or more file system items. Requires Administrator. Supports `-WhatIf`.
        ####
        #### **Parameters**
        #### - `[string]`: __Path__
        #### - *File or directory path. Accepts pipeline input.*
        #### - `[string]`: __Identity__
        #### - *New owner as `DOMAIN\User`. Defaults to the current user.*
        #### - `[switch]`: __Recurse__ / __File__ / __Directory__
        #### - *Passed to `Get-AclPathTargets`.*
        ####
        #### **Returns**
        #### - `[PSCustomObject[]]`
        #### - `[string]`: __Path__
        #### - *Absolute path of the item.*
        #### - `[string]`: __ItemType__
        #### - *`'File'` or `'Directory'`.*
        #### - `[string]`: __PreviousOwner__
        #### - *Owner before the change.*
        #### - `[string]`: __NewOwner__
        #### - *Owner after the change.*
        #### - `[string]`: __Status__
        #### - *`'Changed'` on success, or `'Error: <message>'` on failure.*
        [CmdletBinding(SupportsShouldProcess)]
        param(
            [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
            [ValidateNotNullOrEmpty()]
            [Alias('FullName')]
            [string]$Path,

            [Parameter()]
            [ValidateNotNullOrEmpty()]
            [string]$Identity = "$($env:USERDOMAIN)\$($env:USERNAME)",

            [Parameter()][switch]$Recurse,
            [Parameter()][switch]$File,
            [Parameter()][switch]$Directory
        )
        begin {
            Assert-Administrator
            $newOwner = [System.Security.Principal.NTAccount]::new($Identity)
        }
        process {
            $targets = Get-AclPathTargets -Path $Path -Recurse:$Recurse -File:$File -Directory:$Directory
            foreach ($target in $targets) {
                $acl = Get-Acl -Path $target.FullName
                $previousOwner = $acl.Owner
                $itemType = if ($target -is [System.IO.DirectoryInfo]) { 'Directory' } else { 'File' }

                if ($PSCmdlet.ShouldProcess($target.FullName, "Set owner to '$Identity' (was '$previousOwner')")) {
                    try {
                        $acl.SetOwner($newOwner)
                        Set-Acl -Path $target.FullName -AclObject $acl
                        [PSCustomObject]@{
                            Path          = $target.FullName
                            ItemType      = $itemType
                            PreviousOwner = $previousOwner
                            NewOwner      = $Identity
                            Status        = 'Changed'
                        }
                    }
                    catch {
                        [PSCustomObject]@{
                            Path          = $target.FullName
                            ItemType      = $itemType
                            PreviousOwner = $previousOwner
                            NewOwner      = $Identity
                            Status        = "Error: $($_.Exception.Message)"
                        }
                    }
                }
            }
        }
    }

    #### # Repair-AclItemOwnership
    function Repair-AclItemOwnership {
        #### Convenience wrapper: calls `Set-AclItemOwner -Recurse` to reassign ownership across an entire directory tree. Requires Administrator.
        ####
        #### **Parameters**
        #### - `[string]`: __Path__
        #### - *Root path. Accepts pipeline input.*
        #### - `[string]`: __Identity__
        #### - *New owner as `DOMAIN\User`. Defaults to the current user.*
        [CmdletBinding(SupportsShouldProcess)]
        param(
            [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
            [ValidateNotNullOrEmpty()]
            [Alias('FullName')]
            [string]$Path,

            [Parameter()]
            [ValidateNotNullOrEmpty()]
            [string]$Identity = "$($env:USERDOMAIN)\$($env:USERNAME)"
        )
        begin {
            Assert-Administrator
        }
        process {
            Write-Host "Repairing ownership on '$Path' → '$Identity'" -ForegroundColor Cyan
            Set-AclItemOwner -Path $Path -Identity $Identity -Recurse -WhatIf:$WhatIfPreference
        }
    }

    #### # Grant-AclItem
    function Grant-AclItem {
        #### Add a `FileSystemAccessRule` to one or more targets. Requires Administrator. Supports `-WhatIf`.
        ####
        #### **Parameters**
        #### - `[string]`: __Path__
        #### - *File or directory path. Accepts pipeline input.*
        #### - `[string]`: __Identity__
        #### - *Principal to grant access to (e.g. `DOMAIN\User`).*
        #### - `[FileSystemRights]`: __Rights__
        #### - *Rights to grant (e.g. `ReadAndExecute`, `Modify`, `FullControl`).*
        #### - `[AccessControlType]`: __AccessControlType__
        #### - *`Allow` or `Deny`. Defaults to `Allow`.*
        #### - `[InheritanceFlags]`: __InheritanceFlags__
        #### - *Defaults to `ContainerInherit, ObjectInherit`.*
        #### - `[switch]`: __Recurse__ / __File__ / __Directory__
        #### - *Passed to `Get-AclPathTargets`.*
        ####
        #### **Returns**
        #### - `[PSCustomObject[]]`
        #### - `[string]`: __Path__
        #### - *Absolute path of the item.*
        #### - `[string]`: __ItemType__
        #### - *`'File'` or `'Directory'`.*
        #### - `[string]`: __Identity__
        #### - *Principal that received the grant.*
        #### - `[FileSystemRights]`: __Rights__
        #### - *Rights granted.*
        #### - `[AccessControlType]`: __AccessControlType__
        #### - *`Allow` or `Deny`.*
        #### - `[string]`: __Status__
        #### - *`'Granted'` on success, or `'Error: <message>'` on failure.*
        [CmdletBinding(SupportsShouldProcess)]
        param(
            [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
            [ValidateNotNullOrEmpty()]
            [Alias('FullName')]
            [string]$Path,

            [Parameter(Mandatory)]
            [ValidateNotNullOrEmpty()]
            [string]$Identity,

            [Parameter(Mandatory)]
            [System.Security.AccessControl.FileSystemRights]$Rights,

            [Parameter()]
            [System.Security.AccessControl.AccessControlType]$AccessControlType = [System.Security.AccessControl.AccessControlType]::Allow,

            [Parameter()]
            [System.Security.AccessControl.InheritanceFlags]$InheritanceFlags =
            [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor
            [System.Security.AccessControl.InheritanceFlags]::ObjectInherit,

            [Parameter()]
            [System.Security.AccessControl.PropagationFlags]$PropagationFlags = [System.Security.AccessControl.PropagationFlags]::None,

            [Parameter()][switch]$Recurse,
            [Parameter()][switch]$File,
            [Parameter()][switch]$Directory
        )
        begin {
            Assert-Administrator
            $rule = [System.Security.AccessControl.FileSystemAccessRule]::new(
                $Identity, $Rights, $InheritanceFlags, $PropagationFlags, $AccessControlType
            )
        }
        process {
            $targets = Get-AclPathTargets -Path $Path -Recurse:$Recurse -File:$File -Directory:$Directory
            foreach ($target in $targets) {
                $itemType = if ($target -is [System.IO.DirectoryInfo]) { 'Directory' } else { 'File' }
                if ($PSCmdlet.ShouldProcess($target.FullName, "Grant '$Identity' $Rights ($AccessControlType)")) {
                    try {
                        $acl = Get-Acl -Path $target.FullName
                        $acl.AddAccessRule($rule)
                        Set-Acl -Path $target.FullName -AclObject $acl
                        [PSCustomObject]@{
                            Path              = $target.FullName
                            ItemType          = $itemType
                            Identity          = $Identity
                            Rights            = $Rights
                            AccessControlType = $AccessControlType
                            Status            = 'Granted'
                        }
                    }
                    catch {
                        [PSCustomObject]@{
                            Path              = $target.FullName
                            ItemType          = $itemType
                            Identity          = $Identity
                            Rights            = $Rights
                            AccessControlType = $AccessControlType
                            Status            = "Error: $($_.Exception.Message)"
                        }
                    }
                }
            }
        }
    }

    #### # Revoke-AclItem
    function Revoke-AclItem {
        #### Remove ACEs matching an identity from one or more targets. If `-Rights` is specified, only ACEs that include those rights are removed. Requires Administrator. Supports `-WhatIf`.
        ####
        #### **Parameters**
        #### - `[string]`: __Path__
        #### - *File or directory path. Accepts pipeline input.*
        #### - `[string]`: __Identity__
        #### - *Principal whose ACEs to remove.*
        #### - `[FileSystemRights]`: __Rights__
        #### - *Optional rights filter. Omit to remove all ACEs for the identity.*
        #### - `[switch]`: __Recurse__ / __File__ / __Directory__
        #### - *Passed to `Get-AclPathTargets`.*
        ####
        #### **Returns**
        #### - `[PSCustomObject[]]`
        #### - `[string]`: __Path__
        #### - *Absolute path of the item.*
        #### - `[string]`: __ItemType__
        #### - *`'File'` or `'Directory'`.*
        #### - `[string]`: __Identity__
        #### - *Principal whose ACEs were revoked.*
        #### - `[int]`: __RemovedCount__
        #### - *Number of ACEs removed.*
        #### - `[string]`: __Status__
        #### - *`'Revoked'`, `'NoMatchFound'`, or `'Error: <message>'`.*
        [CmdletBinding(SupportsShouldProcess)]
        param(
            [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
            [ValidateNotNullOrEmpty()]
            [Alias('FullName')]
            [string]$Path,

            [Parameter(Mandatory)]
            [ValidateNotNullOrEmpty()]
            [string]$Identity,

            [Parameter()]
            [System.Security.AccessControl.FileSystemRights]$Rights,

            [Parameter()][switch]$Recurse,
            [Parameter()][switch]$File,
            [Parameter()][switch]$Directory
        )
        begin {
            Assert-Administrator
        }
        process {
            $targets = Get-AclPathTargets -Path $Path -Recurse:$Recurse -File:$File -Directory:$Directory
            foreach ($target in $targets) {
                $itemType = if ($target -is [System.IO.DirectoryInfo]) { 'Directory' } else { 'File' }
                $acl = Get-Acl -Path $target.FullName
                $toRemove = $acl.Access | Where-Object {
                    $_.IdentityReference.Value -like "*$Identity*" -and
                    (-not $PSBoundParameters.ContainsKey('Rights') -or ($_.FileSystemRights -band $Rights))
                }

                if (-not $toRemove) {
                    [PSCustomObject]@{
                        Path         = $target.FullName
                        ItemType     = $itemType
                        Identity     = $Identity
                        RemovedCount = 0
                        Status       = 'NoMatchFound'
                    }
                    continue
                }

                if ($PSCmdlet.ShouldProcess($target.FullName, "Revoke $($toRemove.Count) ACE(s) for '$Identity'")) {
                    try {
                        foreach ($rule in $toRemove) { $acl.RemoveAccessRule($rule) | Out-Null }
                        Set-Acl -Path $target.FullName -AclObject $acl
                        [PSCustomObject]@{
                            Path         = $target.FullName
                            ItemType     = $itemType
                            Identity     = $Identity
                            RemovedCount = $toRemove.Count
                            Status       = 'Revoked'
                        }
                    }
                    catch {
                        [PSCustomObject]@{
                            Path         = $target.FullName
                            ItemType     = $itemType
                            Identity     = $Identity
                            RemovedCount = 0
                            Status       = "Error: $($_.Exception.Message)"
                        }
                    }
                }
            }
        }
    }

    #### # Copy-AclItem
    function Copy-AclItem {
        #### Apply the full ACL from a source path to one or more destination paths. Requires Administrator. Supports `-WhatIf`.
        ####
        #### **Parameters**
        #### - `[string]`: __Source__
        #### - *Path whose ACL to copy from.*
        #### - `[string[]]`: __Destination__
        #### - *One or more target paths. Accepts pipeline input.*
        ####
        #### **Returns**
        #### - `[PSCustomObject[]]`
        #### - `[string]`: __Source__
        #### - *Resolved source path.*
        #### - `[string]`: __Destination__
        #### - *Resolved destination path.*
        #### - `[string]`: __Owner__
        #### - *Owner from the source ACL.*
        #### - `[int]`: __AceCount__
        #### - *Number of ACEs copied.*
        #### - `[string]`: __Status__
        #### - *`'Copied'` on success, or `'Error: <message>'` on failure.*
        [CmdletBinding(SupportsShouldProcess)]
        param(
            [Parameter(Mandatory)]
            [ValidateNotNullOrEmpty()]
            [string]$Source,

            [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
            [ValidateNotNullOrEmpty()]
            [Alias('FullName')]
            [string[]]$Destination
        )
        begin {
            Assert-Administrator
            $sourceResolved = Resolve-Path -Path $Source -ErrorAction Stop
            $sourceAcl = Get-Acl -Path $sourceResolved.ProviderPath
        }
        process {
            foreach ($dest in $Destination) {
                $destResolved = Resolve-Path -Path $dest -ErrorAction Stop
                if ($PSCmdlet.ShouldProcess($destResolved.ProviderPath, "Apply ACL from '$($sourceResolved.ProviderPath)'")) {
                    try {
                        Set-Acl -Path $destResolved.ProviderPath -AclObject $sourceAcl
                        [PSCustomObject]@{
                            Source      = $sourceResolved.ProviderPath
                            Destination = $destResolved.ProviderPath
                            Owner       = $sourceAcl.Owner
                            AceCount    = $sourceAcl.Access.Count
                            Status      = 'Copied'
                        }
                    }
                    catch {
                        [PSCustomObject]@{
                            Source      = $sourceResolved.ProviderPath
                            Destination = $destResolved.ProviderPath
                            Owner       = $sourceAcl.Owner
                            AceCount    = $sourceAcl.Access.Count
                            Status      = "Error: $($_.Exception.Message)"
                        }
                    }
                }
            }
        }
    }

    #### # Set-AclItemInheritance
    function Set-AclItemInheritance {
        #### Enable or disable ACL inheritance on file system items. Use `-Enable` to restore inheritance or `-Disable` to break it. `-PreserveExisting` copies inherited rules as explicit ACEs before breaking. Requires Administrator. Supports `-WhatIf`.
        ####
        #### **Parameters**
        #### - `[string]`: __Path__
        #### - *File or directory path. Accepts pipeline input.*
        #### - `[switch]`: __Enable__
        #### - *Restore inheritance (default parameter set).*
        #### - `[switch]`: __Disable__
        #### - *Break inheritance.*
        #### - `[switch]`: __PreserveExisting__
        #### - *When disabling, copy inherited rules as explicit ACEs before breaking. Only valid with `-Disable`.*
        #### - `[switch]`: __Recurse__ / __File__ / __Directory__
        #### - *Passed to `Get-AclPathTargets`.*
        ####
        #### **Returns**
        #### - `[PSCustomObject[]]`
        #### - `[string]`: __Path__
        #### - *Absolute path of the item.*
        #### - `[string]`: __ItemType__
        #### - *`'File'` or `'Directory'`.*
        #### - `[bool]`: __InheritanceEnabled__
        #### - *Reflects the `-Enable` switch.*
        #### - `[int]`: __PreservedCount__
        #### - *Inherited ACEs copied as explicit when `-PreserveExisting` is used.*
        #### - `[string]`: __Status__
        #### - *`'Applied'` on success, or `'Error: <message>'` on failure.*
        [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Enable')]
        param(
            [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
            [ValidateNotNullOrEmpty()]
            [Alias('FullName')]
            [string]$Path,

            [Parameter(Mandatory, ParameterSetName = 'Enable')]
            [switch]$Enable,

            [Parameter(Mandatory, ParameterSetName = 'Disable')]
            [switch]$Disable,

            [Parameter(ParameterSetName = 'Disable')]
            [switch]$PreserveExisting,

            [Parameter()][switch]$Recurse,
            [Parameter()][switch]$File,
            [Parameter()][switch]$Directory
        )
        begin {
            Assert-Administrator
        }
        process {
            $targets = Get-AclPathTargets -Path $Path -Recurse:$Recurse -File:$File -Directory:$Directory
            foreach ($target in $targets) {
                $itemType = if ($target -is [System.IO.DirectoryInfo]) { 'Directory' } else { 'File' }
                $acl = Get-Acl -Path $target.FullName
                $action = if ($Enable) { 'Enable inheritance' } else { 'Disable inheritance' }

                if ($PSCmdlet.ShouldProcess($target.FullName, $action)) {
                    try {
                        $preservedCount = 0
                        if ($Disable) {
                            $acl.SetAccessRuleProtection($true, $PreserveExisting.IsPresent)
                            if ($PreserveExisting) {
                                $preservedCount = ($acl.Access | Where-Object { $_.IsInherited }).Count
                            }
                        }
                        else {
                            $acl.SetAccessRuleProtection($false, $false)
                        }
                        Set-Acl -Path $target.FullName -AclObject $acl
                        [PSCustomObject]@{
                            Path               = $target.FullName
                            ItemType           = $itemType
                            InheritanceEnabled = $Enable.IsPresent
                            PreservedCount     = $preservedCount
                            Status             = 'Applied'
                        }
                    }
                    catch {
                        [PSCustomObject]@{
                            Path               = $target.FullName
                            ItemType           = $itemType
                            InheritanceEnabled = $Enable.IsPresent
                            PreservedCount     = 0
                            Status             = "Error: $($_.Exception.Message)"
                        }
                    }
                }
            }
        }
    }

    #### # Get-AclItemAccountUnknown
    function Get-AclItemAccountUnknown {
        #### Filter ACEs where `IdentityReference` is a raw SID (`S-1-...`), indicating a deleted or orphaned account.
        ####
        #### **Parameters**
        #### - `[string]`: __Path__
        #### - *File or directory path. Accepts pipeline input.*
        #### - `[switch]`: __Recurse__ / __File__ / __Directory__
        #### - *Passed to `Get-AclItem`.*
        ####
        #### **Returns**
        #### - `[PSCustomObject[]]`
        #### - *Same shape as `Get-AclItem`, filtered to orphaned SID entries.*
        [CmdletBinding()]
        param(
            [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
            [ValidateNotNullOrEmpty()]
            [Alias('FullName')]
            [string]$Path,

            [Parameter()][switch]$Recurse,
            [Parameter()][switch]$File,
            [Parameter()][switch]$Directory
        )
        process {
            Get-AclItem -Path $Path -Recurse:$Recurse -File:$File -Directory:$Directory |
            Where-Object { $_.IdentityReference -match '^S-1-' }
        }
    }

    #### # Show-AclItemAccountUnknown
    function Show-AclItemAccountUnknown {
        #### Format `Get-AclItemAccountUnknown` as a table, or print a green "clean" message if none are found.
        ####
        #### **Parameters**
        #### - `[string]`: __Path__
        #### - *File or directory path. Accepts pipeline input.*
        #### - `[switch]`: __Recurse__ / __File__ / __Directory__
        #### - *Passed through to `Get-AclItemAccountUnknown`.*
        [CmdletBinding()]
        param(
            [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
            [ValidateNotNullOrEmpty()]
            [Alias('FullName')]
            [string]$Path,

            [Parameter()][switch]$Recurse,
            [Parameter()][switch]$File,
            [Parameter()][switch]$Directory
        )
        process {
            $unknown = Get-AclItemAccountUnknown -Path $Path -Recurse:$Recurse -File:$File -Directory:$Directory
            if (-not $unknown) {
                Write-Host "No unknown account principals found on: $Path" -ForegroundColor Green
                return
            }
            $unknown | Format-Table Path, IdentityReference, FileSystemRights, AccessControlType -AutoSize
        }
    }

    #### # Get-AclItemAccountAnomalies
    function Get-AclItemAccountAnomalies {
        #### Detect anomalous ACEs: orphaned SIDs, Sandbox principals, and unexpected write permissions from untrusted identities. Each result includes an `AnomalyReasons` field listing which rules fired.
        ####
        #### **Parameters**
        #### - `[string]`: __Path__
        #### - *File or directory path. Accepts pipeline input.*
        #### - `[string[]]`: __TrustedPrincipals__
        #### - *Identities considered safe. Defaults to `NT AUTHORITY\SYSTEM`, `BUILTIN\Administrators`, `CREATOR OWNER`.*
        #### - `[switch]`: __Recurse__ / __File__ / __Directory__
        #### - *Passed to `Get-AclItem`.*
        ####
        #### **Returns**
        #### - `[PSCustomObject[]]`
        #### - `[string]`: __Path__
        #### - *Absolute path of the item.*
        #### - `[string]`: __ItemType__
        #### - *`'File'` or `'Directory'`.*
        #### - `[string]`: __IdentityReference__
        #### - *Principal the anomalous ACE applies to.*
        #### - `[FileSystemRights]`: __FileSystemRights__
        #### - *Rights granted or denied.*
        #### - `[AccessControlType]`: __AccessControlType__
        #### - *`Allow` or `Deny`.*
        #### - `[bool]`: __IsInherited__
        #### - *`$true` if inherited from a parent.*
        #### - `[string]`: __AnomalyReasons__
        #### - *Comma-separated list of triggered rules: `OrphanedSid`, `SandboxPrincipal`, `UnexpectedWrite`.*
        [CmdletBinding()]
        param(
            [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
            [ValidateNotNullOrEmpty()]
            [Alias('FullName')]
            [string]$Path,

            [Parameter()]
            [string[]]$TrustedPrincipals = @('NT AUTHORITY\SYSTEM', 'BUILTIN\Administrators', 'CREATOR OWNER'),

            [Parameter()][switch]$Recurse,
            [Parameter()][switch]$File,
            [Parameter()][switch]$Directory
        )
        process {
            $entries = Get-AclItem -Path $Path -Recurse:$Recurse -File:$File -Directory:$Directory
            $anomalies = [System.Collections.Generic.List[PSCustomObject]]::new()

            foreach ($entry in $entries) {
                $identity = $entry.IdentityReference
                $isOrphanedSid = $identity -match '^S-1-'
                $isSandbox = $identity -match 'Sandbox'
                $isTrusted = $TrustedPrincipals | Where-Object { $identity -like "*$_*" }
                $isOwner = $identity -like "*$($env:USERNAME)*"
                $hasDangerousRights = $entry.FileSystemRights -match 'Modify|Write|Delete|FullControl'

                $reasons = [System.Collections.Generic.List[string]]::new()
                if ($isOrphanedSid) { $reasons.Add('OrphanedSid') }
                if ($isSandbox) { $reasons.Add('SandboxPrincipal') }
                if (-not $isTrusted -and -not $isOwner -and $hasDangerousRights) { $reasons.Add('UnexpectedWrite') }

                if ($reasons.Count -gt 0) {
                    $anomalies.Add([PSCustomObject]@{
                            Path              = $entry.Path
                            ItemType          = $entry.ItemType
                            IdentityReference = $identity
                            FileSystemRights  = $entry.FileSystemRights
                            AccessControlType = $entry.AccessControlType
                            IsInherited       = $entry.IsInherited
                            AnomalyReasons    = ($reasons -join ', ')
                        })
                }
            }

            $anomalies
        }
    }

    #### # Remove-AclItemAccountUnknown
    function Remove-AclItemAccountUnknown {
        #### Remove all ACEs with orphaned SID identity references from one or more targets. Requires Administrator. Supports `-WhatIf`.
        ####
        #### **Parameters**
        #### - `[string]`: __Path__
        #### - *File or directory path. Accepts pipeline input.*
        #### - `[switch]`: __Recurse__ / __File__ / __Directory__
        #### - *Passed to `Get-AclPathTargets`.*
        ####
        #### **Returns**
        #### - `[PSCustomObject[]]`
        #### - `[string]`: __Path__
        #### - *Absolute path of the item.*
        #### - `[string]`: __ItemType__
        #### - *`'File'` or `'Directory'`.*
        #### - `[string[]]`: __RemovedSids__
        #### - *SID strings that were removed from the ACL.*
        #### - `[int]`: __RemovedCount__
        #### - *Number of orphaned SIDs removed.*
        #### - `[string]`: __Status__
        #### - *`'Cleaned'` when changes were made, `'Clean'` when none were needed.*
        [CmdletBinding(SupportsShouldProcess)]
        param(
            [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
            [ValidateNotNullOrEmpty()]
            [Alias('FullName')]
            [string]$Path,

            [Parameter()][switch]$Recurse,
            [Parameter()][switch]$File,
            [Parameter()][switch]$Directory
        )
        begin {
            Assert-Administrator
        }
        process {
            $targets = Get-AclPathTargets -Path $Path -Recurse:$Recurse -File:$File -Directory:$Directory
            foreach ($target in $targets) {
                $itemType = if ($target -is [System.IO.DirectoryInfo]) { 'Directory' } else { 'File' }
                $acl = Get-Acl -Path $target.FullName
                $unknown = $acl.Access | Where-Object { $_.IdentityReference.Value -match '^S-1-' }

                if (-not $unknown) {
                    Write-Verbose "No orphaned SIDs found on: $($target.FullName)"
                    [PSCustomObject]@{
                        Path         = $target.FullName
                        ItemType     = $itemType
                        RemovedSids  = @()
                        RemovedCount = 0
                        Status       = 'Clean'
                    }
                    continue
                }

                $removed = [System.Collections.Generic.List[string]]::new()
                foreach ($entry in $unknown) {
                    if ($PSCmdlet.ShouldProcess($entry.IdentityReference.Value, "Remove orphaned SID from ACL of $($target.FullName)")) {
                        $acl.RemoveAccessRule($entry) | Out-Null
                        $removed.Add($entry.IdentityReference.Value)
                    }
                }

                if ($removed.Count -gt 0) { Set-Acl -Path $target.FullName -AclObject $acl }

                [PSCustomObject]@{
                    Path         = $target.FullName
                    ItemType     = $itemType
                    RemovedSids  = $removed
                    RemovedCount = $removed.Count
                    Status       = 'Cleaned'
                }
            }
        }
    }

    #### # Reset-AclItem
    function Reset-AclItem {
        #### Strip all explicit (non-inherited) ACEs from one or more targets, leaving only inherited rules. Requires Administrator. Supports `-WhatIf`.
        ####
        #### **Parameters**
        #### - `[string]`: __Path__
        #### - *File or directory path. Accepts pipeline input.*
        #### - `[switch]`: __Recurse__ / __File__ / __Directory__
        #### - *Passed to `Get-AclPathTargets`.*
        ####
        #### **Returns**
        #### - `[PSCustomObject[]]`
        #### - `[string]`: __Path__
        #### - *Absolute path of the item.*
        #### - `[string]`: __ItemType__
        #### - *`'File'` or `'Directory'`.*
        #### - `[int]`: __BeforeCount__
        #### - *Total ACE count before the reset.*
        #### - `[int]`: __AfterCount__
        #### - *Total ACE count after the reset.*
        #### - `[int]`: __Removed__
        #### - *Number of explicit ACEs stripped.*
        #### - `[string]`: __Status__
        #### - *`'Reset'` when ACEs were removed, `'AlreadyClean'` when none were explicit.*
        [CmdletBinding(SupportsShouldProcess)]
        param(
            [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
            [ValidateNotNullOrEmpty()]
            [Alias('FullName')]
            [string]$Path,

            [Parameter()][switch]$Recurse,
            [Parameter()][switch]$File,
            [Parameter()][switch]$Directory
        )
        begin {
            Assert-Administrator
        }
        process {
            $targets = Get-AclPathTargets -Path $Path -Recurse:$Recurse -File:$File -Directory:$Directory
            foreach ($target in $targets) {
                $itemType = if ($target -is [System.IO.DirectoryInfo]) { 'Directory' } else { 'File' }
                $acl = Get-Acl -Path $target.FullName
                $explicit = $acl.Access | Where-Object { -not $_.IsInherited }
                $beforeCount = $acl.Access.Count

                if (-not $explicit) {
                    Write-Verbose "No explicit ACEs on: $($target.FullName) — already inherited-only"
                    [PSCustomObject]@{
                        Path        = $target.FullName
                        ItemType    = $itemType
                        BeforeCount = $beforeCount
                        AfterCount  = $beforeCount
                        Removed     = 0
                        Status      = 'AlreadyClean'
                    }
                    continue
                }

                if ($PSCmdlet.ShouldProcess($target.FullName, "Strip $($explicit.Count) explicit ACE(s), keep inherited")) {
                    foreach ($rule in $explicit) { $acl.RemoveAccessRule($rule) | Out-Null }
                    Set-Acl -Path $target.FullName -AclObject $acl
                    $afterCount = (Get-Acl -Path $target.FullName).Access.Count
                    [PSCustomObject]@{
                        Path        = $target.FullName
                        ItemType    = $itemType
                        BeforeCount = $beforeCount
                        AfterCount  = $afterCount
                        Removed     = $beforeCount - $afterCount
                        Status      = 'Reset'
                    }
                }
            }
        }
    }