|
1 |
| -# Semgrep Pre-commit Hook |
2 |
| -## with diff-awareness ;) |
| 1 | +<!-- markdownlint-disable MD022 --> |
| 2 | +# Semgrep Pre-commit Hook with diff awareness 😉 |
3 | 3 |
|
4 | 4 | This is a pre-commit hook for [Semgrep](https://semgrep.dev) with diff-awareness. It will only run the changes made to the staged files. Yes, that's it.
|
| 5 | + |
| 6 | +## Why I wrote this? |
| 7 | + |
| 8 | +Pre-commit hooks generally chain the names of the staged files as arguments and pass them to the pre-commit entrypoint. By doing this, our hook will run on the entire staged files. This behavior is good for things like linter or test runners. The staged files may have just specific portions of the code that are modified. I wanted Semgrep to scan that diff alone. After learning about how pre-commit works and Semgrep runs in pre-commit, I understood there's no way to do this. So, I wrote this hook. |
| 9 | + |
| 10 | +## How does it work? |
| 11 | + |
| 12 | +What I have done is a hack. We first make a dummy commit with the staged files. Then, we run Semgrep on the diff between the dummy commit (with a `--no-verify` flag) and the previous commit. After that, we perform a `git reset --soft <previous commit>`. Now the repo returns to its original state. We see the exit code that semgrep returns and raises the same exit code. |
| 13 | + |
| 14 | +If there is a better way to do it, please let me know by raising an issue. |
| 15 | + |
| 16 | +I'm hoping that one day this will be a feature in Semgrep itself. Until then feel free to use this hook in your pre-commit configuration. |
| 17 | + |
| 18 | +## Usage |
| 19 | + |
| 20 | +1. Add the following to your `.pre-commit-config.yaml` file |
| 21 | + |
| 22 | + ```yaml |
| 23 | + repos: |
| 24 | + - repo: https://github.com/navhits/semgrep-precommit |
| 25 | + rev: 'v0.1.0' |
| 26 | + hooks: |
| 27 | + - id: semgrep |
| 28 | + # See semgrep.dev/rulesets to select a ruleset and copy its URL |
| 29 | + # Replace auto with the ruleset |
| 30 | + args: ["--config", "auto", "--error", "--disable-version-check", "--quiet", "--skip-unknown-extensions"] |
| 31 | + ``` |
| 32 | +
|
| 33 | +2. Ensure you have pre-commit installed |
| 34 | +
|
| 35 | + ```bash |
| 36 | + pip3 install pre-commit |
| 37 | + ``` |
| 38 | + |
| 39 | +3. Install the pre-commit hook |
| 40 | + |
| 41 | + ```bash |
| 42 | + pre-commit install |
| 43 | + ``` |
| 44 | + |
| 45 | +## Note |
| 46 | + |
| 47 | +The hook was written to work with Python 3.10 and above. If you are using an older version of Python, please upgrade to Python 3.10 or later. |
| 48 | +## Troubleshooting |
| 49 | + |
| 50 | +1. I get an error on macOS for `Library not found: libssl.1.1.dylib` on macOS |
| 51 | + * Try installing openssl via brew `brew install openssl@1.1` |
| 52 | + * Add the software to your path with `echo 'export PATH="/opt/homebrew/opt/openssl@1.1/bin:$PATH"' >> ~/.zshrc` |
| 53 | + * Create a symlink with `brew link openssl@1.1` |
0 commit comments