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^
Correct the endpoint
Run the endpoint-management commands from an elevated PowerShell session.
- Open the original
.pssc file used to register the endpoint.
- Change this setting:
SessionType = 'RestrictedRemoteServer'
- Preserve the existing
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'
}
- Validate the complete file, then register it under a temporary name so the existing endpoint remains available during testing:
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.
- Direct
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.
Tighten the role capability
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.
- Commands that create new runspaces, including
*-Job.
- Writable FileSystem-provider access.
-
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
- JEA Session Configurations
- about_Language_Modes
- JEA Role Capabilities
- JEA Security Considerations