Skip to main content
Semgrep logo

My Semgrep C/C++ ruleset is ready for prime time again

July 15, 2026|Marco IvaldiBy Marco Ivaldi

“Retention of critical thinking and problem solving skills in an AI saturated world will probably become a superpower for those who can resist the autocomplete revolution.”
— Bas Alberts

“I spend a truly unreasonable amount of my life writing YAML.”
— William Woodruff

TL;DR

For those with an attention span shorter than a goldfish, a quick summary of what’s going on here:

So, bear with me while I introduce you to my newly-improved Semgrep C/C++ ruleset.

A blast from the past

First, a quick review of my previous work.

As stated in the summary above, in 2022 I released my custom Semgrep rules for C/C++ vulnerability research and published a well-received article on how to become a better security researcher, using the power of Semgrep to automate some menial tasks even against binary targets.

At the end of 2023, I published a big update to my ruleset. It featured several new rules, a reorganization into three priority tiers, and general accuracy and performance tweaks. These improvements were driven by the experience gained in the field during my vulnerability research efforts and by attending training courses on this subject (namely, OST2‘s Vulns1001 and Vulns1002, and InfoSect‘s Code Review). Finally, I extensively tested my rules against available SAST test suites and test cases, conveniently collected by NIST’s Software Assurance Metrics And Tool Evaluation (SAMATE) project.

Again, these updates sparked quite a bit of interest in the security community, which led me to implement similar functionality in the form of weggli patterns.

Besides presenting my toolkit, in my blog posts I also focused on providing an actionable vulnerability research workflow that can be summarized as follows:

  1. Read the documentation (but don’t believe it!) to uncover attack surface and interesting paths.
  2. Scan with static analysis tools against interesting paths in the codebase.
  3. Review scan results to quickly mark hotspots in code where bugs may be.
  4. Understand relevant code around the hotspots to identify potential vulnerabilities.
  5. Confirm vulnerabilities via further analysis, dynamic testing, targeted fuzzing, etc.
  6. Identify variants of confirmed vulnerabilities in other parts of the codebase.

Revisiting this workflow in 2026, you’ll probably want to weave AI into each step as a force multiplier. Don’t worry though, fuzzer jobs are (probably) safe for now.

For further considerations on methodology applied to real-world scenarios, check out my past articles.

Here we go again

When I created my ruleset, Semgrep’s support for C/C++ was still experimental. It wasn’t until 2024 that Semgrep started to fully support C and C++, languages that are notoriously difficult to analyze statically, due to several inherent complexities (most notably, an ambiguous and hard-to-parse grammar chiefly because of preprocessor directives and macros that are expanded before compilation).

As a result of this fundamental improvement, scanning of C/C++ code with Semgrep became more stable and reliable, new patterns were made possible, and handling of C/C++-related GitHub issues became smoother.

Fast forward to late 2025.

With the above message, cross-posted to my social media accounts, I announced the availability of the v1.1.0 release of my ruleset, which included:

  • New rules for detecting high-entropy assignments and ReDoS vulnerabilities.
  • Several enhancements to existing rules.
  • Reduced false positives without sacrificing coverage.
  • Optimized and more performant patterns.
  • Overall better documentation, including a SARIF sample.

I also issued a call to action to software developers and security researchers to test the new version of the rules, open issues, and submit pull requests with bug fixes and enhancements.

Some researchers responded, and also thanks to their valuable contributions I’ve kept working on improving my ruleset. After half a year of development and testing, my work culminated in the v2.0.0 release, which is a major update and the first version of my ruleset to be included as an external source in the official Semgrep registry.

What’s new in v2.0.0?

Quite a lot is new in this latest release. The repository now features 50 Semgrep rules (and counting). The most relevant changes are:

  • I’ve added detections for plenty of interesting new API calls (but not too many to avoid cluttering results) that were missing in previous versions of the ruleset, including some str*, mem*, and *printf family functions, Windows-specific functions, additional file access and command execution APIs, and more.
  • I’ve improved pattern matching in several rules, to better handle array declarations and memory allocations, and detect dangerous uses of *printf.
  • I’ve optimized uses of the deep inspection operator to match more potential misuse cases for mallocfree, and set*id.
  • I’ve excluded uninteresting matches and generally reduced false positives where possible (but not so much as to start missing true positives as well).
  • I’ve improved performance of the slowest rules based on extensive benchmarking conducted against real-world code.
  • I’ve added several new code samples for testing, and generally improved the project documentation.
  • I’ve rearranged rules based on the new subcategory, likelihood, and impact metrics, and taken care of some general housekeeping.
  • Finally, I’ve added all metadata required to contribute the rules to the Semgrep registry, along with a GitHub workflow for ruleset validation.

The intent of these changes was to carefully enrich and improve the ruleset wherever possible, without breaking existing tools and workflows that rely on it.

I believe I’ve stayed true to the original philosophy behind my rules, that is: we don’t care if there are some false positives as long as true positives aren’t missed. This ruleset is not meant to be used in CI/CD pipelines as is, but only as a tool to assist developers and security researchers in their work by highlighting potential vulnerability hotspots. This ultimately requires human (or at least AI 🤖) intervention to customize the rules where needed and sift through Semgrep’s findings.

Now for the fun part

Ok, time to apply my Semgrep ruleset to a real-world scenario. Let me show you how to use it against a large collection of binary files that I’ve extracted from one of the latest Zyxel firmware packages.

First, let’s batch-decompile and extract the pseudocode of all target binaries, using my IDA plugin haruspex:

Installing and running haruspex against 280 binaries
280 binary files (for a total of 14 MB) were analyzed and decompiled in less than 14 minutes

It took less than 3 seconds per binary to analyze and decompile every function. Not bad! But this is a (hot) topic for another article. Let’s stick to Semgrep here:

23.399 pseudocode files were fully scanned in less than 6 minutes

More than 98% of lines have been parsed. Not bad for a Semgrep scan against pseudocode! This is the view of the scan results that we get in VS Code with SARIF Explorer:

I ❤️ SARIF Explorer

And here’s literally the first potential vulnerability that’s been flagged by Semgrep in this codebase:

Hmm… I wonder if the input source is attacker-controlled?

Well, I guess I have to go now… My friend Claude and I just got a few thousand vulnerability hotspots to check 🪲

“We went from talking like a pirate to Neuromancer real quick.” — Bas

Give me the goods

If you’ve made it this far, you’ve earned a couple of links!

The easiest way to use the ruleset for your own projects is via the official 0xdea rulepack, as follows:

raptor@fnord ~/D/z/_/zyx.dec> brew install semgrep
...
raptor@fnord ~/D/z/_/zyx.dec> cd 2FAd.dec/
raptor@fnord ~/D/z/_/z/2FAd.dec> semgrep --config "p/0xdea"
...
✅ Scan completed successfully.
• Findings: 668 (668 blocking)
• Rules run: 48
• Targets scanned: 65
• Parsed lines: ~99.1%
• No ignore information available
• For a detailed list of skipped files and lines, run semgrep with the --verbose flag
Ran 48 rules on 65 files: 668 findings.
raptor@fnord ~/D/z/_/z/2FAd.dec>

See the README file in the repository for additional usage tips.

Looking ahead

I still have a substantial TODO list of items that I’d like to implement for both my Semgrep rules and weggli patterns for C/C++ (and binary) vulnerability research. In addition, I have a new research project involving Semgrep that’s currently in full swing. Hopefully, I’ll be able to share it before the end of the year.

Meanwhile, I’ll leave you with a psychedelic treat by Undefined Behavior 🍄 (how appropriate):

See you space cowboy! 🪐 🤠