Add support for new WLDP setting EnableFileOnlyEntry#26752
Add support for new WLDP setting EnableFileOnlyEntry#26752SeeminglyScience wants to merge 14 commits into
EnableFileOnlyEntry#26752Conversation
There was a problem hiding this comment.
Pull request overview
This pull request adds support for a new Windows Lockdown Policy (WLDP) setting called FileOnlyEntry that restricts PowerShell to only execute when a file is specified via the -File parameter and -NoExit is not present. This is intended for managed systems where interactive or ad-hoc PowerShell usage should be prevented.
Changes:
- Adds WLDP API integration to query the
FileOnlyEntrysetting with environment variable fallback for testing - Implements command-line parameter validation to enforce the policy across multiple entry points
- Provides test infrastructure and initial test cases for the new functionality
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| src/System.Management.Automation/security/wldpNativeMethods.cs | Adds P/Invoke declaration for WldpGetApplicationSettingBoolean, implements IsFileOnlyEntryEnabled() with caching and environment variable fallback, and provides reusable TestBooleanWldpSetting() helper method |
| src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs | Adds FileOnlyEntry checks at multiple points: empty args, -NoExit, -Command/-EncodedCommand/-CommandWithArgs, -File -, and a final catch-all check |
| src/Microsoft.PowerShell.ConsoleHost/resources/CommandLineParameterParserStrings.resx | Adds error message string for FileOnlyEntry policy violations |
| test/tools/Modules/HelpersSecurity/HelpersSecurity.psm1 | Adds SetFileOnlyEntry and RevertFileOnlyEntry parameters to test cmdlet for setting/clearing the environment variable |
| test/powershell/Modules/Microsoft.PowerShell.Security/FileOnlyEntry.Tests.ps1 | Adds new test file with negative test cases for -NoExit -Command, -Command, -NoExit -File, and -File - scenarios |
| $PwshParameterTestCases = @( | ||
| MakeTestCase -NoExit -Command Get-ChildItem | ||
| MakeTestCase -Command Get-ChildItem | ||
| # File validation should come after `FileOnlyEntry` check, so | ||
| # this file should not need to exist for us to get the error | ||
| # we expect. | ||
| MakeTestCase -NoExit -File this_file_does_not_exist.ps1 | ||
| MakeTestCase -File - | ||
| ) |
There was a problem hiding this comment.
The test suite should include test cases to verify that informational commands like -Version and -Help are still allowed when FileOnlyEntry is enabled, since they don't execute any user code. Consider adding test cases like:
pwsh -Versionshould succeed and display versionpwsh -Helpshould succeed and display helppwsh -?should succeed and display help
| Describe "File Only Entry throws for interactive or non-file scenarios" -Tags 'CI','RequireAdminOnWindows' { | ||
|
|
||
| BeforeAll { | ||
| function MakeTestCase { | ||
| param([Parameter(ValueFromRemainingArguments)] [string[]] $ArgumentList) | ||
| end { | ||
| @{ | ||
| Arguments = $ArgumentList | ||
| TestName = 'With args "{0}"' -f ($ArgumentList -join ' ') | ||
| } | ||
| } | ||
| } | ||
|
|
||
| [SuppressMessage('PSUseDeclaredVarsMoreThanAssignments', 'PwshParameterTestCases')] | ||
| $PwshParameterTestCases = @( | ||
| MakeTestCase -NoExit -Command Get-ChildItem | ||
| MakeTestCase -Command Get-ChildItem | ||
| # File validation should come after `FileOnlyEntry` check, so | ||
| # this file should not need to exist for us to get the error | ||
| # we expect. | ||
| MakeTestCase -NoExit -File this_file_does_not_exist.ps1 | ||
| MakeTestCase -File - | ||
| ) | ||
| } | ||
|
|
||
| It "<TestName>" -TestCases $PwshParameterTestCases { | ||
| param($Arguments) | ||
|
|
||
| $results = $null | ||
| try { | ||
| Invoke-LanguageModeTestingSupportCmdlet -SetFileOnlyEntry | ||
| if ($Arguments[-1] -eq '-') { | ||
| $results = 'Get-ChildItem' | & "$PSHOME\pwsh.exe" @Arguments 2>&1 | ||
| } else { | ||
| $results = & "$PSHOME\pwsh.exe" @Arguments 2>&1 | ||
| } | ||
| } finally { | ||
| Invoke-LanguageModeTestingSupportCmdlet -RevertFileOnlyEntry | ||
| } | ||
|
|
||
| $results.Exception.Message | Should -Be 'The parameter "-File" is required by policy.' | ||
| } | ||
| } |
There was a problem hiding this comment.
The test suite only covers negative test cases (scenarios that should be rejected). There should also be at least one positive test case to verify that legitimate file-based execution is still allowed when FileOnlyEntry is enabled. For example, a test that verifies pwsh.exe -File valid_script.ps1 succeeds when the policy is enabled.
|
|
||
| if (SetFileOnlyEntry) | ||
| { | ||
| Environment.SetEnvironmentVariable("__PSLockdownPolicy_FileOnlyEntry", "1", EnvironmentVariableTarget.Machine); |
There was a problem hiding this comment.
On modern platforms we can use policies.
| } | ||
| } | ||
|
|
||
| private void ParseHelper(string[] args) |
There was a problem hiding this comment.
The current changes allows specifying the following when using -File. We need to consider whether those settings should be supported or not:
-SettingsFile
-ConfigurationFile
-ConfigurationName
There was a problem hiding this comment.
I think those are fine. @TravisEz13 thoughts?
| @@ -1360,6 +1393,12 @@ private bool ParseFile(string[] args, ref int i, bool noexitSeen) | |||
| // Process interactive input... | |||
| if (args[i] == "-") | |||
There was a problem hiding this comment.
I think we should stop the sever modes too. They have no file only ability
There was a problem hiding this comment.
Good call, tbh I assumed the current checks out would be sufficient but turns out it just wrote the error and started server mode anyway.
Only question is if Start-Job should have a custom error message. Right now folks will see this:
OpenError: [localhost] The background process reported an error with the following message: Server mode is disallowed by policy..
I think it's sufficient but open to adding something explicit
|
@TravisEz13 This PR needs user docs. |
Both the generic "file must be specified" and "server mode disallowed" error messages were being written which was confusing.
PR Summary
Setting will ensure that managed systems will only launch PowerShell when a file to execute is specified and
-NoExitis not present. For use in systems where interactive or ad-hoc usage is not expected.PR Context
PR Checklist
.h,.cpp,.cs,.ps1and.psm1files have the correct copyright header