Security is a critical part of the software development lifecycle, and automating security scans is a best practice for ensuring that vulnerabilities are caught early. In this article, we’ll walk through how to automate security scanning using GitLeaks, Semgrep, and NJSScan, and how to upload the scan results to DefectDojo using a GitLab CI pipeline.
DefectDojo is a powerful open-source security management platform that helps teams manage vulnerabilities and security findings in a centralized location. By integrating it with GitLab CI/CD, you can ensure your pipeline includes automated scanning and streamlined vulnerability management.
Prerequisites
Before diving into the CI pipeline setup, ensure that you have the following in place:
- DefectDojo instance – Ensure you have an active DefectDojo installation with API access enabled, or try DefectDojo on our demo server for a hands-on experience.
- DefectDojo API Key – The API key for authenticating to your DefectDojo instance.
- Engagement ID – The ID for the engagement in DefectDojo where the scan results will be uploaded.
- Create a product
- Create a CI/CD engagement for your product
- Note down the ID of the new engagement
- GitLab repository – Your project repository should be hosted in GitLab with CI/CD enabled. Refer to my previous article on setting up the Juice Shop repository on GitLab
- Tools – We will be using the following tools for security scanning:
Step-by-Step Setup
Setting Up Environment Variables
To securely manage the credentials and other necessary information for the CI/CD pipeline, I configured environment variables in GitLab. These variables included:
- DEFECTDOJO_API_IMPORT_SCAN_URL: https://your-defectdojo-instance/api/v2/import-scan/
- DEFECTDOJO_API_KEY: your-defectdojo-api-key
- DEFECTDOJO_ENGAGEMENT_ID: your-defectdojo-engagement-id
These variables were added in settings in the GitLab project under CI/CD > Variables.
Defining the GitLab CI Pipeline
The following pipeline demonstrates a streamlined CI/CD security scan process using Dockerized tools, showcasing how Docker simplifies CI/CD by enabling each security scan to run in isolated, ready-to-use containers. This approach ensures consistent, repeatable scans and minimal setup, allowing you to focus on automating security checks rather than dealing with dependencies and environment configurations.
Create or update the .gitlab-ci.yml file in your repository. This file defines the CI/CD pipeline that will perform the security scans and upload the results to DefectDojo.
Here’s the complete .gitlab-ci.yml:
stages:
- security_scan
- upload_results
variables:
DEFECTDOJO_API_IMPORT_SCAN_URL: $DEFECTDOJO_API_IMPORT_SCAN_URL
DEFECTDOJO_API_KEY: $DEFECTDOJO_API_KEY
DEFECTDOJO_ENGAGEMENT_ID: $DEFECTDOJO_ENGAGEMENT_ID
gitleaks_scan:
stage: security_scan
image:
name: zricethezav/gitleaks
entrypoint: [""]
script:
- gitleaks detect --verbose --source . -f json -r gitleaks_report.json
artifacts:
when: always
paths:
- gitleaks_report.json
allow_failure: true
semgrep_scan:
stage: security_scan
image: returntocorp/semgrep
variables:
SEMGREP_RULES: p/javascript
script:
- semgrep ci --json --output semgrep_report.json
artifacts:
when: always
paths:
- semgrep_report.json
allow_failure: true
njsscan_scan:
stage: security_scan
image: python
before_script:
- pip3 install --upgrade njsscan
script:
- njsscan --exit-warning . --sarif -o njsscan_report.sarif
artifacts:
when: always
paths:
- njsscan_report.sarif
allow_failure: true
upload_to_defectdojo:
stage: upload_results
image: python
when: always
before_script:
- pip3 install requests
script:
- python3 upload-reports.py gitleaks_report.json
- python3 upload-reports.py semgrep_report.json
- python3 upload-reports.py njsscan_report.sarif
allow_failure: true
Understanding the Pipeline
The pipeline is divided into two main stages:
- Security Scan: This stage runs the security scanning tools (GitLeaks, Semgrep, NJSScan) to detect vulnerabilities, secrets, and misconfigurations in your code.
- Upload Results: This stage uploads the scan results to DefectDojo using the DefectDojo API.
Using GitLeaks for Secrets Detection
GitLeaks is a tool that scans your codebase for secrets like API keys, passwords, and tokens. In the pipeline, GitLeaks is configured to run as follows:
gitleaks_scan:
stage: security_scan
image:
name: zricethezav/gitleaks
entrypoint: [""]
script:
- gitleaks detect --verbose --source . -f json -r gitleaks_report.json
artifacts:
when: always
paths:
- gitleaks_report.json
allow_failure: true
GitLeaks scans the repository and outputs the results in JSON format, which are stored in an artifact (gitleaks_report.json).
Using Semgrep for Code Vulnerability Detection
Semgrep is used to scan your codebase for security issues and misconfigurations:
semgrep_scan:
stage: security_scan
image: returntocorp/semgrep
variables:
SEMGREP_RULES: p/javascript
script:
- semgrep ci --json --output semgrep_report.json
artifacts:
when: always
paths:
- semgrep_report.json
allow_failure: true
It produces a report that is later uploaded to DefectDojo.
Using NJSScan for JavaScript Security Analysis
NJSScan focuses on finding vulnerabilities in JavaScript code:
njsscan_scan:
stage: security_scan
image: python
before_script:
- pip3 install --upgrade njsscan
script:
- njsscan --exit-warning . --sarif -o njsscan_report.sarif
artifacts:
when: always
paths:
- njsscan_report.sarif
allow_failure: true
The output is stored in the njsscan_report.json file.
Uploading Scan Results to DefectDojo
The results from each security tool are uploaded to DefectDojo using its REST API. The pipeline leverages a python script to make HTTP POST requests to DefectDojo’s /import-scan endpoint.
Here’s an example for GitLeaks:
upload_to_defectdojo:
stage: upload_results
image: python
when: always
before_script:
- pip3 install requests
script:
- python3 upload-reports.py gitleaks_report.json
allow_failure: true
import requests
import sys
import os
DEFECTDOJO_API_IMPORT_SCAN_URL = os.getenv('DEFECTDOJO_API_IMPORT_SCAN_URL')
API_TOKEN = os.getenv('DEFECTDOJO_API_KEY')
ENGAGEMENT_ID = os.getenv('DEFECTDOJO_ENGAGEMENT_ID')
MINIMUM_SEVERITY = 'Low'
# Mapping of file names to scan types
SCAN_TYPE_MAPPING = {
'gitleaks_report.json': 'Gitleaks Scan',
'njsscan_report.sarif': 'SARIF',
'semgrep_report.json': 'Semgrep JSON Report'
}
def get_scan_type(file_name):
return SCAN_TYPE_MAPPING.get(file_name, 'Unknown Scan Type')
def import_scan_results(file_name, scan_type):
headers = {
'Authorization': f'Token {API_TOKEN}'
}
data = {
'active': True,
'verified': True,
'scan_type': scan_type,
'minimum_severity': MINIMUM_SEVERITY,
'engagement': ENGAGEMENT_ID
}
with open(file_name, 'rb') as file:
files = {'file': file}
response = requests.post(DEFECTDOJO_API_IMPORT_SCAN_URL, headers=headers, data=data, files=files)
if response.status_code == 201:
print('Scan results imported successfully')
else:
print(f'Failed to import scan results: {response.content}')
def main():
if len(sys.argv) < 2:
print("Usage: python upload-reports.py <file_name>")
sys.exit(1)
file_name = sys.argv[1]
scan_type = get_scan_type(file_name)
if scan_type == 'Unknown Scan Type':
print(f"Error: Unsupported file type '{file_name}'")
sys.exit(1)
import_scan_results(file_name, scan_type)
if __name__ == '__main__':
main()
The same process is repeated for Semgrep and NJSScan results, each one specifying the correct scan_type and passing the relevant report file.
Managing Results and Handling Failures
To make the pipeline more flexible, each scan and upload job has allow_failure: true, allowing the pipeline to continue even if one of the security scans fails. This is especially useful when working with security tools that may produce false positives or incomplete results due to configuration or limitations.
Final Thoughts
By integrating security tools like GitLeaks, Semgrep, and NJSScan into your GitLab CI pipeline and uploading results to DefectDojo, you can automate security scanning and vulnerability management in a streamlined manner. This setup ensures that potential security issues are caught early in the development lifecycle and that teams can track and resolve them through DefectDojo.
Start securing your CI/CD pipelines today by implementing these tools and automating the process for continuous security!