skip to content

How do you get two differently filtered reports out of one ZAP automation plan run?

level: seniorimportance: should knowfreq 38%

answer

  1. the jobs list may repeat a type
  2. jobs run in the order written
  3. each job re-reads the alert tree
  4. give every report job its own reportFile

basics

~20 s

Put two report jobs in the same plan. Each filters its own copy of the alert tree and renders its own template, so one run yields two documents. Give each a distinct reportFile or the second overwrites the first.

solid answer

~40 s

A plan's `jobs` list may contain the `report` job more than once, and the jobs run in the order they are written. Each `report` job re-reads the session's alert tree, applies its own `risks`, `confidences`, `sections` and `sites`, and renders its own `template` - so the jobs are independent and neither consumes anything the other needs. The trap is the output path: the file name comes from `reportFile` (or its default pattern) with the template's extension appended, so two HTML templates left on the default resolve to one path and the second render overwrites the first. Set `reportFile` explicitly on every report job. The packaged scan scripts do exactly this when asked for several formats.

code

yaml · 11 lines
yaml
jobs:
  - type: report
    parameters:
      template: traditional-html-plus
      reportFile: engineers-example-com
  - type: report
    parameters:
      template: risk-confidence-html
      reportFile: audit-example-com
    risks: [high, medium]
    confidences: [high, confirmed]

go deeper

for a junior

Know that the report job can appear more than once in a plan, and that each occurrence needs its own reportFile so the outputs do not land on the same path.

for a middle

Explain why the jobs are independent - each builds its own filtered copy of the alert tree and leaves the session's alerts alone - and where the default file name comes from.

for a senior

Design the pair deliberately: which filters each audience gets, how the cut-offs are recorded so absence is not misread, and how the artefacts are archived including any resources folder.

for a principal

Decide who is entitled to the unfiltered document and who is not, and make that a property of the pipeline rather than of whoever wrote the plan that week.

## One run, two readers The question behind this is not really *can* ZAP emit two reports - it is what the second one is allowed to be. Because filtering happens at render time over a copy of the alert tree, two reports from one plan can differ in everything visible and in nothing factual. The engineer's document can carry request and response bodies and every confidence band; the auditor's can carry high and medium risk at confirmed confidence and a short set of sections. Neither document can contain a finding the run did not make, because there was only one run. ## The mechanism 1. **Add the job twice.** A plan's `jobs` list is an ordered sequence and nothing forbids repeating a type. The jobs execute **in the order written in the file** - a job's declared ordering category only tells the desktop plan editor where to slot a newly added job, it does not re-sort a plan you wrote yourself. 2. **Each job filters independently.** When a `report` job runs it walks the session's alert tree and builds its own filtered copy: instances survive the contexts, the `sites` list, the `confidences` list and the `risks` list, and a parent alert is carried over only if at least one of its instances was. The copy is discarded when the job finishes. The session's alerts are never modified, so the second job sees exactly what the first one saw. 3. **Each job picks its own template.** Different `template`, different `theme`, different `sections` - and therefore a different document shape, not just a different subset. ## The collision you have to design around | what is shared | what happens by default | |---|---| | the alert tree | read fresh by each job; no interference | | the output path | **derived the same way for both jobs** | | the resources folder | a new sibling directory per render, numbered if one exists | The output name comes from `reportFile`, or from a default pattern built from the date and the site when `reportFile` is empty, and then the template's declared extension is appended if the name does not already end in it. Two jobs using templates with the **same extension** and the default pattern therefore resolve to the **same path**, and the second render overwrites the first. Two jobs whose templates have different extensions - an HTML one and a JSON one, say - accidentally avoid the clash, which is exactly the sort of near-miss that makes the bug hard to believe when it finally bites. The fix is one line per job: give each `report` job an explicit `reportFile`. This is precisely what the packaged scan scripts do when they are asked for several output formats - they append one `report` job per format, each with its own file name. The resources folder behaves differently again. A template that carries one copies it to a sibling directory beside the output at render time, appending a number if such a directory already exists. So two renders of resource-carrying templates leave two folders, and if the report files collided you are left with a surviving document pointing at the second folder and an orphaned first one. ## What the pair is and is not evidence of - **The two documents are built from the same alert tree.** They disagree about what was shown, not about what was found, so any difference between them is a filter you wrote - unless a job that adds alerts sits between them, which is the one arrangement that breaks the guarantee. - **A narrow report is not a claim that nothing else was found.** It is a claim about the cut-offs, and those have to travel with the document if a reader will draw conclusions from absence. The default template already does this: its `reportParameters` section prints the contexts, sites and the risk and confidence levels it included and excluded. That section can itself be filtered out, which is the one edit to be suspicious of. - **Neither document tells you the scan reached anything.** Report jobs render whatever the session holds, including nothing. A report with no alerts and a run that never reached the target look the same on the page. - **Adding a second report costs a render, not a scan.** The expensive work happened once; a second job is cheap, which is why the pattern scales to three or four outputs when several consumers want different formats. ## Reviewing a plan that does this Read the jobs bottom-up and check three things: that each `report` job has its own `reportFile`; that the narrower job's filters are the ones you meant, since an unrecognised entry silently narrows further; and that any section list matches the template that job actually names, because the two jobs are usually copied from each other and a section belonging to the other template is dropped with only a warning.

  • Both report jobs left reportFile empty and only one file exists afterwards. What happened?
    The default file name is built from the date and the site, and the template's extension is then appended. Two templates sharing an extension therefore produce the same path, and the second render overwrote the first. Setting `reportFile` on each job fixes it; the packaged scan scripts do this for every format they emit.
  • Does the order of the two report jobs in the plan change what they contain?
    Not on its own. Each job reads the alert tree fresh and filters a copy, so neither consumes anything. Order matters only against the rest of the plan - a report job placed before the scanning jobs renders whatever had been found by that point, which is usually nothing.
  • How does a reader of the narrower report know what was filtered out of it?
    Partly by itself. The template is handed the filter settings as well as the filtered alerts, and the default template's `reportParameters` section prints the contexts, the sites and the risk and confidence levels included and excluded. What it cannot show is the alerts themselves, since it never received them - and dropping that section from the `sections` list removes the disclosure too.

saying these in an interview costs you the question

  • Thinks a plan may contain each job type only once
  • Expects the two jobs to write different files automatically
  • Believes the first report job consumes the alerts it renders
  • Runs the scan twice to produce two differently filtered reports
  • Reads a narrow report as evidence that nothing else was found