For the complete documentation index, see llms.txt. This page is also available as Markdown.

Incremental DAST Scanning

Incremental DAST Scanning

A full DAST scan crawls and attacks the entire application on every run. On a typical pull request, though, only a few endpoints have actually changed. Incremental scanning re-tests only those changed endpoints and merges the result with the previous scan, so the report is still a complete snapshot — while cutting scan time dramatically on pull-request pipelines.

Incremental scanning is off by default. Enable it with --incremental.

How the changed endpoints are determined

The endpoints to re-test come from one of two sources. The preferred one is Xygeni's API Security scan; where that is not available, the DAST scanner compares the endpoint surface your own inputs describe. Both are covered below.

From API Security (preferred)

The endpoints to re-test are identified by Xygeni's API Security scan. API Security compares the current code against the baseline using a semantic signature for each endpoint (its method, path, parameters, authentication requirements, response shape, and handler logic). Because the comparison is semantic, cosmetic edits — renaming, reformatting, or comment-only changes — do not mark an endpoint as changed, so you never waste time re-scanning endpoints that did not really change.

API Security writes the result to a manifest file, .xygeni.changed-endpoints.json, describing which endpoints changed, which are unchanged, and (implicitly) which were removed. It prints the manifest path at the end of the scan.

xygeni apisecurity --incremental --dir ./my-api --branch "$PR_BRANCH"

Running an incremental scan

Pass the manifest to the DAST scanner, together with the previous DAST report as the baseline:

xy-dast scan -u https://app.example.com \
  --incremental \
  --changed-endpoints-file ./.xygeni.changed-endpoints.json \
  --baseline-report previous-dast-report.json \
  -o report.json

The scanner seeds the changed endpoints directly, skips crawling, and actively tests (and vulnerability-checks) only those endpoints. It then merges the previous report so the output is a full snapshot.

Option
Description

--incremental

Enable incremental scanning.

--changed-endpoints-file <file>

The .xygeni.changed-endpoints.json manifest from API Security. Optional — the scanner finds it automatically when it is written next to the scan.

--baseline-report <file>

The previous DAST report, used to carry findings on unchanged endpoints forward. Optional — the previous scan's own report is reused when this is not given.

What the merged report contains

The incremental report matches what a full scan would have produced:

Endpoint
Result in the report

Changed

Fresh results from this run. A finding that no longer appears is treated as fixed.

Unchanged

Previous findings are carried forward, marked kept-untested.

Removed

Dropped from the report.

Occasionally an endpoint in the changed set cannot be turned into a request — a path template the scanner cannot fill, or an address outside the target. It is skipped with a warning naming it, and the rest of the changed endpoints are still scanned; the run is not abandoned.

The kept-untested marker is important: because an unchanged endpoint was not actually re-attacked in this run, its findings are preserved (never silently reported as fixed) but flagged as not re-verified this run. A periodic full scan re-confirms them.

Preparing the baseline

Incremental scanning compares against the previous scan, so the first run for a project and branch always tests everything — there is nothing to compare with yet.

You do not have to prepare for this. Every DAST scan records what a later incremental run needs, so --incremental narrows from the next run onward, even if the earlier scans were ordinary ones.

The one part the DAST scanner cannot prepare by itself is the API Security side: that baseline lives in the Xygeni scanner's own cache, and only that scanner writes it. A DAST scan therefore prints the command to establish it:

Or, if you pass --sources and the Xygeni scanner is installed alongside, the DAST scan establishes that baseline for you as part of the run — so the very first --incremental afterwards can narrow.

Keeping the baseline fresh

To prevent the baseline from drifting over many incremental runs, the scan automatically switches back to a full scan when:

  • there is no baseline yet (first run);

  • a broad change (such as a security-configuration or dependency change) affects the whole application;

  • more than a configurable share of endpoints changed in a single run — controlled by fullScanThreshold in xy-dast.yml (default 30%).

The recommended pattern is to run incremental scans on pull requests and a full scan periodically (for example nightly, or on merges to your main branch).

If neither source can produce a changed set, the scan falls back to a full scan automatically.

From your sources, at scan time

If the Xygeni scanner is installed alongside the DAST scanner, point --sources at your code and the changed endpoints are worked out as part of the scan — you do not have to run API Security yourself or pass a manifest:

This discovers endpoints only; it does not look for API security flaws and it uploads nothing, so it neither replaces nor affects your API Security results. The first run establishes the baseline and still scans everything; runs after it are narrowed.

Where the DAST scanner runs in a container, it cannot reach a Xygeni scanner installed on the host. It then prints the command to run and continues with a full scan.

Note that API Security is a separately licensed feature. If your licence does not include it, or the analysis cannot complete for any other reason, the DAST scan reports why and continues as a full scan — it never fails because of it. Use the endpoint-surface comparison below in that case; it needs no API Security licence.

From your API description (no API Security needed)

When no manifest is available, the DAST scanner compares the endpoint surface described by the inputs you already pass — an OpenAPI specification, a Postman collection, a GraphQL schema, a WSDL, a recorded navigation, or a URL list — against the surface recorded by the previous scan, and re-tests what differs:

This needs no API Security licence and no access to the source code. It does have a limit worth understanding: it compares only what those inputs declare, so a handler rewritten behind a route whose path and parameters did not change looks unchanged and is not re-tested. Where the sources and an API Security licence are available, prefer the manifest.

The first run records the surface and scans in full — there is nothing to compare against yet — so the saving begins on the second run. Each report records which source was used, as the dast.incremental.modality property.

Requirements and scope

  • An API Security scan of the repository gives the most precise changed set; it requires the API Security feature in your licence. Without it, the DAST scanner falls back to comparing the endpoint surface your inputs describe (see above), which needs no additional licence.

  • Authentication still runs on every scan; incremental scanning does not shortcut login.

Last updated