(UPDATED: )

An Introduction to Zest

Zest is a JSON/YAML-based scripting language developed by the Mozilla Security team. It is now maintained as part of the ZAP Core project and is used to define and execute automated test scenarios involving HTTP Requests/Responses, Headless Browsers, and Assertions.

Personally, it's my favorite language for writing automation scripts in ZAP.

What is Zest?

A Zest script has the following basic structure. It recently started supporting the YAML format, which has made writing scripts much more convenient than with JSON.

JSON Format

{
  "about": "A description of Zest",
  "zestVersion": "0.8",
  "title": "Script Name",
  "description": "Script Description",
  "prefix": "https://www.hahwul.com",
  "type": "StandAlone",
  "parameters": {
    "tokenStart": "{{",
    "tokenEnd": "}}",
    "tokens": {},
    "elementType": "ZestVariables"
  },
  "statements": [],
  "authentication": [],
  "index": 0,
  "enabled": true,
  "elementType": "ZestScript"
}

YAML Format

about: A description of Zest
zestVersion: '0.8'
title: Script Name
description: Script Description
prefix: 'https://www.hahwul.com'
type: StandAlone
parameters:
  tokenStart: '{{'
  tokenEnd: '}}'
  tokens: {}
  elementType: ZestVariables
statements: []
authentication: []
index: 0
enabled: true
elementType: ZestScript

Interfaces

There are a few ways to work with Zest.

ZAP GUI

Since Zest is ZAP's built-in scripting engine, you can intuitively write and manage scripts through the ZAP GUI.

Zest CLI

While Zest operates as a ZAP library, it also offers a standalone CLI. You can build it separately or use the zest-env Docker image I created to easily run it in various environments like GitHub Actions.

https://github.com/hahwul/zest-env

docker pull hahwul/zest-env:v1.0.0
docker run hahwul/zest-env:v1.0.0 zest -script <YOUR-ZEST-SCRIPT>

How to Write

There are three main methods for writing scripts.

ZAP Script Console

Within ZAP, you can write and test code directly via the GUI and CLI in the "Scripts" and "Script Console" tabs.

ZAP Zest Record

ZAP has a built-in Zest Record feature. Once you start recording, it captures your web requests and automatically generates a draft Zest script. This is incredibly useful for scripting complex workflows.

TextEditor & IDE

Of course, since it's JSON/YAML-based, you can write scripts directly in your favorite text editor or IDE. While JSON can be a bit cumbersome to edit manually, the addition of YAML support in September 2023 has made this process much smoother.

Structure

A Zest script is composed of several key components.

 graph TD
    A[Start] --> B(Statement 1: Request);
    B --> C{Condition: if status == 200};
    C -- True --> D[Assertion: body contains 'login_success'];
    C -- False --> E[Action: Log 'Login Failed'];
    D --> F(Statement 2: ...);
    E --> F;
    F --> G[End];

Statements

The core of Zest is the statements array. The actions included in this array are executed sequentially. Zest processes this array to handle web requests, Actions, Assertions, Conditions, and Assignments, and then returns the final result.

Condition (ifStatements)

You can implement branching logic within your script using Condition. Similar to an if statement, it allows you to control the flow by executing different statements based on specific criteria.

Assertions

Assertion is a verification feature that determines the success or failure of a test. It's the same concept as assertions in unit testing, allowing you to check if the response code, headers, or body content match your expectations.

Action

An Action performs a specific operation. For example, you can introduce a sleep delay or set a variable's value. Some actions are dependent on the ZAP scanner.

Assignment

Assignment is used to handle variables. You can perform tasks like generating a random number or calculating a specific value, and then reference that result elsewhere in the script using {{ variable_name }}.

Variables can be accessed using the {{ variable_name }} format.

Loop

Zest also supports loops through the Loop element. However, configuring complex loops often requires using Assignment as well, so for such cases, a general-purpose scripting language like Ruby or Python might be more efficient.

Tools

Articles

References