Tuesday, February 7, 2017

PowerShell-defined classes' methods are restricted by the runspace they're invoked in

In PowerShell 5, you can define your own .NET types in a script. They can have fields and methods, just like all .NET classes. Method bodies are written in PowerShell. Therefore, you can implement full cmdlet types (not just advanced functions) in PowerShell and allow them to be used in constrained-language runspaces.

Unfortunately, when the method body is run from such a limited runspace, it is subject to the caller's restrictions. This doesn't appear to be for security reasons, since you could just define the type in C# with Add-Type and then approve that cmdlet type for execution in the runspace. Here is a script to test this:

Class TestCmdlet : System.Management.Automation.Cmdlet {
 [void]BeginProcessing() {
  $this.WriteObject('It worked!')
 }
}
$iss = [InitialSessionState]::Create()
$testssce = New-Object System.Management.Automation.Runspaces.SessionStateCmdletEntry ('Test-CustomCmdlet', [TestCmdlet], '')
$iss.Commands.Add($testssce)
$rs = [RunspaceFactory]::CreateRunspace($iss)
$rs.Open()
$rs.LanguageMode = 'ConstrainedLanguage'
$p = $rs.CreatePipeline('Test-CustomCmdlet')
$p.Invoke()

It should return the string It worked!, but it will actually fail with CmdletInvocationException because the script-defined type cannot call its own methods.

I have written a very simple change to a fork of the PowerShell code base that makes this example work. I will see if it can/should be implemented in the real PowerShell.

No comments:

Post a Comment