RESTful API integration with Tenable Nessus automates the vulnerability management lifecycle, enabling security engineering teams to trigger programmatic scans, poll execution states, and ingest vulnerability data directly into CI/CD pipelines. This programmatic approach eliminates manual operational overhead, ensures continuous security validation across ephemeral cloud instances, and enforces strict, code-defined scanning baselines.
API Architecture and Authentication Mechanics
The Nessus API operates over HTTPS (typically TCP port 8834), utilizing standard HTTP methods (GET, POST, PUT, DELETE) to interact with internal scan engines and data stores. The API strictly consumes and returns data serialized in JavaScript Object Notation (JSON).
To interact with the endpoints, scripts must authenticate using provisioned API keys rather than relying on ephemeral session tokens. Administrators generate an Access Key and a Secret Key within the Nessus user interface. The automation script injects these keys into the HTTP request headers as X-ApiKeys: accessKey={access_key}; secretKey={secret_key}. This stateless authentication model prevents session timeouts during long-running execution sequences and facilitates seamless machine-to-machine communication.
When automating scans across diverse network segments, architects must meticulously define target scopes and plugin families. Aggressive active scanning safely enumerates standard IT endpoints but risks causing denial-of-service states in fragile operational environments, such as those covered in Securing Specialized Systems: IoT, Embedded, and SCADA. Engineers must dynamically configure the API JSON payloads to enforce safe-check plugins and omit aggressive network mapping when the target IPs fall within those specialized subnet boundaries.
Asynchronous Execution and Status Polling
Vulnerability scanning represents an asynchronous operation; the script cannot maintain an open HTTP connection for the hours required to complete a subnet sweep. Therefore, automation scripts must implement a state polling loop.
The script initiates the scan by transmitting a POST request to the /scans/{scan_id}/launch endpoint. The Nessus engine immediately returns a 200 OK response containing a scan_uuid, confirming the engine accepted the job. The script then enters a deterministic while loop, transmitting periodic GET requests to the /scans/{scan_id} endpoint. It parses the JSON response to extract the status string. Once the status transitions from running to completed, the script exits the polling loop and executes a subsequent POST request to /scans/{scan_id}/export to generate the final .nessus or .csv report format.
python
import requests
import time
# Define infrastructure targets and authentication headers
NESSUS_URL = "https://nessus-scanner.internal:8834"
HEADERS = {
"X-ApiKeys": "accessKey=YOUR_ACCESS_KEY; secretKey=YOUR_SECRET_KEY",
"Content-Type": "application/json"
}
# Disable insecure request warnings for self-signed internal certificates
requests.packages.urllib3.disable_warnings()
def launch_and_poll_scan(scan_id):
# 1. Trigger the asynchronous scan execution
launch_url = f"{NESSUS_URL}/scans/{scan_id}/launch"
response = requests.post(launch_url, headers=HEADERS, verify=False)
if response.status_code != 200:
print(f"API Error: Failed to launch scan. HTTP {response.status_code}")
return
scan_uuid = response.json().get('scan_uuid')
print(f"Execution initialized. Assigned UUID: {scan_uuid}")
# 2. Enter the state polling loop
status_url = f"{NESSUS_URL}/scans/{scan_id}"
while True:
status_response = requests.get(status_url, headers=HEADERS, verify=False)
current_status = status_response.json()['info']['status']
if current_status == 'completed':
print("Scan cycle completed successfully. Ready for data export.")
break
elif current_status in ['canceled', 'aborted']:
print(f"Execution halted prematurely. Final state: {current_status}")
break
# Throttle API requests to prevent overwhelming the scanner's web server
print(f"Engine status: {current_status}. Polling memory state in 30 seconds...")
time.sleep(30)
if __name__ == "__main__":
# Execute the automation sequence against a predefined Scan ID
launch_and_poll_scan(42)
Authoritative References
https://developer.tenable.com/referencehttps://docs.tenable.com/nessus/Content/API.htm