Powershell: Test-Path -IsValid returns true for invalid path

Created on 4 Feb 2019  路  9Comments  路  Source: PowerShell/PowerShell

Steps to reproduce

[Windows]

Test-Path "c:\..\..\test" -IsValid

Expected behavior

False

Actual behavior

test-path : The path 'C:\..\..\test' referred to an item that was outside the base 'C:'.
At line:1 char:1
+ Test-Path "c:\..\..\test" -IsValid
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (:) [Test-Path], PSArgumentException
+ FullyQualifiedErrorId : System.Management.Automation.PSArgumentException,Microsoft.PowerShell.Commands.TestPathCommand

True

Environment data

Name                           Value
----                           -----
PSVersion                      6.2.0-preview.1
PSEdition                      Core
GitCommitId                    6.2.0-preview.1
OS                             Microsoft Windows 10.0.17134
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
Area-Cmdlets-Management Issue-Bug

Most helpful comment

@vexx32 Thanks! I am happy that New-Item doesn't create new item at root! :-)

All 9 comments

What is with other providers?

Tested that just now @iSazonov

It seems you get one error _per level_ you attempt to step above the root, which is very interesting! But you still get a True result.

#PowerShell 6.1.2
#Copyright (c) Microsoft Corporation. All rights reserved.

#https://aka.ms/pscore6-docs
#Type 'help' to get help.

#Loading personal and system profiles took 1860ms.
PS C:\Program Files\PowerShell\6> Test-Path HKLM:\..\..\..\test
Test-Path : The path 'HKEY_LOCAL_MACHINE\..\..\..\test' referred to an item that was outside the base 'HKEY_LOCAL_MACHINE'.
At line:1 char:1
+ Test-Path HKLM:\..\..\..\test
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (:) [Test-Path], PSArgumentException
+ FullyQualifiedErrorId : System.Management.Automation.PSArgumentException,Microsoft.PowerShell.Commands.TestPathCommand

Test-Path : The path 'HKEY_LOCAL_MACHINE\..\..\..\test' referred to an item that was outside the base 'HKEY_LOCAL_MACHINE'.
At line:1 char:1
+ Test-Path HKLM:\..\..\..\test
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (:) [Test-Path], PSArgumentException
+ FullyQualifiedErrorId : System.Management.Automation.PSArgumentException,Microsoft.PowerShell.Commands.TestPathCommand

Test-Path : The path 'HKEY_LOCAL_MACHINE\..\..\..\test' referred to an item that was outside the base 'HKEY_LOCAL_MACHINE'.
At line:1 char:1
+ Test-Path HKLM:\..\..\..\test
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (:) [Test-Path], PSArgumentException
+ FullyQualifiedErrorId : System.Management.Automation.PSArgumentException,Microsoft.PowerShell.Commands.TestPathCommand

True

I'm even afraid to think what will do New-Item :-)

@iSazonov that amusing comment led me to see the source of the issue. Check this out:

PS C:\Program Files\PowerShell\6> new-item HKLM:\..\..\..\test
new-item : The path 'HKEY_LOCAL_MACHINE\..\..\..\test' referred to an item that was outside the base 'HKEY_LOCAL_MACHINE'.
At line:1 char:1
+ new-item HKLM:\..\..\..\test
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (:) [New-Item], PSArgumentException
+ FullyQualifiedErrorId : System.Management.Automation.PSArgumentException,Microsoft.PowerShell.Commands.NewItemCommand

new-item : A key in this path already exists.
At line:1 char:1
+ new-item HKLM:\..\..\..\test
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : ResourceExists: (Microsoft.Power...RegistryWrapper:RegistryWrapper) [New-Item], IOException
+ FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.NewItemCommand

PS C:\Program Files\PowerShell\6> get-item HKLM:\..\..\..\test
get-item : The path 'HKEY_LOCAL_MACHINE\..\..\..\test' referred to an item that was outside the base 'HKEY_LOCAL_MACHINE'.
At line:1 char:1
+ get-item HKLM:\..\..\..\test
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (:) [Get-Item], PSArgumentException
+ FullyQualifiedErrorId : System.Management.Automation.PSArgumentException,Microsoft.PowerShell.Commands.GetItemCommand

get-item : The path 'HKEY_LOCAL_MACHINE\..\..\..\test' referred to an item that was outside the base 'HKEY_LOCAL_MACHINE'.
At line:1 char:1
+ get-item HKLM:\..\..\..\test
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (:) [Get-Item], PSArgumentException
+ FullyQualifiedErrorId : System.Management.Automation.PSArgumentException,Microsoft.PowerShell.Commands.GetItemCommand

get-item : The path 'HKEY_LOCAL_MACHINE\..\..\..\test' referred to an item that was outside the base 'HKEY_LOCAL_MACHINE'.
At line:1 char:1
+ get-item HKLM:\..\..\..\test
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (:) [Get-Item], PSArgumentException
+ FullyQualifiedErrorId : System.Management.Automation.PSArgumentException,Microsoft.PowerShell.Commands.GetItemCommand



    Hive:


Name                           Property
----                           --------
HKEY_LOCAL_MACHINE

So if you attempt to query a path like this, _first_ it errors on each level above the root (it seems to be checking recursively for some terrible reason!) and _then_ it reaches the root node itself and decides arbitrarily that _that_ is what you were trying to get.

Given the similarities in behaviour, this seems to be a common issue and may trace back to the providers themselves.

@vexx32 Thanks! I am happy that New-Item doesn't create new item at root! :-)

Yeah, it looks like it tries to re-create the root node itself, which is arguably _more_ surprising! 馃槅

Just stumbled on this as well as it's causing my PowerShell 6+ tests to fail for my PEMEncrypt module: https://dev.azure.com/scrthq/SCRT%20HQ/_build/results?buildId=352

Easily able to be reproduced with not even a legitimate path string, i.e. Test-Path '----------' -IsValid. Present in 6.2.0 and 7.0.0-preview.1

Falling back to [System.IO.File]::Exists($path) for now, as that still behaves as expected.

I think that's a different issue @scrthq.

As with other *-Path cmdlets, a path that doesn't contain a drive qualifier automatically defaults to checking against the current location. The name ---------- is a valid file or folder name, so that passing the test would be expected, I think.

That's a fair point. Maybe a better example is what I'm actually testing against (path string is valid). If I include -IsValid when testing a string that is 100% not a valid path string, PS 5.1.1 returns $false, while 6+ returns $true. My use case here is checking if the string is a valid path, as I am using it to determine if the string provided is a path string or not (regardless if the path itself is actual in the event that the string is a valid path string).

The bug outlined below currently make using Test-Path -IsValid unusable for me in PS 6+, so I have to fall back to .NET static methods directly and shortcut path validation by checking if the path exists (which it will never exist if the path is invalid, at the end of the day), as I can rely on that not throwing an error if the path string isn't valid at all. It will simply return $false, as needed.


Experience

Input

$string = @'
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxeBWfgeKhwp97v4EuFfO
.......
-----END PUBLIC KEY-----
'@
Test-Path $string -IsValid

PS 5.1.1 Output

_Returns $false, as expected_

False

PS 6+ Output

_Returns $true, unexpectedly_

True

The only way that PS 6+ returns $false for that call is if the string has an invalid path character in it, regardless if the string has line breaks/carriage returns.

Was this page helpful?
0 / 5 - 0 ratings