AI Pentesting, Part 7: Scaling Nuclei and Nessus: Deterministic Control, AI Triage

Adding workers increases traffic faster than it increases confidence. Keep target selection, plugin policy, rate budgets, and stop conditions outside the model. Let AI explain scanner evidence and group likely root causes, while deterministic orchestration controls every request.

Lab boundary: written authorisation, synthetic identities and data, isolated targets, bounded requests, and human approval for active actions. Examples are instructional fixtures, not claims of testing a live organisation. Tool inventory reviewed 2026-10-28; compatibility and availability can change.

Evidence and trust boundariesApproved manifestPolicy + queueBounded workersEvidence storePropose. Enforce. Verify.
The scheduler owns scope and traffic. The model receives redacted results, not an unrestricted scanner shell.

1. Separate scanning from reasoning

Nuclei is template-driven and particularly useful for repeatable checks with inspectable matchers. Nessus uses a plugin feed and scan policies across infrastructure and application surfaces. Neither a template ID nor a plugin's severity automatically proves a vulnerability. Authentication quality, target availability, matcher specificity, and feed revision all affect interpretation.

Use an approved manifest from Part 1 and applicability decisions from Part 6. A scheduler assigns jobs, deterministic workers execute approved tools, and an evidence store retains raw outputs. The LLM consumes a sanitised projection for triage. It cannot change scope, enable new template classes, raise concurrency, or convert a passive check into exploitation.

LayerResponsibilityReject
Manifest validatorAsset, owner, dates, ports, exclusionsExpired or unresolved scope
SchedulerGlobal/per-target limits and job leasesUnbounded fan-out or duplicate execution
WorkerPinned tool and reviewed check setModel-generated command flags
Evidence storeHashes, logs, status, original resultsFindings without raw evidence
AI triageSummaries and owner questionsUnsupported exploitability claims

2. How to run a reviewed Nuclei lab check

Install a vetted Nuclei release through your organisation's software process, record its version, and review the exact template file. Templates are code-like active content. A signature can establish provenance but not harmlessness. Exclude code, headless, fuzzing, denial-of-service, and out-of-band behaviours unless separately approved. Tags alone are not a sufficiently precise safety policy.

id: psc-lab-health-marker
info:
  name: PSC local health marker
  author: psc-lab
  severity: info
http:
  - method: GET
    path:
      - "{{BaseURL}}/health"
    matchers-condition: and
    matchers:
      - type: status
        status:
          - 200
      - type: word
        part: body
        words:
          - "PSC-LAB-HEALTH"

The template checks only a local health marker; it does not identify a real CVE. Start a lab service you control at loopback port 8080 that returns the marker at /health. The following commands assume the reviewed template is saved locally. Confirm flag names with your pinned release's help output.

nuclei -validate -t psc-lab-health.yaml
nuclei -u http://127.0.0.1:8080 -t psc-lab-health.yaml -rl 2 -c 1 -bs 1 -timeout 5 -retries 0 -jsonl -o lab-results.jsonl

Expected: one informational match only when the marker and status both match. Remove the marker and rerun as a negative control. A timeout is a measurement failure, not a clean result. Use network egress enforcement and redirect policy as well as an input allowlist.

3. Configure Nessus as an explicit policy

Start with a small pilot target group and a policy approved for the environment. Record scanner build, plugin feed date, port range, discovery settings, credentials, safe-check settings, plugin families, concurrency, and maintenance window. Safe checks reduce risk but do not guarantee a check cannot affect a fragile service. Exclude OT, medical, printer, and other sensitive systems unless specialists approve the exact checks.

Use a dedicated least-privilege scanning account with credentials stored in an approved vault, not in model context. Some authenticated configuration checks need elevated read access; document why and isolate that access. Verify authentication success in results. An unauthenticated scan accidentally run after a credential failure is not equivalent coverage.

  1. Create a test policy with a fixed target list and reviewed plugin families.
  2. Run one low-impact pilot and monitor service health.
  3. Confirm credentialed-check success and plugin coverage.
  4. Expand in bounded batches under the same policy revision.
  5. Export machine-readable evidence through the supported interface for your edition.
  6. Pause on service degradation, lockouts, or unexpected traffic.

Nessus edition and licensing affect scheduling, API availability, and integration options. Do not assume every deployment supports an identical automation endpoint. Pin the supported workflow instead of scraping the UI or inventing an API route.

4. Calculate the global traffic budget

If eight workers each enforce 5 requests per second, the fleet can issue 40 requests per second before considering retries or template fan-out. A per-worker flag is not a fleet-wide limit. Enforce a shared global token bucket and a separate per-target or per-service budget. Account for requests inside multi-step checks, redirects, authentication refresh, and retries.

workers = 8
per_worker_rps = 5
global_budget_rps = 12
uncoordinated_rps = workers * per_worker_rps
assert uncoordinated_rps == 40
admitted_rps = min(uncoordinated_rps, global_budget_rps)
print({"uncoordinated_rps": uncoordinated_rps,
       "shared_scheduler_ceiling": admitted_rps})

This arithmetic illustrates why coordination is required; it is not a distributed limiter implementation. Use a proven queue and shared rate-limiter mechanism already supported by your platform. Workers need leases, idempotency keys, bounded retries with jitter, and a dead-letter queue. A lost worker should not cause the same active check to run twice concurrently.

Monitor latency, error rate, scanner health, and target health separately. A rising 429 rate should reduce admission, not prompt the model to invent evasive headers. Respect Retry-After and approved windows. Have a kill switch that revokes queued jobs and prevents workers from starting new requests.

5. Normalise and deduplicate without erasing evidence

{
  "asset_id": "lab-web-01",
  "scanner": "nuclei",
  "check_id": "psc-lab-health-marker",
  "check_revision": "reviewed-fixture-001",
  "location": "/health",
  "identity_context": "anonymous",
  "observed": "marker_present",
  "status": "informational",
  "evidence_ids": ["job-014-response"],
  "human_verified": false
}

Group results using asset identity, check identity, location, and authentication context. A Nessus plugin match and a Nuclei template match may describe the same component but different weaknesses. Ask AI to propose a cluster and explain the relationship; keep original results and require review before merging findings.

Do not deduplicate all responses with similar text. Shared error pages, reverse-proxy banners, and generic login redirects can create false matches. Preserve clean, positive, failed, and not-tested outcomes. Redact tokens and customer content before summarisation while retaining access-controlled originals for verification.

6. Retest and measure the right outcomes

For each candidate, identify the exact matcher or plugin evidence and reproduce the least invasive confirming observation. Distinguish version inference from direct configuration evidence. A changed banner may invalidate a matcher without fixing the root cause. Retest the affected build, identity context, and deployment path after remediation.

Track verified findings per review hour, false-positive rate, coverage gaps, scan failures, authentication failures, and target-health incidents. Raw match counts reward noisy templates. Report the plugin/template revision so a future feed update does not silently change the meaning of historical results.

Lab deliverables: signed scope, reviewed check set, pilot health baseline, global/per-target budgets, immutable raw results, triage decisions, and a retest record. Part 8 brings the same control model into Burp's interactive AI and extension workflows.

7. Step-by-Step Lab: Pilot a Scan and Prove the Traffic Budget

Prerequisites: A pinned scanner release, the local health-marker template earlier in this article, and a service you own on loopback. A Nessus pilot additionally requires an appropriate licence and a reviewed scan policy. Do not point these procedures at production or sensitive devices by default.

  1. Record the exact scanner build and reviewed template/plugin revision. Write an allowlist containing only the owned fixture and a fixed test window. Exclude disruptive, headless, code, fuzzing, and out-of-band behaviours unless separately approved.
  2. Validate the Nuclei template and start a tiny pilot using the one-template command in Section 2. Confirm one informational match when the lab marker exists.
  3. Remove the marker and repeat as a negative control. A timeout or authentication failure is not equivalent to a negative result; preserve it as failed measurement.
  4. Before increasing workers, run the offline admission example below. Verify both the fleet-wide ceiling and the per-asset ceiling. It demonstrates policy accounting, not an actual distributed rate limiter.
  5. For Nessus, use one disposable target and a policy snapshot with reviewed plugin families, safe-check settings, ports, concurrency, and credential requirements. Verify credentialed-check success explicitly in the result.
  6. Monitor service latency, errors, 429 responses, account lockouts, and scanner health during the pilot. Exercise the stop mechanism before any expanded batch.
  7. Export raw results and group potential duplicates by asset, location, check revision, and identity context. Let AI propose clusters, but keep the original evidence and manual verification decision.
const globalLimit = 12;
const perAssetLimit = 3;
const used = new Map();
const admitted = [];
const jobs = Array.from({ length: 16 }, (_, index) => ({ asset: "asset-" + (index % 4) }));
for (const job of jobs) {
    const current = used.get(job.asset) ?? 0;
    if (admitted.length >= globalLimit || current >= perAssetLimit) continue;
    admitted.push(job);
    used.set(job.asset, current + 1);
}
if (admitted.length !== 12 || [...used.values()].some(count => count > 3)) throw Error("budget mismatch");
console.log(JSON.stringify({ admitted: admitted.length, perAsset: [...used] }));

Expected result: Twelve admitted jobs, three per asset. These are counts in one synthetic scheduling interval; a real limiter needs clocked refill, atomic shared state, retries, and accounting for requests inside multi-step checks. Four workers independently allowing twelve jobs would not enforce this fleet policy.

8. Worked Examples and Expected Outcomes

Example A: a generic login page matches many paths

A scanner records the same body for several administrative endpoints. Compare the catch-all control and response signatures. A matcher based only on HTTP 200 or one common word may be noisy; review the template rather than promoting every match to a finding.

Example B: credentials silently stop working

A scan still completes after a test account expires, but authenticated coverage disappears. Mark credentialed checks unavailable and fix the approved account workflow. Do not compare the new result count with the old count as if coverage were unchanged.

Example C: a target returns 429

Respect Retry-After and reduce admission within policy. Do not ask a model to generate rotating identities, alternate headers, or evasive timing. The operational result is a rate-limit signal and a scheduling adjustment, not a challenge to defeat the control.

Pilot record:
target: owned-loopback fixture
check set: reviewed health marker only
positive: marker present -> informational match
negative: marker absent -> no match
measurement failure: timeout -> failed, not clean
expansion: requires owner approval and shared budget

9. Troubleshooting, Retesting, and Completion Evidence

SymptomLikely causeDiscriminating check
Traffic exceeds the configured rateLimits are per process or retries bypass accountingCorrelate timestamps across workers and count actual requests
Results are emptyTarget, credentials, or check selection may have failedVerify health and coverage controls before declaring clean
Duplicate findings multiplyGrouping ignored identity or check revisionRetain raw results and compare the actual root-cause evidence

Retest and completion: Keep the manifest, check hashes/revisions, pilot baseline, request logs, authentication success evidence, failure counts, and verified findings. Rerun the exact reviewed check after a fix. A changed banner or vanished matcher alone does not establish that the vulnerability was remediated.

10. Real Tool Workflow: Run Nuclei Against a Local Marker and Configure a Nessus Pilot

Prerequisites: A reviewed Nuclei binary, Python 3 for a loopback-only static server, and the health-marker YAML template earlier in this article. Nessus requires its own compatible edition/licence and an owned disposable target. The two-terminal marker demonstration does not require Nessus or a vulnerable application.

Use reviewed releases and record the versions actually installed. Command references for this workflow were reviewed on 29 October 2026; product support and flags can change. Instructions and output shapes are not claims of a live assessment.

ToolRoleImportant boundary
Python http.serverServe one harmless local markerBind explicitly to loopback; never use it as a production service
NucleiExecute one reviewed non-destructive templateDo not enable broad templates, generated checks, code, fuzzing, or OAST
NessusPilot a snapshotted authenticated infrastructure policySafe-check settings and successful completion do not guarantee coverage or zero risk

Step-by-Step Tool Operation

  1. Create a fresh local fixture directory containing a file named health with the marker PSC-LAB-HEALTH. Save the earlier reviewed YAML as psc-lab-health.yaml in the working directory and record its hash.
  2. In terminal A, start the Python server with the loopback binding below. Confirm the directory contains no credentials, source archives, or unrelated files. Keep this process under operator control.
  3. In terminal B, check Nuclei's installed version and validate only the local template. Inspect its GET path and matchers before the active command. Stop on a validation error.
  4. Run the one-template scan against the owned loopback service with low concurrency, no retries, redirects disabled, OAST disabled, and update checks disabled for the reproducible pilot.
  5. Replace the local marker content with PSC-LAB-NO-MATCH and rerun into a new output file. Expect the original marker template not to match; a failed connection or parse error is not this negative control.
  6. For a separate Nessus pilot, create a policy in the supported UI, snapshot plugin feed and settings, select one disposable owned target, and verify credentialed-check success. Expand only after service-health monitoring and owner approval; stop the Python process with Ctrl+C in terminal A when finished.
New-Item -ItemType Directory -Path .\http-fixture -ErrorAction Stop
'PSC-LAB-HEALTH' | Set-Content .\http-fixture\health
python --version
python -m http.server 8080 --bind 127.0.0.1 --directory .\http-fixture
nuclei -version
Get-FileHash .\psc-lab-health.yaml -Algorithm SHA256
nuclei -validate -t .\psc-lab-health.yaml
if ($LASTEXITCODE -ne 0) { throw 'Template validation failed' }
nuclei -u http://127.0.0.1:8080 -t .\psc-lab-health.yaml -rl 2 -c 1 -bs 1 -timeout 5 -retries 0 -ni -dr -duc -jsonl -o .\marker-positive.jsonl
'PSC-LAB-NO-MATCH' | Set-Content .\http-fixture\health
nuclei -u http://127.0.0.1:8080 -t .\psc-lab-health.yaml -rl 2 -c 1 -bs 1 -timeout 5 -retries 0 -ni -dr -duc -jsonl -o .\marker-negative.jsonl

Expected Evidence and Interpretation

The first PowerShell block runs in terminal A and remains in the foreground. The second runs in terminal B from the same directory. With the earlier status-and-word template, the positive run should produce an informational match and the changed-marker run should not. Tool errors must be inspected separately from an empty match file. These are expected fixture outcomes, not a claim that the scanner was executed here.

For Nessus, retain the policy revision, port range, discovery configuration, plugin families, safe-check setting, concurrency, credential scope, and feed date. Use supported exports for the installed edition. Do not invent a universal Nessus REST endpoint or embed scanning credentials into an AI prompt.

Troubleshooting and Cleanup

If port 8080 is occupied, choose a free loopback port and update both the server command and target URL. A 404 usually indicates the wrong working directory or missing health file. A missing match after a failed connection is not a clean result. Stop only the server process started for this exercise, retain the approved pilot evidence, and remove temporary fixture files when no longer needed.