Open-source project
trailofbits/semgrep-rules avatar
trailofbits/semgrep-rules

Trail of Bits publishes the Semgrep rules it writes during audits

Semgrep queries developed by Trail of Bits.

533 stars60 forksGoAGPL-3.0

At a glance

What is it?
trailofbits/semgrep-rules is an AGPL-3.0 collection of Semgrep queries for Go, Python and six other languages, each tagged with an impact and confidence rating, and it is the same rule set the firm uses in its own security audits. The rules are also on the Semgrep registry, so running them takes one command.
Who is it for?
trailofbits/semgrep-rules is a good fit for a team that wants static analysis rules written by people who do security audits for a living, especially a Go shop worried about concurrency bugs, because the Go section is dominated by goroutine and mutex misuse rather than by generic pattern matching.
Can I use it commercially?
Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
Is it still maintained?
Yes. The repository last received commits 169 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Audit rules, published rather than kept internal

The repository contains Semgrep rules developed by Trail of Bits and made available to the public. The README states they are part of the firm's ongoing development efforts and are used in its security audits, in vulnerability research and in internal projects, and that they will evolve over time as new techniques are identified. That framing matters for how you read the collection. These are not generic lint rules written from a public advisory database. They are the checks a consultant actually wanted while reading somebody else's code, expressed in a form that anyone can run. The practical consequence is a rule set with a point of view: the Go section is dominated by concurrency mistakes, unreleased locks and unsafe casts rather than by taint tracking, which is what you would expect from a group that reviews systems software and blockchain code for a living. The licence is AGPL-3.0 and the last push was on 2026-05-07.

Running the whole collection from the registry

The easiest route is the Semgrep registry, where the rules are published under the trailofbits namespace. From the root folder of your project:

shell
$ semgrep --config "p/trailofbits"

The alternative is to clone the repository and point Semgrep at a single rule file:

shell
$ semgrep --config /path/to/semgrep-rules/semgreprule.yml

or at the whole cloned set, which is the way to run everything at once:

shell
$ semgrep --config /path/to/semgrep-rules/ .

The last form is what you want in CI, and it is also the form that makes the per-rule files visible to you as YAML you can read, copy and adapt. Cloning is what turns the collection from something you consume into something you can fork.

The flags that decide what actually gets scanned

Three flags change the scope of a run in ways that matter more than they look. By default Semgrep runs against all supported code files except those in your .gitignore, and adding --no-git-ignore makes it run against everything including ignored files and directories, which matters for vendored or generated code that a repository has chosen to exclude but that still ships:

shell
$ semgrep --config /path/to/semgrep-rules/ . --no-git-ignore

The --exclude flag takes a pattern, and the documented example is excluding all Go test files:

shell
$ semgrep --config /path/to/semgrep-rules/ . --exclude='*_test.go'

Excluding test files is a reasonable default for concurrency rules, since a test that deliberately exercises a race is a false positive generator. And -o writes results to a file instead of standard output:

shell
$ semgrep --config /path/to/semgrep-rules/hanging-goroutine.yml -o leaks.txt'

That last command in the README carries a stray quote, which is worth noticing only because you will copy it. The file name leaks.txt tells you what a typical triage artifact looks like: one rule, one output file, one finding class to work through.

Impact and confidence as separate axes

The rules table gives every rule an identifier, a link into the Semgrep playground, an impact rating and a confidence rating, which is the design decision that makes this collection usable. A rule that will only ever fire on a real bug and a rule that will sometimes fire on correct code are different instruments, and collapsing them into one list makes a static analysis tool either unusable or ignorable. The Go section shows the spread. A rule such as unsafe-dll-loading is marked with the highest impact and a lower confidence, because the pattern it matches has real consequences but the surrounding conditions vary. Rules such as iterate-over-empty-map carry the lowest impact with high confidence, since a redundant loop over an empty map is a smell rather than a defect. missing-unlock-before-return and missing-runlock-on-rwmutex sit in the middle, described as a lock that is never released before a function returns and a missing RUnlock on an RWMutex lock before returning from a function, both with the same confidence, so a triage policy can treat them as a pair.

What the Go rules actually look for

The Go list reads like a checklist of the mistakes that survive code review in concurrent Go. There is hanging-goroutine for goroutine leaks, racy-append-to-slice for concurrent calls to append from multiple goroutines, and racy-write-to-map for concurrent writes to the same map, which are the two classic data races that the race detector will not always catch for you. There is waitgroup-add-called-inside-goroutine for calls to sync.WaitGroup.Add inside anonymous goroutines, and waitgroup-wait-inside-loop for calls to sync.WaitGroup.Wait inside a loop, both of which are ways to deadlock a service rather than merely slow it. There is sync-mutex-value-copied for copying a sync.Mutex via value receivers, a mistake that silently defeats the lock. There is invalid-usage-of-modified-variable for a possible unintentional assignment when an error occurs, string-to-int-signedness-cast for integer underflows, and nil-check-after-call for possible nil dereferences. And the two ethereum rules stand apart: eth-rpc-tracetransaction detects attempts to extract trace information from an EVM transaction or block, with a note that exchange and bridge applications need extra logic encapsulating those endpoints so that values transferred during reverted call frames are not counted, and eth-txreceipt-status detects when a transaction receipt's status is read.

The other language directories and the Python rules

The repository is organised by language, with top level directories for go/, python/, javascript/, jvm/, rs/ for Rust, ruby/, swift/, hcl/ for Terraform, generic/ and yaml/. So the collection spans more than the two sections the README's visible table shows, and a team running a polyglot estate can pull from all of them. The Python section shows the same impact and confidence discipline applied to a different class of risk. msgpack-numpy is marked with the highest impact and reads as a warning about potential arbitrary code execution from functions relying on a particular library. lxml-in-pandas is marked for potential XXE attacks from loading lxml in pandas. automatic-memory-pinning is a low-impact high-confidence check for PyTorch memory not being automatically pinned, which is a performance and stability note rather than a security one. That last one is instructive about the collection as a whole: a rule that only says do this for efficiency would be out of place in a security audit, but as a check for correct resource handling it belongs.

Where this rule set is the wrong choice

Three cases. The first is a team that wants a single configuration to cover every language in the estate, because these rules are per-language directories with per-rule YAML, and the maintenance of that configuration is on you. The second is a team that wants findings it can trust without triage, because a collection where impact and confidence vary independently is designed to be triaged, and adopting it as a blocking gate without reading the ratings produces a backlog of findings nobody owns. The third is anyone expecting a stable, versioned rule set, because there are no GitHub releases and the README says the rules will evolve as new techniques are identified, so a rule that fires today may change shape next quarter and break your suppression file. Against a language-native linter, the difference in approach is that a Semgrep rule matches syntactic patterns with semantic constraints and carries a fix description in the rule file itself, which makes it far easier to write a rule for a specific property of a codebase, and far easier for a rule to be wrong in a way that a type checker would not be. The companion resource is the Testing Handbook page on Semgrep, which the README points to for guidance.

Editorial conclusion

trailofbits/semgrep-rules is a good fit for a team that wants static analysis rules written by people who do security audits for a living, especially a Go shop worried about concurrency bugs, because the Go section is dominated by goroutine and mutex misuse rather than by generic pattern matching. It is a poor fit for a team that wants one rule file to cover a whole codebase, and a poor fit if you need rules that are stable over years, because the README says they will evolve as new techniques are identified. Check three things before you wire them into a build: that your Semgrep version supports the rule syntax these files use, that you read the impact and confidence columns before deciding what blocks a merge, since the table distinguishes a high-impact low-confidence rule from a low-impact high-confidence one, and that you are prepared to run the rules on more than one language, because the repository is organised by language directory and your Go rules will say nothing about your Python.

Frequently asked questions

How do I run the Trail of Bits Semgrep rules?

The easiest way is from the Semgrep registry, running semgrep --config "p/trailofbits" from the root of your project. Alternatively clone the repository and run a single rule with semgrep --config /path/to/semgrep-rules/semgreprule.yml, or the whole set with semgrep --config /path/to/semgrep-rules/ .

What do the impact and confidence ratings on the rules mean?

Every rule in the table carries both an impact rating and a confidence rating, so a high-impact low-confidence rule and a low-impact high-confidence rule are distinguishable. Rules are also linked into the Semgrep playground so you can see what a given pattern matches before running it across a codebase.

Which Go concurrency bugs do these Semgrep rules catch?

The Go section includes hanging-goroutine for goroutine leaks, racy-append-to-slice for concurrent append calls, racy-write-to-map for concurrent writes to the same map, waitgroup-add-called-inside-goroutine and waitgroup-wait-inside-loop for WaitGroup misuse, sync-mutex-value-copied for copying a sync.Mutex by value, and missing-unlock-before-return and missing-runlock-on-rwmutex for locks not released before a function returns.

Can I exclude files from a Semgrep run with these rules?

Yes. The --exclude flag takes a pattern, and the documented example is --exclude='*_test.go' to skip Go test files. The --no-git-ignore flag extends the scan to files your .gitignore excludes, and -o writes results to a file such as leaks.txt.

Which languages do the Trail of Bits Semgrep rules cover?

The repository top level holds directories for go, python, javascript, jvm, rs, ruby, swift, hcl, generic and yaml, so the collection spans those languages. The README's visible table details the Go and Python rules, including Python checks for potential XXE attacks from loading lxml in pandas and for potential arbitrary code execution in msgpack-numpy usage.

Official sources

  1. Issues
  2. License: AGPL-3.0
  3. README
  4. trailofbits/semgrep-rules on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/trailofbits-semgrep-rules.svg)](https://hysenlabs.com/projects/trailofbits-semgrep-rules)

Was this useful?