Appearance
Session Management
After a scan completes, its session directory can be uploaded to the Bullium Consulting consultation portal, pushed with a shareable report link, or re-uploaded after a report-template change. Three CLIs cover these flows: upload_session.sh, push_session.sh, and refresh_reports.sh. All three share the multipart uploader in submit_session.sh.
For the wire format and portal endpoints, see the API Contract.
Credentials
Every uploader reads portal credentials from a config file (the -c flag) or from direct URL and key flags. In config files, NV_API_KEY takes precedence over the legacy CONSULTATION_API_KEY alias, and both are accepted for backward compatibility. See Report Configuration and Secrets Management for where these live and how to rotate them.
Session Upload
scripts/upload_session.sh uploads a completed session using a config file for credentials. It defaults to the most recent session.
upload_session.sh -c <config> [options]
Required:
-c <file> Report config file (CONSULTATION_API_URL + NV_API_KEY)
Session Selection (pick one, defaults to --latest):
-s <session_dir> Path to a session directory
-i <session_id> Session ID, for example 20260224_120000
--latest Use the most recent session (default)
Options:
-r <file> HTML report file (overrides auto-detection from the session dir)
-e <file> Executive summary HTML (auto-detected from the session dir)
--dry-run Show what would be uploaded without sending
-h, --help Show helpbash
# Upload the most recent session (default)
./scripts/upload_session.sh -c ~/netvuln-tool/configs/acme.conf
# Upload a specific session by ID
./scripts/upload_session.sh -c ~/netvuln-tool/configs/acme.conf -i 20260224_120000
# Upload a specific session by path
./scripts/upload_session.sh -c ~/netvuln-tool/configs/acme.conf -s ~/netvuln-tool/sessions/20260224_120000
# Preview without sending
./scripts/upload_session.sh -c ~/netvuln-tool/configs/acme.conf --dry-runUpload is also available as option 9 in the interactive menu (vulnscan_menu.sh).
Automatic push after a scan
You rarely need to run the uploader by hand. When the config passed to the recon pipeline with -c defines both CONSULTATION_API_URL and NV_API_KEY (or CONSULTATION_API_KEY), the session is submitted automatically once the pipeline finishes, and a shareable report link is returned on success. The manual uploaders exist for re-pushing older sessions or for hosts where the scan and the upload happen separately.
Session Push
scripts/push_session.sh submits a previously completed session and reports the portal session ID and shareable link that come back in the response. It can auto-discover artifacts from a session directory or take a JSON path directly.
push_session.sh (-d <dir> | -j <file>) [options]
Required (one of):
-d <dir> Session directory (auto-discovers JSON, log, report, exec summary)
-j <file> Path to session_results.json directly
Optional:
-R <file> Path to the HTML report file
-e <file> Path to the executive summary HTML (auto-detected from the session dir)
-c <file> Config file (for CONSULTATION_API_URL and NV_API_KEY)
-u <url> API URL (overrides the config file)
-k <key> API key (overrides the config file)
-h, --help Show helpbash
# Push a session directory using a config file
./scripts/push_session.sh -d ~/netvuln-tool/sessions/20260224_120000 \
-c ~/netvuln-tool/configs/acme_corp.conf
# Push with an explicit URL and key
./scripts/push_session.sh -d ~/netvuln-tool/sessions/20260224_120000 \
-u https://portal.netvulntool.com/api/upload -k nvt_pro_<hex>
# Push a specific JSON alongside its report
./scripts/push_session.sh -j /path/to/session_results.json \
-R /path/to/report.html -c config.confOn a successful upload the tool prints the returned session ID and, when the portal issues one, a shareable report link of the form:
https://<your-portal>/share/?token=<64-hex-chars>That link requires no login. The long random token is the credential, so treat the URL as sensitive.
Remote agents
For agents managed through Command and Control, pushing is handled remotely. Dispatch a run_scan command with upload: true to auto-push the resulting session, or send a push_session command (optionally with a specific session_id, defaulting to the latest) to push an already-completed session. Both report the portal session ID back through the agent's heartbeat.
Report Refresh
When the report template (report_template.sh) changes (cosmetic fixes, new features, bug fixes), you can regenerate and re-upload reports for existing portal sessions without re-running the scan. scripts/refresh_reports.sh drives the PUT /api/refresh endpoint, which replaces report artifacts in place.
refresh_reports.sh [options] SESSION_ID [SESSION_ID ...]
Required (one of):
-c <config.conf> Config file with NV_API_URL and NV_API_KEY
-u <url> -k <key> API URL and key directly
Options:
--all Refresh every session on the portal. Listing them uses
the Identity-authenticated endpoint, so this needs a
JWT in NV_JWT (or CONSULTATION_JWT) as well as the API
key used to refresh.
--dry-run Regenerate locally without uploading
-h, --help Show helpbash
# Refresh a specific session
./scripts/refresh_reports.sh -u https://portal.netvulntool.com/api \
-k nvt_pro_<hex> 20260318_103739
# Refresh several sessions
./scripts/refresh_reports.sh -u https://portal.netvulntool.com/api \
-k nvt_pro_<hex> 20260318_103739 20260220_091500
# Dry run: regenerate locally, upload nothing
./scripts/refresh_reports.sh -u https://portal.netvulntool.com/api \
-k nvt_pro_<hex> --dry-run 20260318_103739
# Refresh every session on the portal. Export the JWT rather than passing it
# as a flag, so the token stays out of ps output and shell history.
export NV_JWT='<identity-jwt>'
./scripts/refresh_reports.sh -u https://portal.netvulntool.com/api \
-k nvt_pro_<hex> --all --dry-run--all needs two credentials
Refreshing and downloading authenticate with the API key, but listing sessions is gated on a Netlify Identity JWT, and neither credential derives from the other. Without NV_JWT (or CONSULTATION_JWT) exported, --all stops before touching anything and tells you which variable to set.
The tool sends that token in the X-Identity-Token header, never in Authorization. You do not have to do anything about this, but it matters if you are scripting the same call by hand: the portal's edge terminates any request carrying a validly-signed Identity JWT in Authorization before the handler runs, and an invalid token returns the same clean 401 under either header, so a test credential will not reveal the difference.
Run it with --dry-run first. The summary reports how many sessions would be touched, and if any of them fail, it lists the failing session IDs so you can retry just those rather than the whole account.
Refresh, not re-push
push_session.sh cannot re-upload to a session that already exists on the portal (it returns an HTTP 500 duplicate error). Use refresh_reports.sh for that. The refresh endpoint accepts only report.html and exec_summary.html; it cannot update session JSON or pipeline logs. Share-page links stay the same after a refresh, because the share token is permanent.
refresh_reports.sh expects the NV_API_URL and NV_API_KEY variable names in a config file. If your config uses CONSULTATION_API_URL / CONSULTATION_API_KEY, pass credentials directly with -u and -k instead.
Under the Hood
Both upload_session.sh and push_session.sh delegate the actual transfer to submit_session.sh, a shared library that performs the multipart upload (25 MB maximum). It sends the session JSON plus, when present, the pipeline log, the report HTML, and the executive-summary HTML, and it exposes the portal's session ID and share token to the calling script on success.
