Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<a href="https://www.bestpractices.dev/projects/12921"><img alt="OpenSSF Best Practices" src="https://www.bestpractices.dev/projects/12921/badge"></a>
<a href="https://codecov.io/gh/TheAbider/RackStack"><img alt="codecov" src="https://codecov.io/gh/TheAbider/RackStack/branch/master/graph/badge.svg"></a>
<img alt="PSScriptAnalyzer 0 errors" src="https://img.shields.io/badge/PSScriptAnalyzer-0%20errors-brightgreen">
<img alt="5428 structural tests" src="https://img.shields.io/badge/structural%20tests-5428-brightgreen">
<img alt="5438 structural tests" src="https://img.shields.io/badge/structural%20tests-5438-brightgreen">
<img alt="Pester 312 tests" src="https://img.shields.io/badge/Pester-312%20tests-brightgreen">
<img alt="SLSA Level 3" src="https://slsa.dev/images/gh-badge-level3.svg">
</p>
Expand Down
86 changes: 86 additions & 0 deletions Tests/Run-Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10517,6 +10517,92 @@ catch {
Write-TestResult "Release Retention Tests" $false $_.Exception.Message
}

# ============================================================================
# SECTION 207: SECRET-SCANNER CONFIG INTEGRITY (.gitleaks.toml)
# ============================================================================
# The gitleaks workflow behaves differently per event: push/pull_request scan
# only the NEW commits, while schedule/workflow_dispatch scan the FULL history.
# A green PR check therefore proves nothing about the weekly scan, so a broken
# allowlist stays invisible until the next Monday failure email. These asserts
# are the only pre-merge signal that the full-history path is still sound.
#
# Two failure modes pinned here:
# 1. gitleaks 8.24.3 SILENTLY ignores the plural [[allowlists]] array at
# global scope — it parses without error, emits no warning, and suppresses
# nothing. Only the singular [allowlist] table works. Verified empirically
# on 8.24.3: identical regexes gave "leaks found: 2" under [[allowlists]]
# and "no leaks found" under [allowlist]. Most upstream docs show the
# plural form, so this is easy to "modernise" into a silent no-op.
# 2. Allowlisting by `paths` or `commits` blinds the scanner to whole files
# or whole commits. Entries must be scoped to exact literal values, so a
# real credential added to the same file still fails the scan.
#
# History: the weekly scan was red for ~11 consecutive Mondays (2026-05-25
# onward) on two non-secrets — a Pester redaction fixture and a base64
# placeholder in the tunnel docs. A permanently red scanner is worse than no
# scanner, because a genuine leak arrives as one extra line in a job everyone
# has learned to skip.
Write-SectionHeader "SECTION 207: SECRET-SCANNER CONFIG INTEGRITY"

try {
$wfDir207 = Join-Path $script:ModuleRoot '.github\workflows'
if (Test-Path -LiteralPath $wfDir207) {
# A workflows directory means this is the source-repo layout, so the
# config must exist. The dist/monolithic layout has neither and skips.
$glPath207 = Join-Path $script:ModuleRoot '.gitleaks.toml'
$glExists207 = Test-Path -LiteralPath $glPath207
Write-TestResult "Gitleaks: .gitleaks.toml present at repo root" $glExists207

if ($glExists207) {
$glRaw207 = Get-Content -LiteralPath $glPath207 -Raw

Write-TestResult "Gitleaks: uses the singular [allowlist] table" `
([bool]($glRaw207 -match '(?m)^\s*\[allowlist\]'))
Write-TestResult "Gitleaks: avoids [[allowlists]] (silent no-op on 8.24.3)" `
([bool]($glRaw207 -notmatch '(?m)^\s*\[\[allowlists\]\]'))

# Value-scoped only — never blind a whole file or a whole commit.
Write-TestResult "Gitleaks: allowlist exempts no whole paths" `
([bool]($glRaw207 -notmatch '(?m)^\s*paths\s*='))
Write-TestResult "Gitleaks: allowlist exempts no whole commits" `
([bool]($glRaw207 -notmatch '(?m)^\s*commits\s*='))

# An allowlist layered on an empty ruleset would scan for nothing.
Write-TestResult "Gitleaks: extends the default ruleset" `
([bool]($glRaw207 -match '(?m)^\s*useDefault\s*=\s*true'))

# Exactly the two reviewed false positives — no silent additions.
$glRegexCount207 = ([regex]::Matches($glRaw207, "'''[^']+'''")).Count
Write-TestResult "Gitleaks: allowlist holds exactly 2 reviewed entries" `
($glRegexCount207 -eq 2) "found $glRegexCount207"

# No catch-all that would silence the scanner wholesale.
Write-TestResult "Gitleaks: allowlist contains no catch-all regex" `
([bool]($glRaw207 -notmatch "'''\s*(\.\*|\.\+)\s*'''"))
}

# Without the schedule trigger and an unshallow checkout, nothing ever
# scans history and historical leaks become permanently invisible.
$glWf207 = Join-Path $wfDir207 'gitleaks.yml'
if (Test-Path -LiteralPath $glWf207) {
$wfRaw207 = Get-Content -LiteralPath $glWf207 -Raw
Write-TestResult "Gitleaks: workflow keeps the scheduled full-history scan" `
([bool]($wfRaw207 -match '(?m)^\s*schedule:'))
Write-TestResult "Gitleaks: workflow checks out full history (fetch-depth: 0)" `
([bool]($wfRaw207 -match 'fetch-depth:\s*0'))
}
else {
Write-TestResult "Gitleaks: workflow present" $false ".github/workflows/gitleaks.yml not found"
}
}
else {
Write-TestResult "Gitleaks: secret-scanner config integrity" -Skipped -Message "no .github/workflows in this layout"
}
}
catch {
Write-TestResult "Secret-Scanner Config Tests" $false $_.Exception.Message
}

# ============================================================================
# SECTION 174: DOCUMENTATION FRESHNESS (counts must match the codebase)
# ============================================================================
Expand Down