OWASP ZAP component
This component runs an OWASP Zed Attack Proxy Automation Framework plan (zap.yaml) and publishes the generated ZAP reports as GitLab artifacts.
The component runs the supplied scan plan, removes any existing ZAP report jobs, and appends standard JSON, HTML, Markdown, and PDF report jobs automatically. After the plan finishes, it converts the traditional JSON report into a GitLab JUnit test report so findings are visible in the pipeline test report.
The bundled scanner image uses ZAP's minimal upstream bare runtime, plus Python and PyYAML for plan normalization. It intentionally excludes the desktop and browser packages from the full ZAP image because the component runs Automation Framework plans in CI.
Usage
Pick the smallest plan that matches the target. Each example uses environment variables so the same plan works for review apps, staging, and local targets.
| Use case | Start with | Required variable |
|---|---|---|
| Crawl a web application | crawl.yaml | ZAP_TARGET_URL |
| Crawl an API behind OAuth | oauth-crawl.yaml | ZAP_TARGET_URL, ZAP_OAUTH_ACCESS_TOKEN |
| Import an OpenAPI definition | openapi.yaml | ZAP_TARGET_URL, ZAP_OPENAPI_URL |
| Test one REST endpoint | rest-endpoint.yaml | ZAP_TARGET_URL |
Create a ZAP Automation Framework plan in your project, for example zap.yaml:
env:
contexts:
- name: application
urls:
- https://www.example.com/
parameters:
failOnError: true
failOnWarning: false
progressToStdout: true
jobs:
- type: spider
parameters:
context: application
url: https://www.example.com/
maxDuration: 5
- type: passiveScan-wait
parameters:
maxDuration: 5
Then include the component and pass the plan path:
include:
- component: $CI_SERVER_FQDN/xrow-public/ci-tools/common@stable
- component: $CI_SERVER_FQDN/xrow-public/ci-tools/zap@stable
inputs:
name: application
plan: zap.yaml
stage: test
needs: []
The component exports ZAP_REPORT_DIR and ZAP_REPORT_BASENAME before running ZAP and appends report jobs that create the standard artifact names:
${ZAP_REPORT_BASENAME}.json${ZAP_REPORT_BASENAME}.html${ZAP_REPORT_BASENAME}.md${ZAP_REPORT_BASENAME}.pdf
The JSON report uses the traditional-json template and is converted into ${ZAP_REPORT_BASENAME}-junit.xml. Informational findings (riskcode: 0) remain available in the original ZAP artifacts but are omitted from the GitLab JUnit report.
The JUnit report contains one failing or passing test case for each non-informational grouped ZAP finding. Test names use <alert name> <risk>, suites use OWASP ZAP <plugin ID>, and the formatted system output for each test case contains its risk, plugin ID, plain-text description, affected instances, solution, and references. risk controls the minimum ZAP risk level that fails a test case and defaults to high; lower non-informational risks are included as passing test cases. The original ZAP artifacts retain the complete scanner output.
Standalone scans use the default environment-action: verify, so GitLab treats the job as a scan instead of a deployment that creates a new environment. Use environment-action: start only when the ZAP job should create or own a GitLab environment.
Web application crawl
Use a traditional spider followed by passiveScan-wait for a server-rendered
application whose routes are reachable through links. Set ZAP_TARGET_URL in a
dotenv artifact from the deployment job or as a CI/CD variable. The
crawl.yaml
example is ready to use with the component configuration above.
Traditional spider options are documented in the
ZAP spider Automation Framework job.
The bundled ZAP image intentionally has no browser, so use a browser-enabled ZAP
image and the spiderAjax job for JavaScript-only navigation.
OAuth-protected application
Obtain a short-lived access token in a dedicated CI job and expose it as the
masked ZAP_OAUTH_ACCESS_TOKEN variable. The
oauth-crawl.yaml
plan uses ZAP's replacer job to add Authorization: Bearer ... to every scan
request. Do not commit access tokens to a plan or print them in job logs.
jobs:
- type: replacer
parameters:
deleteAllRules: false
rules:
- description: OAuth access token
matchType: req_header
matchString: Authorization
replacementString: Bearer ${ZAP_OAUTH_ACCESS_TOKEN}
This pattern is appropriate when the OAuth provider can issue a machine token. Interactive authorization-code and multi-factor login flows need ZAP browser-based authentication and therefore a browser-enabled scanner image.
OpenAPI scan
Use the openapi job when a service publishes a definition. The
openapi.yaml
plan imports ZAP_OPENAPI_URL, rewrites its server URL to ZAP_TARGET_URL, and
passively scans the generated requests. A repository-local definition can use
apiFile instead; relative file paths are normalized by this component.
See the ZAP OpenAPI Automation Framework reference for import limits, authenticated users, and target URL behavior.
Single REST endpoint
Use a requestor job when a focused smoke test is more useful than crawling.
The rest-endpoint.yaml
example sends GET ${ZAP_TARGET_URL}/api/items, asserts HTTP 200, and then waits
for passive analysis. Copy the request entry for additional methods and request
bodies. See the ZAP
requestor job reference
for the complete request schema.
Runnable .NET example
container/zap-example
contains a small ASP.NET Core application with a crawlable page, REST endpoint,
OpenAPI document, optional OAuth bearer-token validation, and OpenTelemetry logs
written to standard output. Its multi-stage Containerfile uses Red Hat
Hardened .NET images and runs the result as a non-root user.
Build the sample with the container component:
include:
- component: $CI_SERVER_FQDN/xrow-public/ci-tools/common@stable
- component: $CI_SERVER_FQDN/xrow-public/ci-tools/container@stable
inputs:
name: zap-example
path: container/zap-example
Deploy it with the included Helm chart and scan the service through an ingress:
helm upgrade --install zap-example charts/zap-example \
--set image.repository="$CI_REGISTRY_IMAGE/zap-example" \
--set image.tag="$CI_COMMIT_SHA" \
--set ingress.enabled=true \
--set ingress.host="zap-${CI_COMMIT_REF_SLUG}.example.com"
Set oauth.authority and oauth.audience on the chart to enable bearer-token
validation. The sample follows the official
ASP.NET Core minimal API authentication guidance
and OpenTelemetry .NET logging guidance.
Review app scan
When scanning a review app, include the review component and make the ZAP job depend on review:start. If the review start script writes values such as ZAP_TARGET_URL to review.env, the plan can use them via Automation Framework variable expansion.
include:
- component: $CI_SERVER_FQDN/xrow-public/ci-tools/review@stable
inputs:
review-start-script: scripts/start-review.sh
- component: $CI_SERVER_FQDN/xrow-public/ci-tools/zap@stable
inputs:
name: review
plan: zap.yaml
needs:
- job: review:start
artifacts: true
environment-action: verify
Example plan fragment:
env:
contexts:
- name: review
urls:
- ${ZAP_TARGET_URL}
jobs:
- type: spider
parameters:
context: review
url: ${ZAP_TARGET_URL}
Inputs
| Name | Required | Description |
|---|---|---|
name | no | Name for the ZAP job and generated report files. |
plan | yes | Path to the ZAP Automation Framework plan file (zap.yaml) to execute. |
stage | no | Pipeline stage for the scan job. |
rules | no | Rules that control when the scan job runs. |
needs | no | Jobs that the scan job depends on. |
allow-failure | no | Let the pipeline continue if the plan fails. |
fail-on-warn | no | Treat warning-level ZAP findings as a failed job after the plan completes. |
risk | no | Minimum ZAP risk that fails JUnit test cases: informational, low, medium, or high (default). Lower risk findings are reported as passing tests. |
environment | no | Review environment name used when verifying a review app. |
environment-identifier | no | Review environment identifier used by the review component. |
environment-action | no | GitLab environment action for the scan job. Defaults to verify; use start only when the scan job should create or own an environment. |
tags | no | Runner tags for the scan job. |
Inputs
| Name | Description | Default | Type |
| --- | --- | --- | --- |
| allow-failure | Should the pipeline continue if the ZAP plan fails? | false | boolean |
| environment | Review environment name used when verifying a review app. | test | string |
| environment-action | GitLab environment action for the ZAP job. Use verify when the job depends on an existing review environment. | verify | string |
| environment-identifier | Review environment identifier used by the review component. | /zap-$CI_PROJECT_NAME-$CI_COMMIT_SHORT_SHA | string |
| fail-on-warn | Should warning-level ZAP findings fail the job after the plan completes? | false | boolean |
| name | Name for the ZAP job and report files. | $CI_PROJECT_NAME | string |
| needs | The jobs that this job depends on. | [] | array |
| plan | Path to the OWASP ZAP Automation Framework plan file (zap.yaml) to execute. | string | |
| risk | Minimum ZAP risk level that fails a JUnit testcase. Lower risk findings are reported as passing testcases. | high | string |
| rules | The rules that control when the ZAP job runs. | [{"if":"$CI_PIPELINE_SOURCE == \"schedule\"","when":"never"},{"if":"$CI_PIPELINE_SOURCE == \"merge_request_event\"","when":"on_success"},{"when":"on_success"}] | array |
| stage | The pipeline stage that the job belongs to. | test | string |
| tags | The runners that this job depends on. | [] | array |