Skip to content

TypeScript GPO XML parser, redaction engine, and CIS Benchmark compliance checker

License

Notifications You must be signed in to change notification settings

DevJCrystal/gpo-parser

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@gpoaudit/parser

Open-source engine for parsing and analyzing Microsoft Group Policy XML exports.

Zero dependencies. Pure TypeScript. Runs anywhere — browser, Node, Deno, Bun.

Powers GPO Audit — the Group Policy audit tool for sysadmins, MSPs, and security teams.

Features

  • Parse GPO XML exports from Get-GPOReport -ReportType Xml
  • Detect conflicts — same setting, different values across GPOs, with precedence resolution
  • Find duplicates — identical settings repeated across multiple GPOs
  • Flag issues — empty, disabled, and unlinked GPOs
  • CIS Benchmark compliance — 29 rules covering password policy, account lockout, Kerberos, audit policy, and Windows Firewall (mapped to NIST 800-53)
  • Redact sensitive data — strip domains, IPs, SIDs, paths, and email addresses before sharing or storing results

Install

npm install @gpoaudit/parser

Quick Start

import { parseGpoXml, analyzeGpos, evaluateCompliance, redactAudit } from '@gpoaudit/parser';

// 1. Parse XML (from Get-GPOReport or GPMC export)
const xmlString = fs.readFileSync('gpo-report.xml', 'utf-8');
const gpos = parseGpoXml(xmlString);

// 2. Analyze for issues
const audit = analyzeGpos(gpos);

console.log(`Total GPOs: ${audit.total}`);
console.log(`Conflicts: ${audit.conflicts.length}`);
console.log(`Duplicates: ${audit.duplicates.length}`);
console.log(`Empty: ${audit.emptyGpos.length}`);
console.log(`Disabled: ${audit.disabledGpos.length}`);
console.log(`Unlinked: ${audit.unlinkedGpos.length}`);

// 3. Check CIS Benchmark compliance
const compliance = evaluateCompliance(audit);
console.log(`Compliance: ${compliance.scorePercent}% (${compliance.passed}/${compliance.totalRules})`);

// 4. Redact sensitive data before sharing
const redacted = redactAudit(audit);
// Safe to send to an API, store in a database, or paste into ChatGPT

Generating the XML Report

Run this in PowerShell on a domain controller or machine with RSAT:

# All GPOs in the domain
Get-GPOReport -All -ReportType Xml -Path "AllGPOs.xml"

# Single GPO
Get-GPOReport -Name "Default Domain Policy" -ReportType Xml -Path "DefaultPolicy.xml"

API

Parser

Function Description
parseGpoXml(xml: string) Parse XML string into Gpo[]
parseGpoXmlBytes(buffer: ArrayBuffer) Parse raw bytes (handles UTF-16 BOM)
analyzeGpos(gpos: Gpo[]) Analyze for conflicts, duplicates, and issues → Audit

Compliance

Function Description
evaluateCompliance(audit: Audit) Evaluate against CIS Benchmark rules → ComplianceSummary
CATEGORY_ORDER Display order for compliance categories

Redaction

Function Description
redactAudit(audit: Audit) Strip sensitive data from full audit → RedactedAudit
redactString(input: string) Redact a single string value

Redaction Targets

The redaction module replaces:

Pattern Replacement
UNC paths (\\server\share) [REDACTED-PATH]
File paths (C:\Users\...) [REDACTED-PATH]
Windows SIDs (S-1-5-21-...) [REDACTED-SID]
FQDNs (host.example.com) [REDACTED-HOST]
IPv4 addresses [REDACTED-IP]
Email addresses [REDACTED-EMAIL]
Domain names (auto-detected) [REDACTED-DOMAIN]

Compliance Rules

29 CIS Benchmark rules across 5 categories, each mapped to NIST 800-53 controls:

Category Rules Examples
Password Policy 6 Min length ≥ 14, complexity, history ≥ 24
Account Lockout 4 Threshold 1–5, duration ≥ 15 min
Kerberos Policy 3 Ticket lifetime, clock skew
Audit Policy 10 Logon, account mgmt, process tracking
Firewall 6 Domain/Private/Public profiles enabled, inbound block

Conflict Resolution

When the same setting exists in multiple GPOs with different values, the parser determines which GPO "wins" using Active Directory precedence rules:

  1. Enforced (No Override) GPOs always win (+1000 precedence)
  2. Deeper OU links override parent OU links (child OU = more specific = wins)
  3. The winning entry is marked with isApplied: true

Browser Usage

Works in any modern browser — no Node.js required:

<input type="file" id="upload" accept=".xml" />
<script type="module">
  import { parseGpoXml, analyzeGpos } from '@gpoaudit/parser';

  document.getElementById('upload').addEventListener('change', async (e) => {
    const text = await e.target.files[0].text();
    const gpos = parseGpoXml(text);
    const audit = analyzeGpos(gpos);
    console.log(audit);
  });
</script>

Contributing

Contributions welcome! Especially:

  • New compliance rules — STIG, DISA, custom frameworks
  • Parser improvements — additional extension namespaces
  • Bug reports — XML exports that don't parse correctly

License

MIT — see LICENSE.


Built by JACrystal · Powering gpoaudit.com

About

TypeScript GPO XML parser, redaction engine, and CIS Benchmark compliance checker

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published