-
Notifications
You must be signed in to change notification settings - Fork 0
Contributing
Thank you for considering contributing to the Windows Security Audit Project! This page provides a guided overview; the canonical contributing document is CONTRIBUTING.md.
Version: 6.1.2
- Code of Conduct
- Ways to Contribute
- Development Setup
- Coding Standards
- Testing Requirements
- Submission Process
- Module Development
- Documentation Standards
We are committed to providing a welcoming and inclusive experience for everyone. We expect all contributors to:
- Use welcoming and inclusive language
- Be respectful of differing viewpoints and experiences
- Gracefully accept constructive criticism
- Focus on what is best for the community
- Show empathy towards other community members
- Trolling, insulting/derogatory comments, and personal attacks
- Public or private harassment
- Publishing others' private information without explicit permission
- Other conduct that could be considered inappropriate in a professional setting
Project maintainers will remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that don't align with this Code of Conduct.
When reporting a bug, include:
- Windows version (e.g., Windows 11 Pro 23H2)
-
PowerShell version (
$PSVersionTable.PSVersion) - Script version (e.g., 6.1.2)
- Module(s) affected
- Steps to reproduce (with the exact command line used)
- Expected behavior
- Actual behavior
-
Relevant log excerpts from
.\logs\audit-yyyyMMdd-HHmmss.log(run with-LogLevel Debug -Verbosefor maximum detail)
Use the Issue Tracker and select the Bug Report template.
When proposing a feature:
- Use case: what problem does this solve?
- Proposed approach: how should it work?
- Compatibility considerations: which OS/PowerShell versions?
- Compliance framework alignment: which framework(s) does it support?
Doc improvements are highly welcome — typos, clarifications, expanded examples, missing edge cases. Edit any .md file under docs/ and submit a PR.
See Module Development below.
Pick an issue, follow the Submission Process, and submit a PR.
- Git
- PowerShell 5.1+ (or PowerShell 7.x)
- A test Windows environment (10/11, Server 2016+) for runtime testing
- (Optional but recommended) Pester 5.x for test execution
- (Optional but recommended) PSScriptAnalyzer for static linting
# Clone the repository
git clone https://github.com/Sandler73/Windows-Security-Audit-Project.git
cd Windows-Security-Audit-Project\Windows-Security-Audit
# Install development tools
Install-Module -Name Pester -RequiredVersion 5.7.1 -Force -Scope CurrentUser
Install-Module -Name PSScriptAnalyzer -Force -Scope CurrentUser
# Verify installation
.\Windows-Security-Audit.ps1 -Help
.\Windows-Security-Audit.ps1 -ListModules
# Run a quick smoke test
.\Windows-Security-Audit.ps1 -Modules Core -OutputFormat Console -Quiet- Visual Studio Code with PowerShell extension
- PowerShell ISE (built into Windows)
Every .ps1 file must have a comment-based help block:
<#
.SYNOPSIS
One-line description of what this module/script does.
.DESCRIPTION
Detailed description, usage context, dependencies, design notes.
.NOTES
Author: Your Name
Version: 6.1.2
Last Updated: 2026-04-25
.EXAMPLE
.\module-cis.ps1
.EXAMPLE
.\module-cis.ps1 | Where-Object { $_.Severity -eq 'Critical' }
#>-
Use
[CmdletBinding()]on every function for consistent behavior - Use approved verbs (Get-, Set-, Test-, New-, Remove-, etc.)
- Use PascalCase for function names; camelCase for variables
- Use try/catch around external system calls; catch should populate Status=Error result
-
Avoid
Write-Hostin modules; useAdd-ResultandWrite-AuditLog -
Avoid
$nullon the right side of comparisons; use$null -eq $varnot$var -eq $null - No external dependencies — pure PowerShell stdlib only
- No BOM characters — files must be UTF-8 without BOM
- No non-ASCII characters — use plain ASCII; no smart quotes, em-dashes, or special characters
-
Balanced braces — every
{must have a matching} -
Exactly one
return $resultsper module file
| Rule | Why |
|---|---|
[CmdletBinding()] on every function |
Consistent error handling, common parameters |
| Comment-based help on every file | Get-Help integration |
| Try/catch with specific exception types | Predictable error behavior |
Cache-aware via -Cache $SharedData.Cache
|
Performance |
| 9-field result objects | Schema consistency |
CrossReferences populated |
Multi-framework correlation |
| Severity rated on every check | Risk prioritization |
| Cross-platform path handling | Use Join-Path, never hard-code \ separators |
| ASCII-only source code | Cross-locale compatibility |
Before submitting a PR, run all of these:
# 1. Lint with PSScriptAnalyzer
Invoke-ScriptAnalyzer -Path .\ -Recurse -ExcludeRule PSAvoidUsingWriteHost,PSUseShouldProcessForStateChangingFunctions
# 2. Verify all modules execute and return results
Get-ChildItem .\modules\*.ps1 | ForEach-Object {
Write-Host "Testing: $($_.Name)"
$r = & $_.FullName
if (-not $r) { Write-Error "Module returned no results" }
Write-Host " $($r.Count) checks emitted"
}
# 3. Run full audit
.\Windows-Security-Audit.ps1 -Modules All -OutputFormat JSON -OutputPath .\test.json -Quiet
# 4. Validate result schema
$data = Get-Content .\test.json | ConvertFrom-Json
$data.Results | ForEach-Object {
foreach ($field in 'Module','Category','Status','Severity','Message','Details','Remediation','CrossReferences','Timestamp') {
if (-not $_.PSObject.Properties.Name.Contains($field)) {
Write-Error "Missing field: $field on $($_.Module)/$($_.Category)"
}
}
}
# 5. Run Pester tests (if you've added them)
Invoke-Pester -Path .\tests\ -Output DetailedGet-ChildItem -Recurse -Include *.ps1 | ForEach-Object {
$content = Get-Content $_.FullName -Raw
$open = ([regex]::Matches($content, '\{')).Count
$close = ([regex]::Matches($content, '\}')).Count
if ($open -ne $close) {
Write-Error "$($_.Name): brace imbalance ($open vs $close, delta=$($open - $close))"
}
}Get-ChildItem -Recurse -Include *.ps1 | ForEach-Object {
$bytes = [System.IO.File]::ReadAllBytes($_.FullName)
$hasBom = $bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF
$hasNonAscii = ($bytes | Where-Object { $_ -gt 127 }).Count -gt 0
if ($hasBom) { Write-Error "$($_.Name): contains BOM" }
if ($hasNonAscii) { Write-Error "$($_.Name): contains non-ASCII characters" }
}Tests live in .\tests\test_<feature>.ps1. Use Pester 5.x syntax:
BeforeAll {
. $PSScriptRoot\..\shared_components\audit-common.ps1
}
Describe "ConvertTo-SafeInt" {
It "Returns 0 for 'None'" {
ConvertTo-SafeInt "None" | Should -Be 0
}
It "Converts numeric string to int" {
ConvertTo-SafeInt "42" | Should -Be 42
}
}For comprehensive test suite design, see Future Compatibility and Testing.
Fork Sandler73/Windows-Security-Audit-Project to your account.
git checkout -b feature/your-feature-name
# or
git checkout -b fix/issue-123-descriptionAdd IPv6 RA filtering check to Core module
- New check: Core - Network Protection / IPv6 RA filter state
- Severity: Medium
- CrossReferences: NIST=SC-8, CIS=4.5
- Documented in Module Documentation wiki page
Fixes #123
- If adding a new check: update Module Documentation
- If adding a new feature: update Usage Guide and README
- If changing behavior: update CHANGELOG.md under
[Unreleased]
- Reference the issue (e.g., "Fixes #123")
- Describe what changed and why
- List the testing you performed (Windows version, PS version, command lines)
- Include screenshots if HTML report changed
Maintainers will review and may request changes. Respond promptly and update the PR.
Every module follows the same structure:
<#
.SYNOPSIS
Brief description of the module's framework focus.
.DESCRIPTION
Detailed module description.
.NOTES
Version: 6.1.2
#>
param(
[hashtable]$SharedData = @{}
)
# Module variables
$moduleName = "MyFramework"
$moduleVersion = "6.1.2"
# Module banner
Write-Host ""
Write-Host "=== $moduleName Module v$moduleVersion ===" -ForegroundColor Cyan
# Initialize results array and helper closures
$results = @()
function Add-Result {
param(
[string]$Category, [string]$Status, [string]$Severity,
[string]$Message, [string]$Details, [string]$Remediation,
[hashtable]$CrossReferences = @{}
)
$script:results += [PSCustomObject]@{
Module = $moduleName
Category = $Category
Status = $Status
Severity = $Severity
Message = $Message
Details = $Details
Remediation = $Remediation
CrossReferences = $CrossReferences
Timestamp = (Get-Date)
}
}
# ============== Check Section: Account Policy ==============
try {
$minLen = ConvertTo-SafeInt (Get-CachedPasswordPolicy -Cache $SharedData.Cache).MinimumPasswordLength
if ($minLen -ge 14) {
Add-Result -Category "MyFramework - Account Policy" `
-Status "Pass" -Severity "Medium" `
-Message "Minimum password length adequate ($minLen chars)" `
-CrossReferences @{ NIST="IA-5"; CIS="5.4" }
} else {
Add-Result -Category "MyFramework - Account Policy" `
-Status "Fail" -Severity "High" `
-Message "Minimum password length insufficient ($minLen chars; need 14+)" `
-Remediation "net accounts /minpwlen:14" `
-CrossReferences @{ NIST="IA-5"; CIS="5.4"; STIG="V-220903" }
}
}
catch {
Add-Result -Category "MyFramework - Account Policy" `
-Status "Error" -Severity "Medium" `
-Message "Failed to check password policy: $_"
}
# ... more check sections ...
# Module summary
$total = $results.Count
$pass = ($results | Where-Object Status -eq 'Pass').Count
$fail = ($results | Where-Object Status -eq 'Fail').Count
Write-Host " Module $moduleName complete: $total checks ($pass pass, $fail fail)" -ForegroundColor Green
return $results- Module file named
module-<name>.ps1(lowercase) - Located in
modules/directory - Comment-based help present
-
param([hashtable]$SharedData = @{})block present -
$moduleVersion = "6.1.2"declared - Results array initialized as
@() -
Add-Resulthelper function defined - All checks wrapped in
try/catch - Every check has
-Severityrating - Every check has
-CrossReferencesmapping - Module summary printed
- Exactly one
return $resultsstatement - Brace-balanced
- No BOM, no non-ASCII characters
- Tested standalone:
.\modules\module-yourname.ps1 - Tested via orchestrator:
.\Windows-Security-Audit.ps1 -Modules YourName - Documented in Module Documentation wiki
- Every page starts with
# Page Title - Include
**Version:** 6.1.2near the top - Use
## Table of Contentsfor any page over 200 lines - Cross-reference related pages:
[Page Name](Page-Name) - Include code examples for any user-facing feature
- Update the Footer page version stamp when making structural changes
- README.md — overview and quick reference
- CHANGELOG.md — release history
- CONTRIBUTING.md — contribution guidelines (this page mirrors)
- LICENSE.md — MIT license text
- SECURITY.md — security policy and disclosure
All contributors are listed in CONTRIBUTORS.md (when present) and in commit history.
Canonical contributing file: docs/project/CONTRIBUTING.md
Windows Security Audit Project · Version 6.1.2 · MIT License
Repository · Releases · Issues · Pull Requests
Changelog · Contributing · Security Policy · License
Frameworks: ACSC · CIS · CISA · CMMC · Core · ENISA · GDPR · HIPAA · ISO 27001 · MS · MS-DefenderATP · NIST · NSA · PCI-DSS · SOC 2 · STIG
Coverage: 16 Modules · 3,994 Automated Security Checks · 5 Native Output Formats · 6 Browser-based Exports · Zero External Dependencies
This documentation reflects Windows Security Audit Project v6.1.2 released 2026-04-25. For older versions, see the release tags.
Page last updated: 2026-04-25
Version 6.1.2 · 16 modules · 3,994 checks
Frameworks Covered
ACSC · CIS · CISA · CMMC · Core · ENISA · GDPR · HIPAA · ISO 27001 · MS · MS-DefenderATP · NIST · NSA · PCI-DSS · SOC 2 · STIG
Output Formats
HTML · JSON · CSV · XML · Console · 6 browser exports
Status Values
Pass · Fail · Warning · Info · Error
Severity Levels
Critical · High · Medium · Low · Informational