Semgrep GitHub Action Integration and SAST Orchestration

The integration of Semgrep into GitHub Actions represents a pivotal shift in Static Application Security Testing (SAST), moving security analysis from a periodic audit to a continuous, automated process. By embedding a powerful static analysis engine directly into the Continuous Integration (CI) pipeline, organizations can identify vulnerabilities, code smells, and security regressions in real-time, long before code is merged into a production branch. This systemic approach transforms the development lifecycle by providing immediate feedback to engineers, thereby reducing the cost and complexity of remediation.

Semgrep operates as a lightweight yet highly extensible static analysis tool that allows users to define custom rules using a syntax that mirrors the actual code they are searching for. When deployed within GitHub Actions, it functions as a quality gate that can be configured to trigger on various events, such as pull requests, pushes to mainline branches, or manual dispatches. The primary objective of this integration is to ensure that every commit is scrutinized against a set of security policies, which are then reported back to the developer via the GitHub interface or sent to the Semgrep AppSec Platform for centralized triage and remediation.

Orchestrating Semgrep via GitHub Actions Workflows

The deployment of Semgrep within a GitHub environment requires the definition of a workflow YAML file located in the .github/workflows/ directory. This configuration dictates when the security scan occurs and how the results are handled. The flexibility of GitHub Actions allows for a nuanced approach to scanning, catering to different stages of the development cycle.

The trigger mechanisms for a Semgrep workflow are typically categorized into three primary event types:

  • pull_request: This trigger enables diff-aware scanning. Instead of scanning the entire codebase, Semgrep focuses on the changes introduced in the pull request. This drastically reduces the noise for developers and ensures that they are only alerted to vulnerabilities they have introduced in their current set of changes.
  • push: This trigger is generally configured for mainline branches, such as master or main. It ensures that the authoritative version of the code is always scanned and that any findings are reported as a baseline of the project's current security posture.
  • workflow_dispatch: This allows for on-demand scanning. Security engineers or developers can manually trigger a scan through the GitHub Actions interface without needing to commit new code, which is essential for testing new rule sets or verifying fixes.

The job execution environment is typically based on ubuntu-latest, though the system is compatible with self-hosted runners. In a standard configuration, the job name is often defined as semgrep/ci. The execution flow involves running the Semgrep engine against the source code, which may be located in a specific directory like vulnerable-source-code/ for testing purposes.

Execution Commands and Output Management

The operational core of Semgrep in CI is the CLI command used to execute the scan. Depending on the desired output and the specific goals of the security team, different flags and configurations are employed.

For a standard scan that outputs results to a text file, the following command is utilized:

semgrep scan -j 100 --config p/default --config ./custom-semgrep-rules/ src > out.txt

In this command, -j 100 specifies the number of jobs for parallel execution, enhancing performance in larger codebases. The --config p/default flag pulls the community-curated default ruleset, while --config ./custom-semgrep-rules/ allows the team to apply organization-specific security policies.

To integrate with the GitHub Security tab, the results must be exported in the Static Analysis Results Interchange Format (SARIF). This is achieved through the following command:

semgrep scan -j 100 -q --sarif --config p/default --config ./custom-semgrep-rules/ src > semgrep-result.sarif

The use of the --sarif flag transforms the output into a machine-readable format that GitHub understands. The -q flag ensures a quiet output, which is preferable in CI environments to avoid cluttering the logs. Once the semgrep-result.sarif file is generated, it is uploaded as an artifact. This process is completed using the upload-sarif action, which allows findings to be visualized directly within the GitHub "Security" tab, providing developers with a native interface for triaging vulnerabilities.

Transitioning from Legacy Wrappers to Native Support

The ecosystem of Semgrep on GitHub has evolved from third-party wrapper scripts to native integration. Historically, users relied on the semgrep-action repository and the corresponding Docker image provided by returntocorp.

The returntocorp/semgrep-action Docker image was designed as a specialized environment to run Semgrep in CI. However, this approach is now considered deprecated. The semgrep-action project was officially archived by its owner on April 9, 2024, and is currently in a read-only state.

The impact of this deprecation is significant for legacy pipelines. Users who are still utilizing the wrapper script are urged to migrate to native Semgrep support. Native support offers better stability, updated engine versions, and more seamless integration with the GitHub ecosystem. The shift from a wrapper-based approach to a native approach removes a layer of abstraction, reducing the risk of version mismatch and simplifying the debugging process within the CI pipeline.

Semgrep AppSec Platform Integration

For organizations requiring a centralized view of security vulnerabilities across multiple repositories, the Semgrep AppSec Platform provides a managed orchestration layer. Integrating a project into the platform involves a guided setup that connects the GitHub account to the AppSec environment.

The process for adding a CI job through the platform is as follows:

  • Access the Semgrep AppSec Platform and sign in.
  • Navigate to the Projects section via the left sidebar.
  • Select Scan new project and choose the CI/CD option.
  • Choose GitHub Actions from the list of supported providers.
  • Select the specific repositories to be onboarded.
  • Commit the generated YAML configuration file to the repository.

If a repository is not visible during this process, it indicates a permission issue within the GitHub Application's Repository Access configuration. To resolve this, users must navigate to their GitHub profile settings, go to Applications (for personal accounts) or Organization Settings > GitHub Apps (for organization accounts), find the semgrep-app entry, and click Configure to grant the necessary access.

Once integrated, the platform automatically initiates a full scan. All subsequent findings are transmitted to the AppSec Platform, where they can be triaged and remediated. This integration removes the need for manual SARIF file management and provides a unified dashboard for security posture management.

Mitigating GitHub Actions Injection Vulnerabilities

A critical aspect of utilizing Semgrep in CI is using Semgrep to secure the CI pipeline itself. GitHub Actions workflows are susceptible to command injection attacks, particularly when handling untrusted user input. Semgrep provides a specific ruleset, p/github-actions, designed to detect these misconfigurations.

A common vulnerability occurs when user-provided data, such as an issue title, is passed directly into a run shell execution. This allows an attacker to inject malicious commands.

The following table compares unsafe and safe implementations of workflow actions:

Implementation Type Workflow Syntax Example Security Status Impact
Unsafe run: echo "${{ github.event.issue.title }}" Vulnerable Allows command injection via input
Safe env: TITLE: ${{ github.event.issue.issue.title }}
run: echo "$TITLE"
Secure Treats input as a literal string

The secure method utilizes environment variables to prevent premature evaluation. By assigning the untrusted input to an environment variable, the shell treats the value as a literal string, which is escaped and cannot be executed as code.

Furthermore, the p/github-actions ruleset checks for unsafe triggers such as pull_request_target. This trigger is dangerous because it grants write permissions to the GITHUB_TOKEN by default, which could be exploited by a malicious actor to modify the repository.

To further harden the CI environment, the following mitigations are recommended:

  • Set job-level permissions to read by default using the permissions: contents: read configuration.
  • Avoid the use of pull_request_target unless it is absolutely required for the workflow's functionality.
  • Limit the access of configured secrets from the organization-wide level to the specific repositories that require them.

To scan for these specific vulnerabilities, users can run the following command:

semgrep --config p/github-actions

Supported CI Ecosystems

While the focus is on GitHub Actions, Semgrep is designed to be provider-agnostic. The AppSec Platform explicitly supports a wide array of CI providers to ensure that security scanning is not siloed.

The supported CI providers include:

  • GitHub Actions
  • GitLab CI/CD
  • Jenkins
  • Bitbucket
  • CircleCI
  • Buildkite
  • Azure Pipelines
  • Semaphore

For providers not explicitly listed, Semgrep can still be integrated manually by utilizing the CLI in a custom shell script or container. Additionally, for those who wish to avoid modifying their CI pipelines entirely, Semgrep Managed Scans provide an alternative by onboarding and scanning repositories directly from the cloud without requiring any YAML configuration in the version control system.

Conclusion

The integration of Semgrep into GitHub Actions transforms the security paradigm from a reactive "find-and-fix" model to a proactive "prevent-and-protect" architecture. By leveraging diff-aware scanning during pull requests and full-branch scanning during pushes, developers can identify vulnerabilities at the earliest possible stage of the software development life cycle (SDLC). The transition from deprecated wrapper scripts to native integration and the use of the Semgrep AppSec Platform further streamlines this process, providing a scalable way to manage security across an entire organization.

Crucially, the security of the CI pipeline itself must be a priority. The use of the p/github-actions ruleset to identify command injection vulnerabilities and the implementation of the principle of least privilege through restricted GITHUB_TOKEN permissions are essential steps in preventing the CI/CD pipeline from becoming an attack vector. Through the combination of automated SAST scanning, SARIF-based reporting, and rigorous pipeline hardening, organizations can achieve a robust security posture that keeps pace with the speed of modern DevOps.

Sources

  1. sample-semgrep-ci GitHub Repository
  2. semgrep-action Docker Hub
  3. semgrep-action GitHub Repository
  4. Semgrep Documentation - Add Semgrep to CI
  5. Semgrep Documentation - GitHub Actions Injection

Related Posts