skip to content

Core and Add-Ons

Which capabilities are really in the program and which arrive as separately versioned add-ons, including the subsystems that left core and left a deprecated stub behind them.

on this pageshow

questions

6

In OWASP ZAP, which capabilities live in the core program and which arrive as add-ons?

level: juniorimportance: must knowfreq 62%

answer

  1. one program, many separate packages
  2. core is a single version line
  3. add-ons are archives in `plugin/`
  4. a move-out may leave a deprecated shim
  5. the passive engine left, the active stayed

basics

~20 s

Core is one versioned program: the command line, the control API, the active-scan engine, and the alert and context models. Almost everything else — the local proxy, the passive-scan engine, the crawlers, automation, reports — ships as separately versioned add-ons.

solid answer

~40 s

ZAP is a small core program plus a directory of `.zap` add-on archives, each with its own version and its own release line. Core owns the command line, the control API, the session database, the **active-scan engine** in `org.parosproxy.paros.core.scanner`, and the `Alert` and `Context` models. The local HTTP proxy and root certificate authority are the `network` add-on; the passive-scan **engine** is the `pscan` add-on, although the passive **rule contract** (`PassiveScanner`, `PluginPassiveScanner`) stayed in core and is live; the crawlers, automation, reports and alert filters are add-ons too. Each add-on registers itself through `ExtensionHook`, so its command-line arguments and API components are indistinguishable from core's at the surface. The trap: when a subsystem moves out, core often keeps a `@Deprecated` shim, so the class still resolves even though the capability is elsewhere.

go deeper

for a junior

Be able to say that ZAP is a small program plus separately versioned add-on archives, and to name two capabilities that are add-ons rather than core — the local proxy and the passive-scan engine are the usual pair.

for a middle

Explain the registration path: an add-on hooks into core and contributes flags, API components and job names that look native. Then explain the asymmetry — the passive engine moved out, the active engine stayed, and the passive rule contract stayed with it.

for a senior

Show that you check ownership rather than assume it. A moved-out class still resolving in core is a deprecated shim, and treating the hit as evidence is how mis-attributed claims get into a report someone else has to defend.

for a principal

Own the vocabulary your organisation uses. If findings are attributed to "ZAP" rather than to a named add-on and rule package, nobody can reproduce a result or reason about what an upgrade changed.

## The shape of the product ZAP is not one monolithic application. It is a **core program** on a single version line plus a directory of **add-ons** — `.zap` archives read out of the install's `plugin/` folder at startup, each with its own independent version number and its own release cadence. Saying *"ZAP does X"* is therefore ambiguous in a way that matters operationally: two installs that report the same program version can differ in what they can do, because they carry different add-on sets. An add-on plugs into core through one surface, `ExtensionHook`. Through it an add-on registers extensions, command-line arguments (`addCommandLine`), control-API components, HTTP-sender listeners, input-vector `Variant`s and automation job names. Because the registration is uniform, an add-on's contributions are **indistinguishable from core's** once ZAP is running: an add-on's flag looks like a core flag, an add-on's API component looks like a core component. That uniformity is the whole reason this distinction has to be learned rather than observed. ## What is genuinely core | capability | where it lives | |---|---| | the command line, the control API, the session database | core | | the **active-scan engine** (`paros.core.scanner`) | core — only the active **rules** are add-ons | | the passive-scan **rule contract** (`PassiveScanner`, `PluginPassiveScanner`) | core, and not deprecated | | the passive-scan **engine** that schedules and runs those rules | the `pscan` add-on | | the local HTTP proxy listener and the root certificate authority | the `network` add-on | | the crawlers | the `spider`, `spiderAjax` and `client` add-ons | | automation plans, rendered reports, alert filters | three separate add-ons | The asymmetry in the middle rows is the single most useful thing on this subject. **The passive engine left core; the active engine did not.** And the passive row itself split: a passive rule is written against a **core** base class, and it is **an add-on** that drains the history table and runs it. Whenever you describe passive scanning, say which half you mean. ## Three shapes the boundary takes Two of these are ways a subsystem leaves core; the third is a packaging shape that never involved a move at all. 1. **A move-out that leaves a deprecated shim.** The old package survives in core with type-level `@Deprecated` markers so that add-ons compiled against it still link. This is the case for the proxy, the certificate authority and the passive engine. 2. **A move-out that leaves nothing.** The traditional spider moved into the `spider` add-on and its old core package simply does not exist any more. A move-out does not have to leave a footprint, so the absence of a shim is not evidence that a capability is core. 3. **An add-on that was never core code at all.** Some add-ons ship **no classes at all** — their manifest lists files that are unpacked into ZAP's home directory on install, for a core subsystem to read. The standard scan policies are packaged this way: the policy *machinery* is core and reads a directory, and the shipped policy *files* arrive as an add-on that drops them there. Nothing about the add-on boundary implies code, and nothing about an add-on's data implies that the subsystem reading it moved. ## Why the shim is a trap A grep or an IDE lookup will happily resolve a moved-out class in the core source tree. That hit proves a shim is present; it does not prove the capability runs from there. The honest checks are different: - read whether the type carries a type-level `@Deprecated` marker; - ask which package the *live* implementation sits in; - from a running install, list what is actually loaded rather than reasoning from the source tree. ## Why a pipeline reader should care - A capability you rely on may be **absent from this build** even though it is present in the project, because its add-on was never installed. - A capability may be present and still **not running**, because its add-on failed a requirement at load time. - Upgrading the program does not upgrade the add-ons, and upgrading an add-on does not upgrade the program. They are separate decisions with separate blast radii. - Describing a finding as *"ZAP reported it"* loses the information a reviewer needs. *"An `ascanrules` active rule reported it"* or *"a `pscan`-scheduled passive rule reported it"* is reproducible. ## How to say it correctly Name the owner every time: *"core's active-scan engine"*, *"the `pscan` add-on"*, *"the `network` add-on's local proxy"*. Never *"ZAP lets you…"*. Every identifier in a mis-attributed sentence can be real while the sentence is false, and no tooling catches that — only the habit of naming the owner does.

  • If the passive-scan engine is an add-on, where does a passive rule's base class live?
    In core. `PassiveScanner` and `PluginPassiveScanner` are declared in core's `org.zaproxy.zap.extension.pscan` package and carry no type-level `@Deprecated` marker; every passive rule shipped in the add-on repository extends them. The **engine** that drains recorded traffic and runs those rules is the `pscan` add-on. So the contract is core and the scheduler is an add-on — name the half you mean.
  • Can an add-on ship no Java code at all?
    Yes. An add-on's manifest can list plain files that are unpacked into ZAP's home directory when it installs, with no classes to load. The standard scan policies arrive that way: core owns the policy machinery and reads the policy directory, and the add-on's only contribution is the files it drops there. Nothing about the add-on boundary implies code.
  • Why does grepping core for a moved-out class find it anyway?
    Because the project usually leaves a `@Deprecated` shim in core so that add-ons compiled against the old package still link. The class is genuinely there; the capability is not. Distinguish the shim from the implementation by checking for a type-level deprecation marker and by locating the live class, rather than treating any hit as proof.

saying these in an interview costs you the question

  • Says the local HTTP proxy and root certificate authority are core code.
  • Treats a class resolving in the core tree as proof the capability runs there.
  • Calls add-ons optional extras rather than where most capability lives.
  • Assumes every moved-out subsystem left a deprecated stub behind it.
  • Thinks one program version describes what the whole install can do.
open as a page

How is the set of add-ons in a ZAP distribution or container image actually decided?

level: middleimportance: must knowfreq 55%

basics

~20 s

A list in ZAP's core repository names every add-on folded into a main release, pinning each by download URL and SHA-256 hash; entries flagged core are the smaller core distribution. Container images then freeze that set at image-build time.

open as a page

What does an OWASP ZAP add-on's alpha, beta or release status actually tell you?

level: middleimportance: should knowfreq 45%

basics

~20 s

An add-on's status is a statement about how settled its public interface is, not about how important, mature or well-tested it is. ZAP's mandatory networking add-on ships at beta and the live passive-scan engine ships at alpha.

open as a page

A ZAP add-on archive sits in the plugin directory but its capability is missing. Why?

level: seniorimportance: should knowfreq 42%

basics

~20 s

Installed is not running. ZAP drops an add-on before loading if the block list or its declared program-version range rejects it, and skips it afterwards if its run requirements fail — a dependency issue, a newer minimum Java version, or missing bundled libraries.

open as a page

Should a scanning pipeline pin its ZAP add-on set or refresh it, and how would you decide?

level: principalimportance: should knowfreq 30%

basics

~20 s

ZAP's detection logic is not in the program — the rule packages and job types are separately versioned add-ons. Pinning the set makes two runs comparable and lets coverage age; refreshing buys coverage and makes a new finding ambiguous between tool change and code change.

open as a page

Which OWASP ZAP add-ons will the program refuse to start without, and how is that enforced?

level: middleimportance: nice to knowfreq 28%

basics

~20 s

ZAP hard-codes two mandatory add-ons, callhome and network, in core's ControlOverrides. If either is missing the add-on collection throws at startup, and once marked mandatory neither can be uninstalled, blocked, or have its extensions disabled.

open as a page