# OWASP ZAP and DAST Modernization Patterns

> **Intro:** Modern DAST is less about pointing a scanner at a URL and more about choosing the right scan mode, keeping scope tight, making authentication deterministic, and turning reports into repeatable evidence. ZAP remains one of the strongest flexible DAST workbenches for teams that need both desktop tuning and CI-friendly packaged scans.
>
> **What this page includes**
>
> * how to choose between baseline, API, full, and automation-framework flows
> * what older ZAP habits should be retired
> * practical GitLab CI examples for baseline and API-first DAST
> * how to keep DAST useful instead of ceremonial

## The modern starting point

In 2026, a practical ZAP strategy usually looks like this:

1. **Baseline scan** for low-friction passive checks and early signal.
2. **API scan** for OpenAPI, SOAP, or GraphQL-defined targets.
3. **Automation Framework** when auth, context, or orchestration logic becomes non-trivial.
4. **Full active scan** only where the environment can tolerate it and the scope is deliberate.

This is a better model than the old habit of treating a single heavy scan profile as the default answer for every application.

## Legacy vs current DAST habits

| Older habit                                           | Why it breaks down                                            | Better current pattern                                                         |
| ----------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| run one big full scan everywhere                      | slow, noisy, brittle, bad for unstable environments           | separate baseline, API, and deeper active scans by purpose                     |
| treat anonymous crawling as “good enough”             | misses the real application surface behind auth               | use context-aware authenticated scanning                                       |
| define the quality gate as “zero findings”            | creates scanner theatre and brittle pipelines                 | use config files, progress files, and rule-level fail criteria                 |
| scan browser-heavy apps only through generic crawling | misses intended flows and API specifics                       | combine API definitions, context scoping, and selective browser-heavy coverage |
| assume scan success equals coverage success           | many successful scans cover only login pages or public shells | validate auth state, in-scope URLs, and discovered endpoints explicitly        |

## Choosing the right scan mode

### Baseline scan

Use the baseline scan when you want:

* passive checks only;
* short CI runtime;
* low risk to the target;
* early signal on headers, cookies, cache behavior, and similar issues.

**Good use cases**

* merge request smoke scanning;
* recurring scheduled scans of non-destructive paths;
* public web entry points.

### API scan

Use API scan when the target is defined by:

* OpenAPI,
* SOAP,
* GraphQL.

This is usually the most efficient DAST mode for modern APIs because it uses the API definition directly instead of pretending the scanner must rediscover everything via HTML routes.

**Good use cases**

* API-first products;
* internal services with a stable OpenAPI spec;
* GitLab pipelines where the definition can be produced or fetched reliably.

### Full scan

Use a full active scan when:

* the environment is intended for deep testing;
* the team has accepted longer runtime and more scan aggressiveness;
* auth and context are already known to be stable.

Do **not** make this the default for every commit pipeline.

### Automation Framework

Use the Automation Framework when:

* you need reusable context and auth orchestration;
* the app uses more than one auth mode or role;
* you need cleaner reproducibility than ad hoc command flags can provide.

## The biggest practical reasons ZAP under-delivers

### 1) In-scope definition is weak

The scan wanders into logout paths, third-party callbacks, or unrelated hosts.

### 2) Authentication is not deterministic

The scanner starts logged in, becomes anonymous mid-run, and the team never notices.

### 3) The wrong scan type is selected

A UI-heavy full scan gets used on a pure API, or a baseline scan is expected to act like a penetration test.

### 4) Rules are not tuned

One noisy rule floods the report and the real findings get normalized away.

### 5) The environment is wrong

A scan meant for staging gets fired at a production-like path without proper rate-limiting expectations or legal clarity.

## A practical GitLab baseline scan job

```yaml
zap_baseline:
  stage: security
  image: ghcr.io/zaproxy/zaproxy:stable
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
  script:
    - mkdir -p reports/zap
    - |
      zap-baseline.py \
        -t "$DAST_TARGET_URL" \
        -c .zap/zap-baseline.conf \
        -J reports/zap/baseline.json \
        -r reports/zap/baseline.html \
        -w reports/zap/baseline.md
  artifacts:
    when: always
    paths:
      - reports/zap/
    expire_in: 14 days
```

### Why this is a good default

* stable packaged scan;
* explicit config file;
* artifacts retained for review;
* low-friction enough for MR pipelines.

## A practical GitLab API scan job

```yaml
zap_api_scan:
  stage: security
  image: ghcr.io/zaproxy/zaproxy:stable
  needs: [deploy_review]
  rules:
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_PIPELINE_SOURCE == "schedule"'
  script:
    - mkdir -p reports/zap
    - |
      zap-api-scan.py \
        -t "$OPENAPI_URL" \
        -f openapi \
        -c .zap/zap-api.conf \
        -J reports/zap/api.json \
        -r reports/zap/api.html
  artifacts:
    when: always
    paths:
      - reports/zap/
    expire_in: 14 days
```

### Why this works well

* it treats the API definition as a first-class test input;
* it keeps the DAST job tied to a known deployed review target;
* it is more reliable for API-first systems than generic crawling.

## A minimal Automation Framework file pattern

```yaml
env:
  contexts:
    - name: app
      urls:
        - ${TARGET_URL}
      includePaths:
        - ${TARGET_URL}.*
      authentication:
        method: manual
      sessionManagement:
        method: headers
      users:
        - name: ci-user
          credentials:
            headers:
              Authorization: Bearer ${AUTH_TOKEN}

jobs:
  - type: openapi
    parameters:
      apiFile: ${OPENAPI_FILE}
      context: app
      targetUrl: ${TARGET_URL}

  - type: passiveScan-wait

  - type: report
    parameters:
      template: traditional-html
      reportFile: zap-report.html
```

### Why this pattern matters

It makes three things explicit:

* scope,
* auth state,
* reporting.

That alone eliminates a large portion of “successful but useless” DAST runs.

## Baseline config and progress files

### Config file

Use config files to control which rules are:

* `FAIL`
* `WARN`
* `IGNORE`

This is the difference between a usable release gate and scanner chaos.

### Progress file

Use a progress file when a finding is:

* already known,
* tracked,
* in remediation,
* intentionally not release-blocking yet.

That keeps CI honest without pretending mature teams instantly remediate every class of issue.

## Controller-driven ZAP automation safety notes

If ZAP is triggered from Jenkins, AWX, or another automation controller:

* do not disable the ZAP API key unless the environment is tightly isolated for a temporary lab;
* do not expose the ZAP API to broad networks with allow-all patterns;
* prefer reviewed job definitions, parameterized targets, and retained artifacts;
* keep authentication tokens in secret stores or controller credentials, not in shell history or copied URLs.

## How to keep DAST reports useful

### Good gate style

* fail on a small set of high-confidence conditions;
* warn on broader hygiene findings;
* keep a progress file for actively tracked issues;
* store artifacts for trend review and evidence.

### Bad gate style

* fail on every alert;
* compare alert counts without considering scope;
* ignore whether auth or coverage succeeded;
* treat HTML output alone as evidence.

## What to measure besides findings

A useful DAST program also tracks:

* number of authenticated endpoints reached;
* number of in-scope URLs discovered;
* percentage of scans that completed with valid auth;
* mean time to tune noisy rules;
* number of tracked accepted or in-progress findings in progress files.

These operational metrics often matter more than raw alert counts.

## Recommended ZAP snippet pack for this KB

* `.zap/zap-baseline.conf`
* `.zap/zap-api.conf`
* `.zap/authenticated-api.yaml`
* `.gitlab/ci/zap-baseline.yml`
* `.gitlab/ci/zap-api.yml`

## Cross-links

* [OWASP ZAP in the Real World: Tuning, Reports, and Quality Gates](/devsecops-cicd-and-supply-chain/index-1/owasp-zap-practical-tuning-and-report-analysis.md)
* [OWASP ZAP Authenticated Scanning and Session Management](/devsecops-cicd-and-supply-chain/index-1/owasp-zap-authenticated-scanning-and-session-management.md)
* [API Testing, Observability, and Release Gates](/architecture-api-crypto-and-identity/index/api-testing-observability-and-release-gates.md)
* [Web Application Security Testing and Gate Patterns](/application-security-and-secure-sdlc/index-1/webapp-security-testing-and-gate-patterns.md)

***

*Author attribution: Ivan Piskunov, 2026 - Educational and defensive-engineering use.*

## 2026 update: what to carry forward from older ZAP material

Older ZAP books and articles are still helpful for learning:

* contexts and in-scope discipline;
* passive versus active scan separation;
* AJAX spider usage;
* report generation;
* Jenkins and API usage as practical starting points.

But treat the following as legacy context, not default modern practice:

* Java 8-era installation assumptions;
* older Docker image naming as the main automation reference;
* GUI-first scanning as the final operating model;
* generic crawl-first API coverage when an OpenAPI definition exists.

For the current Product Security model, use this page together with:

* [OWASP ZAP for APIs, Automation Framework, and OAST — Modern Practice](/devsecops-cicd-and-supply-chain/index-1/owasp-zap-api-automation-oast-modern-practice.md)
* [OWASP ZAP Authenticated Scanning and Session Management](/devsecops-cicd-and-supply-chain/index-1/owasp-zap-authenticated-scanning-and-session-management.md)
* [OWASP ZAP in the Real World: Tuning, Reports, and Quality Gates](/devsecops-cicd-and-supply-chain/index-1/owasp-zap-practical-tuning-and-report-analysis.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.product-security.expert/devsecops-cicd-and-supply-chain/index-1/owasp-zap-dast-modernization-patterns.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
