Skip to content

PR 2/4: Fix PSScriptAnalyzer code quality warnings#29

Open
StrongWind1 wants to merge 6 commits intoCompassSecurity:mainfrom
StrongWind1:fix/pssa-code-quality-fixes
Open

PR 2/4: Fix PSScriptAnalyzer code quality warnings#29
StrongWind1 wants to merge 6 commits intoCompassSecurity:mainfrom
StrongWind1:fix/pssa-code-quality-fixes

Conversation

@StrongWind1
Copy link

Branch: fix/pssa-code-quality-fixes
Base: main (stacked on PR 1)

Disclaimer: I used Claude Opus 4.6 to help with this code review and to draft these changes. I reviewed everything before submitting.


This is the second of four PRs from my PSScriptAnalyzer review. It picks up the actionable code quality warnings, things like incorrect null comparisons, dead variables, empty catch blocks, encoding gaps, and non standard function names. Each fix is its own commit so they're easy to review one at a time.

What this does (5 commits)

Fix null comparison operand order in check_Tenant.psm1 (4 instances). Changed $consentCount -eq $null to $null -eq $consentCount. This is a well known PowerShell gotcha where $null on the right side of -eq can cause PowerShell to filter an array instead of doing a boolean null check. Putting $null on the left side makes sure it behaves correctly no matter what type the variable holds. PSScriptAnalyzer flags this as PSPossibleIncorrectComparisonWithNull.

Remove unused variables in check_EnterpriseApps.psm1, check_PIM.psm1, EntraTokenAid.psm1, shared_Functions.psm1, and Send-GraphBatchRequest.psm1. Removed 7 variables that were assigned but never read. Things like $Owners which was initialized to $null and never referenced, $EntraConnectApp which was a boolean flag that got set but never checked, and $ResultsList plus $MoreNextLinks which were lists created but never populated (probably leftover from a refactor). One interesting case was $AuthCheck which stored an auth test result that got discarded, so I changed it to $null = ... to make the intent clear.

Add UTF-8 BOM to files with non ASCII characters in check_Groups.psm1, EntraTokenAid.psm1, and run_EntraFalcon.ps1. PowerShell 5.1 on Windows defaults to Windows 1252 encoding. Without a BOM, files containing Unicode characters can get misread, which could lead to corrupted output or subtle runtime issues. Adding the BOM tells PowerShell and other tools to use UTF-8. Since EntraFalcon supports PS 5.1, this felt like a good thing to add.

Add verbose logging to empty catch blocks in Send-ApiRequest.psm1, check_Tenant.psm1, and shared_Functions.psm1 (8 instances). All 8 empty catches look intentional to me since they're doing best effort parsing of HTTP status codes, response bodies, date strings, and OS detection. But completely empty catch {} blocks can make debugging tricky when something goes wrong unexpectedly. I added Write-Verbose messages that only show up when -Verbose is used, so there's zero impact on normal operation but you get helpful diagnostic info when troubleshooting.

Suppress false positive unused parameter warnings in check_Roles.psm1, check_AppRegistrations.psm1, check_CAPs.psm1, check_PIM.psm1, check_Users.psm1, check_Groups.psm1, and Send-GraphBatchRequest.psm1. PSScriptAnalyzer flagged 14 parameters as unused, but most of them are actually accessed by nested functions via parent scope, and PSSA just can't see across scope boundaries. For example, check_Roles.psm1 declares $Users, $EnterpriseApps, etc. as parameters, and the inner Get-ObjectDetails function reads them from the parent scope. I added [SuppressMessageAttribute] with explanatory comments for each one so the intent is clear to both the linter and anyone reading the code later.

Rename functions to use approved PowerShell verbs in check_CAPs.psm1 and check_PIM.psm1. Is-Empty renamed to Test-IsEmpty since Test is the approved verb for boolean checks, and Parse-ISO8601Duration renamed to ConvertFrom-ISO8601Duration since ConvertFrom is the approved verb for format conversion. Both are internal functions and all call sites were updated in the same commit.

What I intentionally left alone

PSScriptAnalyzer still reports about 530 warnings after these fixes, but they all look like reasonable design choices for an interactive CLI tool like this. Write-Host (344) because EntraFalcon needs colored console output for progress and status. Global variables (115) since cross module shared state is by design, all nicely prefixed with GLOBAL. Singular nouns (25) because Invoke-CheckUsers reads better than Invoke-CheckUser for a function that processes all users. And ShouldProcess (11) since these are mostly HTML builder functions that don't actually modify system state.

This is PR 2 of 4, stacked on PR 1 (trailing whitespace). If you could merge PR 1 first, then this PR's diff will show only the 5 code quality commits.

  1. PR 1 removes trailing whitespace (cosmetic)
  2. This PR addresses PSScriptAnalyzer code quality warnings
  3. PR 3 fixes a handful of logic bugs
  4. PR 4 normalizes file encoding (ASCII with CRLF line endings)

Each PR builds on the previous one, so merging them in order keeps everything clean and conflict free. However, you can cherry pick individual commits if you would like.

Thanks for reviewing!

Run PSScriptAnalyzer with -Fix to automatically remove 695 instances
of trailing whitespace across all .psm1 and .ps1 files.

Rule: PSAvoidTrailingWhitespace (Information)
No functional changes — whitespace-only diff.
Swap $consentCount -eq $null to $null -eq $consentCount in
the consent count fallback logic (lines 4228-4229, 4672-4673).

When $null is on the right side of -eq and the left operand is an
array, PowerShell filters the array instead of performing a null
check. Placing $null on the left ensures correct behavior
regardless of the operand type.

Rule: PSPossibleIncorrectComparisonWithNull (Warning)
Remove variables that are assigned but never read:
- check_EnterpriseApps.psm1: $Owners (line 382), $EntraConnectApp
  (line 755) — flag set but never checked, warning added directly
- check_PIM.psm1: $CapIssues (line 486) — boolean never read
- EntraTokenAid.psm1: $AuthError init (line 210), $xms_cc
  (line 1645) — value extracted but never used
- shared_Functions.psm1: $AuthCheck (line 5078) — auth test result
  discarded, error handling is in the catch block
- Send-GraphBatchRequest.psm1: $ResultsList and $MoreNextLinks
  (lines 346-347) — lists initialized but never populated

Rule: PSUseDeclaredVarsMoreThanAssignments (Warning)
Replace 8 empty catch blocks with Write-Verbose messages that log
the suppressed exception. These catches are intentional (best-effort
parsing of HTTP status codes, response bodies, date strings, and OS
detection) but the empty blocks masked errors during debugging.

The verbose messages only appear when -Verbose is used, so there is
zero impact on normal operation.

Affected files:
- Send-ApiRequest.psm1: HTTP status, response body, JSON parsing
- check_Tenant.psm1: date string parsing (4 instances)
- shared_Functions.psm1: OS detection fallback

Rule: PSAvoidUsingEmptyCatchBlock (Warning)
Add SuppressMessageAttribute for 14 parameters flagged as unused.

Most are false positives where parameters are accessed by nested
functions via parent scope (check_Roles, check_AppRegistrations,
check_CAPs use inner Get-ObjectDetails/GetObjectInfo functions).
Others are part of the shared module calling interface where the
orchestrator passes all data to every module uniformly.

Each suppression includes a comment explaining why the parameter
is accepted but not directly referenced.

Rule: PSReviewUnusedParameter (Warning)
- check_CAPs.psm1: Is-Empty -> Test-IsEmpty
  'Is' is not an approved verb; 'Test' is the standard for boolean checks.

- check_PIM.psm1: Parse-ISO8601Duration -> ConvertFrom-ISO8601Duration
  'Parse' is not an approved verb; 'ConvertFrom' is the standard for
  converting input formats to PowerShell objects.

Both are internal functions with all call sites updated.

Rule: PSUseApprovedVerbs (Warning)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant