cobra icon indicating copy to clipboard operation
cobra copied to clipboard

Make Powershell completion work in constrained mode

Open lstemplinger opened this issue 1 year ago • 5 comments

Currently the Powershell completion script generated by Cobra does not work in constrained mode because creating CompletionResult Objects is blocked there.

This adds a check to the script that returns results as plain strings if constrained mode is enabled. Results in FullLanguage mode are unchanged.

So far I've tested with Powershell 5.1 on Windows 10, all three completion modes seem to work as expected even in constrained mode.

lstemplinger avatar Oct 09 '24 15:10 lstemplinger

CLA assistant check
All committers have signed the CLA.

CLAassistant avatar Oct 09 '24 15:10 CLAassistant

Cool! @lstemplinger of you could provide steps to test this in the restricted language mode it would be helpful

marckhouzam avatar Oct 09 '24 23:10 marckhouzam

Hi @marckhouzam ,

the test steps I'm using are:

  1. Put Powershell in constrained mode:
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
  1. Register completion for my program as usual:
my-cobra-program.exe completion powershell | Out-String | Invoke-Expression
  1. Type a partial my-cobra-program command and press tab

If i build my program with unmodified cobra 1.8.1 nothing happens, I don't get any completions (I assume Powershell tries to run the completion scriptblock and aborts once that hits an error). If I use my modified version, I get the expected completions just like in the normal FullLanguage mode.

To confirm that CompletionResult is the problem, I also tried manually creating one in a constrained session ([System.Management.Automation.CompletionResult]::new()), which failed with the error Cannot create type. Only core types are supported in this language mode.

lstemplinger avatar Oct 10 '24 13:10 lstemplinger

@lstemplinger Which version of pwsh are you running? I have 7.4.1 and the change does not work for me.

After some debugging I see that there is more code affected by the language restrictions The line $Values = $Values | Sort-Object -Property Name is failing for me:

PS /Users/kmarc> $ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"

# Imitate what the script does
PS /Users/kmarc> $Out = "bash zsh fish powershell"
PS /Users/kmarc> [Array]$Values = $Out | ForEach-Object {@{Name="$Name";Description=""}}
PS /Users/kmarc> $Values = $Values | Sort-Object -Property Name
Sort-Object: Cannot convert value "System.Collections.Hashtable" to type "System.Management.Automation.PSObject". Error: "Cannot convert hashtable to an object of the following type: System.Management.Automation.PSObject. Hashtable-to-Object conversion is not supported in restricted language mode or a Data section."

I'm not familiar much with powershell syntax, but maybe this can help you figure how to fix it?

To help you debug you can set the BASH_COMP_DEBUG_FILE environment variable to a file path and then the completion logic will print traces to that file which are triggered from the completion script at lines with __%[1]s_debug

marckhouzam avatar Oct 12 '24 13:10 marckhouzam

I was testing with v5.1 since that's what i expect most of my users will be on, and I didn't see any changes to constrained mode in later versions. It definitely works there, so seems like something changed with sort-object between those version.

I'll do some testing with 7.4 and see if i can figure out a fix.

lstemplinger avatar Oct 14 '24 15:10 lstemplinger

Storing results as PSCustomObjects instead of Hashtables fixed the issue for me. Sort-Object doesn't have to do any conversions that get blocked, and for the rest of the script accessing attributes works the same.

Tested using the same method as before on:

  • PS 5.1, FullLanguage: Works as before
  • PS 5.1 ConstrainedLanguage: Works as before
  • PS 7.4.5 FullLanguage: Works as before
  • PS 7.4.5 ConstrainedLanguage: Was broken, now works. I get the same expected completions

lstemplinger avatar Oct 22 '24 15:10 lstemplinger