Description
@synergyconsulting/n8n-nodes-qualys


This is an n8n community node. It lets you use Qualys in your n8n
workflows.
Qualys is a cloud platform for vulnerability management and asset inventory. This node reads
from three of its API surfaces through a single node and a single credential: VMDR, VMDR OT and
CyberSecurity Asset Management.
The package ships two nodes: Qualys, which reads on demand, and Qualys Trigger, which
polls VMDR and starts a workflow when something changes. Both are read-only. Nothing either
does modifies your Qualys subscription.
n8n is a fair-code licensed
workflow automation platform.
Installation
Operations
Trigger
Credentials
Compatibility
Usage
Resources
Version history
Development
License
Installation
Follow the installation guide
in the n8n community nodes documentation, using the package name @synergyconsulting/n8n-nodes-qualys.
To install it manually into a self-hosted instance:
cd ~/.n8n/custom && npm install @synergyconsulting/n8n-nodes-qualys
Operations
Resources group endpoints by what the data is; the operation names the record. Four resources,
26 operations.
OT
Operational technology inventory, from the VMDR OT gateway.
| Operation | Qualys endpoint |
|—|—|
| List Host Assets | /ot/1.0/host/list |
| List Vulnerabilities | /ot/1.0/detection/list |
| List Project Files | /ot/1.0/projectfile/list |
IT Asset
IT inventory, from the CyberSecurity Asset Management gateway.
| Operation | Qualys endpoint |
|—|—|
| List Assets | /rest/2.0/search/am/asset |
| Get Asset | /rest/2.0/get/am/asset |
| Count Assets | /rest/2.0/count/am/asset |
| List Software Components | /rest/2.0/am/asset/component |
| Get Software Components | /rest/2.0/am/asset/component/{assetId} |
VMDR
Vulnerability Management, Detection and Response, on the platform API.
| Operation | Qualys endpoint |
|—|—|
| List Detections | /api/5.0/fo/asset/host/vm/detection/ |
| List KnowledgeBase | /api/4.0/fo/knowledge_base/vuln/ |
| List CVE Scores | /api/2.0/fo/knowledge_base/qvs/ |
| List Hosts | /api/5.0/fo/asset/host/ |
| List Virtual Hosts | /api/2.0/fo/asset/vhost/ |
| List Asset Groups | /api/2.0/fo/asset/group/ |
| List Networks | /api/2.0/fo/network/ |
| List Domains | /api/2.0/fo/asset/domain/ |
| List IP Addresses | /api/2.0/fo/asset/ip/ |
| List Excluded Hosts | /api/2.0/fo/asset/excluded_ip/ |
| List Scans | /api/2.0/fo/scan/ |
| List Scanner Appliances | /api/2.0/fo/appliance/ |
| List Reports | /api/3.0/fo/report/ |
| List Static Search Lists | /api/2.0/fo/qid/search_list/static/ |
| List Dynamic Search Lists | /api/3.0/fo/qid/search_list/dynamic/ |
EASM
External attack surface discovery.
| Operation | Qualys endpoint |
|—|—|
| List Profiles | /easm/v2/profile |
| List Unresolved Domains | /rest/2.0/am/domain/list |
| Count Unresolved Domains | /rest/2.0/am/domain/count |
Endpoint versions are pinned to the ones Qualys still marks Active. Host List and Host List
Detection 2.0 through 4.0 reached End-of-Support in December 2025; Report and Dynamic Search
List have each since moved a version on.
Two operations behave unusually. List IP Addresses and List Excluded Hosts return a
single item holding the whole IP set, because Qualys mixes bare addresses and ranges in the
same container. List Dynamic Search Lists is slow: Qualys evaluates each list’s QID query
server-side, and a handful of lists took over two minutes on a small subscription.
Trigger
Qualys Trigger starts a workflow when VMDR reports a change. Qualys has no outbound
webhook for these collections, so the node polls on whatever interval you set.
It is not a separate app in the nodes panel: searching Qualys finds one entry, with these
events under Triggers and the read operations under Actions.
| Event | Reads | Changed-since parameter |
|—|—|—|
| Detection Updated | /api/5.0/fo/asset/host/vm/detection/ | detectionupdatedsince |
| Host Scanned | /api/5.0/fo/asset/host/ | vmscansince |
| KnowledgeBase Updated | /api/4.0/fo/knowledgebase/vuln/ | lastmodified_after |
| Scan Launched | /api/2.0/fo/scan/ | launchedafterdatetime |
Each poll reads one window of time: from where the last poll stopped to the moment this one
started. The mark lives in the node’s static data, so restarting n8n resumes rather than
replaying or skipping. The polling settings sit under Options, beside the watch filters.
First Poll Covers (Minutes) sets how far the very first poll reaches back (default 60) — 0
emits only what happens after activation.
Max Records Per Poll (default 1000) caps a single run so a backlog cannot flood the workflow. Nothing is
dropped: the poll remembers Qualys’ next-batch URL, the high-water mark stays put, and the
following poll finishes that window before opening a new one. Batches are taken whole, so a
poll can overshoot the cap by up to one Batch Size.
Detection Updated asks for Fixed detections as well as New, Active and Re-Opened — the
API omits them otherwise, and a remediation workflow is usually waiting for exactly that.
It offers the same Item Granularity choice as the node.
Delivery is at-least-once. Qualys’ date filters are inclusive, so a record that changes
exactly on a window boundary can arrive twice; key on the record rather than on the fact that
the workflow ran.
Pressing Fetch Test Event in the editor reads the lookback window and deliberately leaves
the stored mark alone, so testing cannot make the live trigger skip records.
Credentials
Create a Qualys API credential.
Platform picks your pod and derives both hosts the node needs — the gateway (gateway.*)
and the platform API (qualysapi.). Choose Custom* for a Private Cloud Platform and enter
the URLs yourself. Help → About in the Qualys UI shows your API server URL. Both URLs must be
HTTPS: the client secret and the token minted from it travel on every request.
One API client authenticates every request. There is no username, no password and no HTTP
Basic fallback — one credential, one mode.
API clients come from User info → View Profile → Auth ID Client Management in the Qualys UI
(requires UI 4.0). Client Type offers User Level, which mints its token at /auth/oidc;
such a client stops working when the user it belongs to is deactivated.
Subscription Level clients (/auth/oauth, which survive user deactivation) are not offered. A
credential saved before they were withdrawn keeps using that endpoint — the transport still
honours the stored setting — but new credentials cannot be pointed at it.
The credential’s Test button mints a token against the endpoint your Client Type
selects, so a wrong choice shows up as Invalid Client ID before any workflow runs. Tokens are
cached for their four-hour lifetime and refreshed automatically.
Known gap: IT Asset and EASM domains
These operations do not work yet, and that is a Qualys-side gap. CyberSecurity Asset
Management rejects a client token with 400 Error validating customer from token - Invalid, an error that blames your subscription rather than the credential. Qualys
Subscription Id
support confirms client-credential support there is still a work in progress, whatever the
documentation says.
The node sends the client token to Asset Management anyway, so those operations start working
the day Qualys ships it, with nothing to change here. Until then they fail, and the error
explains why rather than sending you to check your entitlements.
| Resource | Works today |
|—|—|
| OT | yes |
| VMDR | yes |
| EASM profiles | yes |
| IT Asset, EASM domains | not until Qualys ships client auth for CSAM |
Permissions
- API access enabled on the account, and SSO disabled — SSO blocks API authentication
- VMDR OT needs
VMDR OT.API.ACCESS - CSAM needs the module enabled and “App API Enabled” on the user’s role
- KnowledgeBase access is granted separately by Qualys Support
List Detections.QID→ List KnowledgeBaseQIDsfor descriptions and solutions- KnowledgeBase CVEs → List CVE Scores for per-CVE risk scores
List Detections.ASSET_ID(enable Show Asset ID) → Get Asset / List Assets- One call. Turn on Execute Once and aggregate the QIDs into the
QIDsfield: - One call per detection. Leave Execute Once off and set
QIDsto{{ $json.QID }}. Slower,
Compatibility
Built against n8nNodesApiVersion 1 and requires Node.js 20.15 or later, matching n8n’s own
floor. Developed and tested against n8n 1.x.
The package declares no runtime dependencies and ships no third-party code. The Qualys platform
API answers only in XML, so the node reads it with a small parser of its own
(nodes/Qualys/transport/xmlReader.ts); installing the node adds nothing to the n8n instance.
Usage
Filtering
Each plane takes a different filter language, so the node shows the right one per operation.
OT operations use QQL, built from Filter Groups. Rows within a group are bracketed, and
both rows and groups carry their own AND/OR join.
IT Asset and EASM domain operations use the Asset Management criteria document: a flat list
of field/operator/value rows plus one Match setting for the whole list. There is no
nesting, and the operator must suit the field’s type or the API answers 400. Use the IN
operator with a comma-separated value for OR within a single field.
Platform operations take Qualys’ documented named parameters directly, under **Additional
Fields**.
Combinations the API rejects with an opaque 400 — agids with agtitles, a search list with
qids, qdsmin without showqds — are caught before the request goes out. Anything not
surfaced as a field can be passed through Extra Parameters.
Software Components share the criteria UI, but Qualys splits it into two blocks: rows whose
field starts with component. become the component filter, everything else becomes the asset
filter, and the two are ANDed. It also pages on its own parameter and allows a page size up to
1000 rather than 300.
Paging
Return All pages until the API is exhausted; otherwise Limit caps the result
(default 50).
Each plane pages differently and the node handles all three: page numbers for OT, a
lastSeenAssetId cursor for IT Asset, and the next-batch URL Qualys returns for VMDR. **Batch
Size** controls records per VMDR call (default 1000). Setting it to 0 removes the limit, which
Qualys advises against unless you also narrow by an ID or IP range.
VMDR > List KnowledgeBase is the exception. That API takes no batch size and answers with
every matching QID in one response, which in full detail is larger than Node can hold in a
single string. The node therefore walks the QID space in chunks, one request per **Chunk Size
(QIDs) window (default 10,000), stopping at Maximum QID** or once a run of windows comes
back empty. Naming QIDs outright sends a single request instead, and Minimum QID /
Maximum QID bound the walk. Lower the chunk size if a response is still too large.
Requests are issued serially. The platform API’s concurrency limit is low — 2 on the
subscriptions we measured — so parallel fetching would simply fail.
Output
Options > Output Mode is either one item per record or the raw response, page by page.
VMDR > List Detections additionally offers Item Granularity: one item per detection
with its host context flattened in (the default, and what joins cleanly against the other
operations), or one item per host with detections nested.
Options > Add Response Metadata attaches _qualys to each item with the endpoint, plane,
batch count and the rate-limit headers. It has no effect on a raw response.
VMDR responses are XML and are converted to JSON with Qualys’ quirks handled: CDATA is
unwrapped, keeps both parts, attribute-keyed lists such as
QDSFACTORS and VULNCOUNT become plain objects, self-closing elements and the literal
string "null" become null, and repeated elements stay arrays even when only one is present.
Field names are left exactly as Qualys documents them.
Using upstream data
Every field that carries a value is expression-enabled, so it can be driven from an upstream
node: Asset ID, CVE IDs, filter fields and values, everything under Additional Fields,
and Limit and Batch Size. Only Resource, Operation and the QQL operator/join dropdowns are
fixed, since those drive which fields the panel shows.
Every operation runs once per input item, with parameters resolving against that item. A
List or Count whose query does not depend on its input would then emit the whole result
set once per item; to run it a single time however many items arrive, turn on n8n’s own
Execute Once in the node’s settings.
Output items carry pairedItem, so n8n can trace each record back to the input that produced
it.
Joining the operations together
assetId
Two ways to do the detection → KnowledgeBase join, both valid:
{{ $input.all().map(i => i.json.QID).join(',') }}. Cheapest, and the API accepts a list.
but each output row pairs with its detection.
Errors
Failures keep everything diagnostic and nothing secret.
The message is what Qualys said, with an actionable hint appended rather than substituted:
Error validating customer from token - Invalid Subscription Id. The Asset Management API
does not accept API client credentials yet, and reports that as a subscription problem.
Qualys support has confirmed client support there is still a work in progress; this node
is already wired for it, so the operation will start working once Qualys ships it.
Nothing to change here.
The description identifies the call without needing to reproduce it:
Request: POST /rest/2.0/search/am/asset
API: CyberSecurity Asset Management
Authenticated with: API client
HTTP status: 400
Qualys code: FAILED
The payload is the parsed response body, so a workflow can branch on
error.body.responseCode rather than parsing a string. httpCode is set for HTTP failures.
Credentials never appear. A transport failure in n8n arrives as an axios error carrying the
outgoing request, including Authorization; before that is handed on it is sanitized —
credential-bearing keys redacted, Bearer/Basic/JWT patterns stripped from any string,
raw-header and socket internals dropped, reference cycles broken, and size bounded. With
Continue On Fail the same enriched message is emitted as item data.