Orchestrating Dynamic Application Security Testing via GitLab CI/CD YAML Configurations

The integration of security testing into the software development life cycle (SDLC) represents a critical shift from reactive patching to proactive defense. Within the GitLab ecosystem, Dynamic Application Security Testing (DAST) serves as a cornerstone of this transition, providing a method to probe running applications for vulnerabilities that only manifest during runtime. Unlike Static Application Security Testing (SAST), which examines the dormant source code, DAST operates as an outside-in probe, simulating the actions of a malicious actor interacting with a deployed web service. By utilizing the .gitlab-ci.yml configuration, DevOps engineers and security professionals can automate these complex security probes, ensuring that every deployment is vetted against a battery of attack vectors. This orchestration requires a nuanced understanding of scan profiles, environment variables, and the specific YAML syntax required to trigger, configure, and manage the lifecycle of a security scan within a continuous integration and continuous deployment (CI/CD) pipeline.

Fundamental Architectural Integration and Workflow

Understanding the mechanics of DAST requires a clear view of how the scanner interacts with the deployment pipeline. DAST is not a standalone tool but an integrated component of the CI/CD flow, functioning after the application has been successfully deployed to a target environment. The integration follows a rigorous sequence that ensures the security scan is performed on a live, functional version of the software.

The following sequence diagram illustrates the interaction between the developer, the GitLab CI engine, the deployment targets, and the DAST scanner itself:

  1. Developer initiates the process by pushing code to the repository.
  2. GitLab CI receives the push and begins the Build & Test phase.
  3. The pipeline progresses to the Deployment phase, where the code is pushed to a Staging Server.
  4. Once deployment is verified, the GitLab CI engine triggers the DAST job.
  5. The DAST Scanner begins its lifecycle by crawling the application hosted on the staging server.
  6. The scanner moves to the testing phase, actively probing specific endpoints.
  7. The scanner executes various attack vectors to probe for vulnerabilities.
  8. Findings are captured and a Security Report is generated.
  9. The report is uploaded back to GitLab, and the developer is notified of the results.

This workflow ensures that the feedback loop is tightly coupled with the deployment process, allowing for immediate remediation of vulnerabilities before they reach production environments.

DAST Scan Profiles and Operational Modes

GitLab provides specialized scan profiles designed to address the inherent tension between security thoroughness and pipeline velocity. A "one size fits all" approach to scanning is rarely effective in professional DevOps environments, as different stages of the pipeline demand different levels of intensity.

Full Scan Profile

The Full Scan Profile is designed for maximum coverage. It is the most exhaustive mode available, intended for scenarios where time is a secondary concern to security depth. This profile is ideal for scheduled nightly scans or as a final gate before a major release. A full scan performs deep crawling of the application, exploring all possible paths and parameters to identify obscure vulnerabilities.

To implement a full scan, the .gitlab-ci.yml must be configured to enable deep crawling and extended spidering. The configuration requires specific variables to manage the intensity of the probe:

```yaml
include:
- template: DAST.gitlab-ci.yml

variables:
DASTWEBSITE: "https://staging.example.com"
# Full scan crawls deeply and tests all parameters
DAST
FULLSCANENABLED: "true"
# Increase spider duration for large applications
DASTSPIDERMINS: "30"
# Maximum number of URLs to scan
DASTMAXURLSPERVULNERABILITY: "50"

dast:
rules:
# Run on scheduled pipeline
- if: $CIPIPELINESOURCE == "schedule"
# Run on merge requests to main
- if: $CIMERGEREQUESTTARGETBRANCH_NAME == "main"
```

The impact of these variables is significant. By setting DAST_FULL_SCAN_ENABLED to "true", the scanner shifts from a surface-level probe to an intensive search. Increasing DAST_SPIDER_MINS allows the crawler more time to map out complex, large-scale applications, while DAST_MAX_URLS_PER_VULNERABILITY controls the breadth of the attack surface tested for each specific flaw.

Passive Scan Profile

In contrast to the Full Scan, the Passive Scan Profile is designed for speed and safety. In passive mode, the scanner does not send active attack payloads to the application. Instead, it observes the responses coming from the server, looking for indicators of vulnerability in headers, cookies, or body content. This mode is significantly faster and carries zero risk of disrupting a production environment, as it does not attempt to exploit the system.

Passive scanning is typically utilized in production environments or during quick sanity checks where the primary goal is to detect misconfigurations rather than active exploits.

```yaml
include:
- template: DAST.gitlab-ci.yml

variables:
DASTWEBSITE: "https://production.example.com"
# Passive mode only observes, never attacks
DAST
FULLSCANENABLED: "false"
# Limit crawl depth for quick scans
DASTSPIDERMINS: "5"

dast:
rules:
# Only run passive scans on production
- if: $CICOMMITBRANCH == "main"
```

By restricting DAST_FULL_SCAN_ENABLED to "false", the security engineer ensures that the scan remains non-intrusive. This is critical when scanning production endpoints where an active probe could inadvertently cause a denial-of-service or corrupt database entries.

Technical Implementation and Variable Management

The flexibility of GitLab DAST lies in its variable-driven configuration. Developers can choose between using the stable template or the latest version, and they can control the version of the DAST Docker image used to execute the tests.

Template Selection and Versioning

GitLab offers two primary templates for DAST integration. Choosing the correct template is a matter of balancing stability against the need for cutting-edge features.

Template Name Description Use Case
DAST.gitlab-ci.yml The stable version of the DAST CI/CD template. Recommended for production and standard pipelines to avoid breaking changes.
DAST.latest.gitlab-ci.yml The latest version of the DAST template. Use when specific new features are required, despite the risk of breaking changes.

Version control for the DAST engine itself is managed via the DAST_VERSION variable. This allows teams to pin their security tooling to specific versions to ensure consistent scan results over time.

  • Pinning to a major version (e.g., 1): Automatically updates the scanner with new features and fixes within that major release.
  • Pinning to a minor version (e.g., 1.6): Limits updates to fixes only, providing a balance of stability and security.
  • Pinning to a specific version (e.g., 1.6.4): Prevents all updates, providing the highest level of predictability and control.

Target URL Configuration Methods

A DAST scan cannot execute without a target. GitLab provides multiple mechanisms to define the DAST_WEBSITE or DAST_TARGET_URL.

  1. CI/CD Variables: Setting the DAST_WEBSITE variable in the .gitlab-ci.yml file. This is the most direct method and takes precedence over other methods.
  2. environment_url.txt: A file located at the root of the project. This is particularly useful for dynamic environments where the URL is not known until the deployment stage. In automated pipelines, a prior job can generate this file containing the dynamically created domain.

Scan Execution Modes: Automatic vs. On-Demand

The timing of a security scan determines its role within the DevOps lifecycle. GitLab allows for two primary modes of execution: automatic scans and on-demand scans.

Feature Automatic Scan On-Demand Scan
Trigger Mechanism Initiated by a merge request. Initiated manually, outside the DevOps life cycle.
Variable Sourcing CI/CD variables from .gitlab-ci.yml. CI/CD variables provided in the UI.
Variable Availability All DAST CI/CD variables available. A subset of DAST CI/CD variables available.
Template Used DAST.gitlab-ci.yml template. DAST-On-Demand-Scan.gitlab-ci.yml template.

Automatic scans are integrated into the developer workflow, providing immediate feedback on merge requests. On-demand scans are typically used by security auditors or during emergency investigations, where a specific point-in-time assessment is required without altering the pipeline code.

Advanced Scanning Capabilities

Modern web applications are increasingly complex, often relying on client-side logic and distributed architectures. GitLab DAST has evolved to handle these complexities through several advanced features.

Browser-Based Scanning and Modern JS Support

For contemporary applications built with frameworks like React, Vue, or Angular, standard crawling is insufficient. These applications rely on heavy JavaScript execution to render content and handle client-side routing. GitLab DAST supports browser-based scanning, which utilizes a headless browser to execute JavaScript, interact with client-side routes, and properly map the application's attack surface.

```yaml
include:
- template: DAST.gitlab-ci.yml

variables:
DASTWEBSITE: "https://staging.example.com"
# Browser-based scanning for modern JavaScript apps
DAST
BROWSER_SCAN: "true"

stages:
- build
- test
- deploy
- dast
```

API Scanning

As microservices architectures become the standard, scanning the frontend alone is inadequate. DAST can be configured to perform API scanning. For RESTful services, the analyzer can be pointed directly at an OpenAPI or Swagger specification. For GraphQL-based architectures, providing the endpoint URL allows the scanner to traverse the schema and test queries and mutations.

```yaml
include:
- template: DAST.gitlab-ci.yml

variables:
DASTTARGETURL: "https://staging.example.com"
DASTCRAWLTIMEOUT: "60m"
```

User Interface Configuration and Workflow

While YAML configuration is the preferred method for "Infrastructure as Code" (IaC) enthusiasts, GitLab also provides a high-level User Interface (UI) for configuring DAST. This is particularly useful for teams that prefer a guided experience or need to generate valid YAML without manual syntax construction.

The process for configuring via the UI involves the following steps:

  1. Navigate to the project and select Secure > Security configuration from the left sidebar.
  2. Locate the Dynamic Application Security Testing (DAST) section and select Enable DAST or Configure DAST.
  3. Define the Scanner profile by selecting an existing one or creating a new one.
  4. Define the Site profile by selecting an existing one or creating a new one.
  5. Select Generate code snippet to produce a YAML block tailored to the selected settings.
  6. Use the Copy code or Copy code and open options to move the snippet into the .gitlab-ci.yml file within the Pipeline Editor.
  7. Use the Validate tab to ensure the pipeline is syntactically correct before committing.

Comparison: DAST vs. SAST

It is essential to recognize that DAST is not a replacement for SAST, but a complement. A robust security posture requires both.

Aspect DAST SAST
What it scans Running application Source code
When it runs After deployment Before build
Finds Runtime vulnerabilities Code-level issues
Languages Language agnostic Language specific
False positives Lower Higher
Coverage External attack surface Internal code paths

SAST finds flaws in the logic and syntax of the code itself (e.g., hardcoded credentials, unsafe function calls), whereas DAST finds flaws that occur when that code is executed in a real environment (e.g., insecure server configurations, session management issues, or vulnerabilities exposed via the network).

Prerequisites for Implementation

To successfully implement DAST within a GitLab environment, several prerequisites must be satisfied. Failure to meet these requirements will result in failed pipeline jobs or incomplete security coverage.

  • GitLab Ultimate License: DAST is a premium security feature available only to users with a GitLab Ultimate license.
  • Deployed Application: Since DAST probes a running instance, a target URL must be reachable by the GitLab Runner.
  • CI/CD Pipeline Structure: The pipeline must include a deployment stage that precedes the DAST stage.
  • GitLab CI Proficiency: Users must possess a working knowledge of GitLab CI/CD configuration and variable management.

Analysis of Security Orchestration

The strategic implementation of DAST via .gitlab-ci.yml shifts the security paradigm from a periodic checkpoint to a continuous stream of intelligence. By leveraging scan profiles, engineers can optimize the balance between the "Safety" required for production and the "Depth" required for staging. The distinction between automatic and on-demand scanning allows for the integration of security into both the developer's daily workflow and the auditor's periodic requirements.

Ultimately, the power of GitLab DAST lies in its ability to adapt to the evolving nature of web applications—moving from simple HTML crawling to complex JavaScript execution and API probing. This adaptability ensures that as the application architecture matures from monolithic to microservice-based, the security testing framework evolves in tandem, maintaining a rigorous defense against the ever-changing landscape of web-based threats.

Sources

  1. OneUptime - GitLab CI DAST Security Testing
  2. Diffblue - GitLab DAST Proxy-Based Documentation
  3. AppSec Santa - GitLab DAST

Related Posts