Browse Source

fix: stop processing a path that Remove-NTFSAccess could not read

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>
pull/102/head
Raimund Andree 1 week ago
parent
commit
d679b06ea2
  1. 3
      CHANGELOG.md
  2. 2
      Docs/Cmdlets/Remove-NTFSAccess.md
  3. 2
      Docs/Cmdlets/Remove-NTFSAudit.md
  4. 1
      NTFSSecurity/AccessCmdlets/RemoveAccess.cs
  5. 1
      NTFSSecurity/AuditCmdlets/RemoveAudit.cs
  6. 2
      NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml
  7. 19
      Tests/Access.Tests.ps1
  8. 19
      Tests/Audit.Tests.ps1

3
CHANGELOG.md

@ -115,5 +115,8 @@ The format is based on
- Fix `Copy-Item2`, `Move-Item2`, and `Remove-Item2`, which skipped the
remaining paths of `-Path` after a path that didn't exist or, for copy and
move, a file that already existed at the destination
- Fix `Remove-NTFSAccess` and `Remove-NTFSAudit`, which went on with a path
that didn't exist, wrote a second, misleading `RemoveAceError`, and with
`-PassThru` stopped with a `NullReferenceException`
[Unreleased]: https://github.com/raandree/NTFSSecurity/compare/4.2.6...HEAD

2
Docs/Cmdlets/Remove-NTFSAccess.md

@ -306,6 +306,8 @@ Removing rights from an entry that does not exist is not an error; the cmdlet le
Before 5.0.0, the `-RemoveSpecific` switch was missing, although version 4.1 had introduced it.
A path that does not exist produces the non-terminating error `ReadFileError`, and the cmdlet continues with the next path. Before 5.0.0, the cmdlet also wrote a misleading `RemoveAceError` for that path, and with `-PassThru` it stopped with a `NullReferenceException`.
## RELATED LINKS
[Get-NTFSAccess](Get-NTFSAccess.md)

2
Docs/Cmdlets/Remove-NTFSAudit.md

@ -308,6 +308,8 @@ The cmdlet reports no error when no entry matches the supplied values. Compare t
Before 5.0.0, the cmdlet had no `-RemoveSpecific` switch.
A path that does not exist produces the non-terminating error `ReadFileError`, and the cmdlet continues with the next path. Before 5.0.0, the cmdlet also wrote a misleading `RemoveAceError` for that path, and with `-PassThru` it stopped with a `NullReferenceException`.
## RELATED LINKS
[Get-NTFSAudit](Get-NTFSAudit.md)

1
NTFSSecurity/AccessCmdlets/RemoveAccess.cs

@ -138,6 +138,7 @@ namespace NTFSSecurity
catch (Exception ex)
{
WriteError(new ErrorRecord(ex, "ReadFileError", ErrorCategory.OpenError, path));
continue;
}
if (ParameterSetName == "PathSimple")

1
NTFSSecurity/AuditCmdlets/RemoveAudit.cs

@ -137,6 +137,7 @@ namespace NTFSSecurity
catch (Exception ex)
{
WriteError(new ErrorRecord(ex, "ReadFileError", ErrorCategory.OpenError, path));
continue;
}
if (ParameterSetName == "PathSimple")

2
NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml

@ -8385,6 +8385,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
<maml:para>If the ACL of an item cannot be written because access is denied, the cmdlet tries once more after making the current account the owner of the item, and restores the previous owner afterwards. Changing the owner of an item requires the Take Ownership and Restore privileges, so this fallback only succeeds in an elevated session of an account that holds them.</maml:para>
<maml:para>Removing rights from an entry that does not exist is not an error; the cmdlet leaves the ACL unchanged.</maml:para>
<maml:para>Before 5.0.0, the `-RemoveSpecific` switch was missing, although version 4.1 had introduced it.</maml:para>
<maml:para>A path that does not exist produces the non-terminating error `ReadFileError`, and the cmdlet continues with the next path. Before 5.0.0, the cmdlet also wrote a misleading `RemoveAceError` for that path, and with `-PassThru` it stopped with a `NullReferenceException`.</maml:para>
</maml:alert>
</maml:alertSet>
<command:examples>
@ -9224,6 +9225,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
<maml:para>If the security descriptor cannot be read or written because access is denied, the cmdlet takes ownership of the item, repeats the operation, and restores the previous owner. If the second attempt fails as well, the cmdlet writes an error, and the ownership change is not rolled back.</maml:para>
<maml:para>The cmdlet reports no error when no entry matches the supplied values. Compare the result with `Get-NTFSAudit` to confirm that the entry is gone.</maml:para>
<maml:para>Before 5.0.0, the cmdlet had no `-RemoveSpecific` switch.</maml:para>
<maml:para>A path that does not exist produces the non-terminating error `ReadFileError`, and the cmdlet continues with the next path. Before 5.0.0, the cmdlet also wrote a misleading `RemoveAceError` for that path, and with `-PassThru` it stopped with a `NullReferenceException`.</maml:para>
</maml:alert>
</maml:alertSet>
<command:examples>

19
Tests/Access.Tests.ps1

@ -149,6 +149,25 @@ Describe 'Get-NTFSSimpleAccess' {
}
Describe 'Remove-NTFSAccess' {
Context 'When a path does not exist' {
BeforeAll {
$missing = Join-Path -Path $sandbox -ChildPath 'Missing.txt'
}
# Before 5.0.0, the cmdlet went on with the missing item and wrote a second, misleading RemoveAceError.
It 'Should write only the read error' {
Remove-NTFSAccess -Path $missing -Account 'Everyone' -AccessRights ReadData -ErrorVariable removeErrors -ErrorAction SilentlyContinue
$removeErrors | Should -HaveCount 1
$removeErrors[0].FullyQualifiedErrorId | Should -BeLike 'ReadFileError,*'
}
It 'Should not stop with -PassThru' {
{ Remove-NTFSAccess -Path $missing -Account 'Everyone' -AccessRights ReadData -PassThru -ErrorAction SilentlyContinue } |
Should -Not -Throw
}
}
Context 'With -RemoveSpecific' {
BeforeEach {
$removeFolder = New-TestSandboxItem -Sandbox $sandbox -Name 'RemoveSpecific' -Directory

19
Tests/Audit.Tests.ps1

@ -148,6 +148,25 @@ Describe 'Get-NTFSOrphanedAudit' {
}
Describe 'Remove-NTFSAudit' {
Context 'When a path does not exist' {
BeforeAll {
$missing = Join-Path -Path $sandbox -ChildPath 'Missing.txt'
}
# Before 5.0.0, the cmdlet went on with the missing item and wrote a second, misleading RemoveAceError.
It 'Should write only the read error' {
Remove-NTFSAudit -Path $missing -Account 'Everyone' -AccessRights ReadData -ErrorVariable removeErrors -ErrorAction SilentlyContinue
$removeErrors | Should -HaveCount 1
$removeErrors[0].FullyQualifiedErrorId | Should -BeLike 'ReadFileError,*'
}
It 'Should not stop with -PassThru' {
{ Remove-NTFSAudit -Path $missing -Account 'Everyone' -AccessRights ReadData -PassThru -ErrorAction SilentlyContinue } |
Should -Not -Throw
}
}
Context 'With -RemoveSpecific' {
BeforeEach {
$removeFolder = New-TestSandboxItem -Sandbox $sandbox -Name 'RemoveSpecific' -Directory

Loading…
Cancel
Save