skip to content

Policies and Thresholds

The two per-rule dials people constantly swap: one sets how many requests a rule sends, the other how sure it must be before it reports. Tuning a noisy run needs both.

on this pageshow

questions

5

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

level: middleimportance: must knowfreq 70%

answer

  1. two dials, not one setting
  2. one is about sending, one about reporting
  3. only one of them has an off position
  4. the engine passes them; the rule reads them

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.

solid answer

~40 s

Both live on core's `Plugin` interface and both are set per rule by a scan policy. `AttackStrength` is the attack-side dial — `LOW`, `MEDIUM`, `HIGH`, `INSANE`, plus `DEFAULT` meaning *use the policy default* — and it governs how many payloads and requests a rule spends on each target. `AlertThreshold` is the reporting-side dial — `LOW`, `MEDIUM`, `HIGH`, plus `DEFAULT` and `OFF` — and it governs how much evidence the rule wants before it raises an alert. The asymmetry is real: `OFF` exists only on the threshold, which is why it doubles as the per-rule disable switch. Both are **advisory**: the engine hands them to the rule and enforces neither, so a rule that never reads them behaves identically at every setting.

code

java · 3 lines
java
public enum AlertThreshold { OFF, DEFAULT, LOW, MEDIUM, HIGH }

public enum AttackStrength { DEFAULT, LOW, MEDIUM, HIGH, INSANE }

go deeper

for a junior

Recall which dial is which: strength is about how hard the rule attacks, threshold is about how sure it must be before it reports. Do not swap them.

for a middle

Explain the mechanics — the value sets, what DEFAULT defers to, and that the engine only hands the dials to the rule while the rule decides what to do with them.

for a senior

Show you know the split is a design intent rather than an isolation guarantee: raising a threshold can remove whole check families and their traffic, while strength never moves the reporting bar.

for a principal

Own the consequence for standardisation: because both dials are advisory and rule-dependent, a policy name is not a reproducible scan without a pinned add-on set.

## The two dials Core's `org.parosproxy.paros.core.scanner.Plugin` interface declares two nested enums, and every active scan rule carries one value of each. A scan policy is, in essence, a way of writing those two values down — once as a default for everything, and optionally again per rule. - **`AttackStrength`** — the *attack-side* dial. It is the rule's budget: how many payload variants it tries, how many requests it spends on each parameter, and in some rules which whole families of check it bothers to run. Turning it up finds more and costs more traffic and time. - **`AlertThreshold`** — the *reporting-side* dial. It is the rule's evidence bar: how confident the rule's own logic must be before it raises anything. Turning it up reports less. ## The values, and the one that exists on only one of them | | `AttackStrength` | `AlertThreshold` | |---|---|---| | ordinary values | `LOW`, `MEDIUM`, `HIGH`, `INSANE` | `LOW`, `MEDIUM`, `HIGH` | | the inherit value | `DEFAULT` — use the policy's default | `DEFAULT` — use the policy's default | | an off position | **none** | **`OFF`** | | applies to passive rules | no | yes — `PluginPassiveScanner` carries a threshold and no strength | `DEFAULT` is not a level. It means *defer to whatever the policy set as the default*, and `getAttackStrength()` / `getAlertThreshold()` resolve it before the rule ever sees it; the `incDefault` overloads exist for the UI, which does need to show the difference. `ScanPolicy` refuses `DEFAULT` as a policy-wide default outright, and its own exception text spells out the legal sets: the threshold must be *one of OFF, LOW, MEDIUM, or HIGH*, the strength *one of LOW, MEDIUM, HIGH, or INSANE*. The missing off position on the strength side is not an oversight. There is no such thing as a rule that runs but sends nothing; a rule you do not want is a rule you turn off, and the threshold's `OFF` is where that is expressed. The other asymmetry is the active/passive boundary. A passive rule never sends a request, so a strength would be meaningless for it — and indeed `PluginPassiveScanner` imports and stores only an `AlertThreshold`. One dial crosses the boundary; the other cannot. ## Both dials are advisory This is the part people are surprised by. The active scan engine does **not** enforce either value. `HostProcess` pushes the policy's defaults onto each rule instance and then runs it; nothing in the engine counts a rule's requests against its strength, and nothing filters a raised alert against its threshold. The rule itself reads its own dials, or it does not. Many rules do read them, and read them carefully — branching on `getAttackStrength()` to choose how large a payload list to walk, and on `getAlertThreshold()` to decide which checks are reliable enough to run. Rules that never call either method behave identically whatever you write in the policy. That is why the practical answer to "what does Insane strength do" is always *it depends which rules you have enabled*. ## The clean split is the intent, not a guarantee The textbook line — strength decides how many requests, threshold decides how sure — is the right mental model and it is how the enums are meant. It is not an isolation guarantee in the other direction. Because the threshold is simply an input to a rule's own logic, a rule is free to implement "be more sure" by *not running its noisiest checks at all*, and shipped rules do exactly that: raising a rule's threshold to `HIGH` can switch off whole check families and the requests they would have sent. So: 1. Raising the **strength** does not raise the reporting bar: it is not consulted when a rule decides whether it has seen enough. The rule tries more; it demands no more evidence. 2. Raising the **threshold** always raises the reporting bar, and frequently reduces traffic as a side effect — rule by rule, not as a contract you can plan capacity on. ## Where the values come from In a `.policy` file the policy-wide pair is `<scanner><level>` (threshold) and `<scanner><strength>`, with per-rule overrides under `<plugins>`. In an automation plan's `activeScan-policy` job they are `defaultThreshold` and `defaultStrength`, with per-rule `threshold` and `strength` entries under `rules`. The vocabulary differs between the two surfaces — the file says `level`, the plan says `threshold` — but they set the same enum on the same object.

  • What does the `DEFAULT` member of each enum actually mean?
    Not a level — a deferral. It means *use whatever the policy set as the default*, and the plain `getAttackStrength()` / `getAlertThreshold()` accessors resolve it away before the rule sees it. `ScanPolicy` rejects `DEFAULT` as a policy-wide default, since there would be nothing left to defer to.
  • If two teams both run a policy at Insane strength, why can their scans still differ wildly?
    Because strength is advisory. Only rules that read `getAttackStrength()` change behaviour, and which rules are installed depends on the add-on set on that machine. The same policy on two different builds is not the same scan.
  • Does a passive rule have an attack strength?
    No. A passive rule never sends a request, so there is nothing for a strength to budget. `PluginPassiveScanner` carries an `AlertThreshold` only — the reporting dial crosses the active/passive boundary and the attack dial does not.

A metal detector has two knobs: how many sweeps you make over the ground, and how strong a signal must be before it beeps. Fewer sweeps does not mean fewer beeps - it means you walk over things you never hear.

saying these in an interview costs you the question

  • Treats strength and threshold as two names for one setting
  • Says setting strength to Off disables a rule
  • Believes the engine caps a rule's requests at its strength
  • Thinks DEFAULT is a level between Low and Medium
  • Assumes raising the threshold cannot change how many requests are sent
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 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

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

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