devblogs.microsoft.com Open in urlscan Pro
2a02:26f0:480:b9e::2f1e  Public Scan

URL: https://devblogs.microsoft.com/powershell/powershell-constrained-language-mode/
Submission: On October 18 via api from US — Scanned from DE

Form analysis 3 forms found in the DOM

Name: searchFormGET /search

<form class="c-search" autocomplete="off" id="searchForm" name="searchForm" role="search" action="/search" method="GET"
  data-seautosuggest="{&quot;queryParams&quot;:{&quot;market&quot;:&quot;en-us&quot;,&quot;clientId&quot;:&quot;7F27B536-CF6B-4C65-8638-A0F8CBDFCA65&quot;,&quot;sources&quot;:&quot;Microsoft-Terms,Iris-Products,DCatAll-Products&quot;,&quot;filter&quot;:&quot;+ClientType:StoreWeb&quot;,&quot;counts&quot;:&quot;5,1,5&quot;},&quot;familyNames&quot;:{&quot;Apps&quot;:&quot;App&quot;,&quot;Books&quot;:&quot;Book&quot;,&quot;Bundles&quot;:&quot;Bundle&quot;,&quot;Devices&quot;:&quot;Device&quot;,&quot;Fees&quot;:&quot;Fee&quot;,&quot;Games&quot;:&quot;Game&quot;,&quot;MusicAlbums&quot;:&quot;Album&quot;,&quot;MusicTracks&quot;:&quot;Song&quot;,&quot;MusicVideos&quot;:&quot;Video&quot;,&quot;MusicArtists&quot;:&quot;Artist&quot;,&quot;OperatingSystem&quot;:&quot;Operating System&quot;,&quot;Software&quot;:&quot;Software&quot;,&quot;Movies&quot;:&quot;Movie&quot;,&quot;TV&quot;:&quot;TV&quot;,&quot;CSV&quot;:&quot;Gift Card&quot;,&quot;VideoActor&quot;:&quot;Actor&quot;}}"
  data-seautosuggestapi="https://www.microsoft.com/msstoreapiprod/api/autosuggest"
  data-m="{&quot;cN&quot;:&quot;GlobalNav_Search_cont&quot;,&quot;cT&quot;:&quot;Container&quot;,&quot;id&quot;:&quot;c1c9c3m1r1a1&quot;,&quot;sN&quot;:1,&quot;aN&quot;:&quot;c9c3m1r1a1&quot;}" aria-expanded="false" style="overflow-x: visible;">
  <div class="x-screen-reader" aria-live="assertive"></div>
  <input id="cli_shellHeaderSearchInput" aria-label="Search Expanded" aria-autocomplete="list" aria-expanded="false" aria-controls="universal-header-search-auto-suggest-transparent" aria-owns="universal-header-search-auto-suggest-ul" type="search"
    name="query" role="combobox" placeholder="Search" data-m="{&quot;cN&quot;:&quot;SearchBox_nav&quot;,&quot;id&quot;:&quot;n1c1c9c3m1r1a1&quot;,&quot;sN&quot;:1,&quot;aN&quot;:&quot;c1c9c3m1r1a1&quot;}" data-toggle="tooltip" data-placement="right"
    title="" data-original-title="Search" style="overflow-x: visible;">
  <input type="hidden" name="blog" value="/powershell/" data-m="{&quot;cN&quot;:&quot;HiddenInput_nav&quot;,&quot;id&quot;:&quot;n2c1c9c3m1r1a1&quot;,&quot;sN&quot;:2,&quot;aN&quot;:&quot;c1c9c3m1r1a1&quot;}" style="overflow-x: visible;">
  <button id="search" aria-label="Search" class="c-glyph" data-m="{&quot;cN&quot;:&quot;Search_nav&quot;,&quot;id&quot;:&quot;n3c1c9c3m1r1a1&quot;,&quot;sN&quot;:3,&quot;aN&quot;:&quot;c1c9c3m1r1a1&quot;}" data-bi-mto="true" aria-expanded="false"
    style="overflow-x: visible;">
    <span role="presentation" style="overflow-x: visible;">Search</span>
    <span role="tooltip" class="c-uhf-tooltip c-uhf-search-tooltip" style="overflow-x: visible;">Search</span>
  </button>
  <div class="m-auto-suggest" id="universal-header-search-auto-suggest-transparent" role="group" style="overflow-x: visible;">
    <ul class="c-menu" id="universal-header-search-auto-suggest-ul" aria-label="Search Suggestions" aria-hidden="true" data-bi-dnt="true" data-bi-mto="true" data-js-auto-suggest-position="default" role="listbox" data-tel="jsll"
      data-m="{&quot;cN&quot;:&quot;search suggestions_cont&quot;,&quot;cT&quot;:&quot;Container&quot;,&quot;id&quot;:&quot;c4c1c9c3m1r1a1&quot;,&quot;sN&quot;:4,&quot;aN&quot;:&quot;c1c9c3m1r1a1&quot;}" style="overflow-x: visible;"></ul>
    <ul class="c-menu f-auto-suggest-no-results" aria-hidden="true" data-js-auto-suggest-postion="default" data-js-auto-suggest-position="default" role="listbox" style="overflow-x: visible;">
      <li class="c-menu-item" style="overflow-x: visible;"> <span tabindex="-1" style="overflow-x: visible;">No results</span></li>
    </ul>
  </div>
</form>

POST https://devblogs.microsoft.com/powershell?na=s

<form method="post" action="https://devblogs.microsoft.com/powershell?na=s" onsubmit="return newsletter_check(this)">
  <input type="hidden" name="nlang" value="">
  <div class="col-8 tnp-field tnp-field-email pull-left" style="margin-right:13px;width: 300px;margin-left: 30px;"><input style="border: 1px solid #CED4DA;background-color:#FFF;height: 34px;font-size: 14px;" class="tnp-email x-hidden-focus"
      type="email" name="ne" placeholder="Enter your email" required=""></div>
  <div style="padding:0 10px;" class="tnp-field tnp-field-button"><input style="background-color: #0072cc;padding: 6px 20px;height: 32px;font-size: 14px;" class="tnp-submit x-hidden-focus" type="submit" value="Subscribe">
    <div style="clear: both;"></div>
    <div class="tnp-field tnp-privacy-field"><label style="font-size: 14px;font-weight: normal;">By subscribing you agree to our <a href="https://docs.microsoft.com/en-us/collaborate/terms-of-use" target="_blank">Terms of Use</a> and
        <a href="https://privacy.microsoft.com/en-us/privacystatement" target="_blank">Privacy Policy</a></label></div>
  </div>
</form>

#

<form id="myForm" action="#">
  <div class="modal-body">
    <div class="form-group">
      <label for="code-text">Paste your code snippet</label>
      <textarea class="form-control" id="code-text" style="height: 150px;"></textarea>
    </div>
  </div>
  <div class="modal-footer">
    <button type="button" onclick="myCodeCancelFunction()" class="btn btn-primary" data-dismiss="modal">Cancel</button>
    <button type="button" onclick="myCodeFunction()" class="btn btn-primary">Ok</button>
  </div>
</form>

Text Content

Skip to main content
Microsoft
Powershell Team
Powershell Team
Powershell Team
 * Home
 * DevBlogs
 * Developer
    * Visual Studio
    * Visual Studio Code
    * Visual Studio for Mac
    * DevOps
    * Windows Developer
    * Developer support
    * ISE Developer
    * Engineering@Microsoft
    * Azure SDK
    * IoT
    * Command Line
    * Perf and Diagnostics
    * Dr. International
    * Notification Hubs
    * Math in Office
    * React Native

 * Technology
    * DirectX
    * PIX
    * Semantic Kernel
    * SurfaceDuo
    * Startups
    * Sustainable Engineering
    * Windows AI Platform

 * Languages
    * C++
    * C#
    * F#
    * Visual Basic
    * TypeScript
    * PowerShell Community
    * PowerShell Team
    * Python
    * Q#
    * JavaScript
    * Java
    * Java Blog in Chinese

 * .NET
    * All .NET posts
    * .NET MAUI
    * ASP.NET Core
    * Blazor
    * Entity Framework
    * ML.NET
    * NuGet
    * Servicing
    * Xamarin
    * .NET Blog in Chinese

 * Platform Development
    * #ifdef Windows
    * Azure Depth Platform
    * Azure Government
    * Azure VM Runtime Team
    * Bing Dev Center
    * Microsoft Edge Dev
    * Microsoft Azure
    * Microsoft 365 Developer
    * Microsoft Entra Identity Developer Blog
    * Old New Thing
    * Power Platform
    * Windows MIDI and Music dev
    * Windows Search Platform

 * Data Development
    * Azure Cosmos DB
    * Azure Data Studio
    * Azure SQL Database
    * OData
    * Revolutions R
    * SQL Server Data Tools

 * More

Theme
 * Light
 * Dark

Login

Search Search
 * No results

Cancel
Email Subscriptions are here!

Get notified in your email when a new post is published to this blog

Subscribe
Close


POWERSHELL CONSTRAINED LANGUAGE MODE

PowerShell Team



November 2nd, 20173 0


POWERSHELL CONSTRAINED LANGUAGE MODE



UPDATE (MAY 17, 2018)


In addition to the constraints listed in this article, system wide Constrained
Language mode now also disables the ScheduledJob module. The ScheduledJob
feature uses Dot Net serialization that is vulnerable to deserialization
attacks. So now whenever an application whitelisting solution is applied such as
DeviceGuard or AppLocker, PowerShell will run in Constrained Language mode and
also disable the ScheduledJob module. Use the Windows Task Scheduler or
PowerShell ScheduledTasks module as an alternative. For more information see
CVE-2018-0958.


WHAT IS POWERSHELL CONSTRAINED LANGUAGE?


PowerShell Constrained Language is a language mode of PowerShell designed to
support day-to-day administrative tasks, yet restrict access to sensitive
language elements that can be used to invoke arbitrary Windows APIs.

You can place a PowerShell session into Constrained Language mode simply by
setting a property:

PS C:\> $ExecutionContext.SessionState.LanguageMode
FullLanguage
PS C:\> $ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
PS C:\> $ExecutionContext.SessionState.LanguageMode
ConstrainedLanguage

PS C:\> [System.Console]::WriteLine("Hello")
Cannot invoke method. Method invocation is supported only on core types in this language mode.
At line:1 char:1
+ [System.Console]::WriteLine("Hello")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodInvocationNotSupportedInConstrainedLanguage

Of course, this is not secure. A user can simply start another PowerShell
session which will run in Full Language mode and have full access to PowerShell
features. As part of the implementation of Constrained Language, PowerShell
included an environment variable for debugging and unit testing called
__PSLockdownPolicy. While we have never documented this, some have discovered it
and described this as an enforcement mechanism. This is unwise because an
attacker can easily change the environment variable to remove this enforcement.
In addition, there are also file naming conventions that enable FullLanguage
mode on a script, effectively bypassing Constrained Language. Again, this is for
unit testing. These test hooks cannot override a Device Guard UMCI policy and
can only be used when no policy enforcement is applied.


THEN WHAT IS IT FOR?


PowerShell Constrained Language mode was designed to work with system-wide
application control solutions such as Device Guard User Mode Code Integrity
(UMCI). Application control solutions are an incredibly effective way to
drastically reduce the risk of viruses, ransomware, and unapproved software. For
DeviceGuard UMCI the approved applications are determined via a UMCI policy.
PowerShell automatically detects when a UMCI policy is being enforced on a
system and will run only in Constrained Language mode. So PowerShell Constrained
Language mode becomes more interesting when working in conjunction with
system-wide lockdown policies.

PowerShell’s detection of system policy enforcement through DeviceGuard is
supported only for Windows platform running Windows PowerShell version 5.1 or
PowerShell 7. It does not work on non-Windows platforms. So this is currently
very much a Windows security feature. However, we will continue to enhance this
for non-Windows platforms where feasible.

These lockdown policies are important for high-value systems that need to be
protected against malicious administrators or compromised administrator
credentials. With a policy enforced even administrators are limited to what they
can do on the system.

Since Constrained Language is so limited, you will find that many of the
approved scripts that you use for advanced systems management no longer work.
The solution to this is simple: add these scripts (or more effectively: your
code signing authority that signed them) to your Device Guard policy. This will
allow your approved scripts to run in Full Language mode.

For example, all PowerShell module files shipped with Windows (e.g.,
Install-WindowsFeature) are trusted and signed. The UMCI policy allowing signed
Windows files lets PowerShell run these modules in Full Language mode. But if
you create a custom PowerShell module that is not allowed by the policy then it
will be considered untrusted and run with Constrained Language restrictions.

Consequently, any PowerShell module marked as trusted in the policy needs to be
carefully reviewed for security vulnerabilities. A vulnerability could allow
code injection, or leak private functions not intended for public use. In either
case it could allow a user to run arbitrary code in Full Language mode, thus
bypassing the system policy protections.

We have described these dangers in much more detail in our post, “Writing Secure
PowerShell Scripts” (coming soon).


WHAT DOES CONSTRAINED LANGUAGE CONSTRAIN?


Constrained Language consists of a number of restrictions that limit
unconstrained code execution on a locked-down system. These restrictions are:

 * PowerShell module script files must explicitly export functions by name
   without the use of wildcard characters. This is to prevent inadvertently
   exposing powerful helper function not meant to be used publicly.
 * PowerShell module manifest files must explicitly export functions by name
   without the use of wildcards. Again, to prevent inadvertent exposure of
   functions.
 * COM objects are blocked. They can expose Win32 APIs that have likely never
   been rigorously hardened as part of an attack surface.
 * Only approved .NET types are allowed. Many .NET types can be used to invoke
   arbitrary Win32 APIs. As a result only specific whitelisted types are
   allowed.
 * Add-Type is blocked. It allows the creation of arbitrary types defined in
   different languages.
 * The use of PowerShell classes are disallowed. PowerShell classes are just
   arbitrary C# type definitions.
 * PowerShell type conversion is not allowed. Type conversion implicitly creates
   types and runs type constructors.
 * Dot sourcing across language modes is disallowed. Dot sourcing a script file
   brings all functions, variables, aliases from that script into the current
   scope. So this blocks a trusted script from being dot sourced into an
   untrusted script and exposing all of its internal functions. Similarly, an
   untrusted script is prevented from being dot sourced into a trusted script so
   that it cannot pollute the trusted scope.
 * Command resolution automatically hides commands you cannot run. For example,
   a function created in Constrained Language mode is not visible to script
   running in Full Language mode.
 * XAML based workflows are blocked since they cannot be constrained by
   PowerShell. But script based workflows and trusted XAML based workflows
   shipped in-box are allowed.
 * The SupportedCommand parameter for Import-LocalizedData is disabled. It
   allows additional commands prevented by Constrained Language.
 * Invoke-Expression cmdlet always runs in Constrained Language.
   Invoke-Expression cannot validate input as trusted.
 * Set-PSBreakpoint command is blocked unless there is a system-wide lockdown
   through UMCI.
 * Command completers are always run in Constrained Language. Command completers
   are not validated as trustworthy.
 * Commands and script run within the script debugger will always be run in
   Constrained Language if there is a system-wide lockdown.
 * The DSC Configuration keyword is disabled.
 * Supported commands and Statements are not allowed in script DATA sections.
 * Start-Job is unavailable if the system is not locked-down. Start-Job starts
   PowerShell in a new process and if the system is not locked-down the new
   process runs in Full Language mode.

As we can see, Constrained Language mode imposes some significant restrictions
on PowerShell. Nevertheless, it remains a formidable and capable shell and
scripting language. You can run native commands and PowerShell cmdlets and you
have access to the full scripting features: variables, statements, loops,
functions, arrays, hashtables, error handling, etc.


HOW IS THIS DIFFERENT FROM JEA?


PowerShell Constrained Language restricts only some elements of the PowerShell
language along with access to Win32 APIs. It provides full shell access to all
native commands and many cmdlets. It is not designed to operate independently
and needs to work with application control solutions such as UMCI to fully
lockdown a system and prevent access to unauthorized applications. Its purpose
is to provide PowerShell on a locked-down system without compromising the
system.

JEA (Just Enough Administration) is a sandboxed PowerShell remote session that
is designed to strictly limit what the logged on user can do. It is configured
in ‘no language mode’, has no access to file or other drive providers, and makes
only a small set of cmdlets available. These cmdlets are often custom and
designed to perform specific management functions without giving unfettered
access to the system. The set of cmdlets provided in the session is role based
(RBAC) and the session can be run in virtual or Group Managed Service accounts.

The JEA scenario is where an administrator needs to perform a management task on
a high-value machine (such as collect logs or restart a specific service). The
administrator creates a remote PowerShell session to the machine’s JEA endpoint.
Within that session the user has access to only those commands needed to perform
the task and cannot directly access the file system or the registry or run
arbitrary code.


SUMMARY


PowerShell Constrained Language is designed to work with application
whitelisting solutions in order to restrict what can be accessed in an
interactive PowerShell session with policy enforcement. You configure which
scripts are allowed full system access through the whitelisting solution policy.
In contrast, JEA is a sandboxed PowerShell remote session that restricts an
interactive session to specific commands based on user role.

Paul Higinbotham [MSFT] PowerShell Team





POWERSHELL TEAM POWERSHELL TEAM, POWERSHELL

Follow





READ NEXT

Azure Automation DSC Pricing Flexibility
Today we would like to share a new flexible pricing strategy for managing server
nodes using Azure Automation to deliver PowerShell Desired State Configuration,
giving ...
Michael Greene
November 14, 2017
0 comment
DSC Resource Kit Release November 2017
We just released the DSC Resource Kit! This release includes updates to 10 DSC
resource modules. In these past 6 weeks, 53 pull requests have been merged and
50 ...
Katie Keim [MSFT]
November 15, 2017
0 comment


3 COMMENTS

Comments are closed. Login to edit/delete your existing comments

 * Artem Pronichkin June 2, 2019 11:09 am 1
   collapse this comment copy link to this comment
   
   
   > We have described these dangers in much more detail in our post, “Writing
   Secure PowerShell Scripts” (coming soon).
   so, it’s been over a year already. Was it ever published? Where is it?
   if not, maybe it’s time to remove this announcement
   
   
   
 * Anthony Yates November 19, 2019 7:28 am 0
   collapse this comment copy link to this comment
   
   
   I realise this is old, but I am looking for a definition of what “Script
   Enforcement” does in Windows Defender Application Control.
   It certainly puts PowerShell into Constrained Language mode. BUT where is the
   logic for what scripts are allowed to run? This blog post says that signed
   scripts can run. But does that depend on WDAC allowing those signer
   certificates? And, if it does, then does that mean that any means of
   authorisising a script, not just certificates, also allows the script to run
   in Full Language mode?
   
   
   
 * Shurinbaal Addamasartus April 19, 2020 9:34 pm 0
   collapse this comment copy link to this comment
   
   
   constrained mode is useless when it comes to confidence of security…. dont
   rely on it
   
   
   

RELEVANT LINKS

 * PowerShell on GitHub
 * PowerShell Documentation

TOP BLOGGERS

Sydney Smith
PM



Steven Bucher
Product Manager



Jason Helmick
PROGRAM MANAGER 2



Steve Lee




Jim Truher
Senior Software Engineer



ARCHIVE

October 2023 September 2023 August 2023 July 2023 June 2023 May 2023 March 2023
February 2023 January 2023 December 2022 November 2022 October 2022 September
2022 August 2022 July 2022 June 2022 May 2022 March 2022 February 2022 January
2022 December 2021 November 2021 October 2021 August 2021 July 2021 June 2021
May 2021 April 2021 March 2021 February 2021 January 2021 December 2020 November
2020 October 2020 September 2020 August 2020 July 2020 June 2020 May 2020 April
2020 March 2020 February 2020 December 2019 November 2019 October 2019 September
2019 August 2019 July 2019 June 2019 May 2019 April 2019 March 2019 February
2019 January 2019 November 2018 October 2018 September 2018 August 2018 July
2018 June 2018 May 2018 April 2018 March 2018 February 2018 January 2018
December 2017 November 2017 October 2017 September 2017 August 2017 July 2017
June 2017 May 2017 April 2017 March 2017 February 2017 January 2017 December
2016 November 2016 October 2016 September 2016 August 2016 July 2016 June 2016
May 2016 April 2016 March 2016 February 2016 January 2016 December 2015 November
2015 October 2015 September 2015 August 2015 July 2015 June 2015 May 2015 April
2015 February 2015 December 2014 November 2014 October 2014 September 2014
August 2014 July 2014 June 2014 May 2014 April 2014 March 2014 February 2014
January 2014 December 2013 November 2013 October 2013 August 2013 July 2013 June
2013 April 2013 March 2013 January 2013 December 2012 October 2012 September
2012 August 2012 July 2012 June 2012 May 2012 April 2012 March 2012 February
2012 January 2012 December 2011 October 2011 September 2011 August 2011 July
2011 June 2011 May 2011 April 2011 March 2011 February 2011 January 2011
December 2010 November 2010 October 2010 September 2010 July 2010 June 2010 May
2010 April 2010 March 2010 February 2010 January 2010 December 2009 November
2009 October 2009 September 2009 August 2009 July 2009 June 2009 May 2009 April
2009 March 2009 February 2009 January 2009 December 2008 November 2008 October
2008 September 2008 August 2008 July 2008 June 2008 May 2008 April 2008 March
2008 February 2008 January 2008 December 2007 November 2007 October 2007
September 2007 August 2007 July 2007 June 2007 May 2007 April 2007 March 2007
February 2007 January 2007 December 2006 November 2006 October 2006 September
2006 August 2006 July 2006 June 2006 May 2006 April 2006 November 2001


STAY INFORMED

By subscribing you agree to our Terms of Use and Privacy Policy

 * 
 * 
 * 




CODE BLOCK

×
Paste your code snippet
Cancel Ok

Feedback

What's new
 * Surface Laptop Studio 2
 * Surface Laptop Go 3
 * Surface Pro 9
 * Surface Laptop 5
 * Surface Studio 2+
 * Copilot in Windows
 * Microsoft 365
 * Windows 11 apps

Microsoft Store
 * Account profile
 * Download Center
 * Microsoft Store support
 * Returns
 * Order tracking
 * Certified Refurbished
 * Microsoft Store Promise
 * Flexible Payments

Education
 * Microsoft in education
 * Devices for education
 * Microsoft Teams for Education
 * Microsoft 365 Education
 * How to buy for your school
 * Educator training and development
 * Deals for students and parents
 * Azure for students

Business
 * Microsoft Cloud
 * Microsoft Security
 * Dynamics 365
 * Microsoft 365
 * Microsoft Power Platform
 * Microsoft Teams
 * Microsoft Industry
 * Small Business

Developer & IT
 * Azure
 * Developer Center
 * Documentation
 * Microsoft Learn
 * Microsoft Tech Community
 * Azure Marketplace
 * AppSource
 * Visual Studio

Company
 * Careers
 * About Microsoft
 * Company news
 * Privacy at Microsoft
 * Investors
 * Diversity and inclusion
 * Accessibility
 * Sustainability

California Consumer Privacy Act (CCPA) Opt-Out Icon Your Privacy Choices
California Consumer Privacy Act (CCPA) Opt-Out Icon Your Privacy Choices
 * Sitemap
 * Contact Microsoft
 * Privacy
 * Manage cookies
 * Terms of use
 * Trademarks
 * Safety & eco
 * Recycling
 * About our ads
 * © Microsoft 2023