audit-report
Turns an audit-tools evidence package into a control-mapped, auditor-ready report — Markdown, self-contained HTML, or JSON — driven by declarative rulesets.
audit-tools collects raw CSVs (IAM users, branch protections, security
groups…). audit-report reads that package, applies pass/fail rules, maps each
result to SOC 2, ISO 27001, and NIST SP 800-53 controls, and produces a
report you can hand to an auditor or gate a pipeline on.
Like gh-attest, this tool produces evidence, not a compliance verdict. A failing row means a setting is in a state that does not support a control; the final judgment belongs to the organization and its auditor.
Install
pip install audit-report
To hack on it from a clone instead, see Development.
Usage
Point it at a package directory produced by audit-tools:
# Markdown report to stdout (platform + ruleset auto-detected from the dir name)
audit-report ./output/aws_audit_default_2026-07-29
# All three formats into ./report/
audit-report ./output/github_audit_acme_2026-07-29 --format md,html,json --out report/
# Gate CI: exit non-zero if any high-severity check fails
audit-report ./output/aws_audit_prod_2026-07-29 --fail-on high --out report/
Diff mode — compare two packages
Pass --baseline to report how a package drifted from an earlier one. Both
are evaluated with the same ruleset; the report classifies each rule as
regressed, fixed, drifted (an ongoing failure whose evidence rows changed),
changed, or unchanged — and shows exactly which evidence rows appeared or
disappeared.
# How did prod change between two audit runs?
audit-report ./output/aws_audit_prod_2026-07-29 \
--baseline ./output/aws_audit_prod_2026-06-29 \
--format md,html --out drift/
# Fail CI if this change regressed any high-severity control
audit-report ./output/aws_audit_prod_2026-07-29 \
--baseline ./output/aws_audit_prod_2026-06-29 --fail-on high
In diff mode --fail-on gates on regressions at or above the given
severity, and output files are named diff.* instead of report.*.
Trend mode — track controls over time
Pass --trend and point at a folder of dated packages (for example
audit-tools' output/). Every package in the series is evaluated with the same
ruleset and laid out as a timeline — one row per rule, one column per date — so
you can watch a control drift in and out of compliance.
# Heatmap of every control across all retained prod packages
audit-report ./output --trend --format html,json --out trend/
# Disambiguate when the folder holds more than one series
audit-report ./output --trend --subject prod --out trend/
The series must share one platform and subject (use --subject to pick one) and
contain at least two packages. In trend mode --fail-on reflects the latest
package, so it can double as a snapshot gate. Output files are named trend.*.
You can also run it without installing:
python -m audit_report ./output/aws_audit_default_2026-07-29
Options
| Flag | Description |
|---|---|
--baseline PATH |
Diff mode: report how PACKAGE drifted from this earlier package. |
--trend |
Trend mode: treat PACKAGE as a folder of dated packages and chart each rule over time. |
--subject NAME |
In trend mode, pick one subject when the folder holds several series. |
--ruleset PATH |
Use a specific ruleset instead of the bundled one for the detected platform. |
--format md,html,json |
One or more output formats (default: md). |
--out DIR |
Write report.<ext> files into DIR. Without it, the first format prints to stdout. |
--fail-on low|medium|high|none |
Exit non-zero when a failing finding — or, in diff mode, a regression — meets this severity (default: none). |
What a report contains
- Summary — failing / passing / not-applicable counts.
- Control coverage matrix — every cited control, its framework, and a worst-wins status rolled up from the rules that reference it. One failing rule marks the control as not fully evidenced.
- Findings — failures first, then by severity, each with the reason, why it matters, remediation, and the exact evidence rows that failed.
Bundled rulesets
| Platform | Package prefix | Checks include |
|---|---|---|
| AWS | aws_audit_* |
Console-user MFA, access-key rotation, root MFA & keys, password policy, open SSH, public S3, CloudTrail logging |
| GitHub | github_audit_* |
Org 2FA, base permission, secret-scanning push protection, default-branch protection, required reviews |
| GitLab | gitlab_audit_* |
Force-push on protected branches, code-owner approval, approval-rule strength, public projects, instance password policy, audit logging |
Writing your own rules
A ruleset is a YAML file: a platform and a list of rules. Each rule names a
CSV table, a check, the controls it maps to, and human-readable text. Point at
one with --ruleset.
platform: aws
rules:
- id: aws.iam.console-mfa
title: Console users have MFA enabled
table: iam_users # <table>.csv inside the package
severity: high # high | medium | low
controls: [SOC2:CC6.1, ISO:A.5.17, NIST:IA-2]
rationale: A console user without a second factor is one stolen password from access.
remediation: Enforce MFA for all console users, or remove their console password.
check:
type: fail_rows_where # every matching row is a failure
when:
all:
- {column: console_password, op: is_true}
- {column: mfa_enabled, op: is_false}
Check types
| Type | Meaning |
|---|---|
fail_rows_where |
Each row matching when is a failing finding. |
fail_if_any_rows |
The presence of any row (optionally filtered by when) is a failure. |
require_any_row |
Passes only if at least one row satisfies when. |
assert_row |
Checks each condition in require against the first row of a single-row config table. |
Condition language — a condition is a leaf {column, op, value}, or one of
{all: [...]}, {any: [...]}, {not: ...}. Operators: equals, not_equals,
is_true, is_false, in, not_in, gt, gte, lt, lte, empty,
not_empty. Control codes referenced by a rule must exist in
audit_report/catalog.py.
Continuous integration
Run it on a schedule or in a pipeline to keep evidence current and gate on regressions. See docs/ci.md and the ready-to-copy examples:
The --fail-on exit code (1 = a finding/regression met the threshold, 2 =
usage error) lets a workflow separate "the audit found a problem" from "the job
is misconfigured".
Stability
audit-report is stable as of v1.0.0 and follows semantic versioning.
The JSON report schema — findings carrying their controls and
pass / fail / not_applicable status — is a committed contract that
control-coverage consumes
directly; it will not break without a major-version bump.
Development
pip install -e ".[dev]"
pytest # run from the project root
ruff check .
License
GPL-3.0-or-later. See LICENSE.
Metadata
Release files for audit-report 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| audit_report-1.0.0.tar.gz | 47.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| audit_report-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 94.3 kB
Release files / audit_report-1.0.0.tar.gz
| Download URL | audit_report-1.0.0.tar.gz |
|---|---|
| Size | 47.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d832cc41bb56ca008a9b98550564c01a0f4b49371bff47a7d35312a5794700bd
|
|
BLAKE2b-256 checksum How to use checksums |
366af7769538db24ed2a4e8cfbcb25e0f8ac69b84ecc4ed4ea03c3cb7c861c1f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 8, 2026.
Transparency logRelease files / audit_report-1.0.0-py3-none-any.whl
| Download URL | audit_report-1.0.0-py3-none-any.whl |
|---|---|
| Size | 47.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c26087591b7997e021ee44e9c84bff6a071e27b3ae4cbaf0de08dd7bec11cd19
|
|
BLAKE2b-256 checksum How to use checksums |
13a4c43ba78b68e22290710e1640837bb1ee150c58bcc8490434426419872520
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 8, 2026.
Transparency log