From 59b71590917bb244e306b707923fbfc22ff867ed Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Wed, 6 May 2026 05:22:09 -0400 Subject: [PATCH 1/2] Expand PSScriptAnalyzer coverage - powershell.yml: replace includeRule (2 hand-picked rules) with excludeRule PSAvoidUsingWriteHost so all other rules run; Write-Host is used intentionally throughout for user-facing progress output. - Create External Help.yml: add workflow-level permissions block (contents: read) - workflow had no permissions block, relying on permissive repo defaults. - Private/Invoke-Scans.ps1: suppress PSReviewUnusedParameter for EnrollmentAgentEKU and PreferredOwner; both are declared Mandatory as part of the public API but are not yet wired through to inner Find-* calls (reserved for planned ESC13 and remediation-ownership support). Findings deferred / not fixed: - PSUseShouldProcessForStateChangingFunctions: New-Dictionary and Set-RiskRating operate on in-memory objects only (false positives); Update-ESC* functions are remediation code (out of scope). - PSReviewUnusedParameter in Build-Module.ps1: params are used inside a PSPublishModule scriptblock, causing a PSSA false positive. - Find-ESC17 Mode param: referenced only in commented-out WIP code. - PSUseBOMForUnicodeEncodedFile on Invoke-Locksmith.ps1: that file is a generated build artifact; the fix belongs in the build pipeline. - PSAvoidTrailingWhitespace, PSUseSingularNouns: style / out of scope. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/Create External Help.yml | 3 +++ .github/workflows/powershell.yml | 4 ++-- Private/Invoke-Scans.ps1 | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Create External Help.yml b/.github/workflows/Create External Help.yml index 9e4b8ee7..87b4df2f 100644 --- a/.github/workflows/Create External Help.yml +++ b/.github/workflows/Create External Help.yml @@ -8,6 +8,9 @@ on: # push: workflow_dispatch: +permissions: + contents: read + jobs: package_help: # The New-ExternalHelpCab cmdlet uses makecab, which depends on Windows. diff --git a/.github/workflows/powershell.yml b/.github/workflows/powershell.yml index 30d46d83..331e6d1e 100644 --- a/.github/workflows/powershell.yml +++ b/.github/workflows/powershell.yml @@ -37,8 +37,8 @@ jobs: # The below set up runs PSScriptAnalyzer to your entire repository and runs some basic security rules. path: .\ recurse: true - # Include your own basic security rules. Removing this option will run all the rules - includeRule: '"PSAvoidGlobalAliases", "PSAvoidUsingConvertToSecureStringWithPlainText"' + # Run all rules except PSAvoidUsingWriteHost (Write-Host is used intentionally for progress output) + excludeRule: '"PSAvoidUsingWriteHost"' output: results.sarif # Upload the SARIF file generated in the previous step diff --git a/Private/Invoke-Scans.ps1 b/Private/Invoke-Scans.ps1 index a1af9974..32b07769 100644 --- a/Private/Invoke-Scans.ps1 +++ b/Private/Invoke-Scans.ps1 @@ -30,6 +30,8 @@ function Invoke-Scans { [CmdletBinding()] [OutputType([hashtable])] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'Performing multiple scans.')] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'EnrollmentAgentEKU', Justification = 'Parameter is part of the public API and reserved for future ESC13 enrollment-agent scan support.')] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'PreferredOwner', Justification = 'Parameter is part of the public API and reserved for planned remediation ownership integration.')] param ( # Could split Scans and PromptMe into separate parameter sets. [Parameter(Mandatory)] From 2203d9baa8d9a5cb4bca75cf2c0dcf8d1a0ae523 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Wed, 6 May 2026 05:38:55 -0400 Subject: [PATCH 2/2] fix: add PSReviewUnusedParameter suppressions to Invoke-Locksmith.ps1 monolith Copilot review (#278) correctly identified that the SuppressMessageAttribute entries added to Private/Invoke-Scans.ps1 were not reflected in the generated Invoke-Locksmith.ps1 monolith. PSScriptAnalyzer scans the whole repository recursively, so the monolith would still raise the same warnings that the source suppressions were intended to silence. Applied matching suppressions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Invoke-Locksmith.ps1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Invoke-Locksmith.ps1 b/Invoke-Locksmith.ps1 index 9c2b6dbf..15b424ba 100644 --- a/Invoke-Locksmith.ps1 +++ b/Invoke-Locksmith.ps1 @@ -2789,6 +2789,8 @@ function Invoke-Scans { [CmdletBinding()] [OutputType([hashtable])] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'Performing multiple scans.')] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'EnrollmentAgentEKU', Justification = 'Parameter is part of the public API and reserved for future ESC13 enrollment-agent scan support.')] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'PreferredOwner', Justification = 'Parameter is part of the public API and reserved for planned remediation ownership integration.')] param ( # Could split Scans and PromptMe into separate parameter sets. [Parameter(Mandatory)]