diff --git a/src/System.Management.Automation/engine/LanguagePrimitives.cs b/src/System.Management.Automation/engine/LanguagePrimitives.cs
index ac78e5e80d..87a6dcb780 100644
--- a/src/System.Management.Automation/engine/LanguagePrimitives.cs
+++ b/src/System.Management.Automation/engine/LanguagePrimitives.cs
@@ -3986,44 +3986,46 @@ namespace System.Management.Automation
// - It's in FullLanguage but not because it's part of a parameter binding that is transitioning from ConstrainedLanguage to FullLanguage
// When this is invoked from a parameter binding in transition from ConstrainedLanguage environment to FullLanguage command, we disallow
// the property conversion because it's dangerous.
- if (ecFromTLS == null || (ecFromTLS.LanguageMode == PSLanguageMode.FullLanguage && !ecFromTLS.LanguageModeTransitionInParameterBinding))
+ bool canProceedWithConversion = ecFromTLS == null || (ecFromTLS.LanguageMode == PSLanguageMode.FullLanguage && !ecFromTLS.LanguageModeTransitionInParameterBinding);
+ if (!canProceedWithConversion)
{
- result = _constructor();
- var psobject = valueToConvert as PSObject;
- if (psobject != null)
+ if (SystemPolicy.GetSystemLockdownPolicy() != SystemEnforcementMode.Audit)
{
- // Use PSObject properties to perform conversion.
- SetObjectProperties(result, psobject, resultType, CreateMemberNotFoundError, CreateMemberSetValueError, formatProvider, recursion, ignoreUnknownMembers);
- }
- else
- {
- // Use provided property dictionary to perform conversion.
- // The method invocation is disabled for "Hashtable to Object conversion" (Win8:649519), but we need to keep it enabled for New-Object for compatibility to PSv2
- IDictionary properties = valueToConvert as IDictionary;
- SetObjectProperties(result, properties, resultType, CreateMemberNotFoundError, CreateMemberSetValueError, enableMethodCall: false);
+ throw InterpreterError.NewInterpreterException(
+ valueToConvert,
+ typeof(RuntimeException),
+ errorPosition: null,
+ "HashtableToObjectConversionNotSupportedInDataSection",
+ ParserStrings.HashtableToObjectConversionNotSupportedInDataSection,
+ resultType.ToString());
}
- typeConversion.WriteLine("Constructor result: \"{0}\".", result);
- }
- else
- {
- if (SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Audit)
- {
- SystemPolicy.LogWDACAuditMessage(
+ // When in audit mode, we report but don't enforce, so we will proceed with the conversion.
+ SystemPolicy.LogWDACAuditMessage(
context: ecFromTLS,
title: ExtendedTypeSystem.WDACHashTypeLogTitle,
message: StringUtil.Format(ExtendedTypeSystem.WDACHashTypeLogMessage, resultType.FullName),
fqid: "LanguageHashtableConversionNotAllowed",
dropIntoDebugger: true);
- }
- else
- {
- RuntimeException rte = InterpreterError.NewInterpreterException(valueToConvert, typeof(RuntimeException), null,
- "HashtableToObjectConversionNotSupportedInDataSection", ParserStrings.HashtableToObjectConversionNotSupportedInDataSection, resultType.ToString());
- throw rte;
- }
}
+ result = _constructor();
+ var psobject = valueToConvert as PSObject;
+ if (psobject != null)
+ {
+ // Use PSObject properties to perform conversion.
+ SetObjectProperties(result, psobject, resultType, CreateMemberNotFoundError, CreateMemberSetValueError, formatProvider, recursion, ignoreUnknownMembers);
+ }
+ else
+ {
+ // Use provided property dictionary to perform conversion.
+ // The method invocation is disabled for "Hashtable to Object conversion" (Win8:649519), but we need to keep it enabled for New-Object for compatibility to PSv2
+ IDictionary properties = valueToConvert as IDictionary;
+ SetObjectProperties(result, properties, resultType, CreateMemberNotFoundError, CreateMemberSetValueError, enableMethodCall: false);
+ }
+
+ typeConversion.WriteLine("Constructor result: \"{0}\".", result);
+
return result;
}
catch (TargetInvocationException ex)
diff --git a/src/System.Management.Automation/engine/remoting/client/RunspaceRef.cs b/src/System.Management.Automation/engine/remoting/client/RunspaceRef.cs
index b3bfbe9a0d..f76b836885 100644
--- a/src/System.Management.Automation/engine/remoting/client/RunspaceRef.cs
+++ b/src/System.Management.Automation/engine/remoting/client/RunspaceRef.cs
@@ -5,6 +5,7 @@ using System.Collections.ObjectModel;
using System.Management.Automation.Internal;
using System.Management.Automation.Runspaces;
using System.Management.Automation.Runspaces.Internal;
+using System.Management.Automation.Security;
using Dbg = System.Management.Automation.Diagnostics;
@@ -94,7 +95,22 @@ namespace System.Management.Automation.Remoting
// to be parsed and evaluated on the remote session (not in the current local session).
RemoteRunspace remoteRunspace = _runspaceRef.Value as RemoteRunspace;
bool isConfiguredLoopback = remoteRunspace != null && remoteRunspace.IsConfiguredLoopBack;
- bool isTrustedInput = !isConfiguredLoopback && (localRunspace.ExecutionContext.LanguageMode == PSLanguageMode.FullLanguage);
+
+ bool inFullLanguage = context.LanguageMode == PSLanguageMode.FullLanguage;
+ if (context.LanguageMode == PSLanguageMode.ConstrainedLanguage
+ && SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Audit)
+ {
+ // In audit mode, report but don't enforce.
+ inFullLanguage = true;
+ SystemPolicy.LogWDACAuditMessage(
+ context: context,
+ title: RemotingErrorIdStrings.WDACGetPowerShellLogTitle,
+ message: RemotingErrorIdStrings.WDACGetPowerShellLogMessage,
+ fqid: "GetPowerShellMayFail",
+ dropIntoDebugger: true);
+ }
+
+ bool isTrustedInput = !isConfiguredLoopback && inFullLanguage;
// Create PowerShell from ScriptBlock.
ScriptBlock scriptBlock = ScriptBlock.Create(context, line);
@@ -350,7 +366,7 @@ namespace System.Management.Automation.Remoting
///
private void HandleHostCall(object sender, RemoteDataEventArgs eventArgs)
{
- System.Management.Automation.Runspaces.Internal.ClientRemotePowerShell.ExitHandler(sender, eventArgs);
+ ClientRemotePowerShell.ExitHandler(sender, eventArgs);
}
#region Robust Connection Support
diff --git a/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs b/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs
index c633fd9fe5..3c38a3b5bd 100644
--- a/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs
+++ b/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs
@@ -2278,7 +2278,7 @@ namespace Microsoft.PowerShell.Commands
// Semantic checks on the using statement have already validated that there are no arbitrary expressions,
// so we'll allow these expressions in everything but NoLanguage mode.
- bool allowUsingExpressions = (Context.SessionState.LanguageMode != PSLanguageMode.NoLanguage);
+ bool allowUsingExpressions = Context.SessionState.LanguageMode != PSLanguageMode.NoLanguage;
object[] usingValuesInArray = null;
IDictionary usingValuesInDict = null;
@@ -2428,7 +2428,7 @@ namespace Microsoft.PowerShell.Commands
// GetExpressionValue ensures that it only does variable access when supplied a VariableExpressionAst.
// So, this is still safe to use in ConstrainedLanguage and will not result in arbitrary code
// execution.
- bool allowVariableAccess = (Context.SessionState.LanguageMode != PSLanguageMode.NoLanguage);
+ bool allowVariableAccess = Context.SessionState.LanguageMode != PSLanguageMode.NoLanguage;
foreach (var varAst in paramUsingVars)
{
diff --git a/src/System.Management.Automation/engine/runtime/Binding/Binders.cs b/src/System.Management.Automation/engine/runtime/Binding/Binders.cs
index c93041a7b6..3e3ec3fbca 100644
--- a/src/System.Management.Automation/engine/runtime/Binding/Binders.cs
+++ b/src/System.Management.Automation/engine/runtime/Binding/Binders.cs
@@ -5524,7 +5524,7 @@ namespace System.Management.Automation.Language
return target.ThrowRuntimeError(args, moreTests, errorID, resourceString);
}
- string targetName = (targetValue as Type)?.FullName;
+ string targetName = (targetValue as Type)?.FullName ?? targetValue?.GetType().FullName;
SystemPolicy.LogWDACAuditMessage(
context: context,
title: ParameterBinderStrings.WDACBinderInvocationLogTitle,
diff --git a/src/System.Management.Automation/engine/runtime/Operations/MiscOps.cs b/src/System.Management.Automation/engine/runtime/Operations/MiscOps.cs
index eb3100ea51..8452c27b98 100644
--- a/src/System.Management.Automation/engine/runtime/Operations/MiscOps.cs
+++ b/src/System.Management.Automation/engine/runtime/Operations/MiscOps.cs
@@ -714,6 +714,18 @@ namespace System.Management.Automation
// of invoking it. So the trustworthiness is defined by the trustworthiness of the
// script block's language mode.
bool isTrusted = scriptBlock.LanguageMode == PSLanguageMode.FullLanguage;
+ if (scriptBlock.LanguageMode == PSLanguageMode.ConstrainedLanguage
+ && SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Audit)
+ {
+ // In audit mode, report but don't enforce.
+ isTrusted = true;
+ SystemPolicy.LogWDACAuditMessage(
+ context: context,
+ title: ParserStrings.WDACGetSteppablePipelineLogTitle,
+ message: ParserStrings.WDACGetSteppablePipelineLogMessage,
+ fqid: "GetSteppablePipelineMayFail",
+ dropIntoDebugger: true);
+ }
foreach (var commandAst in pipelineAst.PipelineElements.Cast())
{
@@ -729,7 +741,7 @@ namespace System.Management.Automation
var exprAst = (ExpressionAst)commandElement;
var argument = Compiler.GetExpressionValue(exprAst, isTrusted, context);
- var splatting = (exprAst is VariableExpressionAst && ((VariableExpressionAst)exprAst).Splatted);
+ var splatting = exprAst is VariableExpressionAst && ((VariableExpressionAst)exprAst).Splatted;
commandParameters.Add(CommandParameterInternal.CreateArgument(argument, exprAst, splatting));
}
@@ -797,8 +809,8 @@ namespace System.Management.Automation
}
object argumentValue = Compiler.GetExpressionValue(argumentAst, isTrusted, context);
- bool spaceAfterParameter = (errorPos.EndLineNumber != argumentAst.Extent.StartLineNumber ||
- errorPos.EndColumnNumber != argumentAst.Extent.StartColumnNumber);
+ bool spaceAfterParameter = errorPos.EndLineNumber != argumentAst.Extent.StartLineNumber ||
+ errorPos.EndColumnNumber != argumentAst.Extent.StartColumnNumber;
return CommandParameterInternal.CreateParameterWithArgument(commandParameterAst, commandParameterAst.ParameterName,
errorPos.Text, argumentAst, argumentValue,
spaceAfterParameter);
diff --git a/src/System.Management.Automation/resources/ParserStrings.resx b/src/System.Management.Automation/resources/ParserStrings.resx
index 5631525cac..a45a5165b0 100644
--- a/src/System.Management.Automation/resources/ParserStrings.resx
+++ b/src/System.Management.Automation/resources/ParserStrings.resx
@@ -1361,4 +1361,10 @@ ModuleVersion : Version of module to import. If used, ModuleName must represent
The ForEach keyword will fail '{0}' iteration item method invocation when run in Constrained Language mode.
+
+ Expression Evaluation May Fail
+
+
+ Creating a steppable pipeline from a script block may require evaluating some expressions within the script block. The expression evaluation will silently fail and return 'null' in Constrained Language mode, unless the expression represents a constant value.
+
diff --git a/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx b/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx
index f65d536f63..c45416edb4 100644
--- a/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx
+++ b/src/System.Management.Automation/resources/RemotingErrorIdStrings.resx
@@ -1714,4 +1714,10 @@ SSH client process terminated before connection could be established.
The session configuration file contains an unknown configuration option: {0}.
+
+ Expression Evaluation May Fail
+
+
+ Creating a PowerShell object from a script block may require evaluating some expressions within the script block. The expression evaluation will silently fail and return 'null' in Constrained Language mode, unless the expression represents a constant value.
+