{"id":44318904,"url":"https://github.com/evilbit-labs/opndossier","last_synced_at":"2026-04-03T18:01:24.949Z","repository":{"id":306177880,"uuid":"758166780","full_name":"EvilBit-Labs/opnDossier","owner":"EvilBit-Labs","description":"Generate meaninigful output from your OPNSense/pfSense configuration file","archived":false,"fork":false,"pushed_at":"2026-03-28T05:42:19.000Z","size":6479,"stargazers_count":42,"open_issues_count":58,"forks_count":5,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-28T05:54:15.226Z","etag":null,"topics":["configuration-backup","documentation","documentation-generator","firewalls","golang","opnsense"],"latest_commit_sha":null,"homepage":"https://opndossier.com/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EvilBit-Labs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":"docs/roadmap.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2024-02-15T18:52:08.000Z","updated_at":"2026-03-28T01:57:32.000Z","dependencies_parsed_at":"2025-08-20T15:08:29.889Z","dependency_job_id":"3dbc6125-26e8-4eac-8f2f-80a157da32fc","html_url":"https://github.com/EvilBit-Labs/opnDossier","commit_stats":null,"previous_names":["unclesp1d3r/opnfocus","evilbit-labs/opndossier"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/EvilBit-Labs/opnDossier","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvilBit-Labs%2FopnDossier","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvilBit-Labs%2FopnDossier/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvilBit-Labs%2FopnDossier/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvilBit-Labs%2FopnDossier/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EvilBit-Labs","download_url":"https://codeload.github.com/EvilBit-Labs/opnDossier/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EvilBit-Labs%2FopnDossier/sbom","scorecard":{"id":567646,"data":{"date":"2025-08-20T13:13:58Z","repo":{"name":"github.com/EvilBit-Labs/opnDossier","commit":"bcb8d2773973e22592a35c635a8b19786987e760"},"scorecard":{"version":"v5.2.1","commit":"ab2f6e92482462fe66246d9e32f642855a691dc1"},"score":5.3,"checks":[{"name":"Security-Policy","score":4,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Warn: no linked content found","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#security-policy"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":10,"reason":"30 commit(s) and 24 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#maintained"}},{"name":"Dependency-Update-Tool","score":10,"reason":"update tool detected","details":["Info: detected update tool: Dependabot: .github/dependabot.yml:1"],"documentation":{"short":"Determines if the project uses a dependency update tool.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#dependency-update-tool"}},{"name":"Code-Review","score":0,"reason":"Found 0/11 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql.yml:20","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql.yml:21","Info: jobLevel 'contents' permission set to 'read': .github/workflows/copilot-setup-steps.yml:23","Info: jobLevel 'actions' permission set to 'read': .github/workflows/release.yml:61","Info: jobLevel 'actions' permission set to 'read': .github/workflows/release.yml:85","Info: jobLevel 'contents' permission set to 'read': .github/workflows/release.yml:125","Info: topLevel 'contents' permission set to 'read': .github/workflows/ci.yml:10","Info: topLevel 'pull-requests' permission set to 'read': .github/workflows/ci.yml:11","Info: topLevel 'contents' permission set to 'read': .github/workflows/codeql.yml:14","Warn: no topLevel permission defined: .github/workflows/copilot-setup-steps.yml:1","Warn: topLevel 'contents' permission set to 'write': .github/workflows/release-please.yml:9","Info: topLevel 'contents' permission set to 'read': .github/workflows/release.yml:9","Info: topLevel permissions set to 'read-all': .github/workflows/scorecard.yml:16","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":1,"reason":"dependency not pinned by hash detected -- score normalized to 1","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:59: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:64: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:73: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:85: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:88: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:96: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:106: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:108: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:43: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/copilot-setup-steps.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/copilot-setup-steps.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/copilot-setup-steps.yml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/copilot-setup-steps.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/copilot-setup-steps.yml:45: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/copilot-setup-steps.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/copilot-setup-steps.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/copilot-setup-steps.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/copilot-setup-steps.yml:74: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/copilot-setup-steps.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/copilot-setup-steps.yml:129: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/copilot-setup-steps.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/copilot-setup-steps.yml:134: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/copilot-setup-steps.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release-please.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/release-please.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:69: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:101: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:129: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:132: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:51: update your workflow using https://app.stepsecurity.io/secureworkflow/EvilBit-Labs/opnDossier/release.yml/main?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:32","Warn: pipCommand not pinned by hash: .github/workflows/copilot-setup-steps.yml:58","Warn: goCommand not pinned by hash: .github/workflows/copilot-setup-steps.yml:82","Warn: pipCommand not pinned by hash: .github/workflows/copilot-setup-steps.yml:145","Info:  10 out of  26 GitHub-owned GitHubAction dependencies pinned","Info:   2 out of  12 third-party GitHubAction dependencies pinned","Info:   0 out of   1 goCommand dependencies pinned","Info:   0 out of   3 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":-1,"reason":"internal error: internal error: Client.Checks.ListCheckRunsForRef: error during graphqlHandler.setupCheckRuns: non-200 OK status code: 502 Bad Gateway body: \"\u003chtml\u003e\\r\\n\u003chead\u003e\u003ctitle\u003e502 Bad Gateway\u003c/title\u003e\u003c/head\u003e\\r\\n\u003cbody\u003e\\r\\n\u003ccenter\u003e\u003ch1\u003e502 Bad Gateway\u003c/h1\u003e\u003c/center\u003e\\r\\n\u003chr\u003e\u003ccenter\u003enginx\u003c/center\u003e\\r\\n\u003c/body\u003e\\r\\n\u003c/html\u003e\\r\\n\"","details":null,"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#sast"}},{"name":"CI-Tests","score":-1,"reason":"internal error: internal error: Client.Repositories.ListCheckRunsForRef: error during graphqlHandler.setupCheckRuns: non-200 OK status code: 502 Bad Gateway body: \"\u003chtml\u003e\\r\\n\u003chead\u003e\u003ctitle\u003e502 Bad Gateway\u003c/title\u003e\u003c/head\u003e\\r\\n\u003cbody\u003e\\r\\n\u003ccenter\u003e\u003ch1\u003e502 Bad Gateway\u003c/h1\u003e\u003c/center\u003e\\r\\n\u003chr\u003e\u003ccenter\u003enginx\u003c/center\u003e\\r\\n\u003c/body\u003e\\r\\n\u003c/html\u003e\\r\\n\"","details":null,"documentation":{"short":"Determines if the project runs tests before pull requests are merged.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#ci-tests"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v1.0.0 not signed: https://api.github.com/repos/EvilBit-Labs/opnDossier/releases/237233727","Warn: release artifact v1.0.0-rc1 not signed: https://api.github.com/repos/EvilBit-Labs/opnDossier/releases/236796804","Warn: release artifact v1.0.0 does not have provenance: https://api.github.com/repos/EvilBit-Labs/opnDossier/releases/237233727","Warn: release artifact v1.0.0-rc1 does not have provenance: https://api.github.com/repos/EvilBit-Labs/opnDossier/releases/236796804"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#signed-releases"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#packaging"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#license"}},{"name":"Branch-Protection","score":4,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'main'","Info: 'force pushes' disabled on branch 'main'","Warn: 'branch protection settings apply to administrators' is disabled on branch 'main'","Info: 'stale review dismissal' is required to merge on branch 'main'","Warn: branch 'main' does not require approvers","Warn: codeowners review is not required on branch 'main'","Warn: 'last push approval' is disabled on branch 'main'","Info: 'up-to-date branches' is required to merge on branch 'main'","Info: status check found to merge onto on branch 'main'","Info: PRs are required in order to make changes on branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#branch-protection"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#fuzzing"}},{"name":"Contributors","score":3,"reason":"project has 1 contributing companies or organizations -- score normalized to 3","details":["Info: found contributions from: evilbit-labs"],"documentation":{"short":"Determines if the project has a set of contributors from multiple organizations (e.g., companies).","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#contributors"}}]},"last_synced_at":"2025-08-20T15:24:46.492Z","repository_id":306177880,"created_at":"2025-08-20T15:24:46.493Z","updated_at":"2025-08-20T15:24:46.493Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31368156,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-03T17:53:18.093Z","status":"ssl_error","status_checked_at":"2026-04-03T17:53:17.617Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["configuration-backup","documentation","documentation-generator","firewalls","golang","opnsense"],"created_at":"2026-02-11T06:05:40.512Z","updated_at":"2026-04-03T18:01:24.912Z","avatar_url":"https://github.com/EvilBit-Labs.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# opnDossier - OPNsense and pfSense Configuration Processor\n\n[![OpenSSF Best Practices][ossf-badge]][ossf] [![Go Version][go-badge]][go] [![License][license-badge]][license] [![codecov][codecov-badge]][codecov] [![Documentation][docs-badge]][docs] [![wakatime][wakatime-badge]][wakatime] [![Go Report Card][goreportcard-badge]][goreportcard] [![Mergify Status][mergify-status]][mergify] [![All Contributors][all-contributors-badge]][all-contributors]\n\n## Overview\n\nopnDossier is a command-line tool for network operators and security professionals working with OPNsense and pfSense firewalls. Transform complex XML configuration files into clear, readable documentation and identify security issues, misconfigurations, and optimization opportunities.\n\nBuilt for offline operation in secure environments - no external dependencies, no telemetry, complete airgapped support.\n\n### What It Does\n\n- **Security Analysis** - Automatically detect vulnerabilities, insecure protocols, weak configurations\n- **Dead Rule Detection** - Find unreachable firewall rules and unused interfaces\n- **Configuration Validation** - Comprehensive checks for misconfigurations and best-practice issues\n- **Multi-Format Export** - Convert to markdown documentation, JSON, or YAML for integration\n- **Offline Operation** - Works completely offline, perfect for airgapped networks\n\n## Quick Start\n\n### Installation\n\nDownload pre-built binaries for Linux, macOS, or Windows from [releases](https://github.com/EvilBit-Labs/opnDossier/releases), or install from source:\n\n```bash\ngo install github.com/EvilBit-Labs/opnDossier@latest\n```\n\n### Basic Usage\n\n```bash\n# Generate configuration documentation\nopnDossier convert config.xml -o report.md\n\n# Run security audit (blue mode is default)\nopnDossier audit config.xml\n\n# Display config in terminal\nopnDossier display config.xml\n```\n\n### Example Output\n\n#### Markdown display output\n\n![Terminal screenshot showing opnDossier markdown output with system configuration and firewall rules](images/display.png)\n\n#### Convert to JSON for automation/integration\n\n![Screenshot of JSON export showing structured device data for automation and integration](images/json-output.png)\n\n#### Configuration diff\n\n![Screenshot of structured configuration diff showing added interfaces, changed DHCP ranges, and modified firewall rules](images/diff.png)\n\n#### Audit findings example\n\n![Screenshot of audit compliance findings showing severity levels and remediation recommendations](images/audit.png)\n\n## Analysis \u0026 Security Features\n\nopnDossier automatically analyzes your OPNsense or pfSense configuration to identify security issues, misconfigurations, and optimization opportunities.\n\n### Security Vulnerability Detection\n\nIdentifies common security issues in your firewall configuration:\n\n- **Insecure Protocols** - Detects HTTP admin interfaces, Telnet, unencrypted SNMP\n- **Weak Configurations** - Finds default community strings, overly permissive rules\n- **Certificate Issues** - Identifies expired certificates, weak key sizes\n- **Credential Exposure** - Detects plaintext passwords or weak authentication\n\nExample output:\n\n![Screenshot of security findings with severity indicators and actionable recommendations](images/findings.png)\n\n### Dead Rule Detection\n\nAutomatically identifies firewall rules that will never be reached:\n\n- Rules positioned after \"block all\" rules on the same interface\n- Duplicate rules with identical criteria (type, protocol, source, destination)\n\nExample output:\n\n```text\nDEAD RULES DETECTED:\n- Rule #15: Rules after position 12 on interface lan are unreachable due to preceding block-all rule\n- Rule #31: Rule at position 31 is duplicate of rule at position 28 on interface wan\n```\n\n### Configuration Validation\n\nComprehensive checks for structural and logical issues:\n\n- **Required Fields** - Validates hostname, domain, network interfaces\n- **Data Types** - Ensures IP addresses, subnets, ports are valid\n- **Cross-Field Validation** - Checks relationships between configuration elements\n- **Network Topology** - Validates gateway assignments, routing tables, VLAN configurations\n\nExample validation report:\n\n![Screenshot of configuration validation output showing detected issues and warnings](images/validation.png)\n\n### Unused Resource Detection\n\nFinds enabled resources not actively used:\n\n- Interfaces enabled but not referenced in rules or services\n- Aliases defined but never used in firewall rules\n- VPN tunnels configured but disabled\n- Services running without corresponding firewall rules\n\n### Compliance Checking\n\nBuilt-in validation against security and operational best practices.\n\n- Industry-standard security baselines\n- SANS security guidelines\n\n## Features\n\n### Analysis \u0026 Reporting\n\n- **Security vulnerability detection** - Identify insecure protocols, weak configurations, credential exposure\n- **Dead rule detection** - Find unreachable firewall rules and duplicate rules\n- **Unused resource analysis** - Detect unused interfaces, aliases, and services\n- **Configuration validation** - Comprehensive structural and logical validation\n- **Compliance checking** - Industry-standard security baselines and best practices\n\n### Output \u0026 Export\n\n- **Multi-format export** - Generate markdown documentation, JSON, or YAML output\n- **Terminal display** - Rich terminal output with syntax highlighting and theme support\n- **File export** - Save processed configurations with overwrite protection\n- **Template-based reports** - Customizable markdown templates (legacy, deprecated v3.0)\n- **International character support** - UTF-8, US-ASCII, ISO-8859-1, and Windows-1252 input encodings\n\n### Performance \u0026 Architecture\n\n- **Streaming processing** - Memory-efficient handling of large configuration files\n- **Fast \u0026 lightweight** - Built with Go for performance and reliability\n- **Offline operation** - Works completely offline, perfect for airgapped environments\n- **Cross-platform** - Native binaries for Linux, macOS, and Windows\n\n### Security \u0026 Privacy\n\n- **No external dependencies** - Operates completely offline\n- **No telemetry** - Zero data collection or external communication\n- **Secure by design** - Input validation, sanitization, and SBOM generation throughout\n- **Vulnerability scanning** - Automated dependency scanning and security checks in CI/CD\n\n## Installation\n\n### Pre-built Binaries (Recommended)\n\nDownload the latest release for your platform:\n\n- [Linux (amd64, arm64)](https://github.com/EvilBit-Labs/opnDossier/releases)\n- [macOS (Intel, Apple Silicon)](https://github.com/EvilBit-Labs/opnDossier/releases)\n- [Windows (amd64)](https://github.com/EvilBit-Labs/opnDossier/releases)\n\nExtract and run:\n\n```bash\ntar -xzf opnDossier-*.tar.gz\n./opnDossier --help\n```\n\n### Install via Go\n\n**Prerequisites:** Go 1.26 or later\n\n```bash\ngo install github.com/EvilBit-Labs/opnDossier@latest\n```\n\n### Build from Source\n\n```bash\ngit clone https://github.com/EvilBit-Labs/opnDossier.git\ncd opnDossier\ngo build -o opnDossier main.go\n```\n\nFor development builds with additional tooling, see [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## Usage Examples\n\n### Security Analysis\n\n```bash\n# Run blue team defensive audit (default mode)\nopnDossier audit config.xml\n\n# Blue team audit with specific compliance plugins\nopnDossier audit config.xml --plugins stig,sans\n\n# Red team attack surface analysis\nopnDossier audit config.xml --mode red\n\n# Export audit findings to JSON for automation/integration\nopnDossier audit -f json config.xml -o findings.json\n```\n\n### Configuration Documentation\n\n```bash\n# Convert OPNsense or pfSense config to markdown documentation\nopnDossier convert config.xml -o firewall-docs.md\n\n# Generate YAML for configuration management tools\nopnDossier convert -f yaml config.xml -o config.yaml\n\n# Display in terminal with custom wrap width\nopnDossier display --wrap 100 config.xml\n```\n\n### Validation\n\n```bash\n# Validate configuration file\nopnDossier validate config.xml\n\n# Validate before converting\nopnDossier validate config.xml \u0026\u0026 opnDossier convert config.xml -o report.md\n```\n\n### Advanced Options\n\n```bash\n# Include system tunables in report\nopnDossier convert config.xml -o comprehensive.md --include-tunables\n\n# Verbose output for troubleshooting\nopnDossier --verbose convert config.xml\n\n# Quiet mode - only show errors\nopnDossier --quiet convert config.xml -o output.md\n```\n\n## Configuration\n\nopnDossier can be configured via command-line flags, environment variables, or a configuration file.\n\n### Configuration Options\n\n| Setting         | CLI Flag       | Environment Variable     | Config File         | Description                      |\n| --------------- | -------------- | ------------------------ | ------------------- | -------------------------------- |\n| Verbose logging | `--verbose`    | `OPNDOSSIER_VERBOSE`     | `verbose: true`     | Enable debug/verbose output      |\n| Quiet mode      | `--quiet`      | `OPNDOSSIER_QUIET`       | `quiet: true`       | Suppress all non-error output    |\n| Input file      | (positional)   | `OPNDOSSIER_INPUT_FILE`  | `input_file: path`  | Default input configuration file |\n| Output file     | `-o, --output` | `OPNDOSSIER_OUTPUT_FILE` | `output_file: path` | Default output file path         |\n\nFor a complete list of all configuration options, see the [Configuration Reference](docs/user-guide/configuration-reference.md).\n\n### Configuration File Example\n\nCreate `~/.opnDossier.yaml`:\n\n```yaml\n# Logging\nverbose: false\nquiet: false\n\n# File paths\ninput_file: /path/to/default/config.xml\noutput_file: ./output.md\n```\n\n### Usage Examples\n\n```bash\n# Using CLI flags\nopnDossier --verbose convert config.xml\n\n# Using environment variables\nexport OPNDOSSIER_VERBOSE=true\nopnDossier convert config.xml\n\n# Using config file (automatically loaded from ~/.opnDossier.yaml)\nopnDossier convert config.xml\n```\n\n## Output Formats\n\nopnDossier supports multiple output formats for different use cases:\n\n- **Markdown** - Human-readable documentation with formatted tables and sections\n- **JSON** - Machine-readable format for automation and integration\n- **YAML** - Configuration management and structured data export\n- **Terminal Display** - Rich syntax-highlighted output with theme support\n\nSpecify format with `-f` or `--format` flag:\n\n```bash\nopnDossier convert -f json config.xml -o output.json\nopnDossier convert -f yaml config.xml -o output.yaml\nopnDossier convert -f markdown config.xml -o output.md  # default\n```\n\n## GitHub Actions\n\nopnDossier is available as a GitHub Action backed by its Docker image. Use it to audit or document OPNsense and pfSense configurations automatically on every commit, PR, or scheduled run.\n\n### Quick Start\n\n```yaml\nname: Audit firewall configuration\n\non:\n  push:\n    paths:\n      - config.xml\n  schedule:\n    - cron: 0 6 * * 1   # every Monday at 06:00 UTC\n\njobs:\n  audit:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Audit OPNsense config\n        # No release tags exist yet — use @main until v1 is tagged\n        uses: EvilBit-Labs/opnDossier@main\n        with:\n          command: audit\n          config-file: config.xml\n```\n\n### Inputs\n\n| Input         | Required | Default  | Description                                                                              |\n| ------------- | -------- | -------- | ---------------------------------------------------------------------------------------- |\n| `command`     | No       | `audit`  | Sub-command: `audit`, `convert`, `diff`, `display`, `sanitize`, `validate`, or `version` |\n| `config-file` | **Yes**  | —        | Path to OPNsense or pfSense `config.xml` relative to the workspace root                  |\n| `format`      | No       | —        | Output format for `convert`/`audit`: `markdown`, `json`, `yaml`, `text`, or `html`       |\n| `output`      | No       | —        | Path to write the output file, relative to the workspace root                            |\n| `args`        | No       | —        | Additional arguments split on whitespace (quoted strings with spaces are not preserved)  |\n| `version`     | No       | `latest` | Image tag to pull (e.g. `v1.2.0`); defaults to the latest release                        |\n\n### Export findings to JSON\n\n```yaml\n  - name: Export audit findings\n  # No release tags exist yet — use @main until v1 is tagged\n    uses: EvilBit-Labs/opnDossier@main\n    with:\n      command: audit\n      config-file: firewall/config.xml\n      format: json\n      output: findings.json\n\n  - name: Upload findings\n    uses: actions/upload-artifact@v4\n    with:\n      name: audit-findings\n      path: findings.json\n```\n\n### Generate configuration documentation\n\n```yaml\n  - name: Generate firewall documentation\n  # No release tags exist yet — use @main until v1 is tagged\n    uses: EvilBit-Labs/opnDossier@main\n    with:\n      command: convert\n      config-file: config.xml\n      format: markdown\n      output: docs/firewall.md\n```\n\n### Using the Docker image directly\n\nThe Docker image is published to the GitHub Container Registry alongside every release and can be used independently of the Action:\n\n```bash\n# Pull the latest release\ndocker pull ghcr.io/evilbit-labs/opndossier:latest\n\n# Run an audit, mounting your config directory\n# WORKDIR is /data, so use relative paths after the volume mount\ndocker run --rm \\\n  --volume \"$(pwd):/data\" \\\n  ghcr.io/evilbit-labs/opndossier:latest \\\n  audit config.xml\n```\n\n## Documentation\n\n- **[User Guide](docs/user-guide/)** - Installation, usage, and configuration\n- **[Security Documentation](docs/security/)** - Vulnerability scanning and security features\n- **[API Reference](docs/api.md)** - Detailed API documentation\n- **[Examples](docs/examples/)** - Real-world usage examples\n\nFor developers:\n\n- **[Contributing Guide](CONTRIBUTING.md)** - How to contribute to the project\n- **[Architecture Documentation](docs/development/architecture.md)** - System design and architecture\n\n## Support\n\n- **Issues** - [GitHub Issues](https://github.com/EvilBit-Labs/opnDossier/issues)\n- **Discussions** - [GitHub Discussions](https://github.com/EvilBit-Labs/opnDossier/discussions)\n- **Documentation** - [Full Documentation](docs/index.md)\n- **Contributing** - [Contributing Guide](CONTRIBUTING.md)\n\n## Troubleshooting\n\n- If you see garbled characters, confirm the XML declaration encoding matches the file's actual encoding.\n- Supported input encodings include UTF-8, US-ASCII, ISO-8859-1, and Windows-1252; convert legacy files to UTF-8 if needed.\n\n## Security\n\nopnDossier is designed with security as a first-class concern:\n\n- **No external dependencies** - Operates completely offline\n- **No telemetry** - No data collection or external communication\n- **Secure by design** - Input validation, sanitization, and SBOM generation\n- **Automated scanning** - Daily vulnerability scans and dependency audits in CI/CD\n\nFor security vulnerabilities, please see our [security policy](SECURITY.md).\n\n## License\n\nApache License 2.0 - see [LICENSE](LICENSE) file for details.\n\n## Contributors\n\nSee [CONTRIBUTORS.md](CONTRIBUTORS.md) for the full list of contributors.\n\n## Acknowledgements\n\n- Inspired by [TKCERT/pfFocus](https://github.com/TKCERT/pfFocus) for pfSense configurations\n- Terminal UI powered by [Charm](https://charm.sh/) - [glamour](https://github.com/charmbracelet/glamour), [lipgloss](https://github.com/charmbracelet/lipgloss), [log](https://github.com/charmbracelet/log), [bubbles](https://github.com/charmbracelet/bubbles)\n- CLI framework by [spf13/cobra](https://github.com/spf13/cobra) and [spf13/viper](https://github.com/spf13/viper)\n- Markdown generation by [nao1215/markdown](https://github.com/nao1215/markdown)\n- Documentation built with [MkDocs](https://www.mkdocs.org/) and [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/)\n\n---\n\nBuilt for network operators and security professionals.\n\n\u003c!-- Reference Links --\u003e\n\n[all-contributors]: #contributors\n[all-contributors-badge]: https://img.shields.io/github/all-contributors/EvilBit-Labs/opnDossier?color=ee8449\u0026style=flat-square\n[codecov]: https://codecov.io/gh/EvilBit-Labs/opnDossier\n[codecov-badge]: https://codecov.io/gh/EvilBit-Labs/opnDossier/graph/badge.svg?token=WD1QD9ITZF\n[docs]: https://github.com/EvilBit-Labs/opnDossier/blob/main/docs/index.md\n[docs-badge]: https://img.shields.io/badge/docs-mkdocs-blue.svg\n[go]: https://golang.org\n[go-badge]: https://img.shields.io/badge/go-1.26+-blue.svg\n[goreportcard]: https://goreportcard.com/report/github.com/EvilBit-Labs/opnDossier\n[goreportcard-badge]: https://goreportcard.com/badge/github.com/EvilBit-Labs/opnDossier\n[license]: LICENSE\n[license-badge]: https://img.shields.io/badge/license-Apache-green.svg\n[mergify]: https://mergify.com\n[mergify-status]: https://img.shields.io/endpoint.svg?url=https://api.mergify.com/v1/badges/EvilBit-Labs/opnDossier\u0026style=flat\n[ossf]: https://www.bestpractices.dev/projects/11920\n[ossf-badge]: https://www.bestpractices.dev/projects/11920/badge\n[wakatime]: https://wakatime.com/badge/user/2d2fbc27-e3f7-4ec1-b2a7-935e48bad498/project/018dae18-42c0-4e3e-8330-14d39f574bd5\n[wakatime-badge]: https://wakatime.com/badge/user/2d2fbc27-e3f7-4ec1-b2a7-935e48bad498/project/018dae18-42c0-4e3e-8330-14d39f574bd5.svg\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevilbit-labs%2Fopndossier","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fevilbit-labs%2Fopndossier","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevilbit-labs%2Fopndossier/lists"}