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>
PowerShell 7 has no static File.GetAccessControl, because .NET Core made
it an extension method, so the assertion of the -PassThru test passed
there for the wrong reason: the method was missing. The test now reads
with FileInfo.GetAccessControl or FileSystemAclExtensions and expects an
UnauthorizedAccessException in both editions.
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>
Add tests from the contract of its cmdlet page: the security descriptor
parameter set, an inherited entry with and without -ExcludeInherited, an
entry of an account that resolves, the verbose count, the error for a
missing path and for a descriptor without the audit entries, and the
result without the Security privilege, which the page describes as empty.
The setup of the entries moves into BeforeAll, so that the -Account test
no longer depends on the test before it (#110).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Record in activeContext the link cmdlet tests, the two corrections of the
New-NTFSSymbolicLink page with the lab check of Developer Mode, the
security review of fcb370e..00c3646 and its fix round, the next step, and
the open question about unprivileged symbolic links. Add the milestone to
progress, the cleanup rule for privileges to systemPatterns, and the way
to check the lab client as an account without administrator rights to
techContext.
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>
A cmdlet that enables the Backup, Restore, Take Ownership, and Security
privileges decided which ones to disable on the states that it had read
when it enabled them, and stopped at the first one that failed. When
another command in the pipeline, such as Disable-Privileges, had disabled
one of them, the cmdlet stopped with "Priviledge already disabled" and
left the privileges after that one enabled. After an early stop, which
Dispose handles since this branch, it left them enabled without any
message, because PowerShell ignores exceptions thrown in Dispose; and
Disable-Privileges threw that exception in Dispose on every call while
the privileges were disabled. 4.2.6 already decided on the old states.
DisablePrivilege now reads the current state, and the cleanup tries every
privilege: in EndProcessing, a privilege that it can't disable gives a
warning; in Dispose, it is ignored.
The early-stop tests now pin EnablePrivileges and check that the cmdlet
had enabled the privileges, so that they can't pass without testing
anything.
Found by the security review of fcb370e..00c3646 (findings 1 to 3).
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>
Add 18 tests for New-NTFSHardLink, Get-NTFSHardLink, and
New-NTFSSymbolicLink from the contracts of their cmdlet pages: output with
and without -PassThru, relative paths, the refusal of an existing -Path and
of a folder as the target of a hard link, the non-terminating errors for
missing paths, and the error 1314 without the right to create symbolic
links, compared by its HRESULT because the message is localized.
The tests that need SeCreateSymbolicLinkPrivilege skip without it, and the
test without it skips with it. Elevated and as a basic user, in Windows
PowerShell 5.1 and PowerShell 7, all 20 link tests pass, and each one runs
in at least one of the four configurations.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Record the new tests, the two defects that they found, and the privilege
handling in Dispose since 5.0.0-rc6.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Set-NTFSOwner ran in no test of its own. Cover the owner change with and
without -PassThru, pipeline input, an owner that only the Restore
privilege allows, a missing path, an owner that Windows refuses (1307),
and the -SecurityDescriptor parameter set.
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>
The cmdlets that enable the Backup, Restore, Take Ownership, and Security
privileges disabled them only in EndProcessing, which PowerShell skips
when a later command, such as Select-Object -First, or a terminating
error stops the pipeline. The privileges then stayed enabled in the
session. BaseCmdletWithPrivControl now implements IDisposable and
disables them in Dispose as well; Enable-Privileges keeps them.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Record the release of 5.0.0-rc5, Phase 1 of the quality gate that the
maintainer set before 5.0.0 (Decision 21): the published package passes
the live tests, every test runs in at least one configuration, and the
suite runs 55.9% of the C# lines and 37.4% of the branches. Record the
coverage measurement with AltCover, the GitHub CLI on the third
workstation, and the plan of Phase 2, which ends with 5.0.0-rc6.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Record the results of the live tests against 5.0.0-rc2, 5.0.0-rc4, and
the rc5 build, Decision 20 for the location of the live tests, the third
workstation, the deferred review findings, and the next steps to 5.0.0.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Set the prerelease label rc5, and add 5.0.0-rc4 to the versions that the
PowerShell Gallery already has.
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>
Add Tests\Lab, which runs the module against a Windows file server with
domain accounts in an AutomatedLab lab: #34 over SMB, the audit cmdlets
over SMB, Get-NTFSEffectiveAccess with domain and file server groups,
Get-NTFSOrphanedAccess with a deleted domain account, long paths on a
share, and #108. Invoke-NTFSSecurityLabTest.ps1 prepares the lab and
runs the tests per module version and PowerShell edition; without a
lab, every live test skips. CI excludes the folder.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
- activeContext: the maintainer decided to run live tests of 5.0.0-rc4 in
a lab before 5.0.0, on another workstation with his lab script; the four
cases that no local test covers (#34 and the audit cmdlets over SMB,
effective access with domain accounts and -ServerName, orphaned entries
of a deleted domain account), against rc2 as the baseline and rc4; the
tester feedback on IBM ESS expected in #34.
- progress: 5.0.0 waits for the live tests and the #34 feedback.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
- progress and activeContext: 5.0.0-rc4 published from 01d9264; #41,
#108, #109, and #111 closed as completed, #90 and #107 as not planned;
the deferred review findings are listed in #113; 5.0.0 is next.
- techContext: the label rc4 and the Gallery versions; AlphaFS reaches the
device object for a drive or volume root through DirectoryInfo and the
root folder through the path methods; stale lines shortened.
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>
Set the prerelease label rc4, and add 5.0.0-rc3 to the versions that the
PowerShell Gallery already has.
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>
- progress and activeContext: 5.0.0-rc3 published from 914e8da; #34
reopened for a tester, #67 closed as not planned; 5.0.0 is next.
- Decision 19: the cmdlets write only the sections that they change.
Decision 18: the Gallery description announces the archive, and the
module writes no warning on import.
- techContext: the label rc3 and the Gallery versions; commands for the
maintainer as code blocks at the end of the reply; no closing keywords
in pull requests unless the merge should close the issue; test runs as a
basic user; stale lines removed.
- systemPatterns: Decision 19 in the index, and Set-TestOwner.
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>
- Set the prerelease label rc3, and add 5.0.0-rc2 to the versions that
the PowerShell Gallery already has.
- Extend the description of the manifest, which the PowerShell Gallery
shows, with the archive note (maintainer decision of 2026-10-06,
Decision 18).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Written through its UNC path, the DACL of a share root can't re-inherit
from the parent folder on the server: Windows drops the inherited entries
of a DACL in the auto-inherit format and stores the others as explicit
copies. icacls and Set-Acl behave the same; a subfolder through the share
and the local path keep them (#67).
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>
The maintainer decided on 2026-10-06 to publish 5.0.0-rc3 before 5.0.0
and to archive NTFSSecurity in favor of WindowsAccessControl.
- Decision 18: the project will be archived; the notes in the README,
the docs home, and the changelog stay until then.
- activeContext: rc3 is the focus. #34 reproduces locally with rc2, on a
file owned by TrustedInstaller without the Restore privilege, so CI can
test the fix without a file server.
- progress: rc3, then 5.0.0, with the version steps of each.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
NTFSSecurity will be archived soon. The README, the documentation home,
which is also the wiki home, and the changelog now point users to
WindowsAccessControl, which is on the PowerShell Gallery. The changelog
entry also reaches the release notes of the next prerelease.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
The maintainer approved a label scheme on 2026-10-06, and it was applied
to the 42 issues triaged on 2026-10-05, with the new label Needs Info for
issues that wait for their reporters.
- Decision 17: the meaning of each label and the close reasons.
- activeContext and progress: the labels are applied; five issues wait
for their reporters.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
5.0.0-rc2 is on the PowerShell Gallery and in the GitHub releases. The
PRs #99 to #106 were merged in order with merge commits, CI on master
passed, and the tag 5.0.0-rc2 on 7ddda8d published it on the third
attempt of the release run, after GitHub's Actions outage of 2026-10-05.
The open issues got their replies, 16 were closed, and the follow-up
issues #107 to #111 track the open Minor review findings.
- Decision 14: repository hardening is optional; the outdated "pending"
text is gone.
- Decision 15: merge stacked pull requests in order with merge commits.
- Decision 16: fix only reproducible bugs (the maintainer's decision D6).
- activeContext and progress: the CI fix 629f4e7, the copied inherited
entries behind #34, the issue state, and the next step (test rc2, then
5.0.0 or rc3).
- techContext: the current versions, the second workstation, and
one-line commands for the maintainer.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Enable-NTFSAuditInheritance, Disable-NTFSAuditInheritance, and
Set-NTFSInheritance -AuditInheritanceEnabled failed with "(5) Access is
denied" for a file or folder without a SACL, also elevated with the
Security privilege. The cmdlets read only the audit section and changed
the flag that disables or enables audit inheritance. AlphaFS writes that
flag only together with a SACL, so it wrote no section at all, which
Windows denies; the retry as owner repeated the same write. An empty SACL
is now added first, but only to a descriptor that was read with its SACL.
The elevated CI runs of #100 to #106 showed this through the test of an
omitted -AccessInheritanceEnabled. From #104 on, the test that keeps the
inherited entries of a security descriptor failed as well: elevated,
Get-NTFSSecurityDescriptor reads the SACL, and Windows then returns a DACL
that isn't in the auto-inherit format, such as that of a file in the temp
folder of the user, without its inherited flags. The test now reads the
access section only and checks that the descriptor has inherited entries.
Tests: five cases for items without audit entries, red with "Access is
denied" before the fix; the test that keeps the explicit audit entries now
checks the errors and the inheritance state of both calls; a test checks
that a descriptor read without its audit entries gets no SACL, which would
replace the audit entries of the item when it is written.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Keep the details of the pending repository settings out of the Memory
Bank, which is public. Replace the test for the one published version with a
list of the versions that the PowerShell Gallery has, which the release guide
now asks to maintain, and name the description test after its assertion.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Remove the fixed defects from progress.md, rewrite activeContext.md for the
maintainer, and curate systemPatterns.md below its line budget.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Set the prerelease label rc2, describe the module as a PowerShell module in
the manifest, which the PowerShell Gallery shows, and keep the README free
of a prerelease version, which outlives the release. Tests check the
description, that the published 5.0.0-rc1 isn't reused, and the README.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>