Skip to content

build(analyzers): vendor InjectionHunter for PowerShell injection SAST#21

Closed
NWarila wants to merge 1 commit into
mainfrom
build-vendor-injectionhunter
Closed

build(analyzers): vendor InjectionHunter for PowerShell injection SAST#21
NWarila wants to merge 1 commit into
mainfrom
build-vendor-injectionhunter

Conversation

@NWarila

@NWarila NWarila commented Jun 25, 2026

Copy link
Copy Markdown
Owner

Summary

  • Vendors InjectionHunter 1.0.0 under analyzers/InjectionHunter/ and records source, hashes, audit notes, and license status in VENDORED.md.
  • Wires the vendored ruleset through PSScriptAnalyzerSettings.psd1 while excluding the third-party files from the repo's own lint target set.
  • Adds Pester coverage proving the ruleset loads through the settings file and flags unsafe Invoke-Expression / Add-Type fixtures.
  • Rewrites benign empty-string -replace operands in HouseRules.psm1 as [System.String]::Empty to keep InjectionHunter active without false positives.

Validation

  • powershell.exe -NoLogo -NoProfile -File tests\Invoke-Tests.ps1 -MinimumCoverage 80 — 37 passed, 0 failed, 93.62% coverage.
  • PSScriptAnalyzer local gate with the CI target selection — no issues.
  • Commit is signed and based on origin/main (590bd5f7e3470f9e7c3970ddc7f5cebcdbe3ae53).

Notes

  • Local pwsh and actionlint are not installed in this Windows environment; PR CI will run the PowerShell 7 and actionlint paths.
  • VENDORED.md flags InjectionHunter's unverified redistribution terms explicitly for owner review.

Stop line: did not merge.

Vendor Microsoft/Lee Holmes' InjectionHunter ruleset (PowerShell Gallery
v1.0.0, frozen since 2017) under analyzers/InjectionHunter/ and wire it into
the house PSScriptAnalyzer config via CustomRulePath. It taint-tracks untrusted
input into execution contexts (Invoke-Expression, Add-Type, dynamic member /
method / property access, cmd/powershell command injection, unsafe escaping) --
a defect class the built-in rules do not catch.

The module is pinned, not installed live: InjectionHunter.psd1 and .psm1 are
committed byte-identical to the Gallery package (SHA-256 recorded in
VENDORED.md), marked -text in .gitattributes so EOL normalization cannot alter
the bytes, and allowlisted in the deny-all .gitignore. VENDORED.md records the
source, version, GUID, file hashes, the pre-vendoring audit (eight passive AST
rule functions; no install logic, network, or obfuscation), and the license
status.

The CI analyze step excludes the vendored directory from its own lint target
set (third-party upstream, not restyled to house rules) while still loading it
as a rule provider. tests/InjectionHunter.Tests.ps1 proves the ruleset is loaded
through the settings file and fires on Invoke-Expression and Add-Type fixtures
while staying clean on safe idiom.

Wiring InjectionHunter surfaced three InjectionRisk.UnsafeEscaping false
positives in analyzers/HouseRules.psm1, all from benign empty-string -replace
operands (stripping scope and namespace prefixes from AST type names). They are
resolved by writing the empty replacement as the house-idiomatic
[System.String]::Empty -- behavior-identical, no logic change -- which keeps the
rule fully active everywhere rather than excluding it.
@NWarila

NWarila commented Jun 25, 2026

Copy link
Copy Markdown
Owner Author

Closing: this is the dropped InjectionHunter work (no OSS license; decided against in #20). Not merging.

@NWarila NWarila closed this Jun 25, 2026
@NWarila NWarila deleted the build-vendor-injectionhunter branch June 25, 2026 14:29
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