I thought that might be the case. Sadly don't think we can use RestrictedRemoteServer as the usage needs access to things like if conditions, loop etc.
I'll have to investigate the LanguageMode setting I think
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
I have a question about JEA restrictions on executables (VisibleExternalCommands).
I've setup a JEA endpoint (SessionType = Default) which allows a subset of cmdlets and executables, specifically only one executable:
VisibleExternalCommands = 'C:\Windows\System32\whoami.exe'
In normal usage the restrictions are applied. For example, netstat is not allowed:
However, I can easily escape these restrictions using the call operator, for example
Why is allowed? Surely such a simple escape from the restrictions is a security hole and renders VisibleExternalCommands a bit useless?
I thought that might be the case. Sadly don't think we can use RestrictedRemoteServer as the usage needs access to things like if conditions, loop etc.
I'll have to investigate the LanguageMode setting I think
The issue is that SessionType = 'Default' allows PowerShell language features, including script blocks. As a result, VisibleExternalCommands alone does not enforce a sufficiently restrictive command-execution environment.
To address this, change:
SessionType = 'Default'
to:
SessionType = 'RestrictedRemoteServer'
RestrictedRemoteServer runs in NoLanguage mode, preventing users from executing general PowerShell expressions, defining variables, or running script blocks. This closes the specific bypass you described.
Retain your executable restriction:
VisibleExternalCommands = @(
'C:\Windows\System32\whoami.exe'
)
Register a separate endpoint for validation before replacing the existing one:
Test-PSSessionConfigurationFile `
-Path C:\ProgramData\JEA\WhoAmI.pssc
Register-PSSessionConfiguration `
-Name WhoAmI-Restricted `
-Path C:\ProgramData\JEA\WhoAmI.pssc
Connect to the new endpoint and verify that only the permitted executable runs:
whoami.exe
net.exe
& { Get-Process }
The first command should succeed; the other two should be rejected.
Btw.RestrictedRemoteServer provides stronger language restrictions, but the exposed role capabilities must still be reviewed for commands that could facilitate arbitrary execution or create additional runspaces. For enforcement beyond the PowerShell session, consider AppLocker or Windows Defender Application Control
If the above response helps answer your question, remember to "Accept Answer" so that others in the community facing similar issues can easily find the solution. Your contribution is highly appreciated.
hth
Marcin
AI answer
Replace SessionType = 'Default' with SessionType = 'RestrictedRemoteServer'; Default permits PowerShell language features such as script blocks, so VisibleExternalCommands alone cannot provide a secure command boundary.
VisibleExternalCommands controls which executables are exposed as commands, but your endpoint still permits & { netstat } to invoke a script block. A proper JEA endpoint uses RestrictedRemoteServer, which runs in NoLanguage mode and limits users to command invocation without scripts or variables.^1^ ^2^
Run the endpoint-management commands from an elevated PowerShell session.
.pssc file used to register the endpoint.SessionType = 'RestrictedRemoteServer'
RoleDefinitions, run-as identity, transcript directory, and other endpoint settings. For example, the relevant portions should resemble:@{
SessionType = 'RestrictedRemoteServer'
RunAsVirtualAccount = $true
RoleDefinitions = @{
'CONTOSO\JEAUsers' = @{
RoleCapabilities = 'WhoAmIRole'
}
}
TranscriptDirectory = 'C:\ProgramData\JEA\Transcripts'
}
Test-PSSessionConfigurationFile -Path C:\ProgramData\JEA\WhoAmI.pssc
Register-PSSessionConfiguration `
-Name WhoAmI-Restricted `
-Path C:\ProgramData\JEA\WhoAmI.pssc
Get-PSSessionConfiguration -Name WhoAmI-Restricted
If rebuilding the role, WhoAmIRole.psrc must be stored in a RoleCapabilities directory inside a valid PowerShell module located under a path in $env:PSModulePath. Give the role capability a unique filename because JEA’s search order is not deterministic when duplicate names exist.^1^
Before cutover, inspect the effective commands assigned to the intended user:
Get-PSSessionCapability `
-ConfigurationName WhoAmI-Restricted `
-Username 'CONTOSO\JEAUser'
Then connect to the temporary endpoint and test:
Enter-PSSession -ComputerName localhost `
-ConfigurationName WhoAmI-Restricted
whoami.exe
netstat.exe
& { netstat.exe }
Expected results:
whoami.exe succeeds.netstat.exe fails because it is not visible.& { netstat.exe } fails because script-block syntax is unavailable in NoLanguage mode.After validation, migrate clients to the new endpoint or replace the old registration during a controlled change.
Keep the complete executable path:
VisibleExternalCommands = @(
'C:\Windows\System32\whoami.exe'
)
Microsoft recommends using constrained cmdlets or functions instead of external executables where possible because JEA can restrict cmdlet/function parameters and values, while an executable’s arguments cannot be constrained as granularly.^3^
Also review the effective role for commands that can escape the boundary, particularly:
Start-Process, Invoke-Expression, or other arbitrary execution mechanisms.*-Job.Trace-Command and commands that modify type or format data.These are specifically identified as risks for restricted JEA endpoints.^4^
The observed behavior is therefore a consequence of using a normal Default session as the endpoint foundation, rather than a failure of the VisibleExternalCommands list itself.
References