Skip to content

Output Reference

Ryan edited this page Sep 16, 2026 · 10 revisions

Output Reference

guide to understanding and using the audit report outputs.

Table of Contents


Output Formats Overview

The Windows Security Audit Project generates reports in multiple formats, plus real-time console output:

Format Best For File Extension Typical Size
HTML Human review, management reporting, interactive analysis .html 300-600 KB
JSON Automation, remediation files, API integration .json 100-300 KB
CSV Excel analysis, tracking, dashboards .csv 50-150 KB
XML SIEM integration, compliance systems .xml 150-400 KB
JSON (auto-generated) Machine-readable companion file .json 200-500 KB
Console Real-time monitoring, quick checks N/A N/A

Report Types

Beyond the combined report, two additional report types are produced on request:

Report type Switch Location Contents
Combined report (default) reports\ All modules in one document: executive summary, module compliance, module summary at-a-glance, result distribution, overall compliance, top priority findings, and the full findings tables
Per-framework split reports -SplitReports / -SplitOnly reports\by-framework\ One tailored report per framework, each using that framework's native grouping and scoring (for example STIG scores as Open / Not a Finding with a CAT distribution and V-ID column; CMMC carries an SPRS panel; HIPAA separates current-rule findings from clearly labelled proposed-rule indicators). Companion CSV/JSON/XML are emitted according to -OutputFormat.
Attack-surface report -AttackSurfaceReport reports\ Exposure assessment across ten Windows domains synthesized from the audit findings, with an overall exposure score and rating, per-domain scores and contributing findings, and cross-domain highlights

Output Layout

All reports are written beneath a unified reports\ directory, with one sub-directory per audited host. This keeps results for different hosts cleanly separated, so an operator can copy a single host directory and carry everything for that audit with it:

reports\
  <HOSTNAME>\
    Windows-Security-Audit-<HOSTNAME>-<YYYY-MM-DD_HHMMSS>.html   # composite report
    Windows-Security-Audit-<HOSTNAME>-<YYYY-MM-DD_HHMMSS>.json   # composite data
    Attack-Surface-Report-<HOSTNAME>-<YYYY-MM-DD_HHMMSS>.html    # -AttackSurfaceReport
    by-framework\                                                # -SplitReports / -SplitOnly
      STIG-Report-<HOSTNAME>-<YYYY-MM-DD_HHMMSS>.html
      STIG-Report-<HOSTNAME>-<YYYY-MM-DD_HHMMSS>.json
      NIST-Report-<HOSTNAME>-<YYYY-MM-DD_HHMMSS>.html
      ...one set per framework present in the run

An explicit -OutputPath still takes precedence; the hostname sub-directory is created beneath it so the same separation holds wherever output is directed. Characters that are not valid in a directory name are replaced with an underscore when the hostname folder is created.

File Naming Convention

Every report file carries the hostname and the run timestamp, so a file remains identifiable after being copied out of its directory:

Windows-Security-Audit-<HOSTNAME>-<YYYY-MM-DD_HHMMSS>.{html|json|csv|xml}
Attack-Surface-Report-<HOSTNAME>-<YYYY-MM-DD_HHMMSS>.html
<Module>-Report-<HOSTNAME>-<YYYY-MM-DD_HHMMSS>.{html|json|csv|xml}

Naming Pattern:

  • YYYYMMDD - Date (Year, Month, Day)
  • HHMMSS - Time (Hour, Minute, Second in 24-hour format)
  • Same timestamp for all formats from a single execution

Report provenance. Every generated report embeds the renderer build identifier in an HTML comment near the top of the document and in the page footer. When comparing a report against expected behavior, check that stamp first to confirm which build produced the artifact.


HTML Report

Overview

The HTML report is a self-contained, interactive web application designed for human consumption. It requires no external resources and opens in any modern web browser with advanced features for analysis and export.

Key Features

✨ Interactive Features:

  • 🌙 Dark mode toggle with persistent preference
  • 🔍 Per-column filtering (real-time search)
  • ↕️ Column sorting (click headers)
  • ☑️ Row selection for targeted exports
  • 📊 Collapsible module sections
  • 📤 Built-in export functionality (5 formats)
  • 🎨 Color-coded status indicators

Opening the HTML Report

Method 1: Manual Open from Reports Directory

  • HTML reports are saved to .\reports\audit-yyyyMMdd-HHmmss.html
  • The script does NOT auto-open the report (it only writes the file)
  • Open manually with Start-Process .\reports\audit-*.html or by double-clicking in File Explorer

Method 2: Generate Different Format

# Double-click the .html file in file explorer

# Or open via PowerShell
Start-Process ".\Windows-Security-Audit-*.html"

# Specify browser
Start-Process "chrome.exe" ".\Windows-Security-Audit-*.html"
Start-Process "msedge.exe" ".\Windows-Security-Audit-*.html"
Start-Process "firefox.exe" ".\Windows-Security-Audit-*.html"

HTML Report Structure

1. Header Section

Banner:

========================================================================================================
                        Windows Security Audit Report
                   Multi-Framework Security Assessment
========================================================================================================

Dark Mode Toggle:

  • Located in top-right corner
  • Click to switch between light and dark themes
  • Preference saved in browser's local storage

2. System Information Panel

┌────────────────────────────────────────────────────────────────────────────┐
│ Computer Name      │ WORKSTATION01                                          │
│ Operating System   │ Microsoft Windows 11 Pro (Build 26100)                 │
│ Scan Date          │ 2026-04-25 14:30:22                                    │
│ Duration           │ 00:01:18                                                │
│ Modules Executed   │ acsc, cis, cisa, cmmc, core, enisa, gdpr, hipaa,       │
│                    │ iso27001, ms, ms-defenderatp, nist, nsa, pcidss,       │
│                    │ soc2, stig (16 modules)                                 │
└────────────────────────────────────────────────────────────────────────────┘

3. Executive Summary Dashboard

Visual Status Cards:

┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐
│     4065     │  │     487      │  │      34      │  │      18      │
│ Total Checks │  │    Passed    │  │    Failed    │  │   Warnings   │
└──────────────┘  └──────────────┘  └──────────────┘  └──────────────┘

┌──────────────┐  ┌──────────────┐
│      9       │  │      2       │
│     Info     │  │    Errors    │
└──────────────┘  └──────────────┘

Color Coding:

  • Blue - Total Checks
  • Green - Passed (success)
  • Red - Failed (critical)
  • Yellow/Orange - Warnings
  • Cyan - Informational
  • Purple - Errors

4. Global Export Options (New)

Located below the summary dashboard:

┌────────────────────────────────────────────────────────────────┐
│              Global Export Options                             │
│  [Export All]  [Export Selected]                               │
└────────────────────────────────────────────────────────────────┘

Automatic JSON Companion - Every audit automatically generates a structured JSON file alongside the HTML report, regardless of the -OutputFormat setting.

Export All - Exports all findings across all modules Export Selected - Exports only rows with checked checkboxes from all modules

New Report Features (v6.1)

  • Severity Cards -- Row of 5 cards below status summary showing Critical/High/Medium/Low/Informational distribution; click to filter
  • Category Detail Tables -- Each module section includes an expanded table showing every check category with pass/fail/warn/info/error counts and per-category compliance percentage
  • Overall Compliance Cards -- 4 color-coded cards: Weighted Score (color-coded by result), Overall Rating, Simple Score, Severity-Adjusted Score
  • Remediation Priority Ranking (Top 50) -- Collapsible section after all modules listing the 50 most critical findings ranked by severity
  • Deep Navy Dark Theme -- Theme toggle in top-right banner corner; dark mode uses #0b0e14, #111822, #1a2332 matching the Linux Security Audit report
  • Table of Contents -- Collapsible section below host info cards with links to all modules and Remediation Priority

5. Module Results Sections

Each module section includes:

Module Header (Collapsible):

┌────────────────────────────────────────────────────────────────┐
│ MODULE: STIG                    Pass: 78 | Fail: 8 | Warning: 4 | Info: 2   ▼│
└────────────────────────────────────────────────────────────────┘
  • Click header to collapse/expand section
  • Arrow indicator (▼/▶) shows current state

Results Table:

┌───┬────────┬─────────────────────────┬──────────────────────────────────┐
│ ☑ │ Status │ Category                │ Finding                          │
├───┼────────┼─────────────────────────┼──────────────────────────────────┤
│ ☐ │ FAIL   │ STIG - V-220929 (CAT I) │ Guest account is ENABLED         │
│ ☐ │ PASS   │ STIG - V-220718 (CAT II)│ Minimum password length: 14 chars│
│ ☐ │ WARN   │ STIG - V-220930 (CAT II)│ Administrator account not renamed│
└───┴────────┴─────────────────────────┴──────────────────────────────────┘

Filter boxes under each column header:
┌───┬────────┬─────────────────────────┬──────────────────────────────────┐
│   │[Filter]│[Filter]                 │[Filter]                          │
└───┴────────┴─────────────────────────┴──────────────────────────────────┘

Expandable Details: Click any row to expand inline details:

┌────────────────────────────────────────────────────────────────────────┐
│ STIG - V-220929 (CAT I)                                                  │
│ Guest account is ENABLED                                                 │
├────────────────────────────────────────────────────────────────────────┤
│ Details:                                                                 │
│ STIG CAT I: Guest account must be disabled to prevent anonymous access. │
│ This is a critical security control.                                    │
│                                                                          │
│ REMEDIATION:                                                             │
│ Disable-LocalUser -Name Guest                                           │
│                                                                          │
│ Timestamp: 2026-04-25 14:30:25                                          │
└────────────────────────────────────────────────────────────────────────┘

Module Export Buttons: Each module section has its own export options:

  • [Export Module] - Export all findings from this module
  • [Export Selected from Module] - Export checked rows from this module

Interactive Features Guide

Dark Mode

Activation:

  1. Click "Toggle Dark Mode" button (top-right)
  2. Page theme switches instantly
  3. Preference saved automatically

Benefits:

  • Easier on eyes during long review sessions
  • Reduces eye strain
  • Professional appearance for presentations

Column Filtering

Real-Time Search:

  1. Type in filter box under any column header
  2. Results filter instantly as you type
  3. Case-insensitive matching
  4. Multiple filters work together (AND logic)

Example Use Cases:

Status filter: "fail" → Shows only failures
Category filter: "CAT I" → Shows only Category I findings
Finding filter: "password" → Shows all password-related findings

Sorting

How to Sort:

  1. Click any column header
  2. First click: Ascending sort
  3. Second click: Descending sort
  4. Visual arrow indicator (↑/↓) shows sort direction

Recommended Sorting:

  • Sort by Status to group Pass/Fail/Warning
  • Sort by Category to group by compliance framework
  • Sort by Finding to alphabetically organize results

Row Selection

Selecting Rows:

  • ☐ Click checkbox to select individual row
  • ☑ Click "Select All" checkbox in header to select all visible rows
  • Works with filters (selects only filtered results)

Use Cases:

  1. Select specific findings to remediate
  2. Export subset of results
  3. Create targeted reports for specific teams

Export Modal (New Feature)

Workflow:

  1. Click any Export button (Global or Module-level)
  2. Modal dialog appears with format options
  3. Click desired format
  4. File downloads automatically

Available Export Formats:

Format Description Best For
CSV Comma-delimited spreadsheet Excel analysis, pivot tables
Excel Formatted HTML table (.xls) Presentations, formatted reports
JSON Machine-readable data Remediation files, automation
XML Standards-compliant structure SIEM ingestion, compliance systems
TXT Fixed-width plain text Documentation, email, tickets

Export Workflows

Workflow 1: Export All Failures

Steps:

  1. Open HTML report
  2. Click "Status" column header to sort
  3. Use Status filter box, type: "fail"
  4. Click "Export All" button
  5. Select "Excel" format
  6. Send to management

Result: Formatted Excel report with only failed checks

Workflow 2: Create Remediation Plan

Steps:

  1. Open HTML report
  2. Review findings carefully
  3. Check boxes next to issues you want to fix
  4. Click "Export Selected" button
  5. Select "JSON" format
  6. Save as remediation-plan.json

Use Remediation File:

.\Windows-Security-Audit.ps1 -AutoRemediate -RemediationFile "remediation-plan.json"

Result: Only selected issues are remediated

Workflow 3: Module-Specific Report

Steps:

  1. Navigate to STIG module section
  2. Click "Export Module" button
  3. Select "TXT" format
  4. Include in compliance documentation

Result: Clean text report of all STIG findings

Workflow 4: Selected Issues from Module

Steps:

  1. Filter STIG module to show "CAT I" findings
  2. Select all filtered results (checkboxes)
  3. Click "Export Selected from Module"
  4. Select "CSV"
  5. Import to project tracking tool

Result: CSV of only critical STIG findings

HTML Report Tips and Tricks

Browser Compatibility

✅ Fully Supported:

  • Google Chrome (v90+)
  • Microsoft Edge (v90+)
  • Mozilla Firefox (v88+)
  • Safari (v14+)

⚠️ Limited Support:

  • Internet Explorer (not recommended, lacks modern features)
  • Older browsers (may lack dark mode, export features)

Keyboard Shortcuts

Ctrl+F (Cmd+F on Mac) - Browser's find function
Ctrl+P (Cmd+P on Mac) - Print dialog (save to PDF)
Ctrl+S (Cmd+S on Mac) - Save HTML file
Ctrl+Click - Open link in new tab (if external links present)

Advanced Searching

Browser Find (Ctrl+F) Use Cases:

Search: "CAT I"      → Find all Category I STIG findings
Search: "Fail"       → Jump through all failures
Search: "BitLocker"  → Find encryption-related findings
Search: "V-220929"   → Find specific STIG V-ID
Search: "password"   → Find all password-related checks

Printing to PDF

High-Quality PDF Export:

1. Open HTML report
2. Press Ctrl+P (Cmd+P on Mac)
3. Destination: "Save as PDF"
4. Settings:
   - Layout: Portrait
   - Margins: Default
   - Scale: 100%
   - Background graphics: On (for colors)
5. Click "Save"

Result: Professional PDF with full formatting, colors, and tables

Sharing Reports

Best Practices:

✅ Do:

  • Share complete HTML file (self-contained)
  • Use secure file transfer methods
  • Add date/context in email subject
  • Include summary of key findings
  • Encrypt if sending externally

❌ Don't:

  • Email to untrusted recipients
  • Post to public file shares
  • Modify HTML manually (regenerate instead)
  • Share without management approval
  • Include in public repositories

Secure Sharing Example:

# Compress report with password
Compress-Archive -Path "Windows-Security-Audit-*.html" -DestinationPath "Audit-Report.zip"
# Use 7-Zip or similar to add password protection

# Send via secure email
Send-MailMessage `
    -To "security-team@company.com" `
    -From "auditor@company.com" `
    -Subject "Security Audit - $env:COMPUTERNAME - $(Get-Date -Format 'yyyy-MM-dd')" `
    -Body "Please find attached security audit report. Password will be sent separately." `
    -Attachments "Audit-Report.zip" `
    -Priority High

Accessibility Features

Screen Reader Support:

  • Semantic HTML structure
  • ARIA labels on interactive elements
  • Keyboard navigation support
  • High contrast in dark mode

Keyboard Navigation:

  • Tab through interactive elements
  • Enter to activate buttons
  • Space to toggle checkboxes
  • Arrow keys in filter boxes

JSON Report

Overview

The JSON report contains structured, machine-readable data designed for automation, integration, and programmatic analysis. It can also be used as a remediation file with the -RemediationFile parameter.

JSON Structure

{
  "ExecutionInfo": {
    "ComputerName": "WORKSTATION01",
    "OSVersion": "Microsoft Windows 11 Pro",
    "ScanDate": "2026-04-25 14:30:22",
    "Duration": "00:05:34",
    "ModulesRun": ["Core", "STIG", "NIST", "CIS", "NSA", "CISA", "MS"],
    "TotalChecks": 4065,
    "PassCount": 487,
    "FailCount": 34,
    "WarningCount": 18,
    "InfoCount": 9,
    "ErrorCount": 2
  },
  "Results": [
    {
      "Module": "STIG",
      "Category": "STIG - V-220929 (CAT I)",
      "Status": "Fail",
      "Message": "Guest account is ENABLED",
      "Details": "STIG CAT I: Guest account must be disabled to prevent anonymous access",
      "Remediation": "Disable-LocalUser -Name Guest",
      "Timestamp": "2026-04-25 14:30:25"
    },
    {
      "Module": "STIG",
      "Category": "STIG - V-220718 (CAT II)",
      "Status": "Pass",
      "Message": "Minimum password length: 14 characters",
      "Details": "STIG: Passwords must be at least 14 characters to resist brute force",
      "Remediation": "",
      "Timestamp": "2026-04-25 14:30:25"
    }
  ]
}

Remediation File Format (Exported from HTML)

When you export selected issues from the HTML report, the JSON structure is optimized for use with -RemediationFile:

{
  "exportDate": "2026-04-25T14:30:22Z",
  "modules": [
    {
      "moduleName": "STIG",
      "results": [
        {
          "Status": "Fail",
          "Category": "STIG - V-220929 (CAT I)",
          "Finding": "Guest account is ENABLED"
        },
        {
          "Status": "Fail",
          "Category": "STIG - V-220968 (CAT II)",
          "Finding": "SMBv1 protocol is ENABLED"
        }
      ]
    },
    {
      "moduleName": "CIS",
      "results": [
        {
          "Status": "Fail",
          "Category": "CIS - Account Policy",
          "Finding": "Minimum password length is 8 characters"
        }
      ]
    }
  ]
}

Usage:

# Export selected issues from HTML report to JSON
# Then use for targeted remediation:
.\Windows-Security-Audit.ps1 -AutoRemediate -RemediationFile "selected-issues.json"

Reading JSON in PowerShell

Basic Analysis

# Load JSON file
$report = Get-Content ".\Windows-Security-Audit-*.json" -Raw | ConvertFrom-Json

# Access execution information
$report.ExecutionInfo.ComputerName
$report.ExecutionInfo.TotalChecks
$report.ExecutionInfo.FailCount

# Get all results
$report.Results

# Filter by status
$failures = $report.Results | Where-Object { $_.Status -eq "Fail" }
$warnings = $report.Results | Where-Object { $_.Status -eq "Warning" }

# Display failures
$failures | Format-Table Module, Category, Message -AutoSize

Advanced Filtering

# Get CAT I STIG findings
$catI = $report.Results | Where-Object { $_.Category -like "*CAT I*" }

# Get all password-related findings
$passwordIssues = $report.Results | Where-Object { 
    $_.Message -like "*password*" -or $_.Category -like "*password*"
}

# Filter by module
$stigResults = $report.Results | Where-Object { $_.Module -eq "STIG" }
$cisResults = $report.Results | Where-Object { $_.Module -eq "CIS" }

# Get findings with remediation available
$remediable = $report.Results | Where-Object { 
    $_.Status -eq "Fail" -and $_.Remediation -ne ""
}

# Count findings by module and status
$report.Results | 
    Group-Object Module, Status | 
    Select-Object Count, Name | 
    Sort-Object Name

Statistical Analysis

# Calculate compliance rate
$totalChecks = $report.ExecutionInfo.TotalChecks
$passCount = $report.ExecutionInfo.PassCount
$complianceRate = [math]::Round(($passCount / $totalChecks) * 100, 2)

Write-Host "Compliance Rate: $complianceRate%"

# Status distribution
$statusCounts = $report.Results | Group-Object Status
foreach ($status in $statusCounts) {
    $percentage = [math]::Round(($status.Count / $totalChecks) * 100, 1)
    Write-Host "$($status.Name): $($status.Count) ($percentage%)"
}

# Module performance
$moduleStats = $report.Results | Group-Object Module | ForEach-Object {
    $moduleName = $_.Name
    $total = $_.Count
    $pass = ($_.Group | Where-Object Status -eq "Pass").Count
    $fail = ($_.Group | Where-Object Status -eq "Fail").Count
    $compliance = [math]::Round(($pass / $total) * 100, 1)
    
    [PSCustomObject]@{
        Module = $moduleName
        Total = $total
        Pass = $pass
        Fail = $fail
        Compliance = "$compliance%"
    }
}
$moduleStats | Format-Table -AutoSize

Export and Transform

# Export failures to CSV for tracking
$failures | 
    Select-Object Module, Category, Message, Remediation |
    Export-Csv "Failures-ToRemediate.csv" -NoTypeInformation

# Create remediation checklist
$failures | ForEach-Object {
    [PSCustomObject]@{
        Priority = if ($_.Category -like "*CAT I*") { "HIGH" } 
                   elseif ($_.Category -like "*CAT II*") { "MEDIUM" } 
                   else { "LOW" }
        Module = $_.Module
        Issue = $_.Message
        Remediation = $_.Remediation
        AssignedTo = ""
        Status = "Open"
        DueDate = (Get-Date).AddDays(7).ToString("yyyy-MM-dd")
    }
} | Export-Csv "Remediation-Checklist.csv" -NoTypeInformation

# Generate executive summary
$summary = @"
Security Audit Summary - $($report.ExecutionInfo.ComputerName)
Date: $($report.ExecutionInfo.ScanDate)

Overall Compliance: $complianceRate%

Critical Issues (Fail): $($report.ExecutionInfo.FailCount)
Warnings: $($report.ExecutionInfo.WarningCount)

Top Issues:
$($failures | Select-Object -First 5 | ForEach-Object { "- $($_.Message)" } | Out-String)

Full report: Windows-Security-Audit-$(Get-Date -Format 'yyyyMMdd-HHmmss').html
"@

$summary | Out-File "Executive-Summary.txt"

JSON in Python

import json
from datetime import datetime

# Load JSON
with open('audit-20260425-143022.json', 'r') as f:
    report = json.load(f)

# Access data
exec_info = report['ExecutionInfo']
print(f"Computer: {exec_info['ComputerName']}")
print(f"Total Checks: {exec_info['TotalChecks']}")
print(f"Failures: {exec_info['FailCount']}")
print(f"Compliance: {(exec_info['PassCount']/exec_info['TotalChecks']*100):.1f}%")

# Filter failures
failures = [r for r in report['Results'] if r['Status'] == 'Fail']
print(f"\nFailures ({len(failures)}):")
for fail in failures:
    print(f"  [{fail['Module']}] {fail['Message']}")

# Group by module
from collections import defaultdict
by_module = defaultdict(lambda: {'total': 0, 'pass': 0, 'fail': 0})

for result in report['Results']:
    module = result['Module']
    by_module[module]['total'] += 1
    if result['Status'] == 'Pass':
        by_module[module]['pass'] += 1
    elif result['Status'] == 'Fail':
        by_module[module]['fail'] += 1

print("\nModule Summary:")
for module, stats in by_module.items():
    compliance = (stats['pass'] / stats['total'] * 100)
    print(f"  {module}: {compliance:.1f}% ({stats['pass']}/{stats['total']})")

# Create remediation list
remediation_list = [
    {
        'priority': 'HIGH' if 'CAT I' in r['Category'] else 'MEDIUM',
        'module': r['Module'],
        'issue': r['Message'],
        'remediation': r['Remediation']
    }
    for r in failures if r['Remediation']
]

# Export to JSON
with open('remediation-plan.json', 'w') as f:
    json.dump(remediation_list, f, indent=2)

JSON in JavaScript/Node.js

const fs = require('fs');

// Load JSON
const report = JSON.parse(
  fs.readFileSync('audit-20260425-143022.json', 'utf8')
);

// Access data
const { ExecutionInfo, Results } = report;
console.log(`Computer: ${ExecutionInfo.ComputerName}`);
console.log(`Total Checks: ${ExecutionInfo.TotalChecks}`);
console.log(`Failures: ${ExecutionInfo.FailCount}`);

// Calculate compliance
const compliance = ((ExecutionInfo.PassCount / ExecutionInfo.TotalChecks) * 100).toFixed(1);
console.log(`Compliance: ${compliance}%`);

// Filter and group
const failures = Results.filter(r => r.Status === 'Fail');
const byModule = Results.reduce((acc, r) => {
  if (!acc[r.Module]) {
    acc[r.Module] = { total: 0, pass: 0, fail: 0 };
  }
  acc[r.Module].total++;
  if (r.Status === 'Pass') acc[r.Module].pass++;
  if (r.Status === 'Fail') acc[r.Module].fail++;
  return acc;
}, {});

console.log('\nModule Summary:');
Object.entries(byModule).forEach(([module, stats]) => {
  const moduleCompliance = ((stats.pass / stats.total) * 100).toFixed(1);
  console.log(`  ${module}: ${moduleCompliance}% (${stats.pass}/${stats.total})`);
});

// Create issue tickets
const tickets = failures.map(f => ({
  title: f.Message,
  description: f.Details,
  priority: f.Category.includes('CAT I') ? 'Critical' : 'High',
  category: f.Category,
  remediation: f.Remediation,
  module: f.Module
}));

// Export
fs.writeFileSync('tickets.json', JSON.stringify(tickets, null, 2));

JSON Use Cases

Browser Export Formats (from HTML Report)

The HTML report provides 6 browser-based export formats via the "Export All" / "Export Selected" modal:

Format Description Use Case
CSV Workbook Comma-separated values with all fields Spreadsheet analysis, data import
Excel (XLS) HTML-based Excel workbook format Direct opening in Microsoft Excel
JSON Structured Data Formatted JSON with metadata envelope API integration, programmatic analysis
XML Workbook XSL-styled self-rendering XML Browser viewing, XML-based tools, data interchange
XML SIEM-Compatible Event-based XML with severity/timestamp SIEM ingestion (Splunk, QRadar, ArcSight)
TXT Plain Text Human-readable plain text report Email, documentation, log archival

The XML Workbook format uses an embedded XSLT stylesheet that renders the XML as a styled HTML table when opened in any modern browser. The data remains valid XML within the urn:windows-security-audit namespace, parseable by XML tools.

The XML SIEM-Compatible format produces raw XML without styling, optimized for secondary processing by SIEM appliances and log aggregation platforms.

1. SIEM Integration (Splunk)

# Index JSON files
/opt/splunk/bin/splunk add oneshot /path/to/reports/*.json \
  -sourcetype windows:security:audit \
  -index security

Splunk Search Queries:

# Find all failures
sourcetype="windows:security:audit" ExecutionInfo.FailCount>0
| table ExecutionInfo.ComputerName, ExecutionInfo.FailCount

# Track compliance over time
sourcetype="windows:security:audit"
| eval compliance=(ExecutionInfo.PassCount/ExecutionInfo.TotalChecks)*100
| timechart avg(compliance) by ExecutionInfo.ComputerName

# Alert on critical failures
sourcetype="windows:security:audit" Results{}.Status="Fail" Results{}.Category="*CAT I*"
| table ExecutionInfo.ComputerName, Results{}.Message

2. Ticketing System (ServiceNow)

// Create incidents from failures
const report = require('./Windows-Security-Audit-20260425.json');
const failures = report.Results.filter(r => r.Status === 'Fail');

failures.forEach(fail => {
  const priority = fail.Category.includes('CAT I') ? '1' : 
                   fail.Category.includes('CAT II') ? '2' : '3';
  
  createIncident({
    short_description: `[${fail.Module}] ${fail.Message}`,
    description: fail.Details,
    work_notes: `Remediation: ${fail.Remediation}`,
    priority: priority,
    category: 'Security',
    subcategory: fail.Module,
    assigned_to: 'security-team',
    configuration_item: report.ExecutionInfo.ComputerName
  });
});

3. Dashboard/Metrics (Grafana/InfluxDB)

from influxdb import InfluxDBClient
import json

client = InfluxDBClient(host='localhost', port=8086, database='security_metrics')

with open('Windows-Security-Audit-20260425.json') as f:
    report = json.load(f)

# Write metrics to InfluxDB
points = [{
    "measurement": "security_audit",
    "tags": {
        "hostname": report['ExecutionInfo']['ComputerName'],
        "os_version": report['ExecutionInfo']['OSVersion']
    },
    "time": report['ExecutionInfo']['ScanDate'],
    "fields": {
        "total_checks": report['ExecutionInfo']['TotalChecks'],
        "pass_count": report['ExecutionInfo']['PassCount'],
        "fail_count": report['ExecutionInfo']['FailCount'],
        "warning_count": report['ExecutionInfo']['WarningCount'],
        "compliance_rate": (report['ExecutionInfo']['PassCount'] / 
                           report['ExecutionInfo']['TotalChecks'] * 100)
    }
}]

# Add per-module metrics
for module in set(r['Module'] for r in report['Results']):
    module_results = [r for r in report['Results'] if r['Module'] == module]
    pass_count = sum(1 for r in module_results if r['Status'] == 'Pass')
    
    points.append({
        "measurement": "security_audit_module",
        "tags": {
            "hostname": report['ExecutionInfo']['ComputerName'],
            "module": module
        },
        "time": report['ExecutionInfo']['ScanDate'],
        "fields": {
            "total": len(module_results),
            "pass": pass_count,
            "compliance": (pass_count / len(module_results) * 100)
        }
    })

client.write_points(points)

4. Email Alerts

$report = Get-Content ".\Windows-Security-Audit-*.json" -Raw | ConvertFrom-Json
$failures = $report.Results | Where-Object { $_.Status -eq "Fail" }

# Alert on critical failures
$criticalFailures = $failures | Where-Object { $_.Category -like "*CAT I*" }

if ($criticalFailures.Count -gt 0) {
    $body = @"
CRITICAL SECURITY ALERT
=======================

System: $($report.ExecutionInfo.ComputerName)
Date: $($report.ExecutionInfo.ScanDate)

Critical Failures ($($criticalFailures.Count)):

$(foreach ($fail in $criticalFailures) {
    "• [$($fail.Module)] $($fail.Message)`n  Remediation: $($fail.Remediation)`n"
})

Full Report: \\FileServer\Security\Audits\$($report.ExecutionInfo.ComputerName)\
"@

    Send-MailMessage `
        -To "security-team@company.com", "manager@company.com" `
        -From "security-audit@company.com" `
        -Subject "🚨 CRITICAL: Security Failures on $($report.ExecutionInfo.ComputerName)" `
        -Body $body `
        -Priority High `
        -SmtpServer "smtp.company.com"
}

CSV Report

Overview

The CSV report provides tabular data optimized for spreadsheet analysis, tracking remediation over time, and creating dashboards.

CSV Structure

Module,Category,Status,Message,Details,Remediation,Timestamp
STIG,"STIG - V-220929 (CAT I)",Fail,Guest account is ENABLED,"STIG CAT I: Guest account must be disabled to prevent anonymous access",Disable-LocalUser -Name Guest,2026-04-25 14:30:25
STIG,"STIG - V-220718 (CAT II)",Pass,Minimum password length: 14 characters,"STIG: Passwords must be at least 14 characters to resist brute force",,2026-04-25 14:30:25
CIS,"CIS - Account Policy",Fail,Minimum password length is 8 characters,"CIS Benchmark: Set minimum password length to 14 or more characters",net accounts /minpwlen:14,2026-04-25 14:30:26

Field Descriptions:

  • Module - Framework name (one of: acsc, cis, cisa, cmmc, core, enisa, gdpr, hipaa, iso27001, ms, ms-defenderatp, nist, nsa, pcidss, soc2, stig)
  • Category - Specific control or requirement ID
  • Status - Result status (Pass, Fail, Warning, Info, Error)
  • Message - Brief description of the finding
  • Details - Extended information about the check
  • Remediation - PowerShell command or instructions to fix
  • Timestamp - When the check was performed

Opening in Excel

Method 1: Double-Click

  • Navigate to CSV file
  • Double-click to open in Excel
  • Columns auto-detected

Method 2: Import Data Wizard

Excel → Data → From Text/CSV
→ Select file
→ Delimiter: Comma
→ Text qualifier: " (double quote)
→ Click "Load"

Method 3: Power Query

Excel → Data → Get Data → From File → From Text/CSV
→ Select file
→ Click "Transform Data" for advanced options
→ Data Types detected automatically
→ Click "Close & Load"

Excel Analysis Examples

1. Filter and Sort

Show Only Failures:

1. Select data range (Ctrl+A)
2. Data → Filter
3. Click Status column dropdown
4. Uncheck all except "Fail"
5. Click OK

Sort by Priority:

1. Add helper column: Priority
2. Formula: =IF(ISNUMBER(SEARCH("CAT I",B2)),"Critical",IF(ISNUMBER(SEARCH("CAT II",B2)),"High","Medium"))
3. Sort by Priority column (Critical → High → Medium)

2. PivotTable Analysis

Create Status Summary by Module:

1. Select data range
2. Insert → PivotTable
3. Drag "Module" to Rows
4. Drag "Status" to Columns
5. Drag "Status" to Values (Count)
6. Result: Cross-tab showing Pass/Fail/Warning counts per module

Compliance Percentage Calculation:

1. In PivotTable
2. Add Calculated Field: Compliance
3. Formula: =Pass/(Pass+Fail+Warning)*100
4. Format as percentage

3. Conditional Formatting

Color-Code Status Column:

1. Select Status column
2. Home → Conditional Formatting → New Rule
3. Format cells that contain:
   - "Fail" → Red background, white text
   - "Pass" → Green background, white text
   - "Warning" → Yellow background, black text
   - "Info" → Blue background, white text
4. Apply to range

Highlight Priority Issues:

1. Select Category column
2. Conditional Formatting → Highlight Cell Rules → Text that Contains
3. Enter "CAT I" → Red fill with dark red text
4. Repeat for "CAT II" → Orange fill

4. Dashboard Creation

Compliance Dashboard Template:

A1: Security Audit Dashboard
A2: System: [=B2]
A3: Date: [=B3]

A5: Overall Statistics
A6: Total Checks: [=COUNTA(Status column)]
A7: Passed: [=COUNTIF(Status,"Pass")]
A8: Failed: [=COUNTIF(Status,"Fail")]
A9: Compliance Rate: [=A7/A6] (format as %)

A11: [Pie Chart: Status Distribution]
A20: [Bar Chart: Failures by Module]
A30: [Line Chart: Trend over time (if multiple audits)]

B5: Top 5 Critical Issues
B6: [Table filtered to CAT I failures, top 5]

Charts to Create:

  1. Pie Chart - Status distribution (Pass/Fail/Warning/Info/Error)
  2. Bar Chart - Count of failures by module
  3. Stacked Bar - Pass/Fail/Warning per module
  4. Line Chart - Compliance trend over time (requires multiple audit files)

Tracking Remediation Progress

Initial Setup

Step 1: Run Baseline Audit

.\Windows-Security-Audit.ps1 -OutputFormat CSV

Step 2: Create Tracking Spreadsheet

1. Open baseline CSV in Excel
2. Filter to show only "Fail" status
3. Copy filtered results to new sheet: "Remediation Tracking"
4. Add columns:
   - Column H: Assigned To
   - Column I: Priority (High/Medium/Low)
   - Column J: Due Date
   - Column K: Status (Open/In Progress/Complete)
   - Column L: Completion Date
   - Column M: Notes
5. Save as "Remediation-Tracker-2026-04.xlsx"

Tracking Workflow

Week 1: Assign issues
  - Assign critical (CAT I) to security team
  - Set due dates (7 days for critical, 30 for others)
  - Status: Open

Week 2: Begin remediation
  - Update Status to "In Progress"
  - Add notes on progress/blockers

Week 3: Verify fixes
  - Run new audit
  - Compare results
  - Mark items "Complete" with completion date

Week 4: Management report
  - Generate summary metrics
  - Show improvement trend
  - Identify remaining issues

Comparison Formula

Compare Current vs Baseline:

// In current audit sheet, add column:
=VLOOKUP(B2,Baseline!B:C,2,FALSE)
// Returns status from baseline for same finding

// Conditional format:
// If previous = "Fail" AND current = "Pass" → Green (Fixed)
// If previous = "Fail" AND current = "Fail" → Red (Not Fixed)

Progress Metrics

// Overall improvement
Total Issues (Baseline): [=COUNTIF(Baseline!C:C,"Fail")]
Resolved Issues: [=COUNTIF(Current!C:C,"Pass")-COUNTIF(Baseline!C:C,"Pass")]
Remaining Issues: [=COUNTIF(Current!C:C,"Fail")]
Resolution Rate: [=Resolved/Total*100]%

// By module
Module: STIG
Baseline Failures: [=COUNTIFS(Baseline!A:A,"STIG",Baseline!C:C,"Fail")]
Current Failures: [=COUNTIFS(Current!A:A,"STIG",Current!C:C,"Fail")]
Improvement: [=Baseline-Current]

CSV in PowerShell

# Import CSV
$audit = Import-Csv ".\Windows-Security-Audit-*.csv"

# Basic statistics
$total = $audit.Count
$pass = ($audit | Where-Object Status -eq "Pass").Count
$fail = ($audit | Where-Object Status -eq "Fail").Count
$compliance = [math]::Round(($pass / $total) * 100, 1)

Write-Host "Compliance: $compliance% ($pass/$total)"

# Group by module
$byModule = $audit | Group-Object Module | ForEach-Object {
    $moduleTotal = $_.Count
    $modulePass = ($_.Group | Where-Object Status -eq "Pass").Count
    $moduleCompliance = [math]::Round(($modulePass / $moduleTotal) * 100, 1)
    
    [PSCustomObject]@{
        Module = $_.Name
        Total = $moduleTotal
        Pass = $modulePass
        Fail = ($_.Group | Where-Object Status -eq "Fail").Count
        Compliance = "$moduleCompliance%"
    }
}

$byModule | Format-Table -AutoSize

# Export failures for remediation
$failures = $audit | Where-Object { $_.Status -eq "Fail" }
$failures | Select-Object Module, Category, Message, Remediation |
    Export-Csv "Remediation-List.csv" -NoTypeInformation

# Create summary report
$summary = @"
Security Audit Summary
Date: $(Get-Date -Format 'yyyy-MM-dd')

Overall: $compliance% compliant
- Total: $total
- Pass: $pass
- Fail: $fail

By Module:
$($byModule | Format-Table -AutoSize | Out-String)
"@

$summary | Out-File "Summary-Report.txt"

CSV Use Cases

1. SQL Database Import

-- Create table
CREATE TABLE audit_results (
    id INT IDENTITY(1,1) PRIMARY KEY,
    audit_date DATE,
    hostname VARCHAR(50),
    module VARCHAR(50),
    category VARCHAR(100),
    status VARCHAR(20),
    message VARCHAR(500),
    details TEXT,
    remediation VARCHAR(500),
    timestamp DATETIME
);

-- Bulk import CSV
BULK INSERT audit_results
FROM 'C:\Audits\Windows-Security-Audit-20260425.csv'
WITH (
    FORMAT = 'CSV',
    FIRSTROW = 2,
    FIELDTERMINATOR = ',',
    ROWTERMINATOR = '\n'
);

-- Query compliance trend
SELECT 
    audit_date,
    COUNT(*) as total_checks,
    SUM(CASE WHEN status = 'Pass' THEN 1 ELSE 0 END) as passed,
    SUM(CASE WHEN status = 'Fail' THEN 1 ELSE 0 END) as failed,
    CAST(SUM(CASE WHEN status = 'Pass' THEN 1 ELSE 0 END) * 100.0 / COUNT(*) AS DECIMAL(5,2)) as compliance_rate
FROM audit_results
GROUP BY audit_date
ORDER BY audit_date;

2. PowerBI Dashboard

Setup:

1. Open PowerBI Desktop
2. Get Data → CSV
3. Select Windows-Security-Audit-*.csv
4. Transform Data:
   - Set data types (Module=Text, Status=Text, etc.)
   - Add calculated column: Priority
     = IF([Category] CONTAINS "CAT I", "Critical", 
          IF([Category] CONTAINS "CAT II", "High", "Medium"))
5. Load data

6. Create visualizations:
   - Card: Total Checks, Pass Count, Fail Count, Compliance %
   - Donut Chart: Status distribution
   - Bar Chart: Failures by module
   - Table: Top 10 critical failures
   - Line Chart: Compliance trend (requires multiple imports over time)

DAX Measures:

Compliance Rate = 
    DIVIDE(
        CALCULATE(COUNT('audit'[Status]), 'audit'[Status] = "Pass"),
        COUNT('audit'[Status])
    )

Critical Failures = 
    CALCULATE(
        COUNT('audit'[Status]),
        'audit'[Status] = "Fail",
        'audit'[Priority] = "Critical"
    )

3. Compliance Tracking Database

# Create tracking database
$trackingData = Import-Csv ".\Windows-Security-Audit-*.csv" | 
    Where-Object { $_.Status -eq "Fail" } |
    Select-Object @{N='AuditDate';E={Get-Date -Format 'yyyy-MM-dd'}},
                  @{N='Hostname';E={$env:COMPUTERNAME}},
                  Module,
                  Category,
                  Message,
                  @{N='Priority';E={
                      if ($_.Category -like "*CAT I*") { "Critical" }
                      elseif ($_.Category -like "*CAT II*") { "High" }
                      else { "Medium" }
                  }},
                  @{N='AssignedTo';E={''}},
                  @{N='DueDate';E={(Get-Date).AddDays(7).ToString('yyyy-MM-dd')}},
                  @{N='Status';E={'Open'}},
                  @{N='CompletionDate';E={''}},
                  @{N='Notes';E={''}}

$trackingData | Export-Csv "Remediation-Tracking-$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation

XML Report

Overview

The XML report provides standards-compliant, hierarchical data specifically optimized for SIEM ingestion, compliance management systems, and enterprise security tools.

XML Structure

<?xml version="1.0" encoding="UTF-8"?>
<security_audit>
  <metadata>
    <export_date>2026-04-25T14:30:22Z</export_date>
    <computer_name>WORKSTATION01</computer_name>
    <operating_system>Microsoft Windows 11 Pro</operating_system>
    <scan_date>2026-04-25 14:30:22</scan_date>
    <duration>00:05:34</duration>
    <total_checks>4065</total_checks>
    <pass_count>487</pass_count>
    <fail_count>34</fail_count>
    <warning_count>18</warning_count>
    <info_count>9</info_count>
    <error_count>2</error_count>
  </metadata>
  <events>
    <event>
      <timestamp>2026-04-25T14:30:25Z</timestamp>
      <module>STIG</module>
      <status>Fail</status>
      <category>STIG - V-220929 (CAT I)</category>
      <message>Guest account is ENABLED</message>
      <details>STIG CAT I: Guest account must be disabled to prevent anonymous access</details>
      <remediation>Disable-LocalUser -Name Guest</remediation>
    </event>
    <event>
      <timestamp>2026-04-25T14:30:25Z</timestamp>
      <module>STIG</module>
      <status>Pass</status>
      <category>STIG - V-220718 (CAT II)</category>
      <message>Minimum password length: 14 characters</message>
      <details>STIG: Passwords must be at least 14 characters to resist brute force</details>
      <remediation></remediation>
    </event>
  </events>
</security_audit>

XML Features

Benefits:

  • ✅ Standards-compliant format
  • ✅ Hierarchical structure for complex data
  • ✅ Wide SIEM compatibility
  • ✅ XPath query support
  • ✅ Schema validation capable
  • ✅ Direct ingestion by security tools

Reading XML in PowerShell

# Load XML
[xml]$report = Get-Content ".\Windows-Security-Audit-*.xml"

# Access metadata
$report.security_audit.metadata.computer_name
$report.security_audit.metadata.total_checks
$report.security_audit.metadata.fail_count

# Get all events
$events = $report.security_audit.events.event

# Filter failures
$failures = $events | Where-Object { $_.status -eq "Fail" }

# Display failures
$failures | ForEach-Object {
    Write-Host "[$($_.module)] $($_.message)" -ForegroundColor Red
    Write-Host "  Remediation: $($_.remediation)" -ForegroundColor Yellow
}

# Count by status
$events | Group-Object status | Format-Table Count, Name -AutoSize

# Get critical findings
$critical = $events | Where-Object { 
    $_.status -eq "Fail" -and $_.category -like "*CAT I*" 
}

Write-Host "`nCritical Failures: $($critical.Count)" -ForegroundColor Red
$critical | ForEach-Object {
    Write-Host "- $($_.message)" -ForegroundColor Red
}

XML Parsing in Python

import xml.etree.ElementTree as ET

# Parse XML
tree = ET.parse('audit-20260425-143022.xml')
root = tree.getroot()

# Access metadata
metadata = root.find('metadata')
computer = metadata.find('computer_name').text
total = int(metadata.find('total_checks').text)
failed = int(metadata.find('fail_count').text)
compliance = ((total - failed) / total * 100)

print(f"Computer: {computer}")
print(f"Total Checks: {total}")
print(f"Failed: {failed}")
print(f"Compliance: {compliance:.1f}%")

# Parse events
events = root.find('events')
failures = []

for event in events.findall('event'):
    if event.find('status').text == 'Fail':
        failures.append({
            'module': event.find('module').text,
            'category': event.find('category').text,
            'message': event.find('message').text,
            'remediation': event.find('remediation').text
        })

print(f"\nFailures ({len(failures)}):")
for fail in failures:
    print(f"  [{fail['module']}] {fail['message']}")

XML Use Cases

1. SIEM Integration (Splunk)

<!-- inputs.conf -->
<monitor>
  <path>C:\SecurityAudits\Reports\*.xml</path>
  <sourcetype>windows:security:audit:xml</sourcetype>
  <index>security</index>
</monitor>

Splunk Search Queries:

sourcetype="windows:security:audit:xml"
| xmlkv
| table computer_name, fail_count, compliance_rate

sourcetype="windows:security:audit:xml" status="Fail"
| stats count by module, category

2. ArcSight Integration

<!-- Import XML reports directly into ArcSight -->
<!-- Configure XML FlexConnector to parse security_audit format -->

3. QRadar Integration

# Configure log source to parse XML
# Map fields: module → category, status → severity

Console Output

Overview

Real-time progress display during script execution with color-coded status indicators.

Console Output Format

[*] Starting Windows Security Audit Project v6.7.0
[*] Output Directory: C:\SecurityAudit\Reports
[*] Running Modules: acsc, cis, cisa, cmmc, core, enisa, gdpr, hipaa, iso27001, ms, ms-defenderatp, nist, nsa, pcidss, soc2, stig (16 modules)

[Core] Starting Core security baseline checks...
[Core] Checking User Accounts...
[Core] Checking Account Policies...
[Core] Checking Windows Defender...
[Core] Module completed:
  Total Checks: 42
  Passed: 38
  Failed: 2
  Warnings: 1
  Info: 1
  Errors: 0

[STIG] Starting DISA STIG compliance checks...
[STIG] Checking Account Policies...
[STIG] Checking Audit Policy Configuration...
[STIG] Module completed:
  Total Checks: 92
  Passed: 78
  Failed: 8
  Warnings: 4
  Info: 2
  Errors: 0

...

[*] ========================================
[*] Audit Complete!
[*] ========================================
[*] Total Checks: 4065
[*] Passed: 487 (88.5%)
[*] Failed: 34 (6.2%)
[*] Warnings: 18 (3.3%)
[*] Info: 9 (1.6%)
[*] Errors: 2 (0.4%)
[*] 
[*] Reports generated:
[*]   HTML: C:\WinSecAudit\reports\audit-20260425-143022.html
[*]   JSON: C:\WinSecAudit\reports\audit-20260425-143022.json
[*]   CSV:  C:\WinSecAudit\reports\audit-20260425-143022.csv
[*]   XML:  C:\WinSecAudit\reports\audit-20260425-143022.xml

Color Coding

  • Cyan - Module names and section headers
  • Yellow - Category/check group names
  • Green - Pass status, success messages
  • Red - Fail status, error messages
  • Magenta - Module completion summaries
  • White - Neutral information

Capturing Console Output

# Redirect to file
.\Windows-Security-Audit.ps1 > audit_log.txt 2>&1

# Save transcript
Start-Transcript -Path "audit_transcript.txt"
.\Windows-Security-Audit.ps1
Stop-Transcript

# Run in background job
Start-Job -ScriptBlock { 
    C:\SecurityAudit\Windows-Security-Audit.ps1 
}
# Check job status
Get-Job | Format-Table -AutoSize
# Retrieve job output
Receive-Job -Id 1

Report Locations

Default Output Directory

.\

Current directory where script is executed

Example:
C:\SecurityAudit\audit-20260425-143022.html

Custom Output Directory

# Specify custom location
.\Windows-Security-Audit.ps1 -OutputPath "C:\AuditReports\Report.html"

# Network share
.\Windows-Security-Audit.ps1 -OutputPath "\\FileServer\Security\Audits\Report.html"

# Timestamped folders
$date = Get-Date -Format "yyyy-MM-dd"
.\Windows-Security-Audit.ps1 -OutputPath "C:\Audits\$date\Report.html"

# Per-computer folders
.\Windows-Security-Audit.ps1 -OutputPath "C:\Audits\$env:COMPUTERNAME\Report.html"

Finding Reports

# List recent HTML reports
Get-ChildItem ".\Windows-Security-Audit-*.html" | 
    Sort-Object LastWriteTime -Descending |
    Select-Object -First 5

# Find today's reports
$today = Get-Date -Format "yyyyMMdd"
Get-ChildItem ".\Windows-Security-Audit-$today*.html"

# Find all reports
Get-ChildItem ".\Windows-Security-Audit-*.html"
Get-ChildItem ".\Windows-Security-Audit-*.json"
Get-ChildItem ".\Windows-Security-Audit-*.csv"
Get-ChildItem ".\Windows-Security-Audit-*.xml"

Parsing and Integration

PowerShell Integration

# Load and analyze JSON
$report = Get-Content ".\Windows-Security-Audit-*.json" -Raw | ConvertFrom-Json

# Extract key metrics
$metrics = @{
    Hostname = $report.ExecutionInfo.ComputerName
    TotalChecks = $report.ExecutionInfo.TotalChecks
    Failures = $report.ExecutionInfo.FailCount
    ComplianceRate = [math]::Round(($report.ExecutionInfo.PassCount / $report.ExecutionInfo.TotalChecks * 100), 1)
    AuditDate = $report.ExecutionInfo.ScanDate
}

# Store in database
Invoke-SqlCmd -Query "
    INSERT INTO AuditMetrics (Hostname, Date, Total, Failures, Compliance)
    VALUES ('$($metrics.Hostname)', '$($metrics.AuditDate)', 
            $($metrics.TotalChecks), $($metrics.Failures), $($metrics.ComplianceRate))
"

REST API Example (Node.js)

const fs = require('fs');
const express = require('express');
const app = express();

// Endpoint to retrieve audit results
app.get('/api/audit/:hostname', (req, res) => {
  const reportPath = `./Reports/Windows-Security-Audit-*.json`;
  const report = JSON.parse(fs.readFileSync(reportPath, 'utf8'));
  
  if (report.ExecutionInfo.ComputerName === req.params.hostname) {
    res.json({
      hostname: report.ExecutionInfo.ComputerName,
      date: report.ExecutionInfo.ScanDate,
      compliance: (report.ExecutionInfo.PassCount / report.ExecutionInfo.TotalChecks * 100).toFixed(1),
      failures: report.Results.filter(r => r.Status === 'Fail')
    });
  } else {
    res.status(404).send('Report not found');
  }
});

app.listen(3000);

Elasticsearch Ingestion

from elasticsearch import Elasticsearch
import json

es = Elasticsearch(['http://localhost:9200'])

with open('Windows-Security-Audit-20260425.json') as f:
    report = json.load(f)
    
# Index document
es.index(
    index='security-audits',
    document={
        'hostname': report['ExecutionInfo']['ComputerName'],
        'audit_date': report['ExecutionInfo']['ScanDate'],
        'results': report['Results'],
        'summary': {
            'total': report['ExecutionInfo']['TotalChecks'],
            'pass': report['ExecutionInfo']['PassCount'],
            'fail': report['ExecutionInfo']['FailCount'],
            'compliance': (report['ExecutionInfo']['PassCount'] / 
                          report['ExecutionInfo']['TotalChecks'] * 100)
        }
    }
)

Report Retention

Recommended Retention Policy

Purpose Retention Reasoning
Active Analysis 30 days Recent trend analysis
Compliance Evidence 1-3 years Audit requirements
Historical Trending 1 year monthly Long-term metrics
Baseline Snapshots Indefinite Gold image validation

Archival Strategy

# Compress old reports (>90 days)
$oldReports = Get-ChildItem ".\Windows-Security-Audit-*" | 
    Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-90) }

$archiveName = "SecurityAudits_Archive_$(Get-Date -Format 'yyyyMM').zip"
Compress-Archive -Path $oldReports -DestinationPath ".\Archives\$archiveName"

# Delete originals after successful compression
if (Test-Path ".\Archives\$archiveName") {
    $oldReports | Remove-Item
}

Storage Requirements

Typical sizes per audit:

  • HTML: 300-600 KB
  • JSON: 100-300 KB
  • CSV: 50-150 KB
  • XML: 150-400 KB
  • Total: ~600 KB - 1.6 MB

Annual storage (weekly audits):

  • 52 weeks × ~1 MB = ~52 MB per system
  • 100 systems × 52 MB = ~5 GB per year

Best Practices

Security

✅ Do:

  • Store reports in secured location with access controls
  • Consider encrypting sensitive reports
  • Implement proper file permissions
  • Audit access to report directories

❌ Don't:

  • Email reports unencrypted to large distribution lists
  • Store reports in publicly accessible shares
  • Commit reports to version control
  • Share reports outside organization without review

Organization

Recommended folder structure:
Reports/
├── Active/          # Last 30 days
├── Monthly/         # Monthly baseline snapshots
├── Archives/        # Compressed older reports
└── Remediation/     # Tracking spreadsheets

Automation

# Automated weekly report generation and archival
$scriptPath = "C:\SecurityAudit\Windows-Security-Audit.ps1"
$outputPath = "\\FileServer\Security\Audits\$env:COMPUTERNAME"

# Run audit
& $scriptPath -OutputPath "$outputPath\Report.html"

# Copy to monthly snapshot if first week of month
if ((Get-Date).Day -le 7) {
    $monthlyPath = "\\FileServer\Security\Monthly\$env:COMPUTERNAME"
    New-Item -ItemType Directory -Force -Path $monthlyPath | Out-Null
    Copy-Item "$outputPath\Windows-Security-Audit-*.html" -Destination $monthlyPath
}

# Email summary to security team
$report = Get-Content "$outputPath\Windows-Security-Audit-*.json" -Raw | ConvertFrom-Json
if ($report.ExecutionInfo.FailCount -gt 10) {
    Send-MailMessage -To "security@company.com" `
        -Subject "Security Audit Alert - $env:COMPUTERNAME" `
        -Body "Audit found $($report.ExecutionInfo.FailCount) failures" `
        -SmtpServer "smtp.company.com"
}

Related Documentation:

Windows Security Audit

Version 6.7.0 · 16 modules · 4,065 checks


🚀 Getting Started


📚 Reference


🏗️ Architecture


🛠️ Operations


📦 Release Information


🔍 Quick Reference

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


🔗 External Links

Clone this wiki locally