scanning
GitLab Ultimate Security Scanning
This guide covers all security scanning capabilities available in GitLab Ultimate tier. Security scanners run automatically in CI/CD pipelines to detect vulnerabilities before they reach production.
Overview
GitLab Ultimate provides comprehensive security scanning through multiple specialized analyzers:
- SAST - Static Application Security Testing (code analysis)
- DAST - Dynamic Application Security Testing (runtime testing)
- Dependency Scanning - Third-party library vulnerability detection
- Container Scanning - Docker image vulnerability detection
- Secret Detection - Credential and token detection
- License Compliance - Open source license tracking
- Coverage-Guided Fuzz Testing - Automated input fuzzing
- API Security Testing - REST/GraphQL API vulnerability detection
All scanners integrate into merge requests, pipelines, and vulnerability reports for comprehensive security coverage.
SAST - Static Application Security Testing
Overview
SAST analyzes source code for security vulnerabilities without executing the application. GitLab Ultimate includes Advanced SAST, a proprietary scanning technology that delivers higher-quality results than basic SAST.
Key Ultimate Features
Advanced SAST Capabilities:
- Proprietary scanning technology with improved accuracy
- Advanced Vulnerability Tracking - tracks vulnerabilities as they move through the codebase
- False positive detection with GitLab Duo add-on (automatic confidence scores and explanations)
- Integrated into merge request workflows with Security Policies
- Multiple language support (see supported languages below)
Integration Points:
- Merge request widget (inline vulnerability display)
- Pipeline security tab
- Vulnerability management dashboard
- Security policy enforcement
Supported Languages
SAST supports multiple programming languages through specialized analyzers:
- JavaScript/TypeScript - ESLint Security Plugin, Semgrep
- Python - Bandit, Semgrep
- Java - SpotBugs, Semgrep
- Go - Gosec, Semgrep
- Ruby - Brakeman, Semgrep
- C/C++ - Flawfinder, Semgrep
- C# - Security Code Scan, Semgrep
- PHP - phpcs-security-audit, Semgrep
- Scala - Find Security Bugs, Semgrep
- Kotlin - Detekt, Semgrep
Configuration
Basic Setup (.gitlab-ci.yml):
include: - template: Security/SAST.gitlab-ci.yml sast: stage: test variables: SAST_EXCLUDED_PATHS: "spec,test,tests,tmp" SAST_EXCLUDED_ANALYZERS: "eslint" # Optional: disable specific analyzers
Advanced Configuration:
include: - template: Security/SAST.gitlab-ci.yml # Override defaults sast: variables: # Enable Advanced SAST (Ultimate only) SAST_ADVANCED_ENABLED: "true" # Exclude directories SAST_EXCLUDED_PATHS: "spec,test,tmp,node_modules" # Customize severity threshold SAST_CONFIDENCE_LEVEL: "medium" # Enable experimental features SAST_EXPERIMENTAL_FEATURES: "true"
2026 Roadmap
Scheduled for Feb-Apr 2026:
- Incremental scanning for Advanced SAST (skip unchanged code)
- Faster scan times by analyzing only modified files
- Improved baseline comparison
Best Practices
- Enable Advanced SAST - Use
SAST_ADVANCED_ENABLED: "true"for better accuracy - Exclude Test Directories - Reduce noise by excluding test files
- Use Security Policies - Enforce SAST requirements across all projects
- Review False Positives - Use GitLab Duo's confidence scores to prioritize
- Integrate Early - Run SAST in feature branch pipelines, not just main
Limitations
- SAST only scans code that is compiled or executed
- Cannot detect runtime vulnerabilities (use DAST for these)
- Results depend on analyzer accuracy and configuration
- May produce false positives (use Advanced SAST for reduction)
DAST - Dynamic Application Security Testing
Overview
DAST performs automated penetration testing on running applications. It simulates real-world attacks to find vulnerabilities like XSS, SQL injection, and CSRF.
Key Features
Attack Simulation:
- Cross-Site Scripting (XSS) detection
- SQL Injection (SQLi) testing
- Cross-Site Request Forgery (CSRF) detection
- Authentication and session management testing
- Input validation vulnerability detection
Ultimate Benefits:
- Comprehensive vulnerability reports
- Integration with Security Dashboard
- Merge request vulnerability display
- Automated remediation suggestions
Configuration
Basic DAST Setup:
include: - template: Security/DAST.gitlab-ci.yml dast: variables: DAST_WEBSITE: "https://staging.example.com" DAST_AUTH_URL: "https://staging.example.com/login" DAST_USERNAME: "$DAST_USERNAME" DAST_PASSWORD: "$DAST_PASSWORD"
Advanced DAST Configuration:
include: - template: Security/DAST.gitlab-ci.yml dast: stage: security_test variables: DAST_WEBSITE: "https://staging.example.com" # Authentication DAST_AUTH_URL: "https://staging.example.com/login" DAST_USERNAME: "$DAST_USERNAME" DAST_PASSWORD: "$DAST_PASSWORD" # Scan configuration DAST_FULL_SCAN_ENABLED: "true" DAST_SPIDER_TIMEOUT: "300" DAST_TARGET_AVAILABILITY_TIMEOUT: "60" # API testing DAST_API_SPECIFICATION: "openapi.json" # Custom headers DAST_REQUEST_HEADERS: "Authorization: Bearer $API_TOKEN" only: - schedules # Run on schedule, not every commit
DAST with API Specification:
dast: variables: DAST_WEBSITE: "https://api.example.com" DAST_API_SPECIFICATION: "openapi.yaml" DAST_API_HOST_OVERRIDE: "api.example.com"
Requirements
Prerequisites:
- Running application (deployed to staging/test environment)
- Network access from GitLab Runner to application
- Valid authentication credentials (if required)
Note: DAST requires a deployed, running application. It cannot scan source code directly.
Best Practices
- Run on Staging - Test against staging environments, not production
- Schedule Scans - Run DAST on schedule (nightly) rather than every commit
- Authenticated Testing - Provide credentials to test protected endpoints
- API Specifications - Use OpenAPI specs for comprehensive API coverage
- Rate Limiting - Configure spider timeout to avoid overwhelming servers
- Monitor False Positives - Review and dismiss false positives regularly
Integration Notes
- DAST results appear in merge request widget (if MR pipeline triggers DAST)
- Detected vulnerabilities shown in Pipeline Security tab
- Integrated with Vulnerability Report for tracking
- Security Dashboard shows DAST findings alongside SAST and other scanners
Important: If any pipeline job fails, the Security Dashboard may not show DAST output. Ensure all jobs complete successfully.
Dependency Scanning
Overview
Dependency Scanning detects known vulnerabilities in third-party dependencies and libraries. It analyzes lock files and manifests to identify vulnerable packages.
Supported Ecosystems
Package Managers:
- JavaScript - npm, yarn, pnpm (package-lock.json, yarn.lock, pnpm-lock.yaml)
- Python - pip, poetry, pipenv (requirements.txt, Pipfile.lock, poetry.lock)
- Ruby - bundler (Gemfile.lock)
- Java - Maven, Gradle (pom.xml, build.gradle)
- Go - go modules (go.mod, go.sum)
- PHP - Composer (composer.lock)
- C#/.NET - NuGet (packages.lock.json, project.assets.json)
- Rust - Cargo (Cargo.lock)
Key Features
Ultimate Capabilities:
- CycloneDX SBOM generation for all dependencies
- GitLab advisory database integration (enhanced vulnerability data)
- Automatic vulnerability prioritization
- Remediation advice with version suggestions
- License compliance integration
Configuration
Basic Setup:
include: - template: Security/Dependency-Scanning.gitlab-ci.yml dependency_scanning: stage: test
Advanced Configuration:
include: - template: Security/Dependency-Scanning.gitlab-ci.yml dependency_scanning: variables: # Scan additional directories DS_EXCLUDED_PATHS: "spec,test,tmp" # Disable specific analyzers DS_EXCLUDED_ANALYZERS: "gemnasium-python" # Set severity threshold DS_MAX_DEPTH: "5" # Enable experimental features DS_EXPERIMENTAL_FEATURES: "true" artifacts: reports: cyclonedx: "**/gl-sbom-*.cdx.json"
SBOM Generation
Dependency Scanning automatically generates CycloneDX Software Bill of Materials (SBOM) for all detected dependencies:
Output Format:
{ "bomFormat": "CycloneDX", "specVersion": "1.4", "components": [ { "name": "lodash", "version": "0.4.9", "purl": "pkg:npm/lodash@4.17.21", "licenses": [{"license": {"id": "MIT"}}] } ] }
Viewing SBOMs:
- Download from pipeline artifacts
- View in Dependency List page (Ultimate)
- Export via API
Best Practices
- Lock Files Required - Commit lock files (package-lock.json, Gemfile.lock, etc.)
- Regular Scans - Run on every commit to catch new vulnerabilities
- Update Regularly - Keep dependencies up-to-date to reduce vulnerabilities
- Review Advisories - Check GitLab advisory database for detailed information
- Automate Updates - Use dependency update tools (Dependabot, Renovate)
Container Scanning
Overview
Container Scanning analyzes Docker images for known vulnerabilities in OS packages and application dependencies. It detects CVEs in base images and layers.
Key Features
Scanning Capabilities:
- OS package vulnerability detection (Alpine, Debian, Ubuntu, RHEL, etc.)
- Application dependency scanning (embedded in images)
- Layer-by-layer analysis
- CycloneDX SBOM generation for container contents
- License information in reports (Ultimate)
Ultimate Enhancements:
- GitLab advisory database integration
- Enhanced vulnerability prioritization
- License compliance for container dependencies
- Security policy enforcement
Configuration
Basic Setup:
include: - template: Security/Container-Scanning.gitlab-ci.yml container_scanning: stage: test variables: CS_IMAGE: "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"
Multi-Stage Build Scanning:
include: - template: Security/Container-Scanning.gitlab-ci.yml # Build image build: stage: build script: - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA . - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA # Scan built image container_scanning: stage: test variables: CS_IMAGE: "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA" dependencies: - build
Advanced Configuration:
container_scanning: variables: CS_IMAGE: "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA" # Severity threshold CS_SEVERITY_THRESHOLD: "high" # Analyzer selection CS_ANALYZER_IMAGE: "registry.gitlab.com/security-products/container-scanning:latest" # Disable specific checks CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN: "false" # Enable SBOM generation CS_SBOM_ENABLED: "true" artifacts: reports: container_scanning: gl-container-scanning-report.json cyclonedx: "**/gl-sbom-*.cdx.json"
Supported Base Images
Operating Systems:
- Alpine Linux (all versions)
- Debian (8+)
- Ubuntu (14.04+)
- Red Hat Enterprise Linux (RHEL 6+)
- CentOS (6+)
- Amazon Linux (1, 2)
- Oracle Linux (6+)
Best Practices
- Scan Every Build - Scan images in CI/CD before pushing to registry
- Use Minimal Base Images - Smaller images have fewer vulnerabilities
- Update Base Images - Regularly rebuild with latest base image versions
- Multi-Stage Builds - Reduce final image size and attack surface
- Policy Enforcement - Use scan result policies to block vulnerable images
- Regular Rescans - Scan registry images periodically for new CVEs
Secret Detection
Overview
Secret Detection identifies accidentally committed credentials, tokens, API keys, and other sensitive information in code. It prevents secrets from reaching repositories and production.
Detection Methods
GitLab provides two complementary secret detection approaches:
- Secret Push Protection - Blocks commits at push time (pre-receive hook)
- Pipeline Secret Detection - Scans commits in CI/CD pipelines
Secret Push Protection
How It Works:
- Runs in pre-receive hook before commits are accepted
- Scans file diffs for secrets (not entire files)
- Blocks push immediately if secrets detected
- Prevents secrets from entering repository
Requirements:
- GitLab Ultimate
- Must be enabled at instance or project level
- Works for HTTP(S) and SSH pushes
- Requires Maintainer role to enable
Enabling Push Protection:
# Navigate to: Settings > Security & Compliance > Secret push protection # Toggle: Enable secret push protection
Detected Secret Types:
- AWS Access Keys
- GCP Service Account Keys
- Azure Storage Keys
- GitHub Personal Access Tokens
- GitLab Personal Access Tokens
- Private SSH Keys
- Database Connection Strings
- JWT Tokens
- API Keys (various services)
Bypass (Emergency Only):
If you need to push despite detected secrets (e.g., false positive):
# Add skip-secret-detection trailer to commit message git commit --trailer "skip-secret-detection=true" -m "Your commit message"
Note: Bypass requires explicit justification and should be rare.
Pipeline Secret Detection
How It Works:
- Scans entire commit history during CI/CD pipeline
- Detects secrets in full file contents (not just diffs)
- Reports findings in merge request widget and Security Dashboard
- Allows integration with approval workflows
Configuration:
include: - template: Security/Secret-Detection.gitlab-ci.yml secret_detection: stage: test variables: SECRET_DETECTION_EXCLUDED_PATHS: "test/,spec/" SECRET_DETECTION_HISTORIC_SCAN: "false" # Set true to scan full history
Advanced Configuration:
secret_detection: variables: # Exclude paths SECRET_DETECTION_EXCLUDED_PATHS: "tests/,docs/,*.md" # Historic scan (scans full git history) SECRET_DETECTION_HISTORIC_SCAN: "true" # Custom timeout SECRET_DETECTION_TIMEOUT: "180" # Custom patterns (add to defaults) SECRET_DETECTION_CUSTOM_PATTERNS: "custom-patterns.yml"
Custom Pattern File (custom-patterns.yml):
patterns: - name: "Custom API Key" pattern: "custom_api_key_[a-zA-Z0-9]{32}" severity: "high"
Ultimate Features
Merge Request Integration:
- Detected secrets appear in MR widget
- Block merges with scan result policies
- Require approval for MRs with secrets
- Track secret exposure in Vulnerability Report
Security Dashboard:
- Centralized view of all detected secrets
- Triage workflow (confirm, dismiss, resolve)
- Historical tracking of secret exposure
Best Practices
- Enable Both Methods - Use push protection AND pipeline detection
- Exclude Test Files - Reduce noise from test fixtures
- Rotate Exposed Secrets - Immediately rotate any detected credentials
- Use Secret Management - Store secrets in Vault, AWS Secrets Manager, etc.
- Custom Patterns - Add organization-specific secret patterns
- Regular Audits - Run historic scans periodically to find old secrets
- Developer Training - Educate teams on secret management best practices
Remediation
If Secret Detected:
- Rotate Immediately - Revoke and replace exposed credential
- Remove from History - Use
git filter-branchor BFG Repo-Cleaner - Force Push - Update remote repository with cleaned history
- Audit Access - Check if exposed secret was used maliciously
Example Removal:
# Remove secret from git history git filter-branch --force --index-filter \ "git rm --cached --ignore-unmatch config/secrets.yml" \ --prune-empty --tag-name-filter cat -- --all # Force push to remote git push origin --force --all
License Compliance
Overview
License Compliance tracks open source licenses in project dependencies and enforces license policies. It helps organizations maintain legal compliance and avoid incompatible licenses.
Key Features
Ultimate Capabilities:
- Automatic license detection in dependencies
- License approval policies (allow/deny lists)
- Merge request blocking for unapproved licenses
- CycloneDX SBOM with license information
- Compliance reports and exports
Configuration
Basic Setup:
include: - template: Security/License-Scanning.gitlab-ci.yml license_scanning: stage: test
With Dependency Scanning Integration:
include: - template: Security/Dependency-Scanning.gitlab-ci.yml dependency_scanning: artifacts: reports: cyclonedx: "**/gl-sbom-*.cdx.json"
Note: License information is included in CycloneDX SBOMs generated by Dependency Scanning and Container Scanning.
License Approval Policies
Creating Policies:
- Navigate to: Security & Compliance > Policies
- Click: New policy > License approval policy
- Configure allowed and denied licenses
Policy Configuration:
# .gitlab/license-approval-policy.yml license_approval_policy: name: "License Compliance Policy" description: "Enforce allowed open source licenses" approved_licenses: - MIT - Apache-2.0 - BSD-3-Clause - ISC denied_licenses: - GPL-3.0 - AGPL-3.0 - CC-BY-NC-4.0 approval_required: - Apache-1.0 - EPL-1.0
License Policy Enforcement
How It Works:
- Dependency/Container Scanning detects licenses in dependencies
- License approval policy evaluates detected licenses
- If denied license found, merge request is blocked
- Eligible approver must approve MR to proceed
Approval Requirements:
- Project Maintainer or Owner role
- Cannot be the MR author
- Must explicitly approve despite license violation
Viewing License Information
Locations:
- Dependency List page (Project > Security & Compliance > Dependency List)
- License Compliance page (Project > Security & Compliance > License Compliance)
- Merge request widget (shows license violations)
- CycloneDX SBOM artifacts
Best Practices
- Define Policy Early - Establish license policy before development
- Regular Reviews - Review license compliance quarterly
- Developer Education - Train teams on license implications
- Approval Process - Define clear process for exceptional licenses
- SBOM Export - Maintain SBOM exports for compliance audits
- Third-Party Review - Have legal review license policy annually
Coverage-Guided Fuzz Testing
Overview
Coverage-guided fuzz testing automatically generates malformed, unexpected, or random inputs to discover bugs, crashes, and security vulnerabilities that traditional testing misses.
Note: Coverage-guided fuzz testing was deprecated in GitLab 16.0. Use Web API Fuzz Testing instead for API testing.
Status
Deprecated: GitLab 16.0 (May 2023) Removal: Planned for GitLab 17.0
Migration Path: Use Web API Fuzz Testing for API security testing.
API Security Testing
Overview
API Security Testing performs dynamic analysis of REST and GraphQL APIs to identify security vulnerabilities including OWASP API Security Top 10 issues.
Supported API Types
- REST APIs - OpenAPI Specification v2, v3
- GraphQL APIs - GraphQL schema introspection
- SOAP APIs - WSDL-based testing
Configuration
Web API Fuzz Testing:
include: - template: Security/API-Fuzzing.gitlab-ci.yml apifuzzer_fuzz: variables: FUZZAPI_OPENAPI: "openapi.json" FUZZAPI_TARGET_URL: "https://api.staging.example.com" FUZZAPI_HTTP_USERNAME: "$API_USERNAME" FUZZAPI_HTTP_PASSWORD: "$API_PASSWORD"
Advanced Configuration:
apifuzzer_fuzz: variables: # OpenAPI specification FUZZAPI_OPENAPI: "openapi.yaml" FUZZAPI_TARGET_URL: "https://api.example.com" # Authentication FUZZAPI_HTTP_USERNAME: "$API_USERNAME" FUZZAPI_HTTP_PASSWORD: "$API_PASSWORD" # Or use Bearer token FUZZAPI_OVERRIDES_ENV: | FUZZAPI_HTTP_HEADERS="Authorization: Bearer $API_TOKEN" # Scan configuration FUZZAPI_VERBOSE: "true" FUZZAPI_TIMEOUT: "300" # Rate limiting FUZZAPI_REQUEST_RATE: "100" # requests per second
GraphQL API Testing:
apifuzzer_fuzz: variables: FUZZAPI_GRAPHQL: "https://api.example.com/graphql" FUZZAPI_TARGET_URL: "https://api.example.com" FUZZAPI_HTTP_HEADERS: "Authorization: Bearer $GRAPHQL_TOKEN"
API Security Checks
Vulnerability Detection:
- SQL Injection
- Cross-Site Scripting (XSS)
- Authentication bypass
- Authorization flaws
- Mass assignment
- XML External Entity (XXE)
- Server-Side Request Forgery (SSRF)
- Insecure deserialization
Requirements
Prerequisites:
- Deployed API (running instance required)
- OpenAPI specification or GraphQL schema
- API credentials (if authentication required)
- Network access from GitLab Runner
Best Practices
- Use OpenAPI Specs - Maintain up-to-date API specifications
- Test Staging - Run against staging/test environments
- Authentication - Provide valid credentials for protected endpoints
- Rate Limiting - Configure appropriate request rates
- Schedule Scans - Run API testing on schedule, not every commit
- Review Results - Triage findings and address high-severity issues
Integration and Reporting
Security Dashboard
All security scanners report to the centralized Security Dashboard:
Navigation: Security & Compliance > Security Dashboard
Features:
- Unified view of all vulnerabilities
- Filter by severity, scanner type, status
- Trend analysis and metrics
- Export capabilities
Merge Request Integration
Security findings appear automatically in merge requests:
Widget Display:
- Summary of new vulnerabilities
- Comparison to target branch
- Expandable details for each finding
- Direct link to vulnerability details
Approval Rules:
- Require security approval for vulnerabilities
- Block merges for critical/high severity
- Custom approval rules per project
Pipeline Security Tab
View detailed security results in pipeline view:
Navigation: Pipelines > [Pipeline] > Security
Available Information:
- All scanner results
- Detailed vulnerability listings
- SBOM artifacts
- Raw JSON reports
Vulnerability Report
Comprehensive vulnerability tracking and management:
Navigation: Security & Compliance > Vulnerability Report
Capabilities:
- All detected vulnerabilities across project
- Status tracking (detected, confirmed, resolved, dismissed)
- Assignment and due dates
- Comment threads
- Historical tracking
CI/CD Templates
GitLab provides security scanning templates for easy integration:
Available Templates:
include: - template: Security/SAST.gitlab-ci.yml - template: Security/DAST.gitlab-ci.yml - template: Security/Dependency-Scanning.gitlab-ci.yml - template: Security/Container-Scanning.gitlab-ci.yml - template: Security/Secret-Detection.gitlab-ci.yml - template: Security/API-Fuzzing.gitlab-ci.yml
All-in-One Setup:
include: - template: Security/SAST.gitlab-ci.yml - template: Security/DAST.gitlab-ci.yml - template: Security/Dependency-Scanning.gitlab-ci.yml - template: Security/Container-Scanning.gitlab-ci.yml - template: Security/Secret-Detection.gitlab-ci.yml stages: - build - test - security_test - deploy # SAST and Dependency Scanning run in 'test' stage # DAST runs in 'security_test' stage after deployment
Performance Considerations
Scan Duration
Typical scan times:
- SAST: 2-10 minutes (depends on codebase size)
- Dependency Scanning: 1-3 minutes
- Container Scanning: 2-5 minutes
- Secret Detection: 1-2 minutes
- DAST: 10-60 minutes (depends on application size)
- API Fuzzing: 5-30 minutes
Optimization Strategies
- Parallel Execution - Run scanners in parallel stages
- Conditional Scans - Run DAST only on schedules
- Incremental SAST - Use Advanced SAST incremental scanning (2026)
- Caching - Cache analyzer images and dependencies
- Exclude Paths - Exclude test directories and vendor code
Example Optimized Configuration:
stages: - build - security # All security scans run in parallel - dast # DAST runs separately (slower) - deploy # Fast scans run on every commit include: - template: Security/SAST.gitlab-ci.yml - template: Security/Dependency-Scanning.gitlab-ci.yml - template: Security/Container-Scanning.gitlab-ci.yml - template: Security/Secret-Detection.gitlab-ci.yml # All fast scans run in parallel sast: stage: security dependency_scanning: stage: security container_scanning: stage: security secret_detection: stage: security # DAST runs only on schedule include: - template: Security/DAST.gitlab-ci.yml dast: stage: dast only: - schedules
Troubleshooting
Common Issues
Security Dashboard shows no results:
- Check if all pipeline jobs completed successfully
- Verify scanner artifacts are generated
- Ensure proper GitLab tier (Ultimate required for some features)
False Positives:
- Use GitLab Duo false positive detection (Ultimate with Duo add-on)
- Dismiss false positives in Vulnerability Report
- Configure scanner exclusions
Scan Failures:
- Check runner logs for detailed error messages
- Verify network connectivity for DAST/API testing
- Ensure proper authentication credentials
Performance Issues:
- Implement optimization strategies (see above)
- Run expensive scans (DAST) on schedules only
- Use caching for analyzer images
References
- SAST Documentation
- DAST Documentation
- Dependency Scanning Documentation
- Container Scanning Documentation
- Secret Detection Documentation
- API Fuzzing Documentation
Next Steps
- Vulnerability Management - Triage and remediation workflows
- Security Policies - Enforce security requirements
- Compliance - Meet regulatory requirements