No release in over 3 years
A Ruby SDK for interacting with the Tenable API, covering Vulnerability Management and Web App Scanning.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 13.0
~> 3.12
~> 1.60
~> 6.0
~> 3.18
~> 0.9

Runtime

~> 2.0
 Project Readme

tenable-ruby-sdk

Unofficial — This project is not affiliated with, endorsed by, or sponsored by Tenable, Inc. "Tenable" is a registered trademark of Tenable, Inc.

Ruby SDK for the Tenable.io API. Covers vulnerability management, bulk exports, VM scans, and WAS v2 web application scanning.

Requires Ruby >= 3.2. Uses Faraday for HTTP.

Installation

Add to your Gemfile:

gem 'tenable-ruby-sdk'

Then bundle install.

Authentication

Get your API keys from Tenable.io under Settings > My Account > API Keys.

Pass them directly:

client = Tenable::Client.new(
  access_key: "your-access-key",
  secret_key: "your-secret-key"
)

Or set environment variables and omit them:

export TENABLE_ACCESS_KEY="your-access-key"
export TENABLE_SECRET_KEY="your-secret-key"
client = Tenable::Client.new

Usage

List Vulnerabilities

data = client.vulnerabilities.list
data["vulnerabilities"].each do |vuln|
  puts "#{vuln['plugin_name']} (severity: #{vuln['severity']})"
end

Export Vulnerabilities

For large datasets, use the export workflow:

exports = client.exports

# Start the export
result = exports.export(num_assets: 50)
uuid = result["export_uuid"]

# Wait for it to finish (polls automatically, 5 min timeout by default)
exports.wait_for_completion(uuid)

# Iterate over all chunks
exports.each(uuid) do |vuln|
  puts vuln["plugin"]["name"]
end

VM Scans

# List scans
client.scans.list

# Launch a scan
client.scans.launch(scan_id)

# Check status
client.scans.status(scan_id)

Web App Scans (WAS v2)

was = client.web_app_scans

# Create a scan config
config = was.create_config(name: "My Scan", target: "https://example.com")
config_id = config["config_id"]

# Launch the scan
scan = was.launch(config_id)
scan_id = scan["scan_id"]

# Wait for completion (polls until terminal status)
was.wait_until_complete(config_id, scan_id)

# Get findings
was.findings(config_id)

Configuration

All options with their defaults:

client = Tenable::Client.new(
  access_key:   "...",                          # or TENABLE_ACCESS_KEY env var
  secret_key:   "...",                          # or TENABLE_SECRET_KEY env var
  base_url:     "https://cloud.tenable.com",    # must be HTTPS
  timeout:      30,                             # request timeout (seconds)
  open_timeout: 10,                             # connection timeout (seconds)
  max_retries:  3,                              # retry attempts (0-10)
  logger:       Logger.new($stdout)             # nil = silent (default)
)

Error Handling

All errors inherit from Tenable::Error:

begin
  client.vulnerabilities.list
rescue Tenable::AuthenticationError => e
  # Bad or missing API keys (401)
rescue Tenable::RateLimitError => e
  # Rate limited and retries exhausted (429)
  e.status_code  # => 429
rescue Tenable::TimeoutError => e
  # Request or export poll timed out
rescue Tenable::ApiError => e
  # Any other API error
  e.status_code  # => Integer
  e.body         # => String
rescue Tenable::ConnectionError => e
  # Network failure
end

Rate limiting (429) and server errors (5xx) are retried automatically with exponential backoff before raising.

Thread Safety

The client is frozen after initialization with eagerly instantiated resources. Safe to use across threads.

Development

bundle install
bundle exec rspec        # run tests
bundle exec rubocop      # lint
bundle exec yard doc     # generate docs
bundle audit check       # check for vulnerable dependencies

License

MIT