Skip to main content

Contributing to Semgrep rules

Introductionโ€‹

There are two ways in which you can contribute to the Semgrep rules repository:

For users of Semgrep App
Contribute to the Semgrep rules repository through Semgrep App. This workflow is recommended. See Contributing through Semgrep App (recommended). This workflow creates the necessary pull request for you and streamlines the whole process.
For contributors to the repository through GitHub
Contribute to the Semgrep rules repository through a pull request. See the Contributing through GitHub section for detailed information.

To contribute to the Semgrep rules repository through Semgrep App, follow these steps:

  1. Go to Semgrep App Editor.
  2. Click Create New Rule.
  3. Make one of the following steps:
    • Create a new rule and test code, and then click Save. Note: The test file must contain at least one true positive and one true negative test case to be approved. See the Tests section of this document for more information.
    • Select a rule from a category in Semgrep Registry. Modify the rule or test code, click Save, and then Fork.
  4. Click Share.

This workflow automatically creates a pull request in the GitHub rules repository. Find more about the rules repository by reading the Rule writing and Tests sections.

Contributing through GitHubโ€‹

Fork our repository and make a pull request; we'll contact you about signing our Contributor License Agreement (CLA). Install pre-commit (see installing pre-commit) and make a pull request to the rules repository with two files:

  1. The semgrep pattern (as YAML file).
  2. The test file (with the file extension of the language or framework). The test file must contain at least one true positive and one true negative test case to be approved. See the Tests section of this document for more information.

See an example of a pull request to the rules repository. Pull requests require the approval of at least one maintainer and successfully passed CI jobs.

Find more about the rules repository by reading the Rule writing and Tests sections.

Installing pre-commitโ€‹

If you are contributing to the rules repository through GitHub but you are not contributing through sharing your rule in Semgrep App, install pre-commit. Follow pre-commit installation documentation. Once pre-commit is set up you may commit code and create pull requests to rules repository.

Rule writingโ€‹

Understanding rule namespacingโ€‹

The namespacing format for contributing rules in the rules repository is <language>/<framework>/<category>/$MORE. If the rule does not belong to a particular framework, add it to the language directory, which uses the word lang in place of the <framework>.

Rule messagesโ€‹

A well-written rule message includes:

  1. Description of the pattern. For example: missing parameter, dangerous flag, out-of-order function calls.
  2. Description of why this pattern was detected. For example: logic bug, introduces a security vulnerability, bad practice.
  3. An alternative that resolves the issue. For example: Use another function, validate data first, and discard the dangerous flag.

For an example of a good rule message, see: this rule for Django's mark_safe.

info

'mark_safe()' is used to mark a string as safe for HTML output. This disables escaping and may expose the content to XSS attacks. Use 'django.utils.html.format_html()' to build HTML for rendering instead.

Rule quality checkerโ€‹

When you contribute rules to the rules repository, our quality checkers (linters) evaluate if the rule conforms to r2c standards. The semgrep-rule-lints job runs linters on a new rule to check for mistakes, performance problems, and best practices for submitting to the Semgrep rules repository. To improve your rule writing, you can actually use Semgrep itself to scan semgrep-rules.

Including additional details with rule metadataโ€‹

Rules require a metadata key where you can specify a category of the rule, the technology which a rule is targeting, and give additional information as references. See the following example of a rule with all metadata fields check-dynamic-render-local-file-include.

Include the following keys under the metadata field:

  • Include category field, and then choose one of the following values for this field:
    • security - If you use this value, include owasp and cwe fields as well. To see these fields in use, check the example rule, and Common Weakness Enumeration (CWE) and OWASP categories for more details. If a security rule is detecting the use of a bad pattern, append an audit to your namespace. This distinguishes the rule from a security rule that is aiming to detect a vulnerability.
    • best-practice
    • correctness
    • maintainability
    • performance
  • Include the technology field. This is usually the library or framework the rule is targeting, for example django. If it's for the language itself, use only the language name, for example python.
  • Include the references field. References can provide additional context to users of the rule. It is good practice to include at least one reference for each rule.
  • The use of the YAML multiline string operator >- when rule messages span multiple lines. This presents the best-looking rule message in the command-line.

Rule examples:

Testsโ€‹

Include a test file to accompany new rules. A good test file includes the following:

  • At least one test where the rule detects a finding. This is called a true positive finding.
  • At least one test where the rule does not detect a finding. This is called a true negative finding.

See an example of this approach in the Semgrep App.

Test file names must match the rule file name, except for the file extension. For example, if the rule is in my-rule.yaml, name the test my-rule.js. (You can use any valid extension for the target language.)

In the test file, mark what is demonstratively expected to be a finding. See the examples of the rule and test file below:

Rule file:

rules:
- id: my-rule
pattern: var $X = "...";
โ€ฆ

Test file:

// ruleid: my-rule
var strdata = "hello";
// ok: my-rule
var numdata = 1;

For more information, visit Testing rules.