audit¶
The audit command runs security audit and compliance checks on one or more OPNsense config.xml files. It produces a report with compliance findings, security recommendations, and risk assessments based on the selected audit mode and compliance plugins.
When to use it:
- Running a security posture assessment against a firewall configuration
- Generating STIG/SANS/firewall compliance reports for auditors
- Red team reconnaissance to identify attack surfaces and pivot points
- Producing redacted audit reports safe for sharing with external parties
- Batch-auditing multiple configs for fleet-wide compliance visibility
Usage¶
Flags¶
| Flag | Short | Default | Description |
|---|---|---|---|
--mode |
blue |
Audit mode: blue, red |
|
--plugins |
Comma-separated compliance plugins to run: stig, sans, firewall (blue mode only) |
||
--plugin-dir |
Directory containing third-party dynamic .so compliance plugins (does not affect the built-in stig/sans/firewall plugins). Plugins run with full process privileges; signatures are not verified. See Third-Party Plugin Security. |
||
--output |
-o |
stdout | Output file path |
--format |
-f |
markdown |
Output format: markdown (md), json, yaml (yml), text (txt), html (htm) |
--failures-only |
false |
Show only failing controls in blue mode plugin results tables | |
--force |
false |
Overwrite existing output file without prompt | |
--comprehensive |
false |
Generate detailed comprehensive report | |
--redact |
false |
Redact sensitive fields (passwords, keys, community strings) | |
--wrap |
terminal width | Set text wrap width in columns | |
--no-wrap |
false |
Disable text wrapping | |
--include-tunables |
false |
Include all system tunables in report output (markdown, text, HTML only; JSON/YAML always include all tunables) | |
--section |
all | Comma-separated list of sections to include: system, network, firewall, services, security |
For global flags (--verbose, --quiet, --config, etc.), see Configuration Reference.

Audit Modes¶
| Mode | Audience | Focus |
|---|---|---|
blue |
Blue Team | Defensive audit with security findings |
red |
Red Team | Attack surface and pivot points |
Blue¶
The default mode. Defensive audit mode targeting blue team operators. Runs compliance plugins and produces a report with security findings, control pass/fail results, and remediation recommendations.
When no --plugins flag is specified, all available plugins are run by default. The --plugins flag is only accepted in blue mode and is rejected for red mode.
Red¶
Experimental
Red team mode is not yet fully implemented. Its analysis methods are placeholder stubs that return static metadata. Results will be incomplete and should not be relied upon for real assessments. A CLI warning is emitted when this mode is selected.
Attacker-focused recon mode highlighting attack surfaces, pivot points, and exposed services.
Compliance Plugins¶
opnDossier ships with three built-in compliance plugins that are compiled directly into the opndossier binary. They are always available — no separate install, download, or configuration — and the --plugin-dir flag does not affect them.
Built-in plugins¶
| Plugin | Control Pattern | Description |
|---|---|---|
stig |
V-XXXXXX |
Security Technical Implementation Guide |
sans |
SANS-FW-XXX |
SANS Firewall Baseline |
firewall |
FIREWALL-XXX |
Firewall Configuration Analysis |
Use the --plugins flag to select a subset (e.g. --plugins stig,firewall). Omitting the flag runs every available plugin, built-in and dynamic. The --plugins flag requires --mode blue; it is rejected for red mode.
Third-party dynamic plugins¶
The --plugin-dir flag lets operators extend opnDossier with third-party compliance plugins distributed as Go shared-object (.so) files that implement the compliance.Plugin interface. This mechanism is only for external plugins you or a trusted vendor built; it does not modify, override, or disable the built-in plugins listed above.
- Opt-in. Without
--plugin-dir, no third-party plugins are loaded and the audit runs with the built-in plugins only. There is no default search path. - Additive. Third-party plugins augment the built-in set; they do not replace it. If a third-party plugin registers the same name as a built-in (e.g.,
stig), registration of the third-party plugin fails and the built-in continues to run. - Non-fatal failures. If a third-party
.sofails preflight or fails to open, the audit still runs with every plugin that did load. Each failure is recorded in the audit log. - Explicit directory required. If
--plugin-dirpoints at a missing directory, opnDossier returns an error before running the audit.
Before you use --plugin-dir in production, read the next section. Third-party plugins run inside the opnDossier process with full user privileges, and opnDossier does not verify who built them.
See the Plugin Development Guide if you need to write your own compliance plugin.
Third-Party Plugin Security¶
This section applies only to the third-party .so plugins loaded via --plugin-dir. The built-in stig, sans, and firewall plugins are compiled into the opnDossier binary and are not affected by any of the checks below.
Platform support
Third-party plugin loading only works on Linux, macOS, and FreeBSD. Go's plugin package — which opnDossier uses for --plugin-dir — is not implemented on Windows. On Windows and other unsupported platforms, the flag is accepted for CLI parity, but --plugin-dir becomes a no-op: opnDossier emits a single stderr warning naming the current platform and continues the audit with the built-in compliance plugins only. No .so files are opened, and no spurious per-file load errors are produced. If you need third-party compliance plugins on Windows, run opnDossier under WSL2 or in a Linux container. (The built-in plugins work on every platform opnDossier is built for, including Windows.)
Trust model
A third-party plugin runs with the same privileges as opnDossier itself. There is no sandbox, no signature check, and no provenance verification. Treat every .so file you drop into --plugin-dir exactly as you would treat an unsigned executable that you are about to run as the current user — because that is effectively what happens. The built-in plugins are not subject to this trust model; they ship with the binary you installed.
Every time you pass a non-empty --plugin-dir, opnDossier writes a warning to stderr to make the risk visible at invocation time.
What the loader does for you¶
These restrictions are enforced automatically on every supported platform (Linux, macOS, FreeBSD). A plugin file that fails any of them is rejected before it is loaded, and the rejection is written to the audit log with enough metadata (path, SHA-256, file mode, owner UID, size, verdict, reason) for a security team to investigate:
| Check | Behavior |
|---|---|
| Symlink rejection | The .so itself cannot be a symlink. A symlink planted in --plugin-dir that points at an attacker-controlled file elsewhere is refused. |
| File permission check | The .so must not be group-writable or world-writable (mode & 0o022 == 0). |
| Directory permission check | The --plugin-dir directory itself must not be group-writable or world-writable. A locked-down .so inside a world-writable directory is refused because an attacker could swap the file. |
| Absolute path normalization | A relative --plugin-dir (e.g. ./plugins) is resolved to an absolute path before any check runs, so the audit log and preflight always work on a canonical path. |
| Size cap (64 MiB) | A plugin's SHA-256 is computed during the preflight with a 64 MiB read cap. A .so larger than 64 MiB is rejected rather than memory-mapped. |
| SHA-256 audit trail | Every accepted or rejected load is logged with the file's SHA-256 digest, so the specific binary that ran (or was refused) is identifiable after the fact. |
What the loader does NOT do¶
- No signature or checksum verification. opnDossier does not check a plugin against a known-good hash, a TUF manifest, or a code-signing certificate. Any
.sothat passes the preflight will run. - No sandboxing or privilege separation. A plugin has the same file-system, network, and process privileges as the opnDossier binary. If opnDossier can read
/etc/shadow, so can a malicious plugin. - No capability restriction. Plugins can open sockets, spawn subprocesses, read and write arbitrary files, and call any Go standard-library function.
- No remote fetch. opnDossier never downloads plugins. If a
.soappears in your plugin directory, it got there through your deployment pipeline — verify that pipeline.
Operator responsibilities¶
Because opnDossier's loader cannot make strong guarantees by itself, you are responsible for the rest:
- Own the plugin directory. Set filesystem permissions so only trusted operators can write to it. Mode
0o755on a directory owned by a dedicated deployment user is typical; avoid world-writable paths,/tmp, and any CI scratch directory that external contributors can reach. - Vet the plugin source. Build plugins from known-good checkouts that you have reviewed. Do not load plugins you received as compiled
.sofiles from untrusted sources. - Pin the Go toolchain. Plugins must be built with the same Go toolchain and module versions as the opnDossier binary. A mismatch is detected at load time, but only after the
.sohas been mapped into the process — which means any maliciousinit()code has already executed. - Review the audit log. Every load attempt, accepted or rejected, is logged with the plugin's SHA-256. Ship these logs to your SIEM and alert on rejections.
- Keep
--plugin-dirout of CI that accepts external PRs. A contributor who can write to your plugin directory can execute arbitrary code in your audit pipeline.
Threat scenarios the preflight blocks¶
| Scenario | Blocked by |
|---|---|
Attacker plants evil.so in /tmp/plugins by dropping a symlink from the plugin dir |
Symlink rejection |
Plugin file is world-writable (mode 0o666) and an attacker swaps it after deployment |
File permission check |
Plugin file is mode 0o600 but lives in /tmp/plugins (world-writable dir) |
Directory permission check |
| Attacker replaces a legitimate 500 KB plugin with a 1 GB plugin crafted to exhaust memory during hash | Size cap + SHA-256 audit trail |
| Forensic investigation needs to know which binary ran on a given date | SHA-256 audit trail |
Threat scenarios the preflight does NOT block¶
| Scenario | Mitigation |
|---|---|
Legitimate-looking plugin from an untrusted source contains a backdoor in init() |
Review source; build from a trusted checkout |
| Deployment pipeline is compromised and pushes a signed-looking plugin | Sign your own plugins; verify in your pipeline |
| Plugin exfiltrates data via network after load | Run opnDossier without network access if you cannot vet plugins |
| Plugin-built-for-wrong-Go-version executes malicious init() before the mismatch is detected | Pin the Go toolchain and do not load stale plugins |
Further reading: Plugin Development Guide — Security Model and GOTCHAS §2.5 — Dynamic Plugin Trust Model.
Output Formats¶
| Format | Aliases | Description |
|---|---|---|
markdown |
md |
Markdown documentation (default) |
json |
Structured JSON data | |
yaml |
yml |
Structured YAML data |
text |
txt |
Plain text (markdown without formatting) |
html |
htm |
Self-contained HTML report |
Multiple Files¶
When auditing multiple files, the --output flag cannot be used. Each report is auto-named based on the input path with an -audit suffix and the appropriate format extension. Bare filenames produce simple names (e.g., config1.xml produces config1-audit.md). When inputs include directory components, the full path is encoded into the filename to prevent collisions between files that share the same basename:
config.xml -> config-audit.md
prod/site-a/config.xml -> prod_site-a_config-audit.md
dr/site-a/config.xml -> dr_site-a_config-audit.md
Redacting Sensitive Data¶
The --redact flag replaces sensitive field values with [REDACTED] in the output. This lets you generate reports that are safe to share without exposing credentials or secrets.
For the full list of redacted fields, see convert -- Redacting Sensitive Data.
Examples¶
# Run a blue team audit with all compliance plugins (default)
opndossier audit config.xml
# Blue team defensive audit with STIG and SANS compliance
opndossier audit config.xml --mode blue --plugins stig,sans
# Red team attack surface analysis
opndossier audit config.xml --mode red
# Export audit report as JSON
opndossier audit config.xml --format json -o audit-report.json
# Run audit on multiple files (each report is auto-named)
opndossier audit config1.xml config2.xml --mode blue
# Comprehensive blue team audit with all compliance checks
opndossier audit config.xml --mode blue --comprehensive --plugins stig,sans,firewall
# Show only failing controls (skip passing controls)
opndossier audit config.xml --mode blue --failures-only
# Redact sensitive fields from audit output
opndossier audit config.xml --redact
# Quiet mode (errors only)
opndossier --quiet audit config.xml --mode blue
# Verbose audit diagnostics
opndossier --verbose audit config.xml --mode blue --plugins stig,sans
Related¶
- CLI Reference —
audit-- auto-generated exhaustive flag list - convert -- convert configs to documentation
- display -- render in terminal instead of writing to file
- Configuration Reference -- global flags and settings
- Audit and Compliance Examples -- common audit workflows