Qualys VMDR
Connect Qualys VMDR directly to RAD Security and query host detections, host assets and the QID KnowledgeBase in Qualys' own vocabulary.
RAD Security connects directly to the Qualys VMDR APIs with a Qualys API user and pulls three objects into three dedicated data types: host detections, host assets and the QID KnowledgeBase.
The data keeps Qualys' vocabulary. Severity stays the Qualys 1–5 grade, status stays New / Active / Fixed / Re-Opened, and a detection keeps Qualys' own grain. Nothing is re-scored or re-labelled on the way in, so a number in RAD and the same number in the Qualys console are answering the same question.
Read-only integration. RAD authenticates as a Qualys API user with the Reader role. It never launches scans, never edits or closes detections, and never writes anything back to Qualys.
Prerequisites
- A Qualys subscription with the VM module
- Permission to create a Qualys user (Manager or Unit Manager role)
- The KnowledgeBase download API granted to your subscription — see KnowledgeBase access below
- Your Qualys API Server URL (not the API Gateway URL)
- A RAD Security workspace with integration permissions
What RAD stores
| Object | RAD data type | One row per | Refreshed |
|---|---|---|---|
| Host detections | qualys_detections | host × QID × port × protocol × SSL × FQDN × service | every sync pass; the whole open set at least every 72 hours |
| Host assets | qualys_hosts | host | every 24 hours (Host List census) |
| QID KnowledgeBase | qualys_knowledge_base | QID, per integration | every 24 hours |
The three types are queryable in the Evidence Room, in dashboard widgets, through the data API and through radbot, the same way any other RAD data type is.
Detections from this integration live in qualys_detections only. They are not projected into the shared vulnerability findings views, because those views cannot express Qualys' closure lifecycle without distorting the counts.
Step 1: Create the API user in Qualys
Sign in as Manager or Unit Manager
Sign in to Qualys with an account that holds the Manager or Unit Manager role, open the Vulnerability Management application and go to Users.
Create the user
Select New > User and fill in the General Information section. Use a service mailbox that is not tied to an individual, so the integration survives staff changes.
Assign the Reader role and API access
In the User Role section select the Reader role and tick both the GUI and API boxes.
Reader is sufficient and is the least privilege that works. RAD only lists detections, hosts and KnowledgeBase entries; it never needs a scan-capable role.
Assign asset groups
Under Asset Groups, grant All for full coverage, or name the specific groups you want RAD to see.
The API user's asset-group scope is the ceiling on everything RAD can report. A host outside that scope is invisible to RAD, and so are its detections.
Save the generated username
Qualys generates the username; it is shown in the users list and nowhere else. Record it before you leave the page.
Complete the registration email
The service mailbox receives a registration link and a one-time password. Complete the registration to obtain the account password, then sign in once through the Qualys UI to confirm the account is active.
KnowledgeBase access
The KnowledgeBase download API is a per-subscription grant, separate from the user's role. If it is not granted, Qualys answers the KnowledgeBase call with HTTP 403 while the detection calls succeed.
RAD's verification step reports this case explicitly rather than as a credential failure. If you see it, ask Qualys Support to enable the KnowledgeBase download API for your subscription. Without it, detections still sync, but the title, category, CVE list, threat indicators and CVSS scores stay empty.
Step 2: Find your API Server URL
Qualys publishes two different hostnames per platform. This integration uses the API Server URL (qualysapi.…), not the API Gateway URL (gateway.…).
| Platform | API Server URL |
|---|---|
| US1 | https://qualysapi.qualys.com |
| US2 | https://qualysapi.qg2.apps.qualys.com |
| US3 | https://qualysapi.qg3.apps.qualys.com |
| US4 | https://qualysapi.qg4.apps.qualys.com |
| GOV1 | https://qualysapi.gov1.qualys.us |
| EU1 | https://qualysapi.qualys.eu |
| EU2 | https://qualysapi.qg2.apps.qualys.eu |
| EU3 | https://qualysapi.qg3.apps.qualys.it |
| IN1 | https://qualysapi.qg1.apps.qualys.in |
| CA1 | https://qualysapi.qg1.apps.qualys.ca |
| AE1 | https://qualysapi.qg1.apps.qualys.ae |
| UK1 | https://qualysapi.qg1.apps.qualys.co.uk |
| AU1 | https://qualysapi.qg1.apps.qualys.com.au |
| KSA1 | https://qualysapi.qg1.apps.qualysksa.com |
| Private Cloud Platform | https://qualysapi.<your base URL> |
The platform identifier is embedded in your Qualys username — for example a 2 in the third position means US2. Qualys documents the full mapping at Platform Identification.
Step 3: Configure in RAD Security
Open Data Sources > Integrations > Vulnerabilities, add the Qualys VMDR integration and fill in three fields.
| Field | Value |
|---|---|
| Username | The Qualys API user from Step 1 |
| Password | That user's password |
| POD API Server URL | The API Server URL from Step 2, for example https://qualysapi.qg2.apps.qualys.com |
The URL must use https. The credentials travel as HTTP Basic authentication on every call, so plain http is rejected before anything leaves RAD.
What verification does
Saving the integration spends two to three Qualys API calls:
- Version negotiation — RAD probes the Host List Detection endpoint from version 6.0 downwards and pins the highest version your subscription serves.
- Detection probe — a one-host detection page, parsed end to end. This proves the credentials, the URL and the response pipeline together.
- KnowledgeBase probe — a single QID. This proves the subscription grant described above, not data presence.
The negotiated versions are pinned onto the integration and shown on the configured card alongside the POD URL. They are re-negotiated only if you change the POD API Server URL.
Once the status shows Connected, the first pass begins. The initial pass walks your entire open detection set and can take several cycles on a large subscription; the host census and the KnowledgeBase seed follow.
Reading the data
Open is a column, not a status
A detection is open when is_open = 1. That single column is the answer to "how many open vulnerabilities do we have", on every surface: Evidence Room filters, dashboard widgets, the data API and radbot.
is_open = 1 means all of the following hold:
statusisNew,ActiveorRe-Openedis_ignored = 0andis_disabled = 0absence_reasonis empty
Everything else — Fixed, ignored, disabled, a detection whose host was purged from Qualys, a detection that stopped being reported — reads is_open = 0.
Do not reconstruct openness from status alone. RAD deliberately pulls ignored and disabled detections so they remain visible and auditable, so status:Active includes detections your team has already ignored in Qualys. is_open is the column that accounts for them.
Qualys vocabulary is kept verbatim
| Column | Values |
|---|---|
status | New, Active, Fixed, Re-Opened |
type | Confirmed, Potential, Information Gathered |
severity | 1–5, the Qualys severity level exactly as scanned |
qds | Qualys Detection Score, 1–100 |
epss | EPSS probability from the QDS factors, -1 when Qualys reports none |
Severity is not RAD-normalized. severity:5 is Qualys' Urgent, severity:4 is Qualys' Critical, and they are distinct — see the severity crosswalk if you are migrating queries or dashboards that used RAD's normalized bands.
One row per detection, and what a detection is
Qualys identifies a detection by host, QID, port, protocol, SSL flag, FQDN and service. Two findings of the same QID on the same host over different ports are two detections in Qualys, and two rows in RAD.
Each row is the current state of that detection. RAD stores every observation as a version and reads back the latest one, so a query never sees a superseded version and a closure supersedes the open row immediately.
KnowledgeBase is a second query
Each detection row carries the KnowledgeBase attributes needed to filter and list — title, category, CVEs, threat indicators, patchable flag, CVSS base scores — copied onto the row and refreshed on every re-observation.
The long prose (diagnosis, consequence, solution) is not copied. Query qualys_knowledge_base by qid when you need it.
Copies on a closed detection are frozen as at closure. When a detection goes Fixed, its row stops being re-observed, so its title, CVE list and host attributes stay exactly as they were on the day it closed. This is intentional — a closure record should describe the vulnerability that was actually closed — but it means a Fixed row will not pick up later KnowledgeBase changes such as a newly assigned CVE.
Measuring remediation time
ttr_days is written when a detection closes: the number of days between Qualys' FIRST_FOUND_DATETIME and LAST_FIXED_DATETIME.
- Compute MTTR as
avg(ttr_days), filtered tostatus:Fixedover a Last Fixed window. - Detections that are not closed leave
ttr_daysempty, and empty values are excluded from the average rather than counted as zero. - A closure that Qualys reports without a
LAST_FIXED_DATETIMEalso leaves it empty. RAD does not substitute the observation date, because a guessed zero is indistinguishable from a genuine same-day fix.
ttr_days measures the detection's lifetime, not the last repair. FIRST_FOUND_DATETIME is Qualys' original discovery date and does not reset when a detection reopens. A vulnerability found in January, fixed in February, reopened in June and fixed again in July reports roughly 181 days, not the 30 days of the second episode.
The 90-day closure horizon
Queries reach back 90 days from the Qualys clock you filter on. first_found_datetime, last_found_datetime and last_fixed_datetime all widen the window for you, so "found this quarter" and "fixed this quarter" work.
Beyond 90 days they do not. "Everything we fixed last year" and year-over-year MTTR trends are out of reach of the query surfaces; the underlying storage keeps the full history and RAD support can query it directly.
Sync cadence and API budget
| What | Cadence |
|---|---|
| Incremental detection pull | every sync cycle, roughly 1–5 minutes apart |
| Full re-observation of the open set | at least every 72 hours |
| Host census (Host List) | every 24 hours |
| KnowledgeBase refresh | every 24 hours |
A pass that cannot finish within its cycle stops on a cursor and resumes on the next one, so no cycle occupies your API quota indefinitely.
RAD reads the X-RateLimit-* and concurrency headers Qualys returns on every call and holds itself to one concurrent request. It stops spending as soon as your remaining allowance reaches a 20% reserve of the observed rate-limit window, and resumes on a later cycle — so a fifth of the window is always left for your own automation against the same subscription.
Express and Consultant subscriptions have a 50-calls-per-day quota. That is below what a continuous connector needs. Verification succeeds on such a subscription, and the shortfall only becomes visible as passes that never finish. If your subscription is on one of these tiers, raise it with Qualys Support before rolling the integration out.