Security Testing, AI & ComplianceSecurity Lab
On this page0

Unfamiliar word? See Glossary: words used in these docs. Looking for the tasks in order? Begin at Start Here.

Reference

Included in: Advanced. Which Plan Includes What

Security Lab

Three kinds of automated check, run against the scopes you authorise (a scope is the list of your own hosts that Security Lab is allowed to test): a check for open network ports, a set of vulnerability probes (each one a scripted test for one known kind of weakness), and a check of the software components your systems are built from against published lists of known flaws. They run on your schedule. They are not a penetration test, which is a person hired to try to break in, and they are not a certified assessment against any published security benchmark.

What A Scan Covers

An on-demand scan runs real probes, sorts findings by severity, and produces an A to F posture grade.AUTOMATED SECURITY CHECKSPROBESnmapsqlinucleitrivyjwtbolaFINDINGSCriticalHighMediumBGRADE

Security Note

Ensure you have authorization to scan target IPs. All scans are logged for audit compliance.

Open-Port Check

A port is a numbered door on a server that a program listens behind. This check finds which doors are open on one named host per scan, and which program answers at each: the most commonly used ports on a remote host you have authorised, or your own instance’s service ports on an internal scan. It looks at the one host you name and never at a whole range of addresses. The tool and the exact port lists are in the technical part below.

Vulnerability Probes

Tries the common ways a web application is broken into: sending it commands disguised as ordinary input, opening a record that belongs to someone else, getting in without the right proof of identity, and missing browser-protection settings. Against one of your own apps, the test for opening someone else’s record uses two real sign-ins that you supply on the scope, so it can try one person’s record as the other. The name of each probe is in the technical part below.

Scheduled Scans Of Your Own Hosts

The Security Lab runs automated checks against the hosts you list in a scope, one host at a time, on demand or on a schedule you turn on. It reports the open ports it finds and flags the issues it recognises — which is a useful early warning, not a guarantee that a weakness is caught before anyone can use it. It sees only the hosts you authorise, and only the kinds of issue its probes know how to test for. It does not search your network for servers nobody told it about.

Hostnames Under Your Domains

The Assets view lists hostnames found under the domains you have verified (addresses such as shop.example.com, found in public records of your domain), so a forgotten one shows up in the list. This is an inventory: a discovered hostname is not scanned until you add it to a scope.

Audit Compliance Logs

Maintains detailed logs of every scan, providing the scan-history evidence useful for SOC 2, ISO 27001 and other security audits.

Beyond The Probe Scan

Host CVE Matching And SBOM Scanning

The Scan more menu (shown to roles that can manage findings) has two scans that are not probes. Scan hosts matches the software inventory of your device fleet against the CVE database. Scan SBOM takes a CycloneDX or SPDX file you upload or paste and reports the known CVEs in its components; the file is processed on your instance.

Remediation Deadlines

Remediation SLAs are attached by severity — Critical 7 days, High 14, Medium 30, Low 90 — so a finding carries its own due date. Threat intelligence can only shorten it: a finding tied to a CVE on the CISA KEV list (known to be exploited) gets the Critical deadline whatever its severity, and an EPSS score of 0.5 or higher moves it up one tier.

Exploit Intelligence (KEV / EPSS)

Security Lab keeps a local mirror of the CISA Known Exploited Vulnerabilities list and EPSS scores. The Intel button shows how many CVEs are on file and how many of your open findings are on the KEV list, and refreshes the mirror on demand. A finding tied to a KEV-listed CVE is tagged CISA KEV — actively exploited, takes the Critical remediation deadline, and counts more heavily in the risk score; an EPSS score of 0.5 or higher tightens the deadline by one tier. Intelligence only ever shortens a deadline. Until the first refresh there is no prioritisation data and findings are ordered by severity alone.

The mirror also refreshes by itself, every 24 hours by default. A chip in the header reads Intel fresh or Intel stale, with the age of the data in days.

The Eight Views

ViewWhat it shows
ConsoleRun scans and single probes; open findings worst first.
FindingsOne row per individual issue (for example one CVE in one package), in a sortable, filterable table, under an overview strip and an AI analyst summary. Accept risk and Mark false positive are available per issue. The summary’s figures are computed by code; the narrative is drafted by the local AI model from those figures and never overrides them. The summary card is hidden when it is unavailable.
RiskOne ranked list of the assets Security Lab holds: your instance’s own services and the hostnames discovery finds under your verified domains. They are ordered by a computed risk score that combines severity, exploit intelligence and the criticality you set for the asset. A device is not a row of its own: it is shown on an asset’s row when its hostname or its check-in IP address matches the asset, and its findings and reported exposures then count in that score. The Exposure column reads Unknown and does not change the score, because there is no control that sets it today. Criticality is editable in place and the change is audit-logged.
Attack pathsChains where a real vulnerability sits on an internet-exposed workload whose IAM path reaches a privileged target. These are derived when your cloud graph is mapped; no attack is run to produce them.
RemediationProposed fixes for device findings. "Hand off to Devices" files a record for the device team; Security Lab does not change a device policy or profile itself. The fix is re-tested here once applied.
ExceptionsThe risk exception register: every accepted risk with who asked, why, and when it lapses, plus counts of entries awaiting approval and active. Critical and High need a second person to approve; the requester cannot approve their own. When an entry expires or is revoked, the issue reopens. "Show history" includes expired and revoked entries.
HistoryCompares two scans as New, Regressed and Fixed.
AssetsHostnames discovered under your verified domains (subdomains, certificate-transparency names, DNS records), with a status and a subdomain-takeover flag. "Discover now" runs discovery on demand and asks you to re-authenticate.

The header also has Trends (posture score over time). The overview carries a compliance-evidence card showing, per scope, whether your external-scan cadence still meets SOC 2 CC7.1 and PCI DSS 11.3, and that evidence is passed to the Compliance Hub. It is evidence that scans ran on a cadence, not an attestation of compliance.

Scheduling, Delivery And Alerts

Everything here is under Configure, which appears only for roles that can manage security scopes. All of it is off until you turn it on.

  • Schedule → Run scheduled scans automatically. Re-runs the standard profile against your own instance every 1–168 hours (default 24). Scheduled scans are always the standard profile, so they never include the deep probes.
  • Schedule → Email the report after each scheduled scan. Sends the sealed report to the recipients you list. It needs outbound email to be configured on your instance.
  • Schedule → Continuously scan external scopes. Each interval (1–168 hours, default 24) starts a cycle that queues every named host of every enabled, ownership-verified remote scope. Wildcard entries are skipped, because a pattern is not an address that can be scanned. Hosts are scanned one at a time, up to five per scheduler run, and the rest carry over to the next run. A host held back by its scope’s rules of engagement (outside the scan window, over the rate or host limit, or backing off) is deferred, never dropped. Every unattended scan is audit-logged.
  • Schedule → Container images to scan. The image references the container-image probe checks during an aggressive scan. With no images listed, that probe reports Inconclusive rather than clean.
  • Ticketing. Opens a Jira issue or ServiceNow incident for each new Critical or High finding, using a Jira or ServiceNow integration you have already connected under Integrations.

Two things are not on screen. Overdue-finding emails (a finding past its remediation deadline) are on by default in the service and go to holders of the security-management permission when outbound email is configured; there is no control for this in the Security Lab screens today. And the out-of-band alert webhook for new or regressed Critical and High findings is an instance-level setting that Zonitix configures on your server — ask support to set it; without it those events are only logged.

These are automated checks, not a penetration test. Every probe is a fixed script with a pass/fail oracle. There is no human testing your business logic, and the network probes cover common ports only (the three mesh ports internally; the top 1000 TCP ports on a remote host, with UDP and IPv6 only in the aggressive profile) — not a full-range sweep. Treat a clean run as “the known checks passed,” not “we are secure.”

The AI summaries and explanations in Security Lab run on a model inside your own instance. Which model is active, the switch that turns AI off, and the permission each AI feature needs are described in Local AI & model governance.

If something here is not working as you expect, start with When something goes wrong.

The plain explanation is above. This part is for IT and developers: the exact settings, permission names, API addresses and data fields behind it. Closed: select the heading above to open it. While it is closed, your browser’s find-on-page (Ctrl+F or Cmd+F) does not search this part.

Probe Registry

The scanning service (`security-lab-service`) runs a registry of discrete probes against the scopes you authorise. Network probes run a containerized `nmap`; the rest are application-layer probes and open-source scanners. A readiness check (`remote_preflight`) always runs first, so a missing prerequisite is reported once at the top of the run instead of as a string of identical failures. Each probe returns a severity and structured findings, which are persisted as `SecurityScan` / `SecurityFinding` records — there is no raw-XML host index.

CategoryProbes
Networkremote_preflight, nmap, nmap_vuln*, nmap_udp_ipv6*, subdomain_enum, discovery, tls_audit
Web / APIsqli, xss, bola, idor, ssrf, csrf, directory_traversal, open_redirect, cors_audit, sensitive_files
Identity / Authjwt, mfa_bypass, brute_force, gateway_security, zonitix_self_test
Email posturespf_check, dmarc_check, dkim_check
Supply chain / Codetrivy_fs, trivy_image*, sca, sast, semgrep_scan*, gitleaks_scan, nuclei
AI / Dataprompt_injection, pii_extraction
Infra / Resiliencek8s_leak, vault_check, redos, slowloris, logging, device

Probes marked * are long-running deep probes (each has a time budget of 30–45 minutes) and run only in the aggressive profile: NSE version-to-CVE correlation (`nmap_vuln`), UDP and IPv6 exposure (`nmap_udp_ipv6`), Semgrep, and CVE scanning of your own container images (`trivy_image`, using the image list under Configure → Schedule). `zonitix_self_test`, the code and supply-chain scanners, `csrf`, `k8s_leak` and `vault_check` only make sense against your own instance and are skipped on a remote target.

Driving A Scan

# Internal scan: the three service ports of your own instance’s mesh.

nmap -p 8000,8001,8002 api-gateway identity-service user-management-service

# Remote scan of an authorised host: top 1000 TCP ports with service/version

# detection. Open ports on the high-risk exposure list (databases, caches,

# remote desktop…) are graded as findings.

nmap -Pn -sV -T4 --top-ports 1000 --host-timeout 180s <authorized-host>

# Aggressive profile only, remote host:

nmap -Pn -sV --script 'vuln and safe' --top-ports 200 <authorized-host> # nmap_vuln

# nmap_udp_ipv6: UDP top 50 ports, plus IPv6 top 200 when the host has an AAAA record

# Probes are orchestrated and persisted by the service itself. Drive and

# read scans through the gateway:

// POST /api/v1/auth/security-lab/scans (create a scan)

// GET /api/v1/auth/security-lab/scans/:id (status + findings)

// GET /api/v1/auth/security-lab/scans/:id/report?format=markdown|json|sarif|csv

// GET /api/v1/auth/security-lab/scans/:id/verify (re-check the sealed report)

Running A Scan

The steps on screen are in the guide Run a Security Lab scan. This section gives the rules behind those steps: what authorises a scan, what each profile runs, how the score is computed and what an export contains.

1. Authorise What You Are Allowed To Scan

Before scanning anything outside your own instance, create a scope (manage_security_scopes or manage_compliance). A scope lists the hosts you are attesting you own. Two things must both be true before it authorises a scan: the scope carries your ownership attestation, and you have proven control of the domain by publishing the scope’s zonitix-site-verification=… value as a DNS TXT record and having the scope verified against it. Proof is per domain: a host is covered only if it sits under a domain that actually carries the record. (Scopes created before DNS proof existed keep working on attestation alone.)

A host that is not in an enabled, verified scope can still be scanned with a per-scan attestation — the tick-box on the Console — but only at the safe profile: a full scan is lowered to safe, and a single active probe is refused with 403 ATTESTATION_SAFE_ONLY. The attestation is written to the audit log with the host name. With neither a verified scope nor an attestation, the request is refused with 403 NOT_AUTHORIZED_TARGET, and the refusal is logged too.

Each scope also has a max profile. A scan above it is refused (403 SCOPE_PROFILE_EXCEEDED). It is set when the scope is created and can be changed afterwards, together with the name, description, allowed hosts, injectable URL, BOLA resource URL and its two credentials. The change is PATCH /api/v1/auth/security-lab/scopes/:id: it needs a fresh re-authentication (401 SUDO_REQUIRED otherwise) and is audit-logged as SECURITY_SCOPE_UPDATED. Changing the allowed hosts clears the scope’s ownership proof, so it must be verified again before it authorises a scan. Disabling and enabling a scope are separate actions, not fields of this change.

Your internal service mesh is seeded automatically, so local scans always have a target set without any setup. The scope for your own instance takes its hosts from the deployment’s domain settings: the edit form locks its name and allowed hosts, and the API refuses a change to its hosts with a 400.

2. Choose A Profile

ProfileRunsNotes
safePassive probes only, minus the deep probesRead-only, lowest impact
standardPassive + active, minus the deep probesThe default, and what a scheduled scan always uses. Sends exploit-style payloads, excludes anything destructive. Does not run Semgrep, nmap CVE correlation, UDP/IPv6 or container-image scanning
aggressiveEverything: destructive probes and the long-running deep probesLoad/DoS-style probes that can degrade the target, plus the deep probes marked * in the registry above, which can each take up to 45 minutes. Requires a fresh re-authentication within the last 15 minutes

Scanning a remote target also drops any probe that only makes sense against your own instance. That includes the probes written against Zonitix’s own API paths (BOLA, JWT, MFA bypass, brute force, SSRF, the AI probes): on a remote scan, SQL injection and XSS run only if the scope declares an Injectable URL, and the object-authorisation (IDOR) probe only if it declares a BOLA resource URL with both credentials. Scans run asynchronously — the request returns immediately and you poll for progress. One scan runs at a time; starting a second returns 409. Stop scan cancels the probe that is running (its tool process is killed) rather than waiting for it to finish. Every probe also has a time budget, and one that is stopped or runs over is recorded as Inconclusive, never as a pass.

3. Read The Score Honestly

The posture score is null until something has actually been scanned — it never shows a flattering 100 for an instance that has never run a scan. Open findings reduce the score by severity, and there are hard ceilings: an open Critical caps the score at 50, an open High caps it at 80. You cannot present as healthy while something serious is open.

Findings are de-duplicated per probe and target, so re-running updates a finding’s history instead of creating a duplicate. You can move a finding to acknowledged, in-remediation, risk-accepted or false-positive — but the last two require a written justification. A false positive needs only that justification. Accepting a risk is governed: every acceptance is an entry in the exception register (the Exceptions view), and the register is the only thing that writes the risk-accepted status.

  • Every acceptance expires. Risk accept… asks for the justification and an Accepted until date. The server refuses a request without a valid date in the future (400 EXPIRY_REQUIRED) or without a justification (400 JUSTIFICATION_REQUIRED).
  • Critical and High need a second person. A Low or Medium acceptance is active at once. A Critical or High one is created pending and the finding stays open until someone other than the requester approves it in the Exceptions view; the requester approving their own request is refused with 403 SOD_SELF_APPROVAL. A request whose finding has since been fixed or marked a false positive cannot be approved (409 SUBJECT_NOT_OPEN).
  • One live exception per finding or issue. A second request while one is active or pending is refused with 409 EXCEPTION_EXISTS; revoke the first one.
  • It lapses by itself. When the date passes, or when someone revokes the entry, the finding goes back to open and counts against the score and its deadline again. Requests, approvals and revocations are audit-logged (SECURITY_EXCEPTION_REQUESTED, SECURITY_EXCEPTION_APPROVED, SECURITY_EXCEPTION_REVOKED).

The routes are POST /security-lab/findings/:id/exception, GET /security-lab/exceptions, and POST /security-lab/exceptions/:id/approve and /revoke. There is no “mark as fixed” button: a finding only reaches verified_fixed by passing a clean re-scan, and one that comes back later is flagged as regressed.

4. Export

The Export menu offers Report (Markdown), SARIF 2.1.0 (for code-scanning and CI tools), CSV and Activity log (the console output of your current session, as Markdown); JSON is available from the report API. When a scan finishes, its report body is frozen and a SHA-256 is taken over it, so a later re-scan cannot change what that scan reported. The hash is then written into the platform’s hash-chained audit log as a SECURITY_SCAN_SNAPSHOT_SEALED entry, and the snapshot records that entry’s position in the chain. GET /security-lab/scans/:id/verify recomputes the hash and compares it with both the stored snapshot and the audit-log entry. One limit to know: recording the chain position is best-effort. If that read-back fails the snapshot is still sealed and its body hash still verifies, but the verify result has no audit-log anchor to compare against.

Archiving Findings

Roles that can manage findings see an Archive findings button above the results on the Console. It asks Archive all findings? and then for a re-authentication. Every current finding, and each issue under it, is moved to the archive and leaves the board. Nothing is deleted: archived findings stay in the audit trail (SECURITY_FINDINGS_ARCHIVED), and the next scan re-detects anything still open. Through the API, POST /api/v1/auth/security-lab/findings/archive takes an optional scope of all (the default), remote or local, answers 401 SUDO_REQUIRED without a fresh re-authentication, and returns { archived, archivedIssues, scope }. The older DELETE /security-lab/findings answers 410 Gone.

Loading Exploit Intelligence Through The API

An instance that cannot reach the feeds can load an intelligence bundle through the API instead (POST /api/v1/auth/security-lab/intel-import, for roles that can manage findings); GET /api/v1/auth/security-lab/intel-status returns what the Intel fresh / Intel stale chip shows.

Related reference