skip to content

What must a directory contain before ZAP's reports add-on will load it as a report template?

level: middleimportance: should knowfreq 42%

answer

  1. a folder, not a single file
  2. template.yaml plus the report body
  3. four keys are not optional
  4. pdf is written as html first

basics

~10 s

A readable template.yaml declaring name, format, mode and extension, plus the Thymeleaf file report.<extension> beside it - report.html when the extension is pdf. A Messages.properties file and a resources folder are optional.

solid answer

~40 s

Two files are mandatory. `template.yaml` must declare four keys - `name`, `format`, `mode` and `extension` - and a missing one aborts the load with `Template missing key`. Beside it must sit a readable Thymeleaf file called `report.` plus the declared extension; the single exception is `pdf`, where the file is `report.html`, because a PDF template is written as HTML and converted afterwards. Everything else is optional: `sections` and `themes` lists inside the YAML, a `Messages.properties` bundle supplying the labels for those names, and a `resources` folder of CSS, scripts and images. A directory missing `template.yaml` is not an error - it is just skipped.

code

yaml · 10 lines
yaml
# <zap home>/reports/nightly-console/template.yaml
name: Nightly Console Report   # display title only
format: HTML                   # ZAP's label for the output
mode: HTML                     # the Thymeleaf template mode
extension: html                # so the body beside this is report.html
sections:
  - alertcount
  - alertdetails
themes:
  - light

go deeper

for a junior

Know the shape: a folder holding template.yaml and a report file whose extension matches what the YAML declares. Messages.properties and resources are extras.

for a middle

Explain the four required keys and the pdf special case, and be able to say why format and mode are separate settings rather than one.

for a senior

Bring up the render-time consequence: a template with a resources folder emits a sibling directory, so an archiving step that copies only the report file ships a broken document.

for a principal

Decide how far your team should go: a copied directory you maintain is a real artefact with message keys and a markup contract, and that upkeep has to sit with someone.

## The loader's contract The `reports` add-on builds its template list by walking the immediate subdirectories of the templates folder. For each subdirectory it looks for `template.yaml`; if that file is absent or unreadable, the directory is skipped without complaint. If it *is* there, the add-on parses it and then enforces two hard requirements. Fail either and the template is rejected - and because rejection happens at load, the symptom you see later is an unknown-template error in a plan, not a parse message. ## Requirement one: four keys in template.yaml | key | what it is | values seen in the shipped set | |---|---|---| | `name` | the display title shown in the desktop dialog | `Traditional HTML Report`, `SARIF JSON Report` | | `format` | ZAP's own label for the output kind | `HTML`, `JSON`, `XML`, `Markdown`, `PDF` | | `mode` | the **Thymeleaf template mode** used to parse the file | `HTML`, `XML`, `TEXT` | | `extension` | the extension appended to the generated report | `html`, `json`, `xml`, `md`, `pdf` | All four are mandatory: a missing one throws with the message `Template missing key:` and the key's name. `format` and `mode` are easy to conflate and are genuinely independent - `format` is ZAP's label, while `mode` tells the templating engine how to parse the markup. The shipped JSON and Markdown templates prove the split: both declare a `format` of `JSON` or `Markdown` while declaring `mode: TEXT`, because neither is markup the engine should try to understand. The XML templates, by contrast, declare `XML` for both. ZAP's own help describes `format` as used internally and not otherwise exposed, which is nearly fair: it decides the PDF conversion path and, on a desktop run, whether a generated report is opened in a browser or handed to the operating system. ## Requirement two: the report file, and the PDF exception The template body must be a readable file named `report.` followed by the declared extension - `report.html`, `report.json`, `report.xml`, `report.md`. If it is missing or unreadable the load fails with `Cannot read` and the path. The **exception is `pdf`**. A template declaring `extension: pdf` must supply `report.html`, because PDF output is produced by rendering the HTML template first and then converting the result; the interim HTML file is deleted afterwards. This is the one place the template model does not simply mirror the extension, and it is the first thing to check when a new PDF template refuses to load. ## The optional halves - **`sections`** - a list of names the template's own markup tests before emitting a block. The list is what a plan is allowed to choose from. - **`themes`** - a list of names the template resolves into a stylesheet path. A theme changes presentation only. - **`Messages.properties`** - the template's own resource bundle. Section and theme names must have entries here; the keys are automatically prefixed with `report.template.section.` and `report.template.theme.`. The template's bundle is consulted first and the add-on's own bundle is the fallback, so a template may also override built-in strings. Locale-specific variants sit beside it. - **`resources`** - CSS, JavaScript, fonts and images. This one has a consequence at render time rather than load time, and it surprises people. Both lists are validated leniently: an entry must be **alphanumeric and must not start with a digit**, and an entry that fails is logged and dropped while the template still loads. So a section named `alert-details` does not stop the template loading - the entry is logged, dropped, and simply never exists, and a plan naming it later gets a warning about an unknown section. ## Why the report is a file *plus a folder* If the template directory has a `resources` folder, then every time the report is generated the add-on copies that whole folder to a **sibling directory beside the output file**, named after the report file with its extension stripped. If such a directory already exists it appends a number rather than overwriting. The template references those files through a `resources` variable that holds the created folder's name. The practical consequence for anyone running ZAP in a pipeline: **an HTML report from a template with resources is not self-contained.** Archive only the `.html` and you keep a document that renders unstyled and chartless. Archive the sibling folder with it, or pick a template that has no resources folder at all - the plainer traditional templates and the JSON and XML ones do not have one. ## Putting a new template together The shipped advice, and the fastest route, is to copy an existing directory to a new name at the same level, then edit in place. You inherit a working `template.yaml`, a `report.<ext>` already written against the right variables, and a `Messages.properties` whose keys already line up with the sections the markup tests. What you must not do is rename the report file away from the declared extension, or add a section name to the YAML without adding its message key.

  • A template declares a section name the Messages.properties file has no entry for. What happens?
    The name is legal as far as the loader is concerned, so the template still loads and a plan may select the section. What breaks is the label: the resolver looks for `report.template.section.` plus the name in the template's bundle, falls back to the add-on's own bundle, and finds nothing useful there for a name you invented.
  • Why do the shipped JSON and Markdown templates declare a Thymeleaf mode of TEXT?
    `mode` tells the templating engine how to parse the template body, not what the output is called. JSON and Markdown are not markup the engine should try to interpret as elements, so they are parsed as text while `format` separately records that the result is JSON or Markdown. The XML templates set both to XML because there the two coincide.
  • What is the quickest way to build a template that matches your team's house format?
    Copy a shipped directory whose output shape is closest, rename the copy, and edit its `report.<ext>` body. You inherit a `template.yaml` that already loads, message keys that already match the sections the markup tests, and a resources folder wired to the `resources` variable - all of which are easy to break when starting from an empty directory.

saying these in an interview costs you the question

  • Calls a report template a single file rather than a directory
  • Expects a pdf template's body to be named report.pdf
  • Thinks format and mode are the same setting spelled twice
  • Assumes an HTML report is always one self-contained file
  • Believes an invalid section name stops the template from loading