Open-source Windows image security analyzer suite (17 analyzers)
Project description
rectify-oss
Audit Windows golden images before they ship to your fleet.
The open-source Windows image security analyzer suite. 17 production analyzers, mounted any Windows disk format, JSON output, designed for CI.
Find it. Expose it. Rectify it.
Install · Quick start · Analyzers · CI integration · Contributing
What it does
rectify-oss is a Linux-based static security analyzer for mounted Windows disk images. Point it at the root of a mounted WIM, VHD, VHDX, VMDK, AMI, or Azure managed disk — it produces a structured JSON report of security findings.
It is designed to gate Windows golden images in CI before they ship to your fleet, but you can also run it ad-hoc on any image you have on disk.
BUILD DEPLOY RUNTIME
│ │ │
Build pipelines ──► [ rectify-oss ] ──► (deployment) ──► [ EDR / vuln scanners / SIEM ]
│ │
Catches issues here They catch issues here (after the bad image is on every endpoint)
If you've ever shipped a Windows image and later discovered it had:
Memory.dmpleft inC:\with cleartext credentials in it- A
PSReadLine_history.txtinC:\Users\Defaultthat every new profile inherits - TLS 1.0 still enabled in the Schannel registry
- An RDP listener with NLA disabled
- A WSUS pointing to an old HTTP URL
- 50,000 endpoints inheriting one bad audit policy
rectify-oss catches that at build time.
Install
From source (recommended for now)
git clone https://codeberg.org/rectify-security/rectify-oss.git
cd rectify-oss/analyzers
pip install -e ".[dev]"
From PyPI
Ubuntu via PPA
Requires Python 3.11 or later. Linux only (uses dissect and libguestfs).
Quick start
# 1. Mount your Windows image read-only via libguestfs
sudo guestmount -a windows-image.vhdx -i --ro /mnt/image
# 2. Run the analyzer suite
rectify-oss /mnt/image my-scan-001 win11-corp-gold --output-file report.json
# 3. Read the findings
jq '.analyzer_results[].findings[] | select(.severity == "high" or .severity == "critical")' report.json
# 4. Clean up
sudo guestunmount /mnt/image
That's the entire workflow. JSON in, structured findings out. No agents, no infrastructure, no licence server.
Example output
A single finding looks like this:
{
"id": "ART-002:Memory.dmp",
"analyzer": "artifact_leakage",
"severity": "critical",
"title": "Kernel memory dump left in image",
"description": "Memory.dmp found at C:\\Memory.dmp (4.2 GB). Kernel dumps may contain cleartext credentials, BitLocker keys, and other sensitive material.",
"evidence": {
"path": "C:\\Memory.dmp",
"size_bytes": 4505812992
},
"remediation": "Delete C:\\Memory.dmp before sealing the image. Disable automatic memory dump creation via System Properties > Advanced > Startup and Recovery > Settings.",
"references": [
"https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-system"
]
}
Every finding is Pydantic-validated against a stable schema (see schema.py).
See examples/sample-report.json for a complete real scan report.
What's included
17 production analyzers across two tiers.
Foundation v1 — 8 analyzers
| Analyzer | Checks |
|---|---|
installed_software |
Inventory from registry uninstall keys (CVE-matchable) |
patch_level |
KB rollup currency vs known security patches |
defender_posture |
Microsoft Defender state, AMSI, real-time protection |
persistence_surface |
Run/RunOnce, Services, Image File Execution Options, AppInit |
secret_scanning |
Cleartext credentials in image artifacts |
account_hygiene |
Local users, password-never-expires, last-login flags |
smb_config |
SMBv1, signing, anonymous access, null sessions |
driver_analysis |
Vulnerable drivers (LOLDriver project), unsigned kernel modules |
Tier 1 — Hardening baseline — 9 analyzers
| Analyzer | Checks |
|---|---|
firewall_posture |
Windows Firewall profile state, allow-rules audit |
audit_policy |
Advanced audit policy subcategory coverage |
powershell_hardening |
Constrained Language Mode, ScriptBlock logging, Module logging |
wsus_config |
WSUS server URL, HTTPS-only, TLS posture |
ntp_config |
Time source, drift bounds, NT5DS vs NTP |
rdp_config |
NLA, MinEncryptionLevel, idle timeout, listener state |
lsa_protection |
LSASS RunAsPPL, Credential Guard, WDAC integration |
tls_schannel |
Schannel ciphers/protocols (TLS 1.0/1.1 disabled) |
schannel_apps |
Application-side TLS configuration in registry |
CI/CD integration
The most valuable use of rectify-oss is gating image builds in CI. Here's a typical pattern for Forgejo Actions:
# .forgejo/workflows/image-audit.yml
name: Audit golden image
on:
push:
paths: ['images/**']
jobs:
audit:
runs-on: docker
steps:
- uses: actions/checkout@v4
- run: sudo apt install -y libguestfs-tools python3-pip
- run: pip install -e ./rectify-oss/analyzers
- name: Mount image
run: |
sudo mkdir -p /mnt/image
sudo guestmount -a images/win11-corp.vhdx -i --ro /mnt/image
- name: Run audit
run: rectify-oss /mnt/image $FORGEJO_SHA win11-corp --output-file findings.json
- name: Fail on high/critical findings
run: |
python -c "
import json, sys
report = json.load(open('findings.json'))
findings = [f for r in report['analyzer_results'] for f in r['findings']]
critical = [f for f in findings if f['severity'] in ('high', 'critical')]
if critical:
for f in critical: print(f\"[{f['severity'].upper()}] {f['id']}: {f['title']}\")
sys.exit(1)
"
- run: sudo guestunmount /mnt/image
if: always()
The same pattern works with GitLab CI, Jenkins, Drone, or any CI system that can run Bash.
Architecture
The framework is small and the contract is stable:
┌─────────────────────────────────────────────────────────┐
│ rectify-oss CLI │
│ └─ runner.py │
│ ├─ Loads 17 analyzers │
│ ├─ Runs each in crash isolation │
│ └─ Serializes ScanReport JSON │
├─────────────────────────────────────────────────────────┤
│ Plugin framework (analyzers/base.py) │
│ └─ class Analyzer: │
│ name: str │
│ version: str │
│ def run(mount_root: Path) -> list[Finding]: │
├─────────────────────────────────────────────────────────┤
│ Schema (analyzers/schema.py) │
│ └─ Finding, ScanReport — Pydantic-validated │
└─────────────────────────────────────────────────────────┘
Each analyzer mounts the Windows image read-only, inspects registry hives via regipy or dissect.target, and produces validated Finding objects. The framework handles crash isolation — one analyzer's failure never breaks the scan.
See docs/analyzer-development.md for the plugin contract.
Writing your own analyzers
from pathlib import Path
from winaudit_analyzers.base import Analyzer
from winaudit_analyzers.schema import Finding, Severity
class MyAnalyzer(Analyzer):
name = "my_analyzer"
version = "0.1.0"
def run(self, mount_root: Path) -> list[Finding]:
findings = []
# Inspect mount_root, parse what you need
# Return Pydantic-validated Finding objects
return findings
Drop the file in winaudit_analyzers/plugins/ and add an import + entry to runner.py. The framework handles crash isolation, schema validation, and stable finding IDs.
What this is NOT
- ❌ Not an EDR. Rectify analyzes images, not running endpoints.
- ❌ Not a runtime BAS tool. Rectify is image-time, not attack simulation.
- ❌ Not a Linux image scanner. Rectify v1 is Windows-only.
- ❌ Not a vulnerability-scanner replacement. Use Tenable/Qualys for the running fleet; use Rectify to gate the build.
About the commercial product
rectify-oss is the open-core layer of a larger Rectify product that is currently under active development. The commercial product will add additional analyzers (Tier 2 / Tier 3 / Tier 4), a platform UI with multi-tenancy, curated rule data, and managed deployment options.
It is not yet available for purchase. The open-source distribution stands on its own — install it, run it, contribute to it. The commercial product will be announced separately when it is ready for design partners.
If you're interested in early access as the commercial product develops, open a discussion on this repo and we'll follow up directly.
Contributing
Pull requests welcome. See CONTRIBUTING.md.
Before opening a PR:
- Sign the CLA — instructions in
CONTRIBUTING.md - Run
pytestfromanalyzers/ - Run
ruff check . && mypy src - Open the PR with a clear description of what changed and how you tested it
Security reports go to a different place — see SECURITY.md.
We will not relicense to anything more restrictive than Apache 2.0 without 12 months' public notice.
Project status
| Metric | Status |
|---|---|
| Analyzers registered | 17/17 |
| Schema tests | 7/7 passing |
| Stable API since | v1.0.1 |
| Distribution | source on Codeberg; PyPI and Ubuntu PPA coming soon |
| Issue tracker | Codeberg Issues |
License
Apache License 2.0 — see LICENSE.
Copyright © 2026 Rectify.
The name "Rectify" is a trademark of the project entity. Apache 2.0 does not grant trademark permission. Forks are welcome to use any name except "Rectify" — this protects users from version confusion.
See NOTICE for required Apache 2.0 attribution.
Find it. Expose it. Rectify it.
Issues · Contributing · Security · Changelog
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rectify_oss-1.0.1.post2.tar.gz.
File metadata
- Download URL: rectify_oss-1.0.1.post2.tar.gz
- Upload date:
- Size: 53.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7ba61216c38f0d98735f93a27841c1ff8c16c2f1c70d1efdc47e1bde5d804883
|
|
| MD5 |
a3645df0029262518376734451253916
|
|
| BLAKE2b-256 |
8d7ce51891148a66926449468aa6e8b2385817bbce5af23dd9965c3384072f8d
|
File details
Details for the file rectify_oss-1.0.1.post2-py3-none-any.whl.
File metadata
- Download URL: rectify_oss-1.0.1.post2-py3-none-any.whl
- Upload date:
- Size: 61.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5c16bb91131590e36fa98db41ef036a9958f21bdc728ecfc6c1a49e78b8cfc56
|
|
| MD5 |
235025bffb850696be710695c6b016ee
|
|
| BLAKE2b-256 |
f4b9156ba13be8892727a75871ade579d4c4aac04f6596b12e163998c3640b79
|