|
| 1 | +# Contributing to Security Code Scanner Semgrep Rules |
| 2 | + |
| 3 | +This guide is intended to help guide you though the process of adding a new Semgrep rule that this action will run. |
| 4 | + |
| 5 | +## Prerequisites |
| 6 | + |
| 7 | +Before contributing, ensure that you have [Semgrep](https://semgrep.dev/) installed. You can find installation instructions [here](https://semgrep.dev/docs/getting-started/quickstart). |
| 8 | + |
| 9 | +## Writing Your Own Rules |
| 10 | + |
| 11 | +When adding a new rule follow these guidelines: |
| 12 | + |
| 13 | +1. **Start with a Template** |
| 14 | + - Use the `rule.template.yml` file located in the root of this repository as a starting point. It includes standard fields and formatting we expect in all rules. |
| 15 | + - To create a new rule, copy the template and place it in the appropriate folder: |
| 16 | + ```bash |
| 17 | + cp rule.template.yml rules/src/ < language > / < your-rule-name > .yml |
| 18 | + ``` |
| 19 | + |
| 20 | +2. **Organize Rule Files** |
| 21 | + - Rules should be placed in the `rules/src` directory, organized by language or context. For example: |
| 22 | + ``` |
| 23 | + rules/src/js/your-js-rule.yml |
| 24 | + ``` |
| 25 | + - The rule name (defined in the `id` field) must match the filename, excluding the `.yml` extension. For example: |
| 26 | + - Rule filename: `your-js-rule.yml` |
| 27 | + - Rule ID: `your-js-rule` |
| 28 | + |
| 29 | +3. **Write and Iterate on the Rule** |
| 30 | + - Use the [Semgrep Playground](https://semgrep.dev/playground/new) to draft and refine your rule. If you've never written a Semgrep rule before, I recommend working through [Semgrep's interactive tutorial](https://semgrep.dev/learn). If you want to jump right in, check out Semgrep's [rule writing docs](https://semgrep.dev/docs/writing-rules/overview). |
| 31 | +
|
| 32 | +4. **Add Test Files** |
| 33 | + - Write tests for your rule in the `rules/test` directory, mirroring the structure of `rules/src`. For example: |
| 34 | + ``` |
| 35 | + rules/test/js/your-js-rule.js |
| 36 | + ``` |
| 37 | + - Test filenames should match the rule ID and filename, but with the correct file extension (e.g., `.js` for JavaScript tests). Example: |
| 38 | + - Rule filename: `your-js-rule.yml` |
| 39 | + - Test file: `your-js-rule.js`. |
| 40 | +
|
| 41 | +## Rule Metadata |
| 42 | +
|
| 43 | +In order for our rules to be rendered correctly within GitHub we require additional metadata properties. The screenshots below illustrate how these properties are displayed within GitHub's inline rule warnings and on the detailed rule information page. |
| 44 | + |
| 45 | +**Example Rule: hello-world** |
| 46 | + |
| 47 | +``` |
| 48 | +rules: |
| 49 | + - id: hello-world |
| 50 | + languages: |
| 51 | + - js |
| 52 | + severity: INFO |
| 53 | + metadata: |
| 54 | + tags: [security] |
| 55 | + shortDescription: Hello, World! |
| 56 | + help: "The Security Code Scanner is here to help review your code for vulnerabilities." |
| 57 | + confidence: HIGH |
| 58 | + message: We saw you said hello world and wanted to say hi back! |
| 59 | + pattern: | |
| 60 | + console.log("Hello, World!"); |
| 61 | +``` |
| 62 | +
|
| 63 | +**Metadata shown on the code scanning alert details page** |
| 64 | +<img width="600" alt="" src="https://github.com/user-attachments/assets/d3b79ddf-ab79-46ef-83d7-035fe41fa2fb" /> |
| 65 | +
|
| 66 | +**Metadata shown on an inline code scanning alert** |
| 67 | +<img width="600" alt="" src="https://github.com/user-attachments/assets/e918311f-94d8-4be0-86d8-cc6c30853740" /> |
| 68 | +
|
| 69 | +## Writing Tests For Your Rules |
| 70 | +
|
| 71 | +Testing is a critical step in ensuring the quality and reliability of your rules. Follow these steps: |
| 72 | +
|
| 73 | +1. **Write Thorough Test Cases** |
| 74 | + - Test files can include: |
| 75 | + - **Positive cases**: Examples where the rule should trigger. |
| 76 | + - **Negative cases**: Examples where the rule should not trigger. |
| 77 | + - Refer to the [Semgrep documentation on testing rules](https://semgrep.dev/docs/writing-rules/testing-rules) for more detailed guidance. |
| 78 | +
|
| 79 | +2. **Validate Rule Syntax** |
| 80 | + - Use the `bin/validate-rules` script to check for syntax errors: |
| 81 | + ```bash |
| 82 | + ./bin/validate-rules |
| 83 | + ``` |
| 84 | +
|
| 85 | +3. **Run Tests** |
| 86 | + - Use the `bin/test` script to verify that your rule behaves as expected: |
| 87 | + ```bash |
| 88 | + ./bin/test |
| 89 | + ``` |
| 90 | +
|
| 91 | +## Testing Rules Against Local Repositories |
| 92 | +
|
| 93 | +If you would like to test your rules against a local folder or directory on your machine, you can run the following command to perform a local scan: |
| 94 | +
|
| 95 | +```bash |
| 96 | +./bin/scan path/to/directory |
| 97 | +``` |
| 98 | + |
| 99 | +Note that Semgrep will scan _all_ files within the specified directory. In other words, if the directory contains multiple repositories, all of them will be scanned at once. |
| 100 | + |
| 101 | +## Contribution Workflow |
| 102 | + |
| 103 | +1. Create a new branch from the main branch for your changes. |
| 104 | +2. Add or update rule files and test cases as outlined above. |
| 105 | +3. Run the `bin/validate-rules` and `bin/test` scripts to ensure your changes are valid. |
| 106 | +4. Open a pull request with a clear explanation of the rule's purpose. |
| 107 | + |
| 108 | +## Notes |
| 109 | + |
| 110 | +- Always consider the specific needs and contexts of your codebase when writing rules. Rules should help identify issues or enforce patterns relevant to security. |
| 111 | +- If you encounter challenges or have questions, please reach out to @witmicko. |
0 commit comments