Where a computer doesn't offer the remote interface of the authorization
manager, the cmdlet calculates the result with the local one and warns
that the result might be inaccurate. Only localhost in lowercase counted
as this computer, so the cmdlet warned that the computer couldn't be
reached for ., LOCALHOST, or the computer name, although the local result
is the result of that computer. A name of this computer is now localhost
in any case, ., the NetBIOS name, the DNS host name, or the fully
qualified domain name.
From the security-reviewer pass over be04cb7..4ee01e5 (Nit 7),
reproduced in Windows PowerShell 5.1 and PowerShell 7 on a workstation
without the remote interface.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
From the security-reviewer pass over be04cb7..4ee01e5 (Minor 3 and 4):
ea2f6df compares the paths of folders without regard to case, which no
test covered; a parent folder in another case counted as not reported
before, so the folder was left out. The test of a drive root now expects
all of its entries instead of any. The page and the changelog say that
paths that differ only in case name the same folder.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
From the security-reviewer pass over be04cb7..4ee01e5 (Minor 1, 2, and
5, Nit 9):
- A path with a character that Windows doesn't allow, such as |, stopped
the pipeline in Windows PowerShell, where resolving the path throws an
ArgumentException; both cmdlets now write a non-terminating error with
the category InvalidArgument, also in PowerShell 7, where AlphaFS
rejects the path when it creates the link.
- The errors of New-NTFSSymbolicLink for an existing -Path and a missing
-Target, and of New-NTFSHardLink for a folder as -Target, named no path.
- New-NTFSSymbolicLink checked -Target before -Path, so that the two
cmdlets reported different errors for an existing -Path with a missing
-Target; both check -Path first now.
- The pages list objects with Path and Target as input of their own.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
New-NTFSHardLink and New-NTFSSymbolicLink now require -Path and -Target.
Without -Path, they failed with an index error; without -Target, they
used the current location, so New-NTFSSymbolicLink -Path Link created a
link to the current folder.
For a link that they can't create, they write a non-terminating
CreateHardLinkError or CreateSymbolicLinkError with the category
ResourceExists, ObjectNotFound, InvalidArgument, PermissionDenied, or
WriteError, and continue with the next object from the pipeline; they
stopped with a terminating error.
Fixed on the way: every object piped to the cmdlets failed with
GetDefaultValueFailed, because PowerShell reads a parameter that takes
pipeline input before it binds the input, and the getter of -Path threw
on the empty list. The pages show piping rows of a CSV file.
BREAKING CHANGE: a script that omits -Path or -Target gets a prompt, or
an error in a non-interactive session, and a script that relies on a
terminating error of the link cmdlets needs -ErrorAction Stop.
Decision 22, items 7 and 8: assumptions in autopilot, flagged for the
maintainer's review.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Windows can't move a folder to another volume. Move-Item2 moved folders
with CopyAllowed, so AlphaFS copied and deleted them instead: an empty
folder was deleted without being created at the destination, and a
folder with files failed with an error that named one of its files.
Folders now move without CopyAllowed, and the cmdlet writes a MoveError
with the category InvalidOperation that names the folder and the
destination, and leaves the folder in place. A file still moves to
another volume; with -Force, it keeps the error of Windows, (17).
The tests move to \\localhost\C$, which Windows treats as another volume,
and run only elevated.
Decision 22, item 6: an assumption in autopilot, flagged for the
maintainer's review.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
When the computer of -ServerName can't be reached, the cmdlet calculates
the result with the group memberships known on this computer and warns.
The warning now names that computer, which a command with many items
couldn't tell otherwise. The live test expects the new text as well.
Decision 22, item 5: an assumption in autopilot, flagged for the
maintainer's review.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Get-NTFSSimpleAccess compares each folder with its parent folder. A
folder whose parent folder it hadn't reported was left out, and with it
all of its subfolders; a drive root, which has no parent folder, was left
out or compared with the parent folder of the folder before it; and a
folder that came after its parent folder a second time failed with a
ReadError, "An item with the same key has already been added". Such
folders are now reported with all of their entries, and the paths are
compared without regard to case.
Decision 22, item 2: an assumption in autopilot, flagged for the
maintainer's review.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Without the Security privilege, Get-NTFSOrphanedAudit read the item
without its SACL and returned nothing, which looked like an item without
orphaned entries, and it wrote a warning for an item that it couldn't
read. It now reads only the SACL, like Get-NTFSAudit, and writes a
ReadSecurityError with the category PermissionDenied or OpenError. The
error for a path that doesn't exist stays ReadError.
Decision 22, item 1: an assumption in autopilot, flagged for the
maintainer's review.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Equals of FileSystemAccessRule2, FileSystemAuditRule2, and
FileSystemSecurity2 cast its argument to the .NET type, which throws for
the wrapper types themselves: -eq and -contains, and in PowerShell 7 also
Select-Object -Unique and Compare-Object, stopped with an
InvalidCastException. GetHashCode of FileSystemSecurity2 read a field
that is never set and threw a NullReferenceException. Two objects are now
equal when they hold the same entry or descriptor, like the .NET types.
InheritedFrom: Win32.GetInheritedFrom returned the sources of the SACL
whenever the descriptor had one, also for the access entries, and the
callers gave the filtered entries of -ExcludeExplicit the sources of the
first entries of the ACL. Get-NTFSAccess -SecurityDescriptor stopped with
an ArgumentOutOfRangeException for a descriptor with audit entries, as
Get-NTFSSecurityDescriptor reads them in an elevated session. The method
now takes the ACL of the entries, and the callers map the sources before
they filter.
The coverage report of rc6 pointed at both; each test fails without its
fix.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
- Copy-Item2 and Move-Item2 name a missing destination folder in a verbose
message with -WhatIf, like an existing destination (#108); the operation
itself fails with an error that names the folder (finding 1).
- Invoke-TestsAsBasicUser.ps1 refuses a title with a double quote or a
percent sign, which cmd.exe interprets inside the quoted argument, and
fails when waiting for the test process fails (findings 4 and 5).
- The page of Get-NTFSSimpleAccess says that ReadData is the right to list
a folder (ListDirectory), which the cmdlet reports as Read (finding 10).
Checked and kept: a UNC destination on a share that doesn't exist names
the share, which a new test pins (finding 3); the lab script refuses
machines outside the lab before it changes anything (finding 6).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
The authorization manager of a computer answers only its administrators
and the members of its group Access Control Assistance Operators
(S-1-5-32-579); any other account gets "Access is denied" and no result.
A probe in the lab confirmed it on 2026-10-08: the delegated account got
error 5 without the membership and its rights with it.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Add tests for the error handling that the cmdlets with -Path share: a
path that doesn't exist (16 cmdlets, and 6 audit cmdlets with the
Security privilege), an item whose owner may not read its permissions
(6 cmdlets), and an item whose owner may not change them, which the 6
cmdlets that write the DACL handle by taking ownership. Each error
belongs to its path only, and the cmdlet goes on with the next one.
The tests found one defect: Get-NTFSOrphanedAccess reported an item that
it couldn't read as an AddAceError with the category WriteError. It now
writes a ReadSecurityError, like Get-NTFSAccess.
They also show that the take-ownership retry works without privileges
when the account holds the Take Ownership right and may assign the
previous owner, and that it can't help a denied read, because reading
the owner needs the same right. Concepts and five cmdlet pages said that
the retry needs the privileges; they now describe both, and that Windows
removes the OWNER RIGHTS entries when the owner changes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
The cmdlet read the item again for -PassThru inside the try block that
retries a denied write as the owner (R5 of the review of #113). A read
that was denied after a successful write therefore started another
attempt of the write and ended in a WriteSdError, and a write that
needed the ownership retry wrote no object at all.
The read now follows the write and its retry, and a failed read is a
ReadSecurityError. The page also says what happens when setting the
previous owner back fails.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Windows can't list the names of a file on a network share and answers
with (50) The request is not supported. The new live tests found that
Get-NTFSHardLink then stopped with a terminating error, so that it
skipped the remaining paths, and that New-NTFSHardLink -PassThru did so
after it had created the link. A folder stopped Get-NTFSHardLink the
same way.
Both cmdlets now write a non-terminating GetHardLinkError and go on.
The tests reach the sandbox over the administrative share of its drive,
which behaves like the share of a file server, and skip where that share
isn't available, such as for a basic user. The pages describe the limit
on shares.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
The check for an existing destination looked for a file only. For a
folder whose name existed at the destination, the cmdlets failed in the
middle with a CopyError or a MoveError, and Copy-Item2 could copy a part
of the folder first. They now write DestinationFileAlreadyExists, as
for a file.
When the folder that is to contain the new item didn't exist, AlphaFS
reported a DirectoryNotFoundException that named the source item, which
reproduces the symptom of #21. The cmdlets now write an error that names
the missing folder, with the destination as the target. Copy-Item2 no
longer creates the missing folders for a folder: the workaround that
creates the destination folder for AlphaFS created its parents as well,
which only the prereleases of 5.0.0 did.
The pages also say that -Force merges a folder into an existing folder
of the same name, and that a folder can't move to another volume.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Two deviations from the cmdlet page, found by new tests from its
contract:
- An entry that grants only ReadData became None: the reduction tested
the combined Read mask, and nothing mapped ReadData alone. .NET adds
Synchronize to every allow entry, which hid it; other tools write such
entries.
- With -IncludeRootFolder, on by default, a relative path with a single
folder name had no parent folder in the result, because the parent was
taken from the path before it was resolved.
The tests also cover the rights reduction, the comparison of folders
with their parent, the pipeline, the current location, -ExcludeExplicit,
files, and missing paths, elevated and as a basic user in both editions.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Since this branch, Test-Path2 writes $false for a path that Windows
PowerShell rejects, such as one with a |, but it didn't say why. It now
writes the reason as a debug message. Only the lookup of the item is in
the try block, so that an error elsewhere in the cmdlet can't turn into
$false.
Found by the security review of fcb370e..00c3646 (finding 4).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Since 5.0.0, -PassThru returns a folder object for a link to a folder, as
the OUTPUTS section and the changelog say; the description and the
parameter still said a file object.
The notes said that in Windows Developer Mode, accounts without the right
to create symbolic links can create them. Windows allows that only to
programs that request it, and the cmdlet doesn't: in the lab, with
Developer Mode on, mklink created a link as an account without the right,
and New-NTFSSymbolicLink of 5.0.0-rc5 failed with error 1314.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
In Windows PowerShell, .NET rejects a path with a character that Windows
doesn't allow in names, such as | or <, and Test-Path2 stopped with the
terminating error "Illegal characters in path". Such an item can't
exist, so the cmdlet now writes false, as in PowerShell 7 and like
Test-Path. Add tests for every -PathType, long paths, relative paths,
and the pipeline, and for Get-DiskSpace, which had no tests.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Get-NTFSEffectiveAccess -ServerName with a computer that can't be
resolved or reached returned no access, while it warned that it had
calculated the result on this computer. In that case,
AuthzInitializeRemoteResourceManager fails with RPC_S_SERVER_UNAVAILABLE
(1722); the code fell back to the local authorization manager only for
EPT_S_NOT_REGISTERED (1753), and GetEffectiveAccess swallowed the
exception. It now falls back for 1722 as well, as the cmdlet page
describes. The live tests in a lab found it; the new test in
Access.Tests.ps1 reproduces it on any computer.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
- Read the root folder for a volume name such as \\?\Volume{GUID}\ too,
like for a drive letter, and accept only the letters A to Z as a drive
- Report a security descriptor without the audit entries without naming a
missing Security privilege as the cause, which may not be the reason
- Skip the audit tests that change a descriptor from
Get-NTFSSecurityDescriptor in a session without the Security privilege
- Assert the absence of the old hint in the Get-NTFSEffectiveAccess test
- Narrow the drive-root note of Get-NTFSAccess to the security cmdlets
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
- #41: for the root of a drive, the cmdlets read and changed the security
descriptor of the drive, a device object. FileSystemSecurity2 now routes
drive roots through the path-based AlphaFS methods, which keep the
trailing backslash; the removal and inheritance helpers use it too.
- #109: Add-, Remove-, and Clear-NTFSAudit report a security descriptor
without the audit entries like Get-NTFSAudit, through one helper, and
Get-NTFSEffectiveAccess names the cause that Windows reported instead
of a missing Security privilege.
- #108: Copy-Item2 and Move-Item2 check the destination only for an
operation that runs; with -WhatIf, a verbose message names the conflict.
- #111: Disable-Privileges skips the privileges that the token doesn't
hold, the privilege messages are spelled right, and Get-FileHash2
declares the type name of its objects; 05-Releasing.md documents the
release metadata tests.
- rc3 review leftovers: Remove-NTFSAudit writes nothing for an item
without a SACL, the owner retry of Set-NTFSSecurityDescriptor restores
the previous owner in a finally block and keeps an owner that the
descriptor sets, and FileSystemSecurity2.Write with another item writes
only the sections that were read.
Each fix has a test that failed first, in Windows PowerShell 5.1 and
PowerShell 7; writing a drive root was checked once on a temporary VHD.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
- Set-NTFSSecurityDescriptor -Verbose names the sections that it writes,
or says that it writes nothing for an unchanged descriptor; its page
says "since it was read or last written" (review F-02).
- The pages of Enable-NTFSAccessInheritance, Disable-NTFSAccessInheritance,
and Set-NTFSInheritance get the #34 note, like the other fixed cmdlets
(review F-06).
- Set-TestOwner throws its own error when icacls fails, also when the
caller uses -ErrorAction Stop in Windows PowerShell (review F-07).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
The access and audit cmdlets wrote the owner of an item back with the
entries they changed. For a DACL without the auto-inherit flag, Windows
returns the owner and the group even when only the DACL is read, and the
cmdlets wrote every section that the descriptor held. Without the Restore
privilege, or on a file server that refuses the owner, the write failed
with error 1307 (#34).
- Add-NTFSAccess, Clear-NTFSAccess, Add-NTFSAudit, and Clear-NTFSAudit
read only the DACL or the SACL. FileSystemSecurity2.Write(),
Remove-NTFSAccess, and Remove-NTFSAudit write only the sections they
read, which also fixes the access inheritance cmdlets.
- Read together with the SACL, the inherited entries of such a DACL lose
their inherited flag when the parent folder has no SACL, and the
cmdlets stored them as explicit copies. Get-NTFSSecurityDescriptor now
reads the DACL in a separate call.
- Set-NTFSSecurityDescriptor writes only the sections that changed since
they were read; an unchanged descriptor writes nothing (maintainer
decision of 2026-10-06).
- Clear-NTFSAudit writes nothing for an item without a SACL, and reports
an error without the Security privilege (maintainer decision).
The regression tests failed before and pass after the fix in Windows
PowerShell 5.1 and PowerShell 7, elevated and as a basic user.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
An empty Get-ChildItem2 -Attributes value, such as 0 or None in
PowerShell 7, matched every item and returned hidden items as well; it now
stops the cmdlet with AttributesEmpty, as Get-ChildItem rejects it. The page
says that the + and ! operators of Get-ChildItem aren't supported and that
-Recurse still enters hidden folders, and the changelog says that a call
with several attributes now returns more items. The type data test starts
Windows PowerShell, where the import failed, from both CI legs and checks
that LengthOnDisk is still there.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Get-ChildItem2 -Attributes returned only the items that had all the listed
attributes, so -Attributes Hidden, ReadOnly returned nothing where
Get-ChildItem returns both kinds of items. It now returns the items that have
any of them (#5).
BREAKING CHANGE: to get only the items with all the listed attributes,
filter the result with Where-Object, as the cmdlet page shows.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
FileSystemSecurity.RemoveAccessRule rebuilds a rule that doesn't match an
entry exactly and rejects generic rights then, so removing an entry with
GENERIC_ALL failed with "The value '269484032' is not valid". Windows keeps
generic rights in the inherit-only entries of folders. Such a rule is now
removed through ModifyAccessRule, without the added Synchronize right
(#17).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Mark the Set-NTFSInheritance change as breaking and warn that scripts that
used it to drop the inherited access entries now leave broader access in
place. Report any failure to create the hash algorithm as
HashAlgorithmNotAvailable, assert that error ID, check that the
MACTripleDES warning appears once, and guard the descriptor test.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
The new FAQ page answers the questions that the issues ask again and again
and links the pages with the details. The Get-NTFSEffectiveAccess page said
that a security descriptor produces no result, and the Copy-Item2 page now
says that -PassThru returns the copy; tests pin both -PassThru objects.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
The behavior stays: the cmdlet removes the explicit entries and disables
inheritance without copying the inherited ones. The parameter text now
states the empty DACL and its risk, and a test pins the behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
-AccessInheritanceEnabled $false now copies the inherited access entries
into the DACL, and -AuditInheritanceEnabled $true keeps the explicit audit
entries, as Disable-NTFSAccessInheritance and Enable-NTFSAuditInheritance
do without their switches (Decision 13).
BREAKING CHANGE: to remove the entries, use
Disable-NTFSAccessInheritance -RemoveInheritedAccessRules or
Enable-NTFSAuditInheritance -RemoveExplicitAuditRules.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Disable-NTFSAuditInheritance -RemoveInheritedAccessRules is now
-RemoveInheritedAuditRules, and Enable-NTFSAuditInheritance
-RemoveExplicitAccessRules is now -RemoveExplicitAuditRules. The old names
remain aliases, so existing scripts keep working.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Get-FileHash2 failed in PowerShell 7 for every algorithm, because the hash
method referenced RIPEMD160, which .NET Core and later lack. RIPEMD160 and
MACTripleDES are now created by name; requesting one where .NET lacks it
stops the cmdlet with an error that names the algorithm and points to
Windows PowerShell 5.1. MACTripleDES uses a random key, so its result
differs on every call; the value is deprecated, and the cmdlet warns when
it is used.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Copy-Item2, Move-Item2, and Remove-Item2 wrote the item with -PassThru
also when -WhatIf or a declined confirmation skipped the operation.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Defect 22:
- [OutputType]: Test-Path2 writes System.Boolean, not file objects;
Get-FileHash2 writes the file object with Hash and Algorithm, not access
rules; Add-NTFSAudit and Remove-NTFSAudit write audit entries since
defect 6; Copy-Item2, Move-Item2, Remove-Item2, and the five inheritance
cmdlets with -PassThru declared no type.
- Enable-Privileges and Disable-Privileges with -PassThru wrote the
privileges as one collection; they now enumerate it.
- New-NTFSSymbolicLink -PassThru returned a FileInfo for a link to a
folder; it now returns a DirectoryInfo.
The OUTPUTS sections of the pages name the same types.
Tests/OutputTypes.Tests.ps1 (new): 15 tests; Disable-Privileges and the
symbolic link need privileges and run in CI.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
The cmdlets that take ownership of an item to repeat a denied operation
left the account that ran them as the owner when the second attempt failed
as well. BaseCmdlet.InvokeAsOwner now restores the previous owner on every
exit path and reports a failed restore as RestoreOwnerError.
Add-NTFSAccess, Add-NTFSAudit, Remove-NTFSAccess, and Remove-NTFSAudit
wrote the unchanged entries of an item with -PassThru after a failed
change; they now continue with the next path.
The inheritance tests assert the error identity and cover a missing path
on every runner.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Found while fixing defect 3, in the same loop: the hash variable lived
outside the loop, and after a GetHashError the cmdlet still wrote a
result for the file, with the hash of the previous file. Each path now
starts without a hash, and a failed read writes only the error.
Tests/FileHash.Tests.ps1: 1 test with a file opened without sharing;
like the other Get-FileHash2 tests, it skips in PowerShell 7 until the
RIPEMD160 reference goes (decision D5).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Defect 21. For a -Target that didn't exist, New-NTFSHardLink failed with
"The target path exist, cannot create the link", the opposite of the
cause. The message now names the target and says that it does not exist.
Tests/Links.Tests.ps1 (new): 2 tests, one of them for a link that is
created.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Defect 20 (#74). Enable-NTFSAccessInheritance,
Disable-NTFSAccessInheritance, Enable-NTFSAuditInheritance,
Disable-NTFSAuditInheritance, and Set-NTFSInheritance wrote the
-PassThru object in a finally block. After a failed change, such as an
audit change without the Security privilege, they returned the unchanged
state, which made the inheritance look disabled; when the item could not
be read at all, reading the state in the finally block threw and stopped
the command. The object is now written only after a successful change.
Tests/Inheritance.Tests.ps1: 5 tests. The audit tests need the missing
privilege and skip in CI; the read-deny tests skip where the Backup
privilege may bypass the deny entry (CI).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Defect 19, and the same gap in Remove-NTFSAudit. After the ReadFileError
for a path that doesn't exist, both cmdlets went on with a null item: the
removal failed with a NullReferenceException that they reported as a
second, misleading RemoveAceError, and with -PassThru the null item
stopped the command. Both now continue with the next path.
Tests: Access.Tests.ps1 and Audit.Tests.ps1, 2 tests each.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Defect 18. Copy-Item2, Move-Item2, and Remove-Item2 left ProcessRecord
with "return" when a path didn't exist and, for copy and move, when the
destination file existed without -Force, so the remaining paths of the
same -Path array were not processed. They now write the error and
continue with the next path.
Tests/ItemCmdlets.Tests.ps1: 5 tests.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Write orphaned audit entries outside the read error handler, so that a
stopped pipeline isn't reported as a read error. Pass -RemoveSpecific
through the string path overload of RemoveFileSystemAuditRule, and state
on the Get-NTFSSimpleAccess page that the security descriptor of a file
is reported.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Security review of this branch, Major findings:
- M4: Get-NTFSAudit took ownership of an item whose SACL it couldn't
read. Ownership grants no access to the SACL, so the retry always
failed, and it left the owner changed. The cmdlet now writes a
ReadSecurityError with the category PermissionDenied, as Get-NTFSOwner
does since defect 9; the page says so.
- M1: Remove-TestSandbox reset the ACLs recursively before it removed the
links. Measured: icacls /reset /T did not follow the junction (the
target's explicit entry stayed), but the links now go first anyway; a
folder that denies listing gets a reset without /T. New test: the ACL
of a junction target stays unchanged.
- m4: Assert-TestSandboxPath now rejects a path below a link, which can
point outside the sandbox (new test, failed before).
- M5: the Inherits column reads one ACL per displayed item; the
Get-ChildItem2 page names the cost and how to avoid it.
- M2: the comment of the CI-only Get-NTFSAudit repeat test states what it
guards; Access.Tests.ps1 guards the same loop fix without elevation.
- M3, the stale hash of Get-FileHash2, is fixed on ai/defects-c.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Defect 17. Both cmdlets carried a removeSpecific field that no parameter
set, so they always took the rights away from matching entries; the
version history documents a -RemoveSpecific switch since 4.1. Both
cmdlets now have the switch, which removes only an entry that matches
exactly. The Security2 list overloads didn't pass the flag on, and the
audit item overload didn't support it; all overloads now do.
The applies-to field of both cmdlets is initialized; -AppliesTo is
mandatory in the Simple sets since defect 14, so it is always set when
used.
Tests: Access.Tests.ps1 3 tests, Audit.Tests.ps1 2 tests, on in-memory
security descriptors.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Defect 16. Get-NTFSOrphanedAccess, Get-NTFSOrphanedAudit, and
Get-NTFSSimpleAccess inherit -Account and -SecurityDescriptor from
Get-NTFSAccess or Get-NTFSAudit but override ProcessRecord without them:
- All three now filter by -Account and process security descriptors
(Get-NTFSOrphanedAudit writes an error for one read without its SACL,
like Get-NTFSAudit).
- Get-NTFSOrphanedAudit wrote the entries of each item as one collection;
it now writes one object per entry.
- Get-NTFSOrphanedAccess kept the entries of the previous item and wrote
them in a finally block, like Get-NTFSAccess before; each item now
starts empty.
- SimpleFileSystemAccessRule had no view; it gets a table with Account,
Access Rights, and Type, grouped by folder, with the grouping control
that existed for it but was unused.
Tests: Access.Tests.ps1 6 tests; Audit.Tests.ps1 2 tests, CI-only because
they add audit entries.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Defect 15, all three parts:
- -ExcludeNoneAccessEntries had no effect: the result was written in a
finally block, so "continue" didn't skip it, and the check compared the
rights with None although .NET adds Synchronize to every allow rule. A
result is now written only after the checks, and Synchronize alone
counts as no access.
- Without -Path, BeginProcessing tested the path list for null, which it
never is, so the cmdlet wrote nothing. It now uses the current location,
like the other cmdlets.
- ProcessRecord ignored the SecurityDescriptor parameter set. A new
EffectiveAccess overload computes the effective access from an
in-memory security descriptor; the item overload uses it.
The Security privilege state that selects the error message was read into
a local variable that hid the field; the field is now set.
Tests/Access.Tests.ps1: 4 tests.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Defect 14. Add-NTFSAccess, Remove-NTFSAccess, Add-NTFSAudit, and
Remove-NTFSAudit have the sets PathSimple, PathComplex, SDSimple, and
SDComplex; the default PathComplex needs -Path. A command with
-SecurityDescriptor and without -AppliesTo, -InheritanceFlags, or
-PropagationFlags matched both SD sets and failed with "Parameter set
cannot be resolved". -AppliesTo is now mandatory in the Simple sets, so
such a command resolves to the Complex set and its default flags
(ContainerInherit, ObjectInherit / None, which is what AppliesTo
ThisFolderSubfoldersAndFiles means), as a command with -Path already did.
With -AppliesTo nothing changes.
The pages say "Required: True" for -AppliesTo and drop its never
reachable defaults; platyPS takes that metadata from the shipped help
file, so the help file was regenerated before the build.
Tests/Access.Tests.ps1: 6 tests on in-memory security descriptors.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Defect 13. The Inherits column of the Children2 view, which formats the
Get-ChildItem2 output, negated the IsInheritanceBlocked property. The
module defines that property for System.IO.FileInfo and DirectoryInfo
only, not for the AlphaFS objects that Get-ChildItem2 returns, so the
column showed !$null, that is True, for every item. The view now reads
the protection of the DACL from the item.
Tests/ItemCmdlets.Tests.ps1: 2 tests on the formatted output.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Defect 12. Besides the base class, which enables the privileges only when
the module setting EnablePrivileges is $true and disables them again in
EndProcessing, the six inheritance cmdlets called
EnableFileSystemPrivileges in BeginProcessing unconditionally. With
EnablePrivileges = $false they enabled the privileges anyway and, because
EndProcessing disables them only when the setting is $true, left them
enabled. The extra calls are gone; the inheritance cmdlets now behave like
the other cmdlets.
Tests/Privileges.Tests.ps1: 6 tests, one per cmdlet, CI-only, because
they need a token that holds the privileges. Without the fix the Backup
privilege is enabled after each call.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>