Thanks for considering a contribution. This guide covers module authoring, the test harness, and config contributions.
Drop Check-YourModuleName.ps1 into the modules/ directory. The orchestrator auto-discovers any file matching Check-*.ps1.
At the top of your file, include a metadata comment:
<# MODULE
Name: YourModuleName
Description: What This Module Checks
Category: Security
Author: Your Name
#>The Description field is displayed in the console and report. Name must match the {Name} portion of your filename (Check-{Name}.ps1).
Your file must contain a single function named Invoke-{Name}Checks:
function Invoke-YourModuleNameChecks {
Write-Status "Running your checks..."
# Your detection logic here
Add-Finding -Severity "WARNING" -Category "YourModuleName" `
-Title "Something Suspicious" `
-Description "Explain what was found and why it matters." `
-Remediation "Remove-Whatever -Name 'thing'" `
-Details @{ Key = "value" } `
-MITRE @("T1547.001")
Write-Status "YourModuleName analysis complete."
}- Severity levels:
CRITICAL= strong IOC requiring immediate action.WARNING= suspicious, needs investigation.INFO= informational, worth noting. - Remediation: Include copy-pasteable PowerShell commands when possible. The report auto-detects cmdlet names and makes them clickable.
- Error handling: Use
-ErrorAction SilentlyContinuefor commands that may fail without admin. Wrap sections intry/catchand callWrite-Statuson failure. - Config access: Reference
$script:Configfor whitelists and tuning parameters. - Offline mode: Check
$script:OfflineModebefore making API calls. - No external dependencies: PowerShell 5.1+ built-in cmdlets only.
- MITRE ATT&CK: Every finding should include a
-MITRE @("T1xxx.xxx")array of relevant technique IDs. - Redaction: Handled automatically by
Add-Finding. Module authors do not need to mask sensitive data. - Non-interactive mode:
$script:NonInteractiveis set when-CIModeis used or the environment is non-interactive. Modules do not need to check this -- it's handled at the orchestrator level.
# From the repo root
.\tests\Invoke-MockScan.ps1
# Keep artifacts for debugging
.\tests\Invoke-MockScan.ps1 -KeepArtifactsThe test harness:
- Creates safe mock IOCs (autorun entries, stealer-pattern files, double-extension files)
- Runs
AmIHacked.ps1 -ExportJson -Offline - Validates that expected findings appear in the JSON output
- Validates HTML report structure (CRT toggle, copy buttons, etc.)
- Cleans up all artifacts
Exit code is the number of failed tests (0 = all passed).
Edit config/config.example.json to add (or config/config.json locally):
- ProcessWhitelist: Known-good process names (lowercase, no
.exe) - TrustedIPs: CIDR ranges or single IPs for legitimate services
- TrustedPorts: Expected listening ports
- TrustedCompanies: Version info
CompanyNamestrings for legitimate software vendors - TrustedDomainSuffixes: Domain suffixes (e.g.,
.microsoft.com) for reverse-DNS FP reduction - SuspiciousParentChild: New parent-child process rules for malware detection
- Whitelists should be conservative. Only add entries that generate false positives on a clean default Windows install.
- Include a comment or PR description explaining why the entry is needed.
- Test your config changes with the test harness before submitting.
- All
.ps1files must use UTF-8 BOM encoding (PowerShell 5.1 reads files as Windows-1252 without it, breaking non-ASCII characters). Runfix-bom.ps1after any edit to re-apply the BOM (most editors and the Claude Code Edit tool strip it on save). - PowerShell verb-noun naming for functions
- Consistent indentation (4 spaces)
- Section headers with
# ── N. Section Name ──...pattern - Status messages via
Write-Status, notWrite-Host
A pre-commit hook rejects commits that include .ps1 files without a UTF-8 BOM. Activate it once per clone:
git config core.hooksPath .githooksIf the hook blocks your commit, run fix-bom.ps1, re-stage, and commit again.
- Fork the repo and create a feature branch
- Add or modify your module/check
- Run
.\tests\Invoke-MockScan.ps1and ensure all tests pass - Submit a PR with:
- What the check detects
- False positive considerations
- Any config additions needed