In this article, you can find information on integrating Gitleaks into your GitHub Workflow or Azure Pipeline as part of the PR and Build process.
Gitleaks is an Open-Source tool released under MIT License. It's a SAST tool for detecting and preventing hardcoded secrets like passwords, API keys, and tokens in git repos. Gitleaks is an easy-to-use, all-in-one solution for detecting secrets, past or present, in your code.
Gitleaks produces a scan report as SARIF (Static Analysis Results Interchange Format) file, which is OASIS standard used to streamline how static analysis tools share their results.
In this section, you can find example recipes for GitHub Workflow.
Gitleaks officially released its GitHub Action called Gitleaks Gitleaks Action to perform secret detection, and it's recommended and the easiest solution to use Gitleaks in the GitHub Workflow.
NOTE
Gitleaks Action is released under a commercial license!
- If you are scanning repos that belong to an organization account, you will need to obtain a license key.
- If you are scanning repos belonging to a personal account, no license key is required.
For more information about licensing, go to the official page: gitleaks.io
Gitleaks result (SARIF file) may be uploaded to the GitHub Code Scanning service to see code scanning alerts from third-party tools.
NOTE
GitHub Code Scanning integration it's only available for Organizations that use GitHub Enterprise Cloud and have a license for GitHub Advanced Security.
name: Gitleaks-GHA-official
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
workflow_dispatch:
jobs:
secrets-detection:
name: Secrets Detection
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Run Gitleaks
id: gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} # Only required for Organizations, not personal accounts.
# Only for Organizations that use GitHub Enterprise Cloud and have a license for GitHub Advanced Security.
- name: Upload SARIF report to Code Scanning service
if: always() && steps.gitleaks.outputs.exit-code != 0
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: results.sarif
category: gitleaks
To adjust Gitleaks Action configuration, follow documentation: https://github.com/marketplace/actions/gitleaks#environment-variables
There are a couple of unofficial Gitleaks GitHub Actions on the GitHub Marketplace. In most cases, they do not require a commercial license and are released under open-source licenses.
Each Action has a different approach for Gitleaks usage and scanning, so there is not one answer to what is the best - it depends on scenario requirements.
NOTE
Very often, unofficial Actions are community-powered and may have undefined code maintenance and support approaches.
One community-based GitHub Action has been selected for this example, which has similar results and experience as the official one - Gitleaks Scanner Action.
name: Gitleaks-GHA-unofficial
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
workflow_dispatch:
jobs:
secrets-detection:
name: Secrets Detection
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Run Gitleaks
id: gitleaks
uses: DariuszPorowski/github-action-gitleaks@v2
with:
report_format: sarif
- name: Upload SARIF report to Workflow Artifacts
uses: actions/upload-artifact@v3
if: always() && steps.gitleaks.outputs.exitcode != 0
with:
name: gitleaks
path: |
${{ steps.gitleaks.outputs.report }}
# Only for Organizations that use GitHub Enterprise Cloud and have a license for GitHub Advanced Security.
- name: Upload SARIF report to Code Scanning service
if: always() && steps.gitleaks.outputs.exitcode != 0
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: ${{ steps.gitleaks.outputs.report }}
category: gitleaks
To adjust Gitleaks Scanner Action configuration, follow documentation: https://github.com/marketplace/actions/gitleaks-scanner#inputs
You can run Gitleaks natively as a command line without using any GitHub Actions. In this scenario, you have complete control, but you are responsible for code maintenance based on Gitleaks breaking changes in future releases. Moreover, you have to setup Gitleaks on the agent as well.
The following example contains the setup step that downloads and installs the latest version of the Gitleaks from the official repository and the step with Gitleaks execution to detect secrets in the code.
name: Gitleaks-CMD
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
workflow_dispatch:
jobs:
secrets-detection:
name: Secrets Detection
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Gitleaks
run: |
curl -sSLO $(curl -sSL https://api.github.com/repos/zricethezav/gitleaks/releases/latest | jq --compact-output --raw-output '.assets[] | select( .name | contains("linux_x64") ) | select( .name | endswith(".tar.gz") ).browser_download_url')
filename=$(find . -maxdepth 1 -type f -regex '^.*\/*linux_x64*\.tar.gz')
tar -xf "${filename}" gitleaks
mv -f gitleaks /usr/local/bin/
rm -f "${filename}"
- name: Run Gitleaks
id: gitleaks
run: |
set +e
report_name="gitleaks-report"
report_format="sarif"
command="gitleaks detect --redact --verbose --report-format=${report_format} --report-path=${report_name}.${report_format} --log-level debug"
echo "Running Gitleaks $(gitleaks version)"
echo "${command}"
OUTPUT=$(eval "${command}")
exitcode=$?
echo "::set-output name=command::${command}"
echo "::set-output name=exitcode::${exitcode}"
if [ ${exitcode} -eq 0 ]; then
GITLEAKS_RESULT="SUCCESS! Your code is good to go"
echo "::notice::${GITLEAKS_RESULT}"
elif [ ${exitcode} -eq 1 ]; then
GITLEAKS_RESULT="STOP! Gitleaks encountered leaks or error"
echo "::error::${GITLEAKS_RESULT}"
else
echo "::error::Gitleaks unknown error"
exit ${exitcode}
fi
echo "${OUTPUT}"
echo "Gitleaks Summary: ${GITLEAKS_RESULT}" >>$GITHUB_STEP_SUMMARY
echo "${OUTPUT}" >>$GITHUB_STEP_SUMMARY
echo "::set-output name=report::${report_name}.${report_format}"
exit ${exitcode}
- name: Upload SARIF report to Workflow Artifacts
uses: actions/upload-artifact@v3
if: always() && steps.gitleaks.outputs.exitcode != 0
with:
name: gitleaks
path: |
${{ steps.gitleaks.outputs.report }}
# Only for Organizations that use GitHub Enterprise Cloud and have a license for GitHub Advanced Security.
- name: Upload SARIF report to Code Scanning service
if: always() && steps.gitleaks.outputs.exitcode != 0
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: ${{ steps.gitleaks.outputs.report }}
category: gitleaks
To adjust Gitleaks configuration, follow documentation: https://github.com/zricethezav/gitleaks#usage
- Gitleaks Action (official)
- Gitleaks Scanner Action (unofficial)
In this section, you can find example recipes for Azure Pipelines.
NOTE
Official Azure Pipelines extension for Gitleaks does not exist.
Currently, there is only one Azure Pipelines extension for Gitleaks under Visual Studio Marketplace, and it is an open-source project licensed under MIT License.
NOTE
Very often, unofficial Tasks are community-powered efforts and vary code maintenance and support approaches.
Gitleaks by Foxholenl has been selected for this Pipeline example.
Task automatically uploads SARIF report to Pipeline Artifacts, and the result can be visualized using the SARIF SAST Scans Tab extension.
trigger:
- main
pr:
- main
pool:
vmImage: ubuntu-latest
steps:
- checkout: self
displayName: Checkout repo
- task: Gitleaks@2
displayName: Run Gitleaks
inputs:
configtype: default
scanmode: all
verbose: true
You can run Gitleaks natively as a command line without using any Azure Pipelines extension. In this scenario, you have complete control, but you are responsible for code maintenance based on Gitleaks breaking changes in future releases. Moreover, you have to setup Gitleaks on the agent as well.
The following example contains the setup step that downloads and installs the latest version of the Gitleaks from the official repository and the step with Gitleaks execution to detect secrets in the code.
trigger:
- main
pr:
- main
pool:
vmImage: ubuntu-latest
steps:
- checkout: self
displayName: Checkout repo
- script: |
curl -sSLO $(curl -sSL https://api.github.com/repos/zricethezav/gitleaks/releases/latest | jq --compact-output --raw-output '.assets[] | select( .name | contains("linux_x64") ) | select( .name | endswith(".tar.gz") ).browser_download_url')
filename=$(find . -maxdepth 1 -type f -regex '^.*\/*linux_x64*\.tar.gz')
tar -xf "${filename}" gitleaks
mv -f gitleaks /usr/local/bin/
rm -f "${filename}"
displayName: Setup Gitleaks
- script: |
set +e
report_name="gitleaks-report"
report_format="sarif"
command="gitleaks detect --redact --verbose --report-format=${report_format} --report-path=$(Pipeline.Workspace)/${report_name}.${report_format} --log-level debug"
echo "Running Gitleaks $(gitleaks version)"
echo "##[command]${command}"
OUTPUT=$(eval "${command}")
exitcode=$?
echo "##vso[task.setvariable variable=gitleaks_command]${command}"
echo "##vso[task.setvariable variable=gitleaks_exitcode]${exitcode}"
if [ ${exitcode} -eq 0 ]; then
GITLEAKS_RESULT="SUCCESS! Your code is good to go"
echo "##[command]${GITLEAKS_RESULT}"
elif [ ${exitcode} -eq 1 ]; then
GITLEAKS_RESULT="STOP! Gitleaks encountered leaks or error"
echo "##vso[task.logissue type=error]${GITLEAKS_RESULT}"
else
echo "##vso[task.logissue type=error]Gitleaks unknown error"
exit ${exitcode}
fi
echo "${OUTPUT}"
echo "# ${GITLEAKS_RESULT}" >$(Pipeline.Workspace)/summary.md
echo '' >>$(Pipeline.Workspace)/summary.md
echo '```json' >>$(Pipeline.Workspace)/summary.md
echo "${OUTPUT}" >>$(Pipeline.Workspace)/summary.md
echo '```' >>$(Pipeline.Workspace)/summary.md
cat $(Pipeline.Workspace)/summary.md
echo "##vso[task.uploadsummary]$(Pipeline.Workspace)/summary.md"
echo "##vso[task.setvariable variable=gitleaks_report]$(Pipeline.Workspace)/${report_name}.${report_format}"
exit ${exitcode}
name: gitleaks
displayName: Run Gitleaks
- task: PublishPipelineArtifact@1
displayName: Upload SARIF report to Pipeline Artifacts
condition: and(always(), eq(variables.gitleaks_exitcode, '1'))
inputs:
targetPath: $(gitleaks_report)
artifact: CodeAnalysisLogs
publishLocation: pipeline
- Gitleaks - Azure Pipelines Extension (unofficial)
- SARIF SAST Scans Tab