nessus-export 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 setuidloot
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,254 @@
1
+ Metadata-Version: 2.4
2
+ Name: nessus-export
3
+ Version: 0.1.0
4
+ Summary: Export Nessus scan results via the API, with a reconstruction fallback for trial-mode servers.
5
+ Author-email: setuidloot <michael@mccord.ai>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/setuidloot/nessus-export
8
+ Project-URL: Issues, https://github.com/setuidloot/nessus-export/issues
9
+ Keywords: nessus,tenable,security,vulnerability,export,scanner
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Information Technology
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Security
16
+ Requires-Python: >=3.8
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Dynamic: license-file
20
+
21
+ # nessus-export
22
+
23
+ [![CI](https://github.com/setuidloot/nessus-export/actions/workflows/ci.yml/badge.svg)](https://github.com/setuidloot/nessus-export/actions/workflows/ci.yml)
24
+ [![PyPI](https://img.shields.io/pypi/v/nessus-export.svg)](https://pypi.org/project/nessus-export/)
25
+ [![Python](https://img.shields.io/pypi/pyversions/nessus-export.svg)](https://pypi.org/project/nessus-export/)
26
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
27
+
28
+ Export [Nessus](https://www.tenable.com/products/nessus) scan results from the
29
+ command line via the REST API — **with an automatic fallback that reconstructs a
30
+ valid `.nessus` file even when the server's native export is locked** (as it is
31
+ on Nessus Essentials / trial installations).
32
+
33
+ Zero dependencies. Pure Python standard library.
34
+
35
+ ---
36
+
37
+ ## Why this exists
38
+
39
+ Nessus has a perfectly good export API (`POST /scans/{id}/export`). But on
40
+ **Nessus Essentials** and **trial** installations, every export format is
41
+ license-gated. Ask for one and the server refuses:
42
+
43
+ ```json
44
+ { "error": "Export is not allowed in trial mode. Please purchase a full Nessus license to enable exports." }
45
+ ```
46
+
47
+ That's frustrating, because **the scan data itself is not restricted** — the
48
+ per-scan, per-host, and per-plugin *read* endpoints (`GET /scans/{id}`,
49
+ `GET /scans/{id}/hosts/{host}`, `GET /scans/{id}/hosts/{host}/plugins/{plugin}`)
50
+ return everything: findings, ports/services, severities, CVSS scores, CVEs,
51
+ plugin output, remediation text. The export endpoint is gated; the data is not.
52
+
53
+ **nessus-export** does the obvious thing:
54
+
55
+ 1. **Try the native export API first.** If your server is licensed, you get the
56
+ real, byte-for-byte Nessus export (`.nessus`, CSV, PDF, HTML, DB) — no
57
+ reconstruction, nothing lost.
58
+ 2. **If the server is in trial mode**, it transparently reads the scan data and
59
+ **reconstructs** a spec-compliant `NessusClientData_v2` (`.nessus`) or CSV
60
+ file itself.
61
+
62
+ The reconstructed `.nessus` imports cleanly back into Nessus and into anything
63
+ else that consumes the format (parsers, dashboards, DefectDojo, etc.).
64
+
65
+ ## Install
66
+
67
+ ```bash
68
+ pip install nessus-export
69
+ ```
70
+
71
+ Or from source:
72
+
73
+ ```bash
74
+ git clone https://github.com/setuidloot/nessus-export
75
+ cd nessus-export
76
+ pip install .
77
+ # or run without installing:
78
+ python -m nessus_export --help
79
+ ```
80
+
81
+ Requires Python 3.8+. No third-party packages.
82
+
83
+ ## Authentication
84
+
85
+ Generate API keys in Nessus: **Settings → My Account → API Keys → Generate**.
86
+
87
+ Provide them any of these ways (checked in order):
88
+
89
+ - CLI flags: `--access-key` / `--secret-key`
90
+ - Environment: `ACCESS_KEY` / `SECRET_KEY` (or `NESSUS_ACCESS_KEY` / `NESSUS_SECRET_KEY`)
91
+ - A `.env` file in the working directory (auto-loaded), or `--env-file PATH`
92
+
93
+ ```bash
94
+ cp .env.example .env # then edit in your keys
95
+ ```
96
+
97
+ Nessus ships a self-signed TLS certificate, so certificate verification is
98
+ **off by default**. Turn it on with `--verify-ssl` (optionally `--ca-bundle`).
99
+
100
+ ## Usage
101
+
102
+ ```bash
103
+ # List scans on the server
104
+ nessus-export list
105
+ nessus-export list --status completed
106
+ nessus-export list --json
107
+
108
+ # Export one scan by name or id (defaults to .nessus, into the current dir)
109
+ nessus-export export myscan
110
+ nessus-export export 5 -o results.nessus
111
+
112
+ # Pick a format
113
+ nessus-export export myscan -f csv
114
+ nessus-export export myscan -f pdf --chapters vuln_by_host,remediations
115
+
116
+ # Export several scans into a directory
117
+ nessus-export export web-scan db-scan -d ./exports
118
+ nessus-export export --all --status completed -d ./exports
119
+
120
+ # Force behavior
121
+ nessus-export export myscan -m native # native API only (fails under trial)
122
+ nessus-export export myscan -m reconstruct # skip the API, rebuild locally
123
+ ```
124
+
125
+ ### Commands
126
+
127
+ | Command | Purpose |
128
+ |----------|-----------------------------------------------------|
129
+ | `list` | List scans (`--status`, `--json`) |
130
+ | `export` | Export one/several/all scans |
131
+ | `status` | Show server status |
132
+
133
+ ### Key `export` options
134
+
135
+ | Option | Description |
136
+ |---------------------|-------------------------------------------------------------------|
137
+ | `SCAN…` | One or more scan names or ids |
138
+ | `--all` | Export every scan (combine with `--status`) |
139
+ | `-f, --format` | `nessus` (default), `csv`, `pdf`, `html`, `db` |
140
+ | `-m, --mode` | `auto` (default), `native`, `reconstruct` |
141
+ | `-o, --output` | Output file (single scan) |
142
+ | `-d, --out-dir` | Output directory (multiple scans; filenames from scan names) |
143
+ | `--chapters` | `pdf`/`html` sections, comma-separated |
144
+ | `--db-password` | Required for `-f db` |
145
+ | `-q, --quiet` | Suppress per-step progress |
146
+
147
+ ### Export modes
148
+
149
+ - **`auto`** *(default)* — try the native API; if the server reports a
150
+ trial-mode restriction, fall back to reconstruction (for `nessus`/`csv`).
151
+ - **`native`** — only use the API. Exits non-zero under trial mode. Use this
152
+ when you specifically want the licensed, byte-exact export or nothing.
153
+ - **`reconstruct`** — skip the API export entirely and rebuild locally. Handy
154
+ for consistent output across mixed licensed/trial servers.
155
+
156
+ ### Formats and modes at a glance
157
+
158
+ | Format | Native (licensed) | Reconstruction fallback (trial) |
159
+ |----------|:-----------------:|:-------------------------------:|
160
+ | `nessus` | ✅ | ✅ |
161
+ | `csv` | ✅ | ✅ |
162
+ | `pdf` | ✅ | ❌ (needs a licensed server) |
163
+ | `html` | ✅ | ❌ (needs a licensed server) |
164
+ | `db` | ✅ | ❌ (needs a licensed server) |
165
+
166
+ `pdf`, `html`, and `db` are report renderings Nessus builds server-side; there's
167
+ no faithful way to reproduce them from the read API, so they require a licensed
168
+ server. In `auto` mode, requesting one on a trial server yields a clear error
169
+ rather than a degraded file.
170
+
171
+ ## Caveats when reconstructing (trial mode)
172
+
173
+ When the tool falls back to reconstruction, the **findings are complete and
174
+ faithful** — hosts, ports/services, severities, CVSS v2/v3 scores and vectors,
175
+ CVEs/BIDs/xrefs, synopsis, description, solution, see-also, and plugin output
176
+ are all carried through. But a reconstructed file is **not byte-identical** to a
177
+ licensed export, in these specific ways:
178
+
179
+ 1. **The `<Policy>` block is a stub.** A licensed export embeds the full scan
180
+ policy — every server/plugin preference and the plugin-family selection.
181
+ Trial mode does not expose that data through the API, so the policy elements
182
+ are emitted empty. Your *findings* are intact; the scan *configuration*
183
+ metadata is not.
184
+ 2. **`HostProperties` is a subset.** It contains what the host-info endpoint
185
+ returns (IP, FQDN, OS, MAC, start/end time, …) — generally fewer tags than a
186
+ native export writes.
187
+ 3. **Plugin output honors the API's truncation.** Very large outputs flagged
188
+ `max_attachments_exceeded` by the API are carried through exactly as the API
189
+ returned them (i.e. possibly truncated).
190
+ 4. **No attachments.** Binary attachments some plugins produce are not
191
+ reassembled.
192
+ 5. **CSV columns approximate** the native Nessus CSV layout; exact column
193
+ ordering/quoting may differ slightly.
194
+
195
+ If any of that matters for your use case, use a licensed server with
196
+ `-m native`. For the common need — "get my findings out in a portable,
197
+ importable format" — the reconstructed `.nessus` does the job.
198
+
199
+ ## Supported Nessus versions
200
+
201
+ Developed and verified against **Nessus 10.12.1** (latest at time of writing);
202
+ expected to work on the Nessus 10.x API generally. It uses only long-standing,
203
+ stable REST endpoints, so older 8.x/9.x servers will likely work too but are
204
+ untested. If you run it against another version, a PR updating this section is
205
+ welcome.
206
+
207
+ | Nessus version | Status |
208
+ |----------------|---------------------|
209
+ | 10.12.1 | ✅ Verified |
210
+ | 10.x (other) | 🟡 Expected to work |
211
+ | 8.x – 9.x | 🟡 Likely, untested |
212
+
213
+ ## How it works
214
+
215
+ ```
216
+ export ──► native API export ──► ready? ──► download (licensed servers)
217
+
218
+ └─ trial-mode 403 ──► read scan + hosts + plugins
219
+ └─► serialize NessusClientData_v2 / CSV
220
+ ```
221
+
222
+ The reconstruction walks every host and every plugin finding, so it makes more
223
+ API calls than a native export — expect it to take longer on large scans.
224
+
225
+ ## Library use
226
+
227
+ ```python
228
+ from nessus_export.client import NessusClient
229
+ from nessus_export.exporter import export_scan
230
+
231
+ client = NessusClient(url="https://localhost:8834",
232
+ access_key="…", secret_key="…")
233
+ result = export_scan(client, scan_id=5, fmt="nessus", mode="auto")
234
+ open("myscan.nessus", "wb").write(result.content)
235
+ print(result.mode) # "native" or "reconstruct"
236
+ ```
237
+
238
+ ## Security notes
239
+
240
+ - Never commit your `.env` / API keys. `.gitignore` already excludes `.env` and
241
+ common export artifacts (`*.nessus`, `*.pdf`, `*.db`).
242
+ - Exported scan results contain sensitive vulnerability data — handle and store
243
+ them accordingly.
244
+
245
+ ## License
246
+
247
+ MIT — see [LICENSE](LICENSE).
248
+
249
+ ## Disclaimer
250
+
251
+ Not affiliated with or endorsed by Tenable, Inc. "Nessus" is a trademark of
252
+ Tenable, Inc. This tool uses only documented REST endpoints and does not
253
+ circumvent licensing: it reads data the API already exposes and formats it
254
+ locally.
@@ -0,0 +1,234 @@
1
+ # nessus-export
2
+
3
+ [![CI](https://github.com/setuidloot/nessus-export/actions/workflows/ci.yml/badge.svg)](https://github.com/setuidloot/nessus-export/actions/workflows/ci.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/nessus-export.svg)](https://pypi.org/project/nessus-export/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/nessus-export.svg)](https://pypi.org/project/nessus-export/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
+
8
+ Export [Nessus](https://www.tenable.com/products/nessus) scan results from the
9
+ command line via the REST API — **with an automatic fallback that reconstructs a
10
+ valid `.nessus` file even when the server's native export is locked** (as it is
11
+ on Nessus Essentials / trial installations).
12
+
13
+ Zero dependencies. Pure Python standard library.
14
+
15
+ ---
16
+
17
+ ## Why this exists
18
+
19
+ Nessus has a perfectly good export API (`POST /scans/{id}/export`). But on
20
+ **Nessus Essentials** and **trial** installations, every export format is
21
+ license-gated. Ask for one and the server refuses:
22
+
23
+ ```json
24
+ { "error": "Export is not allowed in trial mode. Please purchase a full Nessus license to enable exports." }
25
+ ```
26
+
27
+ That's frustrating, because **the scan data itself is not restricted** — the
28
+ per-scan, per-host, and per-plugin *read* endpoints (`GET /scans/{id}`,
29
+ `GET /scans/{id}/hosts/{host}`, `GET /scans/{id}/hosts/{host}/plugins/{plugin}`)
30
+ return everything: findings, ports/services, severities, CVSS scores, CVEs,
31
+ plugin output, remediation text. The export endpoint is gated; the data is not.
32
+
33
+ **nessus-export** does the obvious thing:
34
+
35
+ 1. **Try the native export API first.** If your server is licensed, you get the
36
+ real, byte-for-byte Nessus export (`.nessus`, CSV, PDF, HTML, DB) — no
37
+ reconstruction, nothing lost.
38
+ 2. **If the server is in trial mode**, it transparently reads the scan data and
39
+ **reconstructs** a spec-compliant `NessusClientData_v2` (`.nessus`) or CSV
40
+ file itself.
41
+
42
+ The reconstructed `.nessus` imports cleanly back into Nessus and into anything
43
+ else that consumes the format (parsers, dashboards, DefectDojo, etc.).
44
+
45
+ ## Install
46
+
47
+ ```bash
48
+ pip install nessus-export
49
+ ```
50
+
51
+ Or from source:
52
+
53
+ ```bash
54
+ git clone https://github.com/setuidloot/nessus-export
55
+ cd nessus-export
56
+ pip install .
57
+ # or run without installing:
58
+ python -m nessus_export --help
59
+ ```
60
+
61
+ Requires Python 3.8+. No third-party packages.
62
+
63
+ ## Authentication
64
+
65
+ Generate API keys in Nessus: **Settings → My Account → API Keys → Generate**.
66
+
67
+ Provide them any of these ways (checked in order):
68
+
69
+ - CLI flags: `--access-key` / `--secret-key`
70
+ - Environment: `ACCESS_KEY` / `SECRET_KEY` (or `NESSUS_ACCESS_KEY` / `NESSUS_SECRET_KEY`)
71
+ - A `.env` file in the working directory (auto-loaded), or `--env-file PATH`
72
+
73
+ ```bash
74
+ cp .env.example .env # then edit in your keys
75
+ ```
76
+
77
+ Nessus ships a self-signed TLS certificate, so certificate verification is
78
+ **off by default**. Turn it on with `--verify-ssl` (optionally `--ca-bundle`).
79
+
80
+ ## Usage
81
+
82
+ ```bash
83
+ # List scans on the server
84
+ nessus-export list
85
+ nessus-export list --status completed
86
+ nessus-export list --json
87
+
88
+ # Export one scan by name or id (defaults to .nessus, into the current dir)
89
+ nessus-export export myscan
90
+ nessus-export export 5 -o results.nessus
91
+
92
+ # Pick a format
93
+ nessus-export export myscan -f csv
94
+ nessus-export export myscan -f pdf --chapters vuln_by_host,remediations
95
+
96
+ # Export several scans into a directory
97
+ nessus-export export web-scan db-scan -d ./exports
98
+ nessus-export export --all --status completed -d ./exports
99
+
100
+ # Force behavior
101
+ nessus-export export myscan -m native # native API only (fails under trial)
102
+ nessus-export export myscan -m reconstruct # skip the API, rebuild locally
103
+ ```
104
+
105
+ ### Commands
106
+
107
+ | Command | Purpose |
108
+ |----------|-----------------------------------------------------|
109
+ | `list` | List scans (`--status`, `--json`) |
110
+ | `export` | Export one/several/all scans |
111
+ | `status` | Show server status |
112
+
113
+ ### Key `export` options
114
+
115
+ | Option | Description |
116
+ |---------------------|-------------------------------------------------------------------|
117
+ | `SCAN…` | One or more scan names or ids |
118
+ | `--all` | Export every scan (combine with `--status`) |
119
+ | `-f, --format` | `nessus` (default), `csv`, `pdf`, `html`, `db` |
120
+ | `-m, --mode` | `auto` (default), `native`, `reconstruct` |
121
+ | `-o, --output` | Output file (single scan) |
122
+ | `-d, --out-dir` | Output directory (multiple scans; filenames from scan names) |
123
+ | `--chapters` | `pdf`/`html` sections, comma-separated |
124
+ | `--db-password` | Required for `-f db` |
125
+ | `-q, --quiet` | Suppress per-step progress |
126
+
127
+ ### Export modes
128
+
129
+ - **`auto`** *(default)* — try the native API; if the server reports a
130
+ trial-mode restriction, fall back to reconstruction (for `nessus`/`csv`).
131
+ - **`native`** — only use the API. Exits non-zero under trial mode. Use this
132
+ when you specifically want the licensed, byte-exact export or nothing.
133
+ - **`reconstruct`** — skip the API export entirely and rebuild locally. Handy
134
+ for consistent output across mixed licensed/trial servers.
135
+
136
+ ### Formats and modes at a glance
137
+
138
+ | Format | Native (licensed) | Reconstruction fallback (trial) |
139
+ |----------|:-----------------:|:-------------------------------:|
140
+ | `nessus` | ✅ | ✅ |
141
+ | `csv` | ✅ | ✅ |
142
+ | `pdf` | ✅ | ❌ (needs a licensed server) |
143
+ | `html` | ✅ | ❌ (needs a licensed server) |
144
+ | `db` | ✅ | ❌ (needs a licensed server) |
145
+
146
+ `pdf`, `html`, and `db` are report renderings Nessus builds server-side; there's
147
+ no faithful way to reproduce them from the read API, so they require a licensed
148
+ server. In `auto` mode, requesting one on a trial server yields a clear error
149
+ rather than a degraded file.
150
+
151
+ ## Caveats when reconstructing (trial mode)
152
+
153
+ When the tool falls back to reconstruction, the **findings are complete and
154
+ faithful** — hosts, ports/services, severities, CVSS v2/v3 scores and vectors,
155
+ CVEs/BIDs/xrefs, synopsis, description, solution, see-also, and plugin output
156
+ are all carried through. But a reconstructed file is **not byte-identical** to a
157
+ licensed export, in these specific ways:
158
+
159
+ 1. **The `<Policy>` block is a stub.** A licensed export embeds the full scan
160
+ policy — every server/plugin preference and the plugin-family selection.
161
+ Trial mode does not expose that data through the API, so the policy elements
162
+ are emitted empty. Your *findings* are intact; the scan *configuration*
163
+ metadata is not.
164
+ 2. **`HostProperties` is a subset.** It contains what the host-info endpoint
165
+ returns (IP, FQDN, OS, MAC, start/end time, …) — generally fewer tags than a
166
+ native export writes.
167
+ 3. **Plugin output honors the API's truncation.** Very large outputs flagged
168
+ `max_attachments_exceeded` by the API are carried through exactly as the API
169
+ returned them (i.e. possibly truncated).
170
+ 4. **No attachments.** Binary attachments some plugins produce are not
171
+ reassembled.
172
+ 5. **CSV columns approximate** the native Nessus CSV layout; exact column
173
+ ordering/quoting may differ slightly.
174
+
175
+ If any of that matters for your use case, use a licensed server with
176
+ `-m native`. For the common need — "get my findings out in a portable,
177
+ importable format" — the reconstructed `.nessus` does the job.
178
+
179
+ ## Supported Nessus versions
180
+
181
+ Developed and verified against **Nessus 10.12.1** (latest at time of writing);
182
+ expected to work on the Nessus 10.x API generally. It uses only long-standing,
183
+ stable REST endpoints, so older 8.x/9.x servers will likely work too but are
184
+ untested. If you run it against another version, a PR updating this section is
185
+ welcome.
186
+
187
+ | Nessus version | Status |
188
+ |----------------|---------------------|
189
+ | 10.12.1 | ✅ Verified |
190
+ | 10.x (other) | 🟡 Expected to work |
191
+ | 8.x – 9.x | 🟡 Likely, untested |
192
+
193
+ ## How it works
194
+
195
+ ```
196
+ export ──► native API export ──► ready? ──► download (licensed servers)
197
+
198
+ └─ trial-mode 403 ──► read scan + hosts + plugins
199
+ └─► serialize NessusClientData_v2 / CSV
200
+ ```
201
+
202
+ The reconstruction walks every host and every plugin finding, so it makes more
203
+ API calls than a native export — expect it to take longer on large scans.
204
+
205
+ ## Library use
206
+
207
+ ```python
208
+ from nessus_export.client import NessusClient
209
+ from nessus_export.exporter import export_scan
210
+
211
+ client = NessusClient(url="https://localhost:8834",
212
+ access_key="…", secret_key="…")
213
+ result = export_scan(client, scan_id=5, fmt="nessus", mode="auto")
214
+ open("myscan.nessus", "wb").write(result.content)
215
+ print(result.mode) # "native" or "reconstruct"
216
+ ```
217
+
218
+ ## Security notes
219
+
220
+ - Never commit your `.env` / API keys. `.gitignore` already excludes `.env` and
221
+ common export artifacts (`*.nessus`, `*.pdf`, `*.db`).
222
+ - Exported scan results contain sensitive vulnerability data — handle and store
223
+ them accordingly.
224
+
225
+ ## License
226
+
227
+ MIT — see [LICENSE](LICENSE).
228
+
229
+ ## Disclaimer
230
+
231
+ Not affiliated with or endorsed by Tenable, Inc. "Nessus" is a trademark of
232
+ Tenable, Inc. This tool uses only documented REST endpoints and does not
233
+ circumvent licensing: it reads data the API already exposes and formats it
234
+ locally.
@@ -0,0 +1,4 @@
1
+ """nessus-export: export Nessus scan results via the API, with a
2
+ reconstruction fallback for trial-mode servers."""
3
+
4
+ __version__ = "0.1.0"
@@ -0,0 +1,6 @@
1
+ import sys
2
+
3
+ from .cli import main
4
+
5
+ if __name__ == "__main__":
6
+ sys.exit(main())