GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Skip the AppLocker policy test files when no script policy is configured by azchohfi · Pull Request #28374 · PowerShell/PowerShell

Conversation

@azchohfi

@azchohfi Alexandre Zollinger Chohfi (azchohfi) commented Nov 6, 2026

Copy link
Copy Markdown

PR Summary

Fixes #28372.

On every start, SystemPolicy.GetSystemLockdownPolicy() finds the system-wide AppLocker policy by writing two __PSScriptPolicyTest_* files to %TEMP%, checking them with SaferIdentifyLevel/SaferComputeTokenFromLevel, and deleting them. When the machine has no AppLocker script rules and no Software Restriction Policy, the answer is always "allowed".

This adds a check before the test files are written. They are skipped only when none of these has a policy:

  • %windir%\System32\AppLocker\Script.AppLocker, the compiled effective AppLocker script policy (group policy, local policy or MDM);
  • HKLM\SOFTWARE\Policies\Microsoft\Windows\SrpV2\Script (AppLocker script rules from group policy);
  • SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers in HKLM and HKCU (Software Restriction Policies, which the SAFER call also enforces).

A location counts as "no policy" only if it does not exist. The one exception is the CodeIdentifiers key: Windows can create it with just AuthenticodeEnabled and nothing else, and that key with no subkeys and no other values does not define an SRP policy (creating one adds DefaultLevel, TransparentEnabled, rule subkeys and so on). If anything exists or cannot be read, the test files are written as before. WDAC and the per-file checks are unchanged.

PR Context

Measured on Windows 11 26100 (i9-10900K), Release builds of master 1aac7f5 with and without this change (the two outputs differ only in System.Management.Automation.dll), 40 interleaved runs, median of the paired differences with 95% confidence interval:

pwsh -NoProfile -NonInteractive -Command ... before after difference
exit 366 ms 326 ms -44.4 ms (27.8 to 56.7)
Get-ChildItem -Name src | Select-Object -First 5 546 ms 508 ms -38.7 ms (30.6 to 43.7)

On this machine (no AppLocker or SRP policy) the build without the change writes two test files to %TEMP% per start and the build with it writes none; both report GetSystemLockdownPolicy() = None and FullLanguage.

Tests:

  • xUnit SystemPolicyTests (new): the registry check against a temporary HKCU key (missing, empty, only AuthenticodeEnabled, other value, rule subkey), the file check, and that HasAppLockerOrSaferScriptPolicy() matches the machine.
  • Pester AppLockerProbe.Tests.ps1 (new): starts pwsh with a private TEMP and checks that the test files are written if and only if HasAppLockerOrSaferScriptPolicy() is true.
  • Ran Start-PSxUnit for SystemPolicy and SecuritySupport (4 passed) and Start-PSPester for test/powershell/engine/Security and the ConstrainedLanguage*.Tests.ps1 files (23 passed, 0 failed; the 101 tests tagged RequireAdminOnWindows did not run because I ran unelevated).

I could not test with a real AppLocker or SRP policy because writing those policy keys needs admin rights. To check enforcement on a test machine (as admin):

  1. AppLocker: start AppIDSvc, create the default script rules and set Script rules to Enforce (secpol.msc or Set-AppLockerPolicy), run gpupdate /force, and confirm Script.AppLocker exists. As a standard user, pwsh -c '$ExecutionContext.SessionState.LanguageMode' should print ConstrainedLanguage with and without this change, and the new Pester test should pass (test files written).
  2. SRP: in secpol.msc create Software Restriction Policies with Security Level "Disallowed" (default path rules allow Windows and Program Files). Same check: ConstrainedLanguage for both builds, test files written.
  3. Remove the policies: FullLanguage, and with this change no test files in %TEMP%.

I used GitHub Copilot to investigate this and to help write the change and tests; I reviewed the code and ran the tests above myself.

PR Checklist

  • PR has a meaningful title
    • Use the present tense and imperative mood when describing your changes
  • Summarized changes
  • Make sure all .h, .cpp, .cs, .ps1 and .psm1 files have the correct copyright header
  • This PR is ready to merge. If this PR is a work in progress, please open this as a Draft Pull Request and mark it as Ready to Review when it is ready to merge.
  • Breaking changes
    • None
    • OR
    • Experimental feature(s) needed
      • Experimental feature name(s):
  • User-facing changes
    • Not Applicable
    • OR
    • Documentation needed
      • Issue filed:
  • Testing - New and feature
    • N/A or can only be tested interactively
    • OR
    • Make sure you've added a new test if existing tests do not effectively test the code changed

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@azchohfi
Skip the AppLocker policy test files when no script policy is configured
10724a9
To find the system-wide AppLocker policy, PowerShell writes two
__PSScriptPolicyTest_* files to %TEMP% on every start, checks them with
SAFER, and deletes them. When the machine has no AppLocker script rules
and no Software Restriction Policy, the result is always Allowed.

Check the places such a policy lives first and skip the test files when
none of them has a policy: the compiled AppLocker script policy
(%windir%\System32\AppLocker\Script.AppLocker), AppLocker script rules
under HKLM\SOFTWARE\Policies\Microsoft\Windows\SrpV2\Script, and SRP
under SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers in HKLM
and HKCU. A CodeIdentifiers key with only AuthenticodeEnabled is treated
as no policy. Anything that exists or cannot be read keeps the test.

Co-authored-by: Copilot App <[email protected]>
@azchohfi
Alexandre Zollinger Chohfi (azchohfi) requested review from a team, Patrick Meinecke (SeeminglyScience) and Travis Plunk (TravisEz13) as code owners November 6, 2026 22:54
Copilot AI balanced review requested due to automatic review settings November 6, 2026 22:54
@azure-pipelines

azure-pipelines Bot commented Nov 6, 2026

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Copilot started reviewing on behalf of Alexandre Zollinger Chohfi (azchohfi) November 6, 2026 22:54
View session
Copilot AI reviewed Nov 6, 2026
View reviewed changes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The WOW64 path lookup can miss an effective AppLocker policy and leave the session in FullLanguage, while additional policy-detection and test-reliability issues remain unresolved.

5 open issues
  • High severity Use the native AppLocker policy path under WOW64 · New
  • Medium severity Treat an existing empty AppLocker key as present · New
  • Medium severity Fail the test when the child process exits unsuccessfully · New
  • Medium severity Account for WLDP early return in the policy probe assertion · New
  • Medium severity Match File.Exists expectations to conservative error handling · New
What changed in this PR

This PR addresses #28372 by reducing PowerShell startup overhead when no AppLocker script policy or Software Restriction Policy is detected, avoiding temporary policy-test files and their SAFER checks.

Changes:

  • Adds policy-file and registry checks before running the existing AppLocker probe.
  • Adds xUnit coverage for policy detection helpers and machine configuration.
  • Adds a Pester test that monitors policy-test file creation during startup.
File Description
test/​xUnit/​csharp/​test_SystemPolicy.cs Tests registry, file, and machine-policy detection.
test/​powershell/​engine/​Security/​AppLockerProbe.Tests.ps1 Monitors temporary probe-file creation in a child PowerShell process.
src/​System.Management.Automation/​security/​wldpNativeMethods.cs Adds policy-presence checks and skips the SAFER probe when no policy is detected.

Review effort: Balanced

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread src/System.Management.Automation/security/wldpNativeMethods.cs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread src/System.Management.Automation/security/wldpNativeMethods.cs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread test/powershell/engine/Security/AppLockerProbe.Tests.ps1 Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread test/powershell/engine/Security/AppLockerProbe.Tests.ps1 Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread test/xUnit/csharp/test_SystemPolicy.cs Resolved

Uh oh!

There was an error while loading. Please reload this page.

@azchohfi
Address review feedback
9b94905
- Keep the AppLocker probe in 32-bit processes on 64-bit Windows, where
  the system directory is redirected.
- Treat an existing SrpV2\Script key as a policy even when it is empty.
- Fail the Pester test if the child pwsh exits with an error, and do not
  expect the test files when WDAC enforces lockdown.
- Use the same helpers in the xUnit machine check.

Co-authored-by: Copilot App <[email protected]>
@m6w6e6x-collab Mwex (m6w6e6x-collab) mentioned this pull request Nov 11, 2026
Startup: the AppLocker probe costs about 40 ms on every pwsh start, also when no AppLocker policy exists #28372
Open
@azchohfi
Merge branch 'master' into skip-applocker-probe-without-policy
ea4ee30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

Copilot code review Copilot
Copilot review effort
Applies to this pull request for everyone.Learn more about Copilot code review.
Copilot left review comments
@TravisEz13 Travis Plunk (TravisEz13) Awaiting requested review from TravisEz13 TravisEz13 is a code owner
@SeeminglyScience Patrick Meinecke (SeeminglyScience) Awaiting requested review from SeeminglyScience SeeminglyScience is a code owner

At least 1 approving review is required to merge this pull request.

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Startup: the AppLocker probe costs about 40 ms on every pwsh start, also when no AppLocker policy exists

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@azchohfi
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.