Powershell: In RestrictedLanguage mode, an instance of a given type cannot be created with a cast, but can be created with New-Object

Created on 12 Nov 2020  路  11Comments  路  Source: PowerShell/PowerShell

Note: I may have a misconception here, but the difference in behavior strikes me as unusual.

Steps to reproduce

try {

  $ps = [powershell]::Create()
  $ps.Runspace.SessionStateProxy.LanguageMode = 'Restricted'

  try {
    $ps.AddScript('[regex] "."').Invoke()
    $ps.Streams.Error | Write-Warning
  }
  catch { Write-Warning $_ }

  $ps.Commands.Clear(); $ps.Streams.ClearStreams()

  try {
    $ps.AddScript('New-Object regex "."').Invoke()
    $ps.Streams.Error | Write-Warning
  }
  catch { Write-Warning $_ }

}
finally { $ps.Dispose() }

Expected behavior

Both attempts to create a [regex] instance should fail, because it appears that [regex] is not on an apparent, but undocumented whitelist of permitted types (the whitelist is only documented for ConstrainedLanguage); by contrast, a type such as [int] can be constructed successfully with either method ([int] 0 and New-Object int).

Actual behavior

The cast method fails, whereas the New-Object method succeeds:

WARNING: Exception calling "Invoke" with "0" argument(s): "At line:1 char:1
+ [regex] "."
+ ~~~~~~
+ The type regex is not allowed in restricted language mode or a Data section."

Options RightToLeft MatchTimeout
------- ----------- ------------
   None       False -00:00:00.0010000

Environment data

PowerShell Core 7.1.0
Issue-Bug WG-Security

Most helpful comment

I set Issue-Bug and WG-Security until team triages this.

All 11 comments

@mklement0 It affects all accelerators ? I try PSModuleInfo, same

try {

  $ps = [powershell]::Create()
  $ps.Runspace.SessionStateProxy.LanguageMode = 'Restricted'

  try {
    $ps.AddScript('[psmoduleinfo]::new($true)').Invoke()
  }
  catch { Write-Warning $_ }

  $ps.Commands.Clear(); $ps.Streams.ClearStreams()

  try {
    $ps.AddScript('New-Object psmoduleinfo $true').Invoke()
  }
  catch { Write-Warning $_ }

}
finally { $ps.Dispose() }

Same behavior on PS5.1

No, there are types that do work, such as [int].

about_Language_Modes only talks about a whitelist of permitted types for ConstrainedLanguage, but it looks like there is also one - a more restrictive one - for RestrictedLanguage, which seems to surface only with the casts (note that you cannot call ::new() in RestrictedLanguage mode, because no member access is allowed).

(Also, it's not about type _accelerators_ per se; you get the sam behavior if you use [System.Text.RegularExpressions.Regex]).

Import-LocalizedData use it.

https://github.com/PowerShell/PowerShell/blob/4b9b0788ed28ea6d463ce857d1ed81bd4a977a59/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Import-LocalizedData.cs#L173

After reading the 'about language modes', everything is working as described. You are only allowed to use command.

Look at the error message:

The type regex is not allowed in restricted language mode or a Data section.

Yet you can create an instance with New-Object.

So at the very least there is an inconsistency - and I don't know what the true intent is.

Also: [int] 42 works, for instance. Also note that in addition to commands _expressions_ are allowed, and a cast is an expression.

Furthermore: ConstrainedLanguage, which is generally _less_ restrictive, does not exhibit the same discrepancy; e.g., both [System.IO.FileInfo] "/" and New-Object System.IO.FileInfo "/" trigger the same error: Only core types are supported in this language mode

I was about to raise a similar issue based on the Docs issue Incomplete Allowed Types list #6884 I created yesterday:

$ExecutionContext.SessionState.LanguageMode = 'ConstrainedLanguage'
$test = [System.Collections.Specialized.OrderedDictionary]@{ a = 1 }

InvalidArgument: Cannot convert value to type "System.Collections.Specialized.OrderedDictionary".
Only core types are supported in this language mode.

But I am allowed to do this:

$test = [ordered]@{ a = 1 }
$Test.PSTypeNames
System.Collections.Specialized.OrderedDictionary
System.Object

@iRon7, it sounds like the _syntactic sugar_ is bypassing the permitted-type check ([ordered] @{ ...} isn't a regular cast).

IIRC (I ran into this years ago), this is also true for New-Object PSObject vs [pscustomobject]@{}

I set Issue-Bug and WG-Security until team triages this.

This sounds like a case where New-Object itself should have the same type restrictions applied for restricted language mode -- or else it's just an accepted security hole, which seems... well, odd.

@vexx32 there is precheck? and runtime check, i dont think runtime check in restricted mean no object, it only allows a list of cmdlet, some typecode
type and refuse scriptblock. The default is configured for Data first, so the default whitelist is not the default case, we should have in mind (like class for DSC, using for class, etc ...馃槒). RestrictedLanguage means NoLanguage configured for Data and Constrained is another area in the runspace linked to security mode.

Was this page helpful?
0 / 5 - 0 ratings