Metadata-Version: 2.4
Name: rectify-oss
Version: 1.0.3
Summary: Open-source Windows image security analyzer suite (17 analyzers)
Project-URL: Repository, https://codeberg.org/rectify-security/rectify-oss
Project-URL: Issues, https://codeberg.org/rectify-security/rectify-oss/issues
Project-URL: Changelog, https://codeberg.org/rectify-security/rectify-oss/src/branch/main/CHANGELOG.md
Author: Rectify
License: Apache-2.0
Keywords: audit,cd,ci,image,security,windows
Classifier: Development Status :: 5 - Production/Stable
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security
Classifier: Topic :: System :: Systems Administration
Requires-Python: >=3.11
Requires-Dist: dissect-target<4,>=3.20
Requires-Dist: pydantic<3,>=2.5
Requires-Dist: regipy>=4.2
Provides-Extra: dev
Requires-Dist: mypy>=1.8; extra == 'dev'
Requires-Dist: pytest-cov>=4.1; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.3; extra == 'dev'
Description-Content-Type: text/markdown

<div align="center">

<img src="rectify-logo.png" alt="Rectify" width="160" />

# 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.

[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-C94B2C.svg?style=flat-square)](LICENSE)
[![Python 3.11+](https://img.shields.io/badge/Python-3.11+-1A1A1A.svg?style=flat-square)](https://www.python.org)
[![Status: stable](https://img.shields.io/badge/Status-Stable-1A1A1A.svg?style=flat-square)](#)
[![Platform: Linux](https://img.shields.io/badge/Platform-Linux-888780.svg?style=flat-square)](#)

*Find it. Expose it.* ***Rectify it.***

[**Install**](#install) · [**Quick start**](#quick-start) · [**Analyzers**](#whats-included) · [**CI integration**](#cicd-integration) · [**Contributing**](#contributing)

</div>

---

## 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.dmp` left in `C:\` with cleartext credentials in it
- A `PSReadLine_history.txt` in `C:\Users\Default` that 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)

```bash
git clone https://codeberg.org/s3cur3n3t/rectity-oss.git
cd rectify-oss/analyzers
pip install -e ".[dev]"
```

### From PyPI

[Rectify on PyPI](https://pypi.org/project/rectify-oss/1.0.2/)

### Ubuntu via PPA

[Rectify on Launchpad](https://launchpad.net/~s3cur3n3t/+archive/ubuntu/rectify-oss)

Requires Python 3.11 or later. Linux only (uses `dissect` and libguestfs).

---

## Quick start

```bash
# 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:

```json
{
  "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`](analyzers/src/winaudit_analyzers/schema.py)).

See [`examples/sample-report.json`](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:

```yaml
# .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`](docs/analyzer-development.md) for the plugin contract.

---

## Writing your own analyzers

```python
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`](CONTRIBUTING.md).

Before opening a PR:

1. Sign the CLA — instructions in `CONTRIBUTING.md`
2. Run `pytest` from `analyzers/`
3. Run `ruff check . && mypy src`
4. 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`](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.0 |
| Distribution | source on Codeberg; PyPI and Ubuntu PPA coming soon |
| Issue tracker | [Codeberg Issues](https://codeberg.org/rectify-security/rectify-oss/issues) |

---

## License

Apache License 2.0 — see [`LICENSE`](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`](NOTICE) for required Apache 2.0 attribution.

---

<div align="center">

**Find it. Expose it.** ***Rectify it.***

[Issues](https://codeberg.org/rectify-security/rectify-oss/issues) · [Contributing](CONTRIBUTING.md) · [Security](SECURITY.md) · [Changelog](CHANGELOG.md)

</div>
