Nowadays a very common practice is to integrate security scans during the continuous integration and continuous delivery (CI/CD) phase of software development. It has the benefit of providing early detection of security defects, potentially blocking the delivery of the application when a critical issue is found.
One of the most famous static scanners today is Semgrep. It is an open-source static analysis tool used for finding bugs and enforcing coding standards. It can be run at various levels of the software development cycle, including the CI/CD phase. It can be configured to run at each pull request or when a push is made to specific branches and files. In its CI mode, it will return a different status code depending on what happens during its execution, whether it is a blocking defect found or internal errors.
Conviso Platform [5, 6] is our Software as a Service (SaaS) platform that supports the entire security lifecycle in software development. One of the benefits of the Conviso Platform is that it helps to centralize the communication of security and development teams, through the integration of tools.
In this post, we will show how to configure Semgrep to run through GitHub Actions and send the issues found to Conviso Platform.
Semgrep on GitHub Actions
GitHub Actions is a CI/CD platform that allows you to automate tasks for your project. The workflow is defined in YAML files that are created in the .github/workflows directory of the repository. In these files, you can define jobs that are triggered when certain events occur (e.g., pull requests). You can either write workflows on your own or you can use some from GitHub marketplace (e.g., semgrep-action).
A simple configuration can be seen below:
name: Semgrep
on:
pull_request: {}
push:
branches:
- main
- master
paths:
- .github/workflows/semgrep.yml
schedule:
- cron: '0 0 * * 0'
workflow_dispatch: {}
jobs:
semgrep:
name: Scan
runs-on: ubuntu-20.04
env:
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
container:
image: returntocorp/semgrep
steps:
- uses: actions/checkout@v3
- name: Semgrep scan
id: scan
run: semgrep ci --config=auto --sarif -o result.sarif
- name: Upload results
if: failure() && steps.scan.outcome == 'failure'
uses: actions/upload-artifact@v3
with:
name: result.sarif
path: result.sarif
It will run the Semgrep job once a week, at every pull request, and also when the semgrep.yml file is pushed in the main and master branches. It will also save the result of the Semgrep scan in the SARIF format.
What are Artifacts
An artifact is a file or collection of files produced during a workflow run. The artifacts can also be used to share data with multiple jobs in your workflow. In GitHub Actions, there are two actions ready to handle artifacts. When a job needs to make data available for another job, it can use action/upload-artifact to upload a file, when the upload is done, the other job can use actions/download-artifact to download the file and do whatever it should do with it.
How to communicate with Conviso Platform’s API
It is possible to interact with the Conviso Platform via Conviso CLI and you can use the feature to import the result from SARIF file to create findings for a project. As an example, we wrote a Gitub Action workflow that gets the SARIF generated by Semgrep, extracts the findings, and submit them to the Conviso platform.
The information needed by the workflow are: FLOW_API_KEY, FLOW_PROJECT_CODE, and OUTPUT_FILEPATH. You can store them as Action Secrets in your GitHub repository (Settings > Security/Secrets > Actions).
The final configuration file to submit the issues found during a scan can be seen below:
name: Semgrep + Conviso Platform
on:
workflow_dispatch:
push:
branches:
- main
jobs:
# You can change the Scanner here to anyone who performs SARIF output
scan:
name: Security Scan
runs-on: ubuntu-20.04
container:
image: returntocorp/semgrep
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Semgrep scan
id: scan
run: semgrep --config=auto --sarif -o ${{secrets.OUTPUT_FILEPATH}}
- name: Upload results
uses: actions/upload-artifact@v3
with:
name: ${{secrets.OUTPUT_FILEPATH}}
path: ${{secrets.OUTPUT_FILEPATH}}
submit_findings:
name: Conviso Findings Importation
needs: scan
runs-on: ubuntu-20.04
container:
image: convisoappsec/flowcli:1.12.0-rc.2
env:
FLOW_API_KEY: ${{secrets.FLOW_API_KEY}}
FLOW_PROJECT_CODE: ${{secrets.FLOW_PROJECT_CODE}}
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Download result from previous scan
uses: actions/download-artifact@v3
with:
name: ${{secrets.OUTPUT_FILEPATH}}
- name: SARIF Importation
run: |
conviso findings import-sarif --input-file ${{secrets.OUTPUT_FILEPATH}}
The workflow has two jobs. One is responsible run Semgrep and generate the SARIF file and the other will send the findings to Conviso Platform.
The findings at Conviso Platform
This screen shows the findings grouped by title.

And this screen shows an individual finding.

Conclusion
In this post, we demonstrated just one way to integrate the results of the Semgrep scanner, running in CI mode, with our platform. Conviso Platform supports different types of integrations and has many features to assist you in enhancing the security of your business.
References
- Understanding GitHub Actions
- Semgrep Action
- Upload-Artifact v3
- Download-Artifact v3
- Conviso Platform
- Conviso Platform: A complete DevSecOps platform
Authors:
Gabriel Quadros – Security Analyst
Ricardo Silva – Security Analyst
Translate: Anderson Bosa – Backend Engineer
