Static code analysis in 2026: revisit Semgrep, Opengrep and SonarQube Community Build before you add another code scanner to CI

Most teams add a code scanner to CI in an afternoon. A YAML job, a default rule pack, a green tick. Six months later, the scanner has raised a few thousand findings, nobody reads them, and the one finding that mattered sat in the list next to four hundred warnings about string formatting. Static analysis is cheap to switch on and expensive to make useful. The tool you choose matters, but how you choose rules, where you put the gate and who owns the noise matter more.

This post compares three free tools that teams shortlist for static application security testing (SAST) and code quality when they run things themselves: Semgrep Community Edition, Opengrep (the community fork of Semgrep) and SonarQube Community Build. Two of them are pattern engines you run as a command in CI. The third is a server with a dashboard, quality gates and history. They overlap, but they are not the same kind of tool.

Static analysis is one layer among several. For leaked keys and tokens, see secret scanning in 2026. For known vulnerable libraries and images, see vulnerability scanners in 2026, and for keeping those libraries current, dependency updates in 2026. The CI runner that will execute all of these is covered in self-hosted CI in 2026, and the forge where pull request comments land in self-hosted Git forges in 2026.

We end with a small, safe drill that ran Semgrep CE and Opengrep on the same tiny rules, and a plain list of what we did not run.

A scenario to keep us honest

Imagine a company in Mysuru that builds booking, billing and guest management software for heritage hotels, homestays and tour operators across Karnataka. The company is invented for this post. It has about 35 engineers, a two-person platform team and one security engineer who joined this year.

The setup today:

  • A Django monolith for bookings and billing, a few Java Spring Boot services for payments and partner integrations, a TypeScript front end, and two small Go services.
  • Code on a self-hosted GitLab, with GitLab CI runners on rented VMs.
  • An old SonarQube Community Edition server from the 9.9 LTS line, installed in 2023 on a single VM with PostgreSQL, and never upgraded since. It analyses the main branch of the monolith once a night. The dashboard shows a little over two thousand open issues. Nobody looks at it.
  • Last year a developer added a Semgrep job to one repository with a registry rule pack and no settings. It runs on every merge request, fails nothing, and its output is a long log that nobody scrolls.

Four things push the team to revisit this. First, a penetration test found a SQL injection in a reporting view that built a raw query by string concatenation; neither scanner in place was set up to stop that merge. Second, developers want findings in the merge request, not in a nightly dashboard, and the old SonarQube does not analyse branches or merge requests. Third, the new security engineer wants to write a few rules specific to the company, such as “never pass a guest’s phone number to the logger”. Fourth, product managers are planning a paid “code health report” for partner developers who build plug-ins on the booking platform, and somebody asks whether the licences of these tools allow that.

We will come back to Mysuru in the worked plan.

The short version

  • Semgrep CE and Opengrep are command line pattern engines. You write rules that look like the code you want to find, and the engine matches them on the syntax tree. They are fast, easy to run in a CI job, and as good as the rules you give them.
  • Semgrep CE (1.182.1 on PyPI, 22 October 2026) has an LGPL 2.1 engine. Since December 2024, the rules maintained by Semgrep, Inc. are under the Semgrep Rules License v1.0, which allows internal use but not use in competing products or SaaS offerings. Some output fields, such as finding fingerprints, now need a login.
  • Opengrep (1.33.0, 27 October 2026) is a fork of Semgrep 1.100.0, launched in January 2025 by a group of application security companies. The engine is LGPL 2.1, ships as self-contained signed binaries, and adds cross-function taint tracking within a file through a flag. It does not come with a maintained rule set of its own, so rules are your job.
  • SonarQube Community Build (26.10, released on GitHub on 12 October 2026) is a server with a web UI, quality profiles, quality gates and history, for code quality and some security rules. The platform is LGPL 3.0, but the language analysers inside it have been under the Sonar Source-Available License since December 2024. The free build analyses only the main branch, has no pull request decoration and no taint analysis for injection flaws.
  • The rules you enable, and where the gate sits, matter more than the engine. Start small, gate on new findings only, and give every rule an owner.

Where things stand on 29 October 2026

Semgrep Community Edition. The latest GitHub release is v1.182.0, published on 21 October 2026 at 1:57 AM IST, and PyPI has 1.182.1, uploaded on 22 October 2026 at 7:43 AM IST. Releases come roughly every week: v1.181.0 on 14 October, v1.180.0 on 7 October and v1.179.0 on 2 October 2026 (GitHub dates). The 1.182.0 notes add alpha support for Objective-C, update the Terraform (HCL) and Lua grammars and fix C++ range-based for loops with structured bindings. The PyPI package needs Python 3.10 or newer. The engine is licensed under LGPL 2.1.

Opengrep. The latest release is 1.33.0, published on GitHub on 27 October 2026 at 6:28 PM IST, a small release about ASP.NET handler files. Before it came 1.32.0 (22 October), 1.31.0 (15 October) and 1.30.2 (7 October 2026). The project also publishes alpha builds of a 2.0 line with “nopython-interfile” in the tag name; we did not test them. Each release has binaries for Linux (glibc and musl), macOS and Windows, with Cosign signature and certificate files next to each binary. The engine is LGPL 2.1.

SonarQube Community Build. The latest release is 26.10.0.133078, published on GitHub on 12 October 2026 at 3:31 PM IST and announced on the Sonar community forum on 14 October. The announcement lists three built-in quality profiles for each language (Sonar way core, Sonar way extended and Sonar way comprehensive), new rules for several languages, and two changes worth reading before you upgrade: installing from the ZIP file is deprecated in favour of the Docker image or Helm chart, and the “Anyone” group has been removed, so unauthenticated analysis is no longer possible. Community Build releases every month and uses calendar versions (YY.M.0.build); there is no long-term support line for it.

Licences changed in late 2024, and that still shapes the choice

Two of the three projects changed their licensing terms within a few weeks of each other, and the third exists because of one of those changes.

Semgrep, 13 December 2024. Semgrep announced that Semgrep OSS would be called Semgrep Community Edition, and that rules maintained by Semgrep, Inc. move to the Semgrep Rules License v1.0. The announcement says these rules are “available only for internal, non-competing, and non-SaaS contexts”. The engine stayed LGPL 2.1. At the same time, certain fields in JSON and SARIF output were reserved for the logged-in commercial engine (from Semgrep 1.100.0), and features marked experimental moved to the commercial engine. Vendors got a grace period until 31 January 2025. Semgrep’s own documentation says the rules were earlier under LGPL 2.1 with the Commons Clause.

Opengrep, January 2025. On 23 January 2025, a press release announced Opengrep, a fork of the Semgrep engine backed by more than ten application security companies, including Aikido Security, Arnica, Amplify Security, Endor Labs, Jit, Kodem, Legit Security, Mobb and Orca Security. The stated reason was the move of features behind a commercial licence. The press release also said the group intends to place Opengrep under foundation management. The project’s README says it is a fork of Semgrep 1.100.0. Its first stable release, 1.0.0, came on 18 March 2025.

SonarQube, November and December 2024. On 29 October 2024 Sonar announced that SonarQube Community Edition would be called SonarQube Community Build, with the change appearing in the product in December. On 19 November 2024 it announced the Sonar Source-Available License v1 (SSALv1) for its language analysers. According to that announcement, Community Build without the analysers stays under LGPL 3.0, but the analysers, which do the actual work of finding issues, are source-available under SSALv1. The conditions include that you may not use the software to offer a product or service with the same or substantially similar functionality as SonarQube, and that derivative works must be released publicly under SSAL. The first renamed release, 24.12, arrived on 2 December 2024. Its announcement also said that .NET analysis in Community Build no longer includes the advanced dataflow bug detection rules, and that secrets detection in the free build covers commonly used secrets only.

What this means in practice. For a company that scans its own code for its own use, all three are free to use. The licence questions start when you sell something built on them: a hosted scanning service, a product that bundles rules, or a paid report for other people’s code. In those cases, read the Semgrep Rules License, the SSALv1 text and the LGPL obligations with a lawyer. For Mysuru’s “code health report” for partners, this is a real question, not a formality.

The first question: what are you trying to catch?

Before comparing tools, write down what you want the scanner to do. Three kinds of goals get mixed up:

  • Known dangerous patterns. Raw SQL built from strings, shell commands with user input, disabled TLS checks, weak hash functions for passwords, debug mode in production settings. Pattern engines are very good at this, and you can write a rule for your own framework in minutes.
  • Data flow from input to danger. A request parameter that travels through three functions before reaching a database call. This needs taint analysis. How far the tool can follow the data (within one function, across functions in a file, across files) decides what it finds and what it misses.
  • Code quality and maintainability. Duplicated code, overly complex functions, unused variables, test coverage trends, and the long tail of “this will become a bug”. This is SonarQube’s home ground.

Then decide where the result goes. A rule that blocks a merge request needs to be precise. A rule that only shows up on a dashboard can be broader. Most noise problems come from putting broad rules in a blocking gate, or putting precise rules where nobody sees them.

What each tool is

Semgrep Community Edition

Semgrep began as sgrep, a syntactic grep written at Facebook by Yoann Padioleau. The company r2c revived and generalised it and renamed it Semgrep in 2020, according to Semgrep’s own history post; the company itself took the Semgrep name in April 2023. The GitHub repository was created in December 2019. The engine is written mostly in OCaml, with a Python command line wrapper that you install with pip, Homebrew or a container image.

You write rules in YAML. A rule has an id, a list of languages, a message, a severity and one or more patterns. Patterns look like code, with metavariables such as $X that match any expression, and an ellipsis (…) that matches any sequence of arguments or statements. You can combine patterns with pattern-not, pattern-inside and pattern-either, and switch a rule to taint mode with sources, sinks and sanitisers. In the Community Edition, taint analysis follows data within a single function. Rules can live in your repository, so they are reviewed like code.

Here is the kind of small rule we used in the drill:

rules:
  - id: subprocess-shell-true-nonconstant
    languages: [python]
    severity: ERROR
    message: non-constant command string with shell=True
    patterns:
      - pattern: subprocess.run($CMD, shell=True, ...)
      - pattern-not: subprocess.run("...", shell=True, ...)

Semgrep also runs a public rule registry. In the December 2024 announcement, Semgrep said Community Edition comes with more than 2,800 rules and needs no login. The company’s commercial platform adds cross-file analysis, its own Pro rules, dependency and secrets scanning, triage and dashboards; those are outside the scope of this post.

Opengrep

Opengrep is the same engine family, forked at Semgrep 1.100.0 in early 2025 (the GitHub repository was created in mid-December 2024). The rule format is the same, and the README says existing Semgrep rules and rulesets work unchanged. The command is opengrep scan instead of semgrep scan, and many flags are the same, though Semgrep’s own comparison page notes that individual arguments have diverged.

What Opengrep has added since the fork, according to its README and release notes:

  • Cross-function taint within a file, through the –taint-intrafile flag, including constructor and field tracking and higher-order functions. Semgrep’s comparison page says the equivalent in Semgrep is a commercial capability.
  • Extra languages, such as Visual Basic, Apex and Elixir, which the README says are not in Semgrep CE, plus newer language versions for C# and PHP.
  • Packaging: self-contained binaries compiled from OCaml, with no Python runtime needed, signed with Cosign.
  • Full output: fingerprints and metavariable values in JSON and SARIF output, without a login.

What it does not have is a maintained rule set. The opengrep-rules repository on GitHub, created in November 2025, describes itself as a fork of semgrep-rules as of 13 December 2024, says the rules are “intended for research, testing and benchmarking”, and carries the older Commons Clause plus LGPL 2.1 licence. In practice, you write your own rules, adopt rules from other sources with compatible licences, or use that snapshot knowing it is not updated. Opengrep also has no official IDE extension at the time of writing, according to Semgrep’s comparison page.

SonarQube Community Build

SonarQube is a different kind of tool. It is a Java server with a web UI, backed by a database and an embedded Elasticsearch, and the source code is analysed by a separate scanner (sonar-scanner, or the Maven, Gradle and .NET scanner variants) that runs in your CI job and uploads results to the server. The server keeps history, shows trends, applies quality profiles (which rules are on) and quality gates (the conditions a project must pass, such as “no new bugs” or “coverage on new code above a threshold”). The GitHub repository dates from January 2011.

Its rules are written by Sonar in its language analysers, not by you in YAML. You choose and tune profiles, mark issues as false positives or accepted in the UI, and in recent versions choose between three built-in profile levels per language.

The Community Build documentation lists these languages and formats as supported in the free build: Java, Kotlin, Scala, C#, VB.NET, Python, PHP, Ruby, Go, Rust, JavaScript, TypeScript, CSS, HTML, XML, Flex, plus infrastructure files for Docker, Kubernetes and Helm, Terraform, CloudFormation and Azure Resource Manager, and basic secrets detection. C, C++, Objective-C, Swift, Dart and PL/SQL, among others, are not in the free build.

The free build also has three limits that matter for CI design, from Sonar’s feature comparison table:

  • Only the main branch is analysed. There is no branch analysis, and no pull request analysis or decoration.
  • Injection vulnerability detection (Sonar’s taint analysis) is not included.
  • Sonar’s editions comparison says the Community Build processes one analysis at a time, and recommends it for code bases under about 100,000 lines. This is Sonar’s own guidance, not a measured limit we checked.

Side by side

Licence and governance

  • Semgrep CE: engine LGPL 2.1, controlled by Semgrep, Inc. Semgrep-maintained rules under the Semgrep Rules License v1.0, which is not an open source licence; internal use is allowed, competing products and SaaS are not. Third-party rules in the registry keep their own licences.
  • Opengrep: engine LGPL 2.1, maintained by a consortium of vendors with a full-time developer team, according to the project website. The press release said foundation management is the plan; check the current status before you rely on it. No maintained rules of its own.
  • SonarQube Community Build: platform LGPL 3.0, analysers SSALv1 (source-available, with a non-compete clause), controlled by Sonar.

None of the three sits under a neutral foundation today. Look at release pace and who merges pull requests. All three released several versions in October 2026 alone.

How rules work

  • Semgrep CE and Opengrep: rules are YAML files you can read, write, test and keep in Git. A new rule for your own logging helper or ORM takes minutes. Each finding points to a rule you can open and change. The downside is that the quality of results depends fully on the rules, and broad community rules can be noisy.
  • SonarQube: rules are built into the analysers, with descriptions and examples in the UI. You can turn rules on and off and set parameters, but writing a new rule means writing a plugin in Java against the analyser APIs, which few teams do. The upside is a large, curated rule set for quality issues that you do not maintain yourself.

Depth of analysis

  • Semgrep CE: matches on the syntax tree, with constant propagation and taint analysis within a single function. A flow that passes through a helper function is not followed.
  • Opengrep: same by default. With –taint-intrafile, taint follows calls between functions in the same file. Semgrep’s comparison page describes Opengrep’s analysis scope as single file, so flows across files are not followed.
  • SonarQube Community Build: rich per-language analysis for bugs and code smells, plus security hotspots (code that a human should review), but no injection taint analysis in the free build.

None of the free options follows data across files. If your request handler is in one file and your raw SQL helper is in another, a free pattern engine sees each half separately. Write rules for the dangerous helper itself (for example, “any call to raw() with a non-constant string”), which often works better than hoping taint analysis connects the dots.

Languages

  • Semgrep CE: more than 30 languages in its engine, with different levels of maturity. Semgrep’s documentation lists which languages are generally available, beta or experimental; check your language’s level before you rely on it.
  • Opengrep: the same base, plus the extra languages listed earlier. The README lists more than 30 languages.
  • SonarQube Community Build: the list in the previous section. If you need C or C++ analysis, the free build is not enough.

CI integration

  • Semgrep CE: one command in a CI job, with –config pointing to a rule file, directory or registry pack. Output as text, JSON, SARIF, JUnit XML or GitLab SAST format, among others. The –error flag makes the job fail when there are findings. Diff-aware scans with –baseline-commit report only findings new since a given commit, which is the simplest way to gate merge requests without drowning in old issues. There is also pre-commit support and IDE extensions.
  • Opengrep: the same shape of command and similar outputs, as a single binary you can download and verify. Because it has no Python dependency, it is easy to put in a minimal CI image.
  • SonarQube: a scanner step in CI that uploads to the server, then the server computes the quality gate. On the free build, this is useful for the main branch after merge, not as a merge request gate.

A pattern that works for many teams: a pattern engine as a fast, precise gate on merge requests, and SonarQube on the main branch for trends and quality.

Data leaving your network

  • Semgrep CE: its metrics documentation says that with –metrics auto (the default), metrics are sent when rules are pulled from the Semgrep registry or the user is logged in, and not when only local rule files are used. Metrics include things like run time, rule counts and pseudonymised hashes, and the page says source code and private rules are never sent. You can set –metrics off or the SEMGREP_SEND_METRICS environment variable. The same page notes that GitLab’s Semgrep-based SAST analyser turns metrics on for every run.
  • Opengrep: the 1.33.0 binary we used showed a version check option in its help output and no metrics option. We did not inspect its network behaviour beyond running it with the version check disabled.
  • SonarQube Community Build: the analysis goes to your own server. Check its telemetry settings in the administration pages if this matters to you.

Security of the scanner itself

A scanner sees all your code and, in CI, often runs with a token. Treat it like any other privileged tool:

  • Pin versions of the engine and of rule packs. A rule pack fetched fresh on every run can change your gate without a code review.
  • Verify downloads. Opengrep publishes Cosign signatures and certificates for each binary; verify them in your image build. For Semgrep, pin the pip package version and, ideally, install from a hashed lock file.
  • Scope tokens. The SonarQube analysis token should be a project-level token with only the rights it needs. Note that 26.10 removed the Anyone group, so anonymous analysis no longer works; check your permission templates after the upgrade.
  • Keep the server off the internet and on a current release. With monthly Community Build releases and no long-term line, falling behind is easy; the Mysuru server is about three years behind.

We checked the GitHub security advisories pages of the three repositories and found none published there. That does not mean no bugs; it means look at each project’s release notes and the security notices of their dependencies.

Operations and upgrades

  • Semgrep CE: a pip package, updated weekly. Upgrade on purpose, say once a month, and run your rule tests (Semgrep supports test files with annotated expected matches) before you roll it out.
  • Opengrep: a single binary, updated roughly weekly. Same advice. Keep the binary in your CI image rather than downloading it in each job.
  • SonarQube Community Build: a real server to run. Three Java processes (web, compute engine and Elasticsearch) with default maximum heaps of 1 GB, 1.5 GB and 512 MB; the 26.10 documentation notes that the web and compute engine defaults increased in that release. For a small installation, the documentation suggests 4 GB of RAM, two cores and 30 GB of disk, and asks for at least 10% free disk because Elasticsearch locks indices when the disk fills. On Linux, it needs kernel settings such as vm.max_map_count of 524288. Production needs PostgreSQL (15 to 18 from 26.8), Microsoft SQL Server or Oracle; the embedded H2 database is for tests only. The documentation says environments where these Elasticsearch prerequisites cannot be met, such as AWS Fargate, are not supported. Monthly upgrades mean a monthly change window, and the 26.10 ZIP deprecation means planning a move to Docker or Helm.

False positives and noise

This is where most static analysis projects fail, so it deserves its own section.

  • Pattern engines: noise comes from broad rules. The fix is to narrow the rule (pattern-not for safe forms, pattern-inside for context), or drop it. Inline suppressions use a comment such as nosemgrep, ideally with the rule id, so that only that rule is silenced. Our drill showed exactly this: a suppression naming one rule left a second rule on the same line still firing.
  • SonarQube: noise comes from the default profile being too wide for your team’s priorities. Mark false positives in the UI, tune the profile, and use the “new code” setting in the quality gate so that old issues do not block new work. The new core, extended and comprehensive profiles in 26.10 are a good chance to start with a smaller set.
  • Everywhere: a finding that nobody owns is noise. Every enabled rule should have someone who decides whether it stays.

Performance

We ran no benchmarks and quote no speed numbers. Semgrep’s comparison page says Semgrep publishes no head-to-head speed comparison with Opengrep and advises measuring on your own repositories, which is the right advice for all three. In practice, pattern engines on a medium code base run in seconds to minutes depending on the number of rules, and the slowest part is often a few badly written rules. Both Semgrep and Opengrep have per-rule timeout settings. SonarQube’s analysis time includes the scanner step and the server’s background processing, and depends heavily on language and code size.

A worked plan for Mysuru

Step 1. Decide what the gate is for. The team writes down three goals: stop injection and shell command flaws at merge request time, enforce a few company rules about personal data in logs, and track code quality trends on the main branch. Anything else is “nice to have”.

Step 2. Start with a small rule set you own. The security engineer writes about fifteen rules for the Django monolith: raw SQL with non-constant strings, extra() and RawSQL with formatting, subprocess with shell=True and non-constant input, logging calls that include guest phone or email fields, DEBUG=True in settings files, and requests calls with verify=False. Each rule gets a test file with one positive and one negative example, and a named owner. Similar small sets follow for Java and Go.

Step 3. Gate only on new findings. The merge request job runs the pattern engine with a baseline of the target branch, so existing issues do not block anyone. Blocking severity is used only for rules that have stayed precise for a month. Everything else is reported but does not fail the job.

Step 4. Read the licences for the partner product. The “code health report” for partner plug-ins is a separate decision. Give the Semgrep Rules License, SSALv1 and LGPL texts, with a clear description of the paid report, to the company’s legal adviser. Until that answer comes back, the report is built only with the company’s own rules.

Step 5. Choose a path.

  • Path A: upgrade SonarQube to the current Community Build. Keep it for main branch quality trends and the quality gate on new code. Move it to the Docker image with PostgreSQL, read the upgrade notes for the supported path from the 9.9 line, and fix permissions after the Anyone group removal. Accept that merge request decoration needs a paid edition or a different tool.
  • Path B (chosen for trial): one pattern engine as the merge request gate. Run Semgrep CE and Opengrep on the same in-house rules for one month, in parallel, with output to SARIF. Compare findings, run time and the effort of keeping each in the CI image. Prefer Semgrep CE if the team wants IDE extensions and occasional use of community rules for internal scanning. Prefer Opengrep if the team wants a single signed binary, cross-function taint within a file, and fingerprints in output without a login.
  • Path C: a commercial platform. If the team later needs cross-file taint analysis, merge request decoration in SonarQube, or maintained rules with triage workflows, compare the commercial offerings of Semgrep and Sonar, and others, on the same rule goals.

Mysuru does Path A to get the old server onto a supported release, and time-boxes Path B for one month.

Step 6. Make findings visible in the merge request. Convert SARIF or JSON output into the forge’s own report format, or into a merge request comment, so developers see findings where they work. Keep the full report as a CI artefact.

Step 7. Review the noise every two weeks. Look at the most frequent rules, the most suppressed rules and any finding that a developer marked as false. Narrow or drop rules. Track how many findings were fixed versus suppressed.

Step 8. Test the gate with a known bad change. Once a quarter, open a merge request that reintroduces the SQL injection from the penetration test, and confirm the job fails. A gate that has never failed on purpose may not be working.

When each is better

  • Semgrep CE is better when you want a widely used pattern engine with IDE extensions, pre-commit support and access to a large community rule registry for internal scanning, and you may later move to Semgrep’s commercial platform.
  • Opengrep is better when you want an open source engine end to end, write your own rules, value self-contained signed binaries, need cross-function taint within a file in the free tool, or need fingerprints and metavariables in output without logging in.
  • SonarQube Community Build is better when you want a dashboard for code quality on the main branch, curated quality rules for many languages without writing rules, quality gates on new code, and history over time.
  • Using two of them together is often better than any one alone: a pattern engine as the merge request gate, and SonarQube for main branch quality.

When not to change

  • If your current scanner runs on merge requests, gates only on new findings with a small precise rule set, and developers fix what it reports, the tool is probably not your problem.
  • If nobody triages findings today, a new tool will produce new findings that nobody triages. Fix ownership first.
  • If you rely on Semgrep’s or Sonar’s commercial features, such as cross-file analysis, Pro rules or pull request decoration, moving to a free engine means losing them.
  • If your main languages are C or C++, the free SonarQube build does not cover them; check language maturity in the pattern engines before you switch.

A short history

  • Semgrep grew from sgrep at Facebook, was revived by r2c, and was renamed Semgrep in 2020; its GitHub repository dates from December 2019. The company renamed itself Semgrep in April 2023. In December 2024 the open source edition became Semgrep Community Edition, and its maintained rules moved to the Semgrep Rules License.
  • Opengrep was announced on 23 January 2025 as a fork of Semgrep 1.100.0, with 1.0.0 released on 18 March 2025 and roughly weekly releases since. In 2026 it added language support and deeper taint options, and started alpha builds of a 2.0 line.
  • SonarQube has been developed by SonarSource for well over a decade; its GitHub repository dates from January 2011. In late 2024 the free edition became SonarQube Community Build with monthly calendar-versioned releases, and its analysers moved to the Sonar Source-Available License.

Decision guide

  • Do you mainly want to block known dangerous patterns at merge request time? Use a pattern engine, Semgrep CE or Opengrep, with your own small rule set.
  • Do you need taint tracking across functions in a file without paying? Trial Opengrep with –taint-intrafile.
  • Do you want IDE extensions and a large community rule registry for internal use? Use Semgrep CE.
  • Do you want quality trends, quality gates and curated rules on the main branch? Run SonarQube Community Build, on PostgreSQL, kept current.
  • Do you need merge request decoration in SonarQube, injection taint analysis or cross-file analysis? These are in commercial editions; budget for them or accept the gap.
  • Will you sell a product or report built on these tools? Get the rule and analyser licences reviewed before you build.

Checklist

  • The scanner’s goals are written down: patterns, data flow, quality.
  • Every enabled rule has an owner and a test file with positive and negative examples.
  • Merge request jobs report only new findings, using a baseline.
  • Only precise rules block a merge; broad rules report without failing.
  • Inline suppressions name a rule id and are reviewed.
  • Engine versions and rule packs are pinned; downloaded binaries are verified.
  • Semgrep runs with metrics settings you chose on purpose.
  • SonarQube runs on PostgreSQL (or another supported database), not H2, with Elasticsearch prerequisites met.
  • SonarQube is on a current Community Build, and permission templates were reviewed after 26.10.
  • Analysis tokens are scoped to projects and stored as CI secrets.
  • A known bad change is used to test the gate at least once a quarter.
  • The licences have been read for any product or service you sell.

Common mistakes

  • Turning on a large default rule pack and blocking merges. The team learns to ignore or bypass the job in a week.
  • Gating on all findings instead of new findings. Old issues block unrelated work, and people start suppressing in bulk.
  • Suppressing without a rule id. A bare ignore comment can hide future findings from other rules on the same line.
  • Assuming taint analysis follows everything. In the free tools it stops at the function, or at the file. Write rules for dangerous helpers directly.
  • Fetching rules from the internet in every CI run. Your gate can change without review, and with Semgrep it also turns on metrics under the default setting.
  • Running SonarQube on H2 or on a full disk. H2 is for tests, and Elasticsearch locks indices when disk is nearly full.
  • Leaving SonarQube on an old release. With monthly releases and no long-term line for the free build, the gap grows fast.
  • Expecting merge request comments from SonarQube Community Build. The free build analyses only the main branch.
  • Treating “no findings” as “no vulnerabilities”. A clean scan means your rules did not match, nothing more.

The drill we ran

We wanted to see how the two pattern engines behave on the same rules, without touching system packages or running any server. So we did a small drill as an ordinary user, in a scratch folder, with no sudo, no services and no network listeners, using only local rule files.

  1. Setup. Semgrep 1.182.1 installed with pip in a Python virtual environment, run with –metrics=off and the version check disabled. Opengrep 1.33.0 downloaded as the release binary for Linux x86 (about 46 MB), run with the version check disabled. We did not verify the Opengrep Cosign signature, because Cosign was not installed.
  2. Pattern rules. An invented billing.py with four functions: a shell command built from an invoice id with shell=True, a constant command with shell=True, a safe list-form call, and the risky form again with a nosemgrep comment naming one rule. Two rules: a broad one for any subprocess.run with shell=True, and a narrow one that excludes constant strings with pattern-not. Both engines gave the same four findings. The broad rule flagged the constant command too, and the narrow rule correctly skipped it, which is a small example of how rule wording controls false positives. The list-form call was not flagged. The suppression comment silenced only the rule it named; the other rule still fired on that line.
  3. Taint rule. An invented flow.py where a request parameter reaches a shell command in two ways: inline in one function, and through two helper functions in the same file. Semgrep CE found only the inline case. Opengrep with default settings found the same single case. Opengrep with –taint-intrafile found both.
  4. Output. In Semgrep CE’s JSON output, the fingerprint field said “requires login”, and the SARIF fingerprint value said the same. Opengrep’s JSON had a real fingerprint and the metavariable values for the taint finding. Both engines returned exit code 1 with –error when findings existed. Semgrep’s –validate reported the three rules as valid. No scanner processes were left running afterwards.

Not run: no SonarQube Community Build (it needs Java, Elasticsearch, a database and kernel settings, which we did not set up on a shared machine); no registry rule packs or –config auto; no Semgrep commercial engine or cross-file analysis; no Opengrep 2.0 alpha; no Cosign verification; no IDE extensions; no timing or benchmark comparison; no real code base. These were two tiny files, so treat the results as a demonstration of behaviour, not of accuracy.

Unlearn, re-learn

  • Unlearn “a scanner in CI means we are secure”. Re-learn that a scanner finds only what its rules describe, and a clean scan is not proof.
  • Unlearn “more rules means more safety”. Re-learn that a small, precise, owned rule set that blocks merges beats a large pack that nobody reads.
  • Unlearn “Semgrep is open source, so the rules are too”. Re-learn that the engine is LGPL 2.1, but Semgrep’s maintained rules are under a separate, restrictive licence.
  • Unlearn “SonarQube Community Build is fully LGPL”. Re-learn that the analysers inside it are under the Sonar Source-Available License.
  • Unlearn “taint analysis follows the data everywhere”. Re-learn where each free tool stops: the function, or the file.
  • Unlearn “the free SonarQube can review my merge requests”. Re-learn that it analyses the main branch only, and plan the merge request gate separately.

Sources

comments powered by Disqus

Releted Posts

Container engines in 2026: revisit Docker Engine, Podman and containerd before you install another container daemon

On most teams, installing a container engine is the first thing done on a new machine and the last thing anybody thinks about.

Read more

Configuration management in 2026: revisit Ansible, Salt and Puppet before you write another server setup script

Almost every team has one: a setup.sh or bootstrap.sh written for the first production server and grown every year since. It installs packages, edits configuration files with sed, creates users and starts services.

Read more

TLS certificate automation in 2026: revisit cert-manager, Certbot and step-ca before the next certificate expires on you

Think of a bicycle and auto parts manufacturer in Ludhiana that sells through about 400 dealers across Punjab, Haryana, Rajasthan and the hill states (an invented example, not a real client).

Read more