Custom Engine Rules
This section explains the process of how to add your own custom engine rules for specific languages in order to use it as a part of your scans.
At the moment, you can add your own custom rules for the amazing Semgrep tool. We are planning to support a range of other tools and allow you to plugin your own rules and patterns, which will be instantly available to scan every new line of code across all your repositories.
Table of Contents
To get started with leveraging your own rules for Semgrep, there are three steps to follow:
- Step 1: Write your rule and test it in the playground
- Step 2: Add the rules to the custom engine rules section on the GuardRails dashboard
- Step 3: Make a test PR/MR to see that all is working well
Let's take a look at our simple example rule code:
- id: custom-guardrails-test-rule
- pattern: |
- pattern-not: |
message: The dangerousFunction is called.
grTitle: Use of dangerousFunction()
rules: object is required to make it a proper Semgrep rule file. The
rules objects have an array of
id objects that are used to uniquely identify a
rule must have either one of these
pattern-regex. In our case we are using
patterns, which can have an array of
Message is another required element that can provide more details about what this rule identifies. The last two required elements are
severity which could be either
languages. A list of supported languages can be found here.
In addition to these objects and elements that are required by Semgrep, we have to add 3 elements to the
metadata object to help GuardRails understand how to map and process these rules. The first element,
grId, is the only required element. It must have one of these
- GR0001: Insecure Use of SQL Queries
- GR0002: Insecure Use of Dangerous Function
- GR0003: Insecure Use of Regular Expressions
- GR0004: Hard-Coded Secrets
- GR0005: Insecure Authentication
- GR0006: Insecure Access Control
- GR0007: Insecure Configuration
- GR0008: Insecure File Management
- GR0009: Insecure Use of Crypto
- GR0010: Insecure Use of Language/Framework API
- GR0011: Insecure Processing of Data
- GR0012: Insecure Network Communication
- GR0013: Using Vulnerable Libraries
- GR0014: Privacy Concerns
- GR0015: Information Disclosure
grTitle element will determine what is shown when the issue is being flagged in a PR/MR or shown in the dashboard. Finally, the
grDocs element can point to any documentation link, even to your intranet and will allow developers to see how to fix a flagged issue.
As the next step, you should create some test code to make sure that the rule is working as expected. The example test code is shown below:
console.log("calling dangerousFunction() with static string");
var userInput = req.body.danger;
lib.dangerousFunction("static input is fine"); // compliant
console.log("calling dangerousFunction() with user input");
lib.dangerousFunction(userInput); // non-compliant
console.log("dangerousFunction() called successfully");
A screenshot of a successful execution looks on semgrep.dev is shown below:
More up-to-date information on how to write Semgrep rules can be found here.
Now that we have tested our rules in the Semgrep playground, it is time to add them to the GuardRails dashboard. Login to the dashboard first and then browse to
This will look like this:
You can copy the rules yaml text into the textarea and press save.
Note that you can also configure the engine behavior. For example, you can prevent your custom rules from running, or you can ignore the core rules that we have created and shipped with each Semgrep-specific engine from running. If your own rules are too noisy, you can quickly disable them, without having to delete the textarea, or if you just want to run your own rules, then you can disable the GuardRails rules from running.
As an example we show a PR in the GitHub UI that identifies that issue:
And also how this looks in the GuardRails dashboard:
That's it, from this moment onwards every use of
dangerousFunction() would be flagged across your entire portfolio. No need to directly tinker with any tools, CI/CD pipelines, etc. It just works :)