skip to content

Scan Engines

The machinery that turns recorded traffic into findings: one half only reads messages that already went past, the other sends crafted requests of its own.

on this pageshow

explore

questions

21

In OWASP ZAP, where does the active-scan engine live, and where do its attack rules come from?

level: juniorimportance: must knowfreq 58%

answer

  1. two halves, shipped apart
  2. the scheduler stayed at home
  3. payloads arrive as add-ons
  4. paros.core.scanner versus ascanrules

basics

~20 s

ZAP's active-scan engine ships in core, in org.parosproxy.paros.core.scanner. The rules that craft the payloads ship separately, as scan-rule add-ons. A build with no rule add-ons still has a working scheduler with almost nothing to run.

solid answer

~40 s

ZAP's active scan is two halves that ship apart. The **engine** is core: `Scanner` fans out one `HostProcess` per site, `HostProcess` walks the Sites tree and drives each rule over the nodes it found, and `AbstractPlugin` — the base class every active rule extends — owns `sendAndReceive`, the one method that puts an attack request on the wire. The **rules**, the classes that build a payload and read the response, ship as add-ons: the `ascanrules` family in the `zap-extensions` repository. Core keeps one active rule of its own, `ScriptsActiveScanner`, and even that is marked `@Deprecated(forRemoval = true)` with the live version in the `scripts` add-on. The asymmetry is worth remembering because the passive side went the other way — its engine moved out to the `pscan` add-on.

go deeper

for a junior

Remember the shape: the machinery that runs a scan is in ZAP core, the things that actually attack are add-ons. If nobody installed scan-rule add-ons, a scan still runs and still reports nothing.

for a middle

Be able to name the core classes — Scanner, HostProcess, AbstractPlugin — and say that the shipped rules live in the ascanrules add-ons. Explain why that is the opposite arrangement from the passive engine.

for a senior

Treat engine and rules as two release surfaces when you own a pipeline. Know which one to suspect when finding counts move, and pin the image so both halves move together rather than one drifting.

for a principal

Decide the team's stance on add-on drift: a pinned image with frozen rules is reproducible but goes stale, and a self-updating one finds more but makes every result non-comparable. Pick deliberately and write it down.

## The split in one sentence ZAP's active scan is two products running in one process. The **engine** — the code that decides which URLs get attacked, which rule runs against them, how often, and how the request physically leaves the process — ships inside ZAP core, in the package `org.parosproxy.paros.core.scanner`. The **rules** — the classes that build a payload and read the response to decide whether it proved anything — ship as installable add-ons. Neither half does anything useful alone. ## What core actually contains | piece | class | job | |---|---|---| | the fan-out | `Scanner` | creates one `HostProcess` per site — scheme, host and port together — and runs them on a pool | | the scheduler | `HostProcess` | walks the Sites tree, builds the list of nodes to attack, and drives each rule over that list | | the rule contract | `AbstractPlugin` | the base class every active rule extends; owns `sendAndReceive`, the only method that sends an attack request | | the fire-count shapes | `AbstractHostPlugin`, `AbstractAppPlugin`, `AbstractAppParamPlugin` | subclasses that fix how often the engine invokes a rule | | the baseline prober | `Analyser` | requests deliberately non-existent paths before rules start, so rules can tell a real page from a soft "not found" | All of that is core, and none of it carries a deprecation marker. ## What the add-ons contain The shipped attack rules live in the `ascanrules` family of add-ons — one class per rule, each extending one of core's base classes. They carry the payload strings, the response oracles and the alert text. Core ships exactly one active rule of its own, `ScriptsActiveScanner` (the rule that runs user-supplied active scripts), and even that is annotated `@Deprecated(forRemoval = true)`; the live implementation sits in the `scripts` add-on. So the honest statement is: **core keeps the engine plus a shim, and every working rule is an add-on.** ## Why the asymmetry is the fact to memorise ZAP has moved several subsystems out of core over the years. The local HTTP proxy and the certificate authority went to the `network` add-on. The traditional spider left with no shim at all. The **passive**-scan engine moved to the `pscan` add-on. The active-scan engine is the one that stayed. That makes "where does this live?" a question with opposite answers on the two sides of the same scanner, and it changes what each kind of change can break: - an active **rule** update is an add-on update, and it changes only what gets sent; - an active **engine** change is a core change, and it can alter target selection, ordering, concurrency and the send path for every rule at once; - a build with no scan-rule add-ons still has a fully functioning scheduler that finds nothing. ## What it means for a pipeline 1. **Two upgrade surfaces, two changelogs.** Core moves on its own line; each rule add-on versions independently. When a scan starts reporting more — or fewer — findings after an image refresh, a rule add-on change is far more likely than an engine change. Read that changelog first. 2. **Pin both halves together.** Pinning a container tag pins the engine and the add-on set at once. Letting add-ons update themselves inside a pinned image reintroduces exactly the drift the pin was for. 3. **A clean run proves the engine ran, not that rules did.** If the rule add-ons you assumed were present are absent, the engine still completes a scan and still reports nothing. "No findings" and "nothing installed to find them with" look identical from outside. 4. **Some of the traffic is the engine's own.** `HostProcess` starts an `Analyser` for each start node, and it requests random non-existent paths before any rule fires, so that rules can later distinguish a genuine page from a site that answers everything with a friendly page. "No rules installed" therefore does not mean "no requests sent" — which matters when you have to explain to a target owner exactly what your job did. ## How to check it yourself The clones make this a two-line question. Search core for the engine's own classes and the add-on repository for the rules that extend them: - `grep -rn "class HostProcess" <core>/zap/src/main/java` lands in `paros/core/scanner`; - `grep -rln "extends AbstractAppParamPlugin" <extensions>/addOns` lands almost entirely under `addOns/ascanrules*`. That is the whole claim, measured rather than remembered. ## The words to use Say *"core's active-scan engine"* and *"the `ascanrules` add-ons"*, never *"ZAP's scanner"*. In this tool "scanner" can mean the active engine, the passive engine or the whole program, and those three live in different repositories on different release cadences. Naming the half you mean is the difference between a claim a colleague can verify and one they cannot.

  • Does ZAP core ship any active scan rule of its own?
    One, and it is on its way out. `ScriptsActiveScanner` — the rule that runs active *scripts* — sits in core's `org.zaproxy.zap.extension.ascan` package but is annotated `@Deprecated(forRemoval = true)`; the live implementation is in the `scripts` add-on. Core keeps the engine and a shim, not a working rule set.
  • What practical difference does the split make to a CI pipeline?
    Two upgrade surfaces. Core fixes scheduling, target selection and the send path; each rule add-on versions independently and changes only what gets sent. When findings move after an image refresh, look at the rule add-on changelog before suspecting the engine.
  • If no rule sends anything, does the engine still touch the target?
    Yes. `HostProcess` starts an `Analyser` per start node before rules run, and it requests deliberately non-existent paths to learn how the site answers for a missing resource. That traffic is the engine's own and reaches the target regardless of which rules are installed.

saying these in an interview costs you the question

  • Says the whole active scanner is an add-on, like the passive one
  • Assumes the core jar alone carries the attack rules
  • Thinks updating scan rules also changes the scheduling engine
  • Claims the engine sends nothing of its own before rules run
  • Uses the bare word scanner without saying which half is meant
open as a page

In ZAP, what is a passive scan rule handed to work with, and what stops it sending a request?

level: juniorimportance: must knowfreq 70%

basics

~20 s

A ZAP passive scan rule implements the core PassiveScanner interface, which hands it a recorded HTTP message and that message's history id. The interface declares no send method, so a rule can only read traffic already captured.

open as a page

In ZAP, how does the pscan add-on's passive engine get the messages that its rules scan?

level: middleimportance: must knowfreq 60%

basics

~20 s

ZAP's pscan add-on runs a PassiveScanController that walks the History table by record id rather than the live wire. For each record it queues a PassiveScanTask, which re-reads the message and runs every enabled passive rule.

open as a page

In OWASP ZAP, what do a scan rule's `Plugin.AttackStrength` and `Plugin.AlertThreshold` each control?

level: middleimportance: must knowfreq 70%

basics

~20 s

AttackStrength sets how hard a rule tries: how many payloads and requests it spends per parameter. AlertThreshold sets how much evidence it demands before raising anything. They are separate dials, and only the threshold has an OFF value.

open as a page

In a ZAP active scan, which parts of a request may rules change by default, and which are left alone?

level: middleimportance: must knowfreq 62%

basics

~20 s

By default a ZAP active scan may change query-string parameters, post-data parameters and a plain request body. Cookies, HTTP headers and URL path segments are left alone: TARGET_INJECTABLE_DEFAULT omits them, and no scan policy can add them.

open as a page

How does ZAP's active scan engine turn its input-vector setting into the parameters a rule attacks?

level: middleimportance: must knowfreq 52%

basics

~20 s

VariantFactory.createVariants reads the injectable bitmask and the enabled-RPC bitmask and returns a list of Variant objects for that one message. Each Variant exposes its own parameter list, and a parameter-based rule loops over every variant and every parameter.

open as a page

A ZAP active scan finished in seconds with no alerts against a live site. What explains it?

level: seniorimportance: must knowfreq 50%

basics

~20 s

Almost always an empty target list. HostProcess builds its targets by walking the Sites tree, not by exploring the network; when that list is empty it skips every rule with the reason no nodes to scan and the scan completes normally.

open as a page

In OWASP ZAP, what does a saved scan policy file hold, and how does a run select one?

level: juniorimportance: should knowfreq 45%

basics

~20 s

A ZAP scan policy is an XML file with the .policy extension holding a default attack strength, a default alert threshold and optional per-rule overrides. Core's PolicyManager lists the policies folder under ZAP home and loads one by filename.

open as a page

In ZAP's active-scan engine, why does one scan rule fire once per site and another once per parameter?

level: middleimportance: should knowfreq 46%

basics

~10 s

The base class the rule's author chose decides it. HostProcess invokes an AbstractHostPlugin once, on a single message, and an AbstractAppPlugin once per in-scope node. AbstractAppParamPlugin then loops over that node's parameters itself.

open as a page

What does ZAP's AbstractPlugin.sendAndReceive change about an active rule's request before sending it?

level: middleimportance: should knowfreq 38%

basics

~20 s

It clears If-Modified-Since and If-None-Match so a 304 cannot hide the response, recomputes Content-Length for the body the rule just edited, optionally adds a scan-id header, regenerates any anti-CSRF token, and follows redirects through a scope check.

open as a page

In ZAP, what does the passive engine's scanOnlyInScope setting gate, and where is that check made?

level: middleimportance: should knowfreq 42%

basics

~20 s

ZAP's PassiveScanController checks scanOnlyInScope per history record before queueing. With it on, a record the session calls out of scope is never queued, so no passive rule sees it and the cursor moves past it permanently.

open as a page

In an OWASP ZAP scan policy, how do you turn a single active scan rule off?

level: middleimportance: should knowfreq 55%

basics

~20 s

Set that rule's AlertThreshold to OFF. There is no equivalent attack-strength value, so the threshold doubles as the per-rule disable switch, and OFF and the rule's enabled flag are kept in sync as one state.

open as a page

In ZAP's active-scan engine, what actually runs in parallel: the rules, the hosts, or the nodes?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Hosts and nodes, not rules. Scanner runs several host processes at once, bounded by scanner.hostPerScan; inside one host process, scanner.threadPerHost worker threads run one rule's node scans together, and the next rule waits for them.

open as a page

A ZAP automation plan finishes cleanly with no passive findings after a good crawl — what do you check?

level: seniorimportance: should knowfreq 55%

basics

~20 s

Check whether the plan waited. ZAP runs a plan's jobs in the order written, so a report above passiveScan-wait — or a plan with no wait job — reads the alert store while the passive queue is still draining.

open as a page

A ZAP active scan rule floods your pipeline with alerts — why won't lowering its attack strength help?

level: seniorimportance: should knowfreq 50%

basics

~20 s

Attack strength is spent before the requests go out and does not move the reporting bar. Lowering it makes the rule try fewer payloads, so you keep the cheap false positives and lose real findings. Noise is a threshold question.

open as a page

Why can installing a ZAP add-on add an input vector that no plan setting switches off?

level: seniorimportance: should knowfreq 40%

basics

~20 s

An add-on registers a Variant class through its extension hook, and VariantFactory appends every registered Variant at the end of createVariants, after all the bitmask checks. Nothing in the inputVectors block or the policy gates that path.

open as a page

Why does a ZAP plan's activeScan-config job undo input vectors you set with -config at startup?

level: seniorimportance: should knowfreq 36%

basics

~20 s

That job does not patch the current setting. It rebuilds the injectable bitmask from TARGET_INJECTABLE_DEFAULT, sets bits only for the blocks the YAML names, and writes the whole mask back, discarding whatever a startup config key had put there.

open as a page

Which input vectors should an unattended ZAP scan enable in CI, and what do you accept it misses?

level: principalimportance: should knowfreq 38%

basics

~20 s

Treat it as a scoped decision, not a dial. Keep the shipped set for pipeline runs; enable cookies and headers only where the target owner agreed and the session survives it; record the enabled set beside every verdict.

open as a page

What does ZAP's scanner.excludeAntiCsrfTokens setting exclude from an active scan, and what does it miss?

level: middleimportance: nice to knowfreq 26%

basics

~20 s

It is on by default and skips a parameter when that parameter is post data and core's anti-CSRF extension recognises its name as a token. A token in the query string or a JSON body is still attacked.

open as a page

In ZAP, what can quietly reduce what a completed passive sweep reports, without raising any error?

level: seniorimportance: nice to knowfreq 30%

basics

~20 s

Limits inside ZAP's passive engine cut findings without failing anything: a per-rule alert cap that disables the rule outright once exceeded, a maximum body size that skips oversized bodies, and a rule exception that is caught and logged.

open as a page

In ZAP's `activeScan-policy` job, what does the `alertTags` block select, and what can it never reach?

level: seniorimportance: nice to knowfreq 30%

basics

~20 s

It adds rules whose declared alert-tag keys match its include regexes, matched as a full match. It never reaches a rule that declares no alert tags, and its exclude list only narrows the include pass rather than removing any rule.

open as a page