My June and July 2026 audits produced 958 confirmed findings across 21 third-party apps, 58 of them critical. Static code analysis tools are the cheap first pass at that kind of problem: they read source without running it and flag injection, hard-coded secrets and unsafe calls. One free scanner in CI is my working rule for a small app. The skill is triage.
What static code analysis tools are, and where they sit
Static code analysis tools read source code without running it and report constructs that match known problems. There are 4 kinds: linters, type checkers, code-quality analyzers and security scanners, which are called SAST tools. My working rule: a small codebase needs one of each at most, and the security scanner belongs in CI on every pull request.
Those 21 apps were ones I audited in June and July 2026, a selected set, not a random sample, so the counts describe that set and not AI-built apps in general. Scanning is one of several ways to check the controls covered in web app security; this page is about the scanning part.
OWASP’s static code analysis page describes the practice as running tools “that attempt to highlight possible vulnerabilities” in source code that is not running, and it treats static code analysis and source code analysis as one term. OWASP’s tool list adds that such tools can read “source code or compiled versions of code”. So “static” means the code at rest: nothing is executed, and a static analyzer is the program that does the reading. Static program analysis in the academic sense, proving properties of software without running it, is the root all four kinds grow from. The Clang Static Analyzer’s own page puts the working definition of static analysis plainly: “a collection of algorithms and techniques used to analyze source code in order to automatically find bugs”.
The table sorts the software that does static analysis by what it looks for. Every tool in it does static source code analysis, so the difference is the rulebook, not the method. Which security tool to run is in the tools section further down.
| Kind of static tool | What it looks for | Example | Blocks a merge? |
|---|---|---|---|
| Linter | Style problems and bug-prone constructs | ESLint | Yes, on errors you configure as errors |
| Type checker | Values used as the wrong type | Your language’s compiler or checker in strict mode | Yes, on any type error |
| Code-quality analyzer | Duplication, complexity, maintainability | SonarQube | Only if you set a quality gate |
| Security scanner (SAST) | Injection paths, secrets, dangerous calls | Semgrep Community Edition, Bandit | Yes, on new findings only |
Each of the common linters, and what it checks, is a topic of its own. Strict typing belongs to the type checker, a separate topic. Static analysis tools beyond the linter earn their place because a linter polices style and obvious bugs, while a security scanner follows data toward dangerous calls. The general definition of a code scan, the four kinds of code checker and the per-language quality tools are in what a code scan is. The other meanings of “static code” (a fixed coupon code, an HTTP status code) have nothing to do with this page, and neither has “basic static analysis” in malware work, which means reading a binary’s strings and hashes without running it.
SAST meaning: static application security testing in one paragraph
SAST stands for static application security testing: static analysis aimed at security flaws, run against the code itself rather than the running app. A SAST scan is one run of such a tool over a repository, and each finding carries a rule id, a file and line, and a severity.
The SAST definition I work from is NIST’s description of a source code security analyzer: a tool that “examines source code” to “detect and report weaknesses that can lead to security vulnerabilities”. NIST gives that definition on the same page that lists the tools, linked in the tools section below. In cyber security, SAST is static code analysis pointed at security: the same parsing, with rules written for vulnerabilities instead of style. SAST testing needs no deployed app and no test accounts, which makes it an easy first security check to add. Where SAST sits beside DAST, SCA and IAST, and the order a small team adds them in, is covered in SAST vs DAST.
Why it matters for an AI-built codebase: what a SAST scan finds, and what it misses
A SAST scan finds what is visible in code: injection paths, hard-coded secrets, dangerous functions and copied bad patterns. It misses what is not: who may see what, business logic, configuration outside the repository. In 3 of the 21 third-party apps I audited, scanners flagged 33 to 44 vulnerabilities and the audit traced exactly zero as reachable.
That count comes from the same selected set of 21 third-party apps I audited in June and July 2026; it is not a false-positive rate for AI-built apps, and it is not a SAST statistic: the count is of what scanners flagged, without naming their kind. Code security, for a founder, means the places where the code itself, not the hosting or the settings, decides whether data leaks, and a scanner is how you start on it. (“Coded security” also names door keypads and alarm codes; not this.)
| A SAST scan finds | It misses | Who finds that instead |
|---|---|---|
| Injection: user input reaching a query, a shell or an HTML sink | Broken access control: who may read which record | A person testing with two accounts |
| Hard-coded secrets (a secrets scanner does this better) | Business logic, such as a refund that can run twice | A person who knows the product rules |
Dangerous functions: eval, unsafe deserialization, weak hashes | Configuration outside the repository: RLS policies, bucket settings | A check of the live settings |
| Missing security flags the framework makes visible in code | Runtime behavior of the deployed app | A dynamic scan against a running copy |
| Bad patterns an AI assistant repeats across files | Whether a finding is reachable at all | A person tracing the path from entry point to line |
Injection is what scanners find best. OWASP’s page says that for flaws such tools “can automatically find with high confidence, such as buffer overflows, SQL Injection Flaws, etc. they are great”. The fixes live elsewhere: SQL injection prevention and how to mitigate cross-site scripting. In one app I audited, a delete-file route pasted the user-supplied path into the database filter grammar instead of passing it as a value; the full telling is in input validation for a web app. That is the source-to-sink shape a taint rule is written to look for, in my reading, which is different from saying any particular scanner would have caught it.
Hard-coded secrets are better handled by a dedicated tool; secret scanning covers that. The last “finds” row is where code vulnerability scanning pays off most on an AI-built app: an assistant that wrote one unsafe query tends to write the same shape in every route, so one rule finds every copy. That is my reading of how these codebases repeat, not a measured rate.
The misses matter more. Broken access control is the big one, because no scanner knows who may see what. In the same audits, 7 of the 21 third-party apps had confirmed cross-user or cross-tenant authorization failures, where a logged-in user could read or write another customer’s data. OWASP’s own list of weaknesses names “access control issues” among the flaws that are “very difficult to find automatically”, and it says such tools frequently cannot find configuration issues “since they are not represented in the code”. Static vulnerability analysis stops at the repository boundary.
The 958 confirmed findings across the 21 third-party apps break down as 58 critical, 362 medium, 403 smell and 135 hygiene. A scanner is the first pass on findings like these, not the audit (my reading). SAST findings are leads with a file and a line, and the report section below shows how to sort them. What every scanner class leaves open, SAST beside DAST, SCA and secret scanners, is in what each security scanner leaves unresolved.
Code review is sometimes called static code review, since nobody runs the app there either, but the difference from static analysis is who reads: a scanner is fast, tireless and literal, and a reviewer knows what the code is for. Use both, scanner first, then the secure code review checklist for the paths the scanner cannot judge.
How it works: pattern matching, data flow analysis and taint analysis
Taint analysis is data flow analysis with a security question: does data from an untrusted source reach a sensitive sink without passing a sanitizer. A request parameter is a source, a SQL query is a sink. Of the 4 techniques OWASP lists, it is the one that traces user-controllable input to a vulnerable function.
A scanner first parses the code into a structure it can walk. Bandit, for example, “builds an AST” from each file and runs appropriate plugins against the tree’s nodes, and gosec inspects Go source “by scanning the Go AST and SSA code representation”. Then it applies one or more techniques. OWASP’s static code analysis page names four: lexical analysis, control flow graphs, data flow analysis and taint analysis. Automated code analysis is the umbrella term for all of them.
| Technique | What it sees | What it costs in noise or time |
|---|---|---|
| Lexical or pattern matching | The shape of code: a call to eval, a string glued into a query | Fast; flags every match, including safe ones |
| Control flow analysis | Which paths through a function can run, as blocks joined by jumps | Moderate; needs code the tool can parse whole |
| Data flow analysis | Where a value travels through assignments and calls | Slower; precision drops across files |
| Taint analysis | Whether untrusted input reaches a sink without a sanitizer | Slowest; tracking across files is often outside the open source engine |
Data flow analysis, in OWASP’s words, is “used to collect run-time (dynamic) information about data in software while it is in a static state”. Taint analysis narrows that to one question, and OWASP states the rule exactly: “If the tainted variable gets passed to a sink without first being sanitized it is flagged as a vulnerability.” Tainted data is input nobody has validated yet: a request parameter, a header, a webhook body. The sink is where that input can do harm: a query, a shell call, innerHTML.
Here is the shape in under ten lines of Node.js. The request value reaches the SQL string three calls away from where it enters.
// Vulnerable: req.query.name reaches the SQL text three calls away
app.get('/users', (req, res) => listUsers(req.query.name, res));
function listUsers(name, res) { findByName(name).then((rows) => res.json(rows)); }
function findByName(name) { return runSql(`SELECT * FROM users WHERE name = '${name}'`); }
function runSql(sql) { return pool.query(sql).then((r) => r.rows); }
// Fix: send the value separately so it is never parsed as SQL
function findByName(name) { return pool.query('SELECT * FROM users WHERE name = $1', [name]).then((r) => r.rows); }
A pattern rule that looks only at the line with pool.query sees a variable called sql, not a request value. Following it back to req.query.name needs taint tracking across three function calls, which is exactly the cross-function tracking Semgrep’s docs say its Community Edition does not do: it “can’t track data beyond a single function or file”. The fix is the one node-postgres documents: pass parameters separately instead of “string concatenating parameters into the query text directly”.
The limits follow from the mechanism. Analysis inside one function is cheap; across files and frameworks it is harder, and a framework the tool does not model breaks the chain, which is why results differ between tools and between the free and paid tiers of one tool (the Semgrep section says which tier does what). A static scan also costs time: the Clang project warns that static analysis “can be much slower than compilation”. Static and dynamic code analysis split the other way: static reads the code, dynamic watches the app run, and the SAST vs DAST article above covers the second.
Which SAST tools to run on a small codebase, and the open source options
A small codebase needs one multi-language SAST tool in CI on every pull request, plus the single-language scanner for its main backend language where one exists: that is my working rule. Semgrep Community Edition, Opengrep and CodeQL cover many languages; Bandit, Brakeman and gosec cover Python, Rails and Go. Each has a free path, with conditions.
The other half of my working rule is restraint: add nothing else until those findings are at zero or suppressed with reasons. A second multi-language source code scanner adds a second report to triage and, in my reading, rarely changes what you fix first. If a customer questionnaire asks which static application security testing tools you run, the honest answer for a small team is one name from the table below and the date of its last clean run.
The table is documented analysis from each project’s own pages, not a benchmark: I have not run these tools against each other, and none of them is ranked. The long catalogs of SAST scanners are OWASP’s Source Code Analysis Tools list and NIST’s Source Code Security Analyzers list, which NIST last updated on May 1, 2026. This short SAST tools list is only the free options a small team is likely to need.
| Tool | Languages | License | What is free | Where it runs | Source |
|---|---|---|---|---|---|
| Semgrep Community Edition | 30+ languages | Engine LGPL-2.1; Semgrep-maintained rules under the Semgrep Rules License v1.0 | The engine and community rules; the hosted Free Edition covers up to 10 contributors | CLI, CI, VS Code and IntelliJ extensions | Semgrep’s repository and docs |
| Opengrep | Semgrep’s rule format; adds Visual Basic, and Apex and Elixir beyond Semgrep CE | LGPL-2.1 | The engine; its rules fork carries a Commons Clause condition | CLI, CI | Opengrep’s repositories |
| CodeQL (GitHub code scanning) | C/C++, C#, Go, Java, Kotlin, JavaScript, TypeScript, Python, Ruby, Rust, Swift, GitHub Actions | GitHub CodeQL Terms and Conditions | Public repositories; private ones need GitHub Code Security | GitHub Actions, or the CodeQL CLI | GitHub Docs, CodeQL docs |
| Bandit | Python | Apache-2.0 | All of it | CLI, CI | PyCQA’s repository |
| Brakeman | Ruby on Rails | Brakeman Public Use License (code since June 15, 2018) | Non-commercial use, which the license says includes analyzing your own software | CLI, CI | brakemanscanner.org and its repository |
| gosec | Go | Apache-2.0 | All of it | CLI, GitHub Action | securego’s repository |
| Psalm (taint analysis) | PHP | MIT | All of it | CLI with --taint-analysis | psalm.dev |
| Clang Static Analyzer | C, C++, Objective-C | Open source, part of the Clang project | All of it | scan-build, Xcode, clang-tidy’s clang-analyzer checks | clang-analyzer.llvm.org |
Licenses and prices checked September 28, 2026.
The free column matters more than the license column. Free SAST tools with a condition (public repositories only, non-commercial use, up to 10 contributors) can stop being free the day the repository goes private or the team grows. Static code analysis tools that are free on a private repository with no condition on the engine, in this table, are Bandit, gosec, Psalm, the Clang analyzer and the Semgrep and Opengrep engines; the rule sets for the last two carry their own conditions, covered below. Every open source SAST tool here can run on your own machine or CI runner.
Open source static code analysis has one catch worth knowing before you pick: the license on the rules can differ from the license on the engine, as Semgrep’s do (details below). The code analysis tools open-source projects ship are engines first; the rule set you feed them decides most of what they find.
The best SAST tools for a small team are the ones that cover its main language, run in its CI and have a free path it qualifies for. Rankings of top SAST tools answer a question a small team does not have. The best static code analysis tool for a given app starts with its language, which is why the table has a Languages column.
Secure coding tools in an editor are these same scanners run as extensions: Semgrep’s docs say its Community Edition includes VS Code and IntelliJ extensions. On GitHub the feature is called code scanning, and the code scanning tools it accepts are CodeQL plus any third-party tool that outputs SARIF. Some security tools for static code analysis come as a free engine with a platform built on top: in Semgrep’s case the platform’s SAST solution, Semgrep Code, adds cross-file analysis over the Community Edition, and the platform adds a dashboard. When a buyer’s questionnaire says code auditing tools, it means scanners like these, and each source code audit tool here produces candidates, not verdicts; a code audit by a person is a different purchase. Products that sell code quality and security tools in one platform, SonarQube among them, are placed in the matchups section below.
Scanners that test the running app are a different job, covered in a website security check, and five scanners built for AI-built apps are compared in vibe coding security scanners compared.
Semgrep: what it is, the rules and registry, and what is free
Semgrep is a static analysis tool whose rules are YAML patterns written to look like the code they match. It comes in two layers: the open source Community Edition, which analyzes within one file or function, and the Semgrep AppSec Platform, which adds cross-file analysis, dependency scanning, secrets detection and a web dashboard.
What Semgrep does, in its repository’s words, is search code, find bugs and enforce “secure guardrails and coding standards”, across “30+ languages”. Semgrep rules are YAML files, and the README’s pitch is that “Semgrep rules look like the code you already write”. The Semgrep Registry is the public rule collection, which the README counts at “2,000+ community-driven rules”, and the Semgrep Playground is “an online interactive tool for writing and sharing rules”. Semgrep Academy is the vendor’s course site, which it says is “completely free for the whole world”.
The Semgrep Community Edition is the open source engine, licensed LGPL-2.1. The rules Semgrep maintains carry a different license, the Semgrep Rules License v1.0. Its limitation reads: “You may use the rules only for your own internal business purposes. This license does not allow you to distribute the rules, or to make them available to others as a service.” Scanning your own app is internal use; building a scanning service on those rules is not. That rules license, together with engine features Semgrep moved behind a commercial license, is what prompted the Opengrep fork below.
Semgrep taint analysis is where the tiers split. The docs list the Community Edition’s analyses as “Single function taint analysis” and “Single file, cross function constant propagation”, while Semgrep Code, the company’s SAST product, adds “Cross file, cross function taint analysis”. On the supported languages page, Semgrep Code is listed at “35+ languages”, with maturity tiers of generally available, beta and experimental, and cross-file dataflow analysis for C#, Go, Java, JavaScript, Kotlin, Python, TypeScript and C/C++.
“Pro” is the label on the platform’s engine and rules, which the hosted Free Edition includes too: the README describes Semgrep Code’s Pro engine as “designed to detect complex vulnerabilities, and reduce false positives”. The SCA product is Semgrep Supply Chain, “a high-signal dependency scanner that detects reachable vulnerabilities in open source third-party libraries”; dependency scanning has its own page at the npm audit command.
Semgrep is free in two senses. The engine and community rules cost nothing. Semgrep’s pricing page, checked September 28, 2026, lists a Free Edition with “Cross-file analysis with Pro rules”, “Scan up to 10 repositories” and “Maximum 10 contributors”, including Code and Supply Chain at $0 per contributor; the Teams tier starts at $30 per month per contributor, with Code at $30, Supply Chain at $30 and Secrets at $15 per contributor per month. The pricing page counts a contributor as “someone who made at least one commit to your organization’s private repository scanned by Semgrep in the past 90 days”. So a small team of up to 10 contributors, scanning up to 10 repositories, can use cross-file analysis with Pro rules on private repositories without paying, once it has an account; the Community Edition needs no account at all.
Everything in this section comes from Semgrep docs, the repository and the pricing page, not from Semgrep threads on Reddit. Semgrep’s AI and MCP features are covered on the code scan page linked earlier.
Semgrep install, the CLI and CI: GitHub, GitLab and Docker
Semgrep installs with pip, Homebrew or a Docker image, and one command scans a repository with a named rule pack and no account. In CI it runs on every pull request with read-only permissions and fails the job on findings; sending results to GitHub’s security tab needs a public repository or GitHub Code Security.
Before the terminal, there is a no-install first rung if GitHub Actions is enabled and your repository is public, or belongs to an organization on GitHub Team or Enterprise with GitHub Code Security enabled: GitHub’s default setup runs CodeQL for you. The click path in GitHub’s docs: in the repository, click Settings; in the “Security and quality” section of the sidebar, click Advanced Security; under “Code Security”, next to “CodeQL analysis”, select Set up, then Default; review and click Enable CodeQL. On a private repository without that license, code scanning is not available at all, so use the commands below instead.
To install Semgrep, the repository README gives python3 -m pip install semgrep and brew install semgrep, plus the semgrep/semgrep Docker image; Semgrep’s quickstart now suggests pipx or uv, and calls Homebrew “best-effort”. The Semgrep CLI has two scan commands: semgrep scan is for local scans “without requiring a Semgrep account”, and semgrep ci is for CI pipelines, including diff-aware scans on pull requests, and uses the rules and policies your Semgrep organization defines. By default semgrep scan does not fail on findings; --error makes it “Exit 1 if there are findings”, and --sarif-output or --json-output writes a copy of the results to a file. The --metrics=off flag stops the usage metrics Semgrep otherwise sends when it pulls rules from the registry.
python3 -m pip install semgrep
semgrep scan --config p/owasp-top-ten --metrics=off --json-output=semgrep.json
docker run --rm -v "${PWD}:/src" semgrep/semgrep semgrep scan --config p/owasp-top-ten --error --sarif-output=semgrep.sarif
In CI, the job below follows Semgrep’s own sample for the Community Edition on GitHub Actions: it runs on pull requests, inside the semgrep/semgrep image, with read-only repository permissions. It fails on findings and keeps the SARIF file as a build artifact even when the scan step fails.
name: semgrep
on:
pull_request: {}
permissions:
contents: read
jobs:
semgrep:
runs-on: ubuntu-latest
container:
image: semgrep/semgrep
steps:
- uses: actions/checkout@v6
- run: semgrep scan --config p/owasp-top-ten --metrics=off --error --sarif-output=semgrep.sarif
- uses: actions/upload-artifact@v7
if: ${{ !cancelled() }}
with:
name: semgrep-sarif
path: semgrep.sarif
To see findings in GitHub’s security tab instead, the SARIF upload step needs security-events: write, and on a private repository it works only with GitHub Code Security enabled, per GitHub’s code scanning docs. Where the workflow file sits in the rest of your pipeline is in CI/CD best practices, and pinning the two actions to commit SHAs and scoping the token are in CI CD security best practices.
On GitLab, SAST is built in: “In all tiers, you can use GitLab-provided analyzers, based on open-source scanners,” and GitLab’s SAST docs note that the standard analyzers use the “Semgrep analyzer with GitLab-managed rules unless otherwise specified”. Cross-file scanning there is GitLab Advanced SAST, an Ultimate feature. SAST in DevOps terms is exactly this: the scan is a pipeline step with a pass condition.
Opengrep vs Semgrep: the fork, and what it changes
Opengrep is a fork of Semgrep’s open source engine, started by a group of security vendors after Semgrep changed its licensing. Opengrep says existing Semgrep rules and rulesets work unchanged, so trying it costs a small team little; the choice is about license terms and a few features.
The consortium’s press release is dated Jan. 23, 2025 and says “10+ competing security companies” launched it after “Semgrep’s December 13 decision to restrict its open-source security project by changing its license”. It names Aikido Security, Arnica, Amplify Security, Endor Labs, Jit, Kodem, Legit Security, Mobb and Orca Security. On GitHub, the Opengrep repository describes itself as “a fork of Semgrep, under the LGPL 2.1 license”, forked from Semgrep v1.100.0, and states the goal plainly: “Opengrep was created when Semgrep moved critical features behind a commercial licence.” It lists taint analysis within a file (--taint-intrafile) and Visual Basic as additions, with JSON and SARIF output.
The Opengrep rules live in a separate repository, a fork of semgrep-rules dated December 13, 2024, which says its rules “are intended for research, testing & benchmarking” and carries a Commons Clause condition on top of LGPL 2.1. So for a small team, Opengrep vs Semgrep changes little on day one: both read the same rule format. It matters if the Semgrep rules license or a feature the Community Edition lacks is what blocks you.
Other Semgrep alternatives, by category only. CodeQL runs semantic queries over a database built from your code; see CodeQL’s overview. It is free on public repositories and part of GitHub Code Security for private ones. The single-language scanners in the next section are the second kind of alternative, and the commercial suites in the matchups section are the third. Semgrep competitors in the commercial sense are those suites.
Bandit, Brakeman, gosec and the other single-language scanners
Bandit “is a tool designed to find common security issues in Python code”, maintained under PyCQA and licensed Apache-2.0. Its README calls it “A security linter from PyCQA”, and on a Python backend the Bandit scanner is the single-language tool my working rule adds next to the multi-language one.
Brakeman is “a free vulnerability scanner designed for Ruby on Rails applications”, in its site’s words. Its license changed: code committed on or after June 15, 2018 is under the Brakeman Public Use License and owned by Synopsys, Inc., which says “Commercial Uses (as defined below) of the Software for commercial purposes require a commercial, non-free license”, while listing “Using the Software to analyze Licensee’s software” as a use that is not commercial. For Ruby teams, running Brakeman on your own Rails app fits the free terms; selling Brakeman scans as a service does not.
gosec, the Go Security Checker (sometimes written go sec), “Inspects source code for security problems by scanning the Go AST and SSA code representation”, under Apache-2.0, and ships as a GitHub Action.
For static code analysis for PHP, Psalm’s taint mode is the open source security option: Psalm “can attempt to find connections between user-controlled input” and places that input should not reach, enabled with --taint-analysis, per Psalm’s security analysis docs. As a PHP code audit tool it finds candidates for a person to confirm. PHPStan and PHPMD are quality tools, covered on the code scan page.
For C, the static code analyzer to start with is the Clang Static Analyzer, “a source code analysis tool that finds bugs in C, C++, and Objective-C programs”, which ships with scan-build in the official LLVM releases. C is rare in the web apps this series is about, so most readers can skip this row.
A GitHub vulnerability scanner can mean three features people blur, and only one of them is SAST:
| GitHub feature | Kind of scan | Public repositories | Private repositories |
|---|---|---|---|
| Code scanning (CodeQL) | SAST | Available | Organization-owned, with GitHub Code Security |
| Dependabot alerts | SCA | Available | Organization-owned and user-owned |
| Secret scanning | Secrets | Runs automatically for free | Organization-owned, with GitHub Secret Protection |
Semgrep vs SonarQube, Semgrep vs Snyk, Fortify vs SonarQube: what the matchups compare
Most of these matchups compare products in different categories. The table says what each product calls itself on its maker’s site and names no winner.
| Product | Category in its maker’s words | Open source or commercial | What the matchup is really asking |
|---|---|---|---|
| Semgrep | A static analysis tool; Semgrep Code is its SAST scanner | Open source engine, commercial platform with a free tier | Do I want rules I can read and write myself? |
| SonarQube | A platform for automated code quality and security analysis | A free Community Build and paid editions | Do I need a quality gate, a security scanner, or both? |
| Snyk Code | A developer-first SAST solution | Commercial, with a Free plan | Do I want SAST bundled with the vendor’s other security products? |
| OpenText Fortify SAST | Static application security testing and code analysis | Commercial | Is this an enterprise buying process? |
Going by its maker’s wording in the table, SonarQube sits among code quality analysis tools that also carry security rules, while Semgrep is a rule-driven security scanner. So “Semgrep vs SonarQube” usually asks whether you need a security scanner as well as a quality gate, and for a small team my working rule from the top of this page applies: a linter and type checker for quality, one SAST tool for security.
Snyk static code analysis is sold as Snyk Code, which Snyk’s docs call “a developer-first static application security testing (SAST) solution”. Snyk’s plans page lists Snyk Code at 100 tests a month on the Free plan and 1,000 on the Team plan (checked September 28, 2026). Semgrep vs Snyk is therefore two SAST products with free tiers and different limits: Semgrep’s free tier counts contributors and repositories, Snyk’s counts tests. The Snyk and SonarQube pair is compared on the code scan page.
Fortify is sold under OpenText’s name: the product page is titled “OpenText Fortify SAST” and describes it as “Static application security testing and code analysis”. Per OpenText’s data sheet, developers review Fortify’s scan results in Fortify Audit Workbench or in IDE plugins. Fortify vs SonarQube sets an enterprise SAST suite against a code quality platform, and choosing among Fortify alternatives is an enterprise procurement question, well beyond what a small team needs.
If you are choosing between top code quality tools and a SAST scanner, you are comparing two different jobs. For code quality alone, a linter and a type checker are the free start, and the tools to check code quality by type are in code quality checks. Every other SonarQube comparison is on the code scan page.
SAST and the OWASP Top 10: what a rule pack covers, and what it cannot
An OWASP Top 10 rule pack tags findings by category; it does not cover the 10 categories. Injection and weak cryptographic calls are visible in code. Broken access control, insecure design and logging failures mostly are not, in my reading, so a clean OWASP-tagged scan supports a few rows of a review, never the whole review.
Scanners sort findings by OWASP category in two ways. For Semgrep OWASP Top 10 coverage there is a registry rule pack, p/owasp-top-ten, whose rules carry owasp tags from the 2017, 2021 and 2025 editions next to their CWE ids. For OWASP Top 10 SonarQube coverage there are security reports: Sonar’s docs say they “are available starting in Enterprise Edition” of SonarQube Server and cover the 2025, 2021 and 2017 editions, and the page names no plugin to install. In SonarQube Cloud, the product formerly called SonarCloud, OWASP Top 10 reports are “only available in the Enterprise plan”, and the default PDF download covers the 2021 edition.
A tag means the rule’s finding belongs to that category. It does not mean the category is covered. The table runs through OWASP Top 10 static code analysis category by category, using the 2025 names.
| Top 10:2025 category | Can a SAST rule see it? | What else is needed |
|---|---|---|
| A01 Broken Access Control | Rarely: path traversal and similar patterns, not who may see which record | Tests with two accounts and a review of every route |
| A02 Security Misconfiguration | Partly: settings written in code | A check of the live host and service settings |
| A03 Software Supply Chain Failures | Partly: the dependency manifest, through SCA rather than SAST | A dependency scan and an update policy |
| A04 Cryptographic Failures | Partly: weak algorithms and hard-coded keys, not whether crypto is used correctly | A person reviewing key handling |
| A05 Injection | Yes, this is where taint rules work best | Fix confirmation with a test |
| A06 Insecure Design | No | A design review |
| A07 Authentication Failures | Rarely | Tests of login, reset and session flows |
| A08 Software or Data Integrity Failures | Partly: unsafe deserialization calls | A review of update and webhook paths |
| A09 Security Logging and Alerting Failures | No | A check that alerts fire |
| A10 Mishandling of Exceptional Conditions | Partly: swallowed errors visible in code | Tests that force failures |
The hard rows match OWASP’s own weakness list, quoted in the findings section above, which also names authentication problems and insecure use of cryptography. The review itself, category by category, is in how to test OWASP Top 10 vulnerabilities. Category names follow the edition the tool cites, which may lag the current list, so check the year on each tag.
How to check your own app: a first scan, and how to read the SAST report
A first SAST scan is read by rule, not by file, in 7 steps. For each rule decide once: fix everywhere, suppress with a written reason, or disable as a false positive. In my working order, injection and secrets rules get fixed first, then CI fails only on new findings so the backlog does not block every change.
This is my working order for a code security scan on a small app.
- 01 Pick the one tool from the table that covers your main language
- 02 Run it locally with a named security rule pack and write the output to a file
- 03 Read the totals by rule, not by file: an AI-built codebase repeats itself, so a handful of rules usually explain most findings
- 04 For each rule decide once: true and reachable (fix the pattern everywhere), true and not reachable (suppress with a comment that says why), false positive (suppress and consider disabling the rule), or not a security issue (move it to the lint backlog)
- 05 Fix the injection and secrets rules first
- 06 Add the scan to CI and fail it only on new findings, so the old backlog does not block every pull request
- 07 Record the tool, its version, the rule pack, the counts before and after, and the date
For step 4 in Semgrep, a suppression is a comment on or above the matched line, // nosemgrep: rule-id, and your reason goes in an ordinary comment beside it. For step 6, semgrep scan --baseline-commit shows only results “not found in this commit hash”, and semgrep ci runs diff-aware scans on pull requests. The pass for step 7 is my working rule: on the second run, the count for each fixed rule is zero, or every remaining hit carries a suppression with a reason. No duration or finding count is given here on purpose; your own run is the number.
A SAST report lists findings, and each finding has the same few fields whichever tool wrote it. The names below are the SARIF names from GitHub’s docs and the rule metadata names from Semgrep’s registry.
| Field | What it tells you | What to do with it |
|---|---|---|
Rule id (ruleId) | Which rule fired | Group and decide by this, per step 3 |
Severity (level, or a security-severity score) | How bad the rule’s author thinks a true hit is | Order the work; GitHub reads over 9.0 as critical |
Confidence (confidence, or precision) | How often the rule is right | Low confidence plus no reachable path is a suppression candidate |
File and line (locations) | Where the hit is | Open it and trace the input back |
Data flow trace (codeFlows, or Semgrep’s --dataflow-traces) | How the value got there, where the tool gives one | Check each hop for a sanitizer |
CWE and OWASP tags (cwe, owasp) | The weakness class | Map to the OWASP table above |
That answers how to check code security in practice: run one tool, read by rule, decide once per rule, and keep the record. A SAST assessment, as buyers use the phrase, is this same pass done by a person with the triage written down. A source code security scan that finds nothing still leaves the misses from the table near the top of this page. Tracking findings over time and scoring them is covered in vulnerability management tools, and dependency findings come from a different scan, on the npm audit page.
Where the sprint fits
In the Production Hardening Sprint, four deliverables cover this ground, in the published wording. Deliverable 3.7, the OWASP Top 10 review, is to review the application against the OWASP Top 10 and record findings, fixes, and evidence by category. For dependencies, deliverable 3.5, dependency remediation, is to audit dependencies, upgrade or remove known-vulnerable packages, and remove unused packages. Deliverable 7.3, pull-request CI, is to run linting, type checks, builds, and tests on every pull request. The production readiness report, deliverable 13.1, delivers the result for every scope item, the work completed, and its verification evidence. Formal third-party certifications and independent audit opinions are separate from the sprint deliverables. Hosting, paid tools and API usage are paid through your accounts, and we explain any required costs before enabling them. The full list is in the security and CI deliverables in the published scope.
Common questions about SAST and Semgrep
Can AI do static code analysis?
Partly. A language model can read code and explain a finding, and scanner vendors now add model-based triage on top of rules: Semgrep’s docs list “Semgrep Multimodal (AI-assisted) post-processing analysis” in its AppSec Platform. A model’s answer can change from one run to the next, so it complements a rule-based scan and does not replace one (my reading). AI review bots are compared in the live article on AI code review tools.
What are the key differences between Semgrep and CodeQL?
Semgrep matches patterns written to look like the code they find, from YAML rule files. CodeQL first builds a database from the code, “a single relational representation” of each file, then runs queries against it. Semgrep’s engine is LGPL-2.1 open source; CodeQL’s terms allow automated analysis on open source codebases, and private repositories need a paid GitHub license. Neither is better in general; they differ in how you write rules and where they may run.
Is SonarQube a static analysis tool?
Yes. Sonar’s product page says SonarQube “qualifies as a Static Application Security Testing (SAST) tool”, on top of its code quality checks. Editions, the free build and alternatives are on the code scan page.
Is Semgrep SCA or SAST?
Both, as separate products. The engine and Semgrep Code are SAST: they read your own source. Semgrep Supply Chain is the SCA product, a dependency scanner that checks whether known vulnerabilities in open source libraries are reachable from your code.
Is Fortify a SAST or DAST tool?
OpenText sells both under the Fortify name. OpenText Fortify SAST is static application security testing in OpenText’s own words, and the same product page lists OpenText Fortify DAST as a related product that tests live apps.
The checks in this guide show you where the app is open. The sprint below closes those gaps, tests the result and writes the evidence down.
Built it with AI. Now it has to hold up for real customers.
The Production Hardening Sprint takes the app you already have and builds the production foundation underneath it. Authentication and access rules, payments that stay consistent, error handling, monitoring, backups, automated tests and a documented handover. Our engineers work inside your existing codebase for ten working days. All 123 deliverables are included, and you get the evidence for each one.
See the Production Hardening Sprint →
$2,500 fixed price · 10 working days · One codebase