- Bandit is Python-only. Semgrep covers 30+ languages including Python, JavaScript, TypeScript, Java, Go, Ruby, C, C++, C#, Kotlin, and Swift.
- Both are open source. Bandit ships under Apache 2.0, the Semgrep CE engine under LGPL-2.1 (with the Opengrep community fork on the same license). Semgrep AppSec Platform layers managed rules and a SaaS dashboard on top with paid tiers.
- Bandit's ruleset is small and Python-specific (about 90 plugins covering common Python crypto, deserialization, and shell-injection risks). Semgrep's public rules registry has thousands of community-maintained rules across all supported languages.
- Semgrep wins on custom rules. You write Semgrep rules in YAML using a Python-like pattern syntax. Bandit custom rules require writing a Python plugin against its AST API, which is much more work.
- Most teams converge on Semgrep for polyglot stacks and custom-rule needs. Bandit stays useful as a Python-specialised second opinion, with rules curated by Python security researchers since 2014.
Which Is Better: Bandit or Semgrep?
Bandit vs Semgrep in one line: Bandit is a Python-only AST scanner with around 90 curated plugins under Apache 2.0. Semgrep is a polyglot rules engine covering 30+ languages with thousands of YAML-defined rules under LGPL-2.1.
Choose Bandit when the project is pure Python and you want zero-config, drop-in scanning with a Python-specialised ruleset.
Choose Semgrep when the codebase is polyglot, you need custom rules, or you want IDE-time feedback and a SaaS triage dashboard.
For polyglot codebases, Semgrep is the practical pick. One engine handles 30+ languages, thousands of community rules, and YAML-based custom rules anyone on the team can write.
Bandit is built only for Python; Semgrep covers 30+ languages with adapted generic patterns.
For pure Python projects, the case for Bandit holds up. Its Python ruleset has been curated by Python security researchers since 2014, and pip install bandit && bandit -r src/ is the lowest-friction Python SAST in the OSS world.
Most teams that start with Bandit add Semgrep as the second engine when they outgrow Python-only or need custom rules. Semgrep then often becomes the primary engine and Bandit stays as a Python-specialised second opinion.
Key Differences
| Dimension | Bandit | Semgrep |
|---|---|---|
| Language coverage | Python only | 30+ languages |
| License | Apache 2.0 | LGPL-2.1 engine (Opengrep fork same license) + paid AppSec Platform |
| Rule count | ~90 plugins | Thousands across all languages in public registry |
| Custom rules | Python plugin against Bandit AST API | YAML pattern syntax, easy to author |
| CI integration | CLI, pre-commit, GitHub Actions | CLI, pre-commit, CI integrations + SaaS dashboard |
| IDE plugins | None first-party | VS Code, JetBrains, Vim, Emacs |
| Best for | Pure Python projects, drop-in scanner | Polyglot stacks, custom rules, security guardrails |
Head-to-Head
Language coverage
Bandit is Python-only. The scanner reads Python source code, parses it into an AST, and runs around 90 plugins that look for Python-specific risk patterns.
A real bandit run flagging an unsafe yaml.load call with location, severity, and a docs link.
Semgrep covers 30+ languages: Python, JavaScript, TypeScript, Java, Go, Ruby, C, C++, C#, Kotlin, Swift, PHP, Scala, Rust, Bash, Terraform, Dockerfile, and more.
semgrep --config=auto runs the same project through 3,247 rules across multiple languages in one pass.
For a Python-only project, both work. For anything else, Semgrep is the only one of the two that helps.
Rule philosophy
Bandit ships a curated, Python-specific set of around 90 plugin rules. They cover classic Python AppSec risks: hardcoded credentials, weak crypto (insecure hashlib usage), Pickle deserialization, shell injection via subprocess, SQL injection, SSL verification disabled, debug mode in Flask / Django, and so on.
Bandit on PyPI: maintained by PyCQA, Apache 2.0, installable via pip install bandit.
Semgrep is rules-based pattern matching on the abstract syntax tree. Rules are written in YAML using a Python-like pattern syntax. The public registry at semgrep.dev/r hosts thousands of community-maintained rules across all supported languages.
Semgrep tracks how user input flows through the code, matching rules against the resolved data path.
Bandit’s Python ruleset is dense and tuned. Semgrep’s Python ruleset is broader because it includes generic SAST patterns alongside Python-specific rules.
Writing custom rules
Bandit custom rules require writing a Python plugin module that registers itself with Bandit’s plugin manager and walks the AST using Bandit’s API. It is closer to writing a small Python linter than a config snippet.
The PyCQA/bandit repo: plugins live in the bandit/ directory; new rules are Python modules in that tree.
Semgrep custom rules are YAML: a pattern, a message, a severity, and optional metadata. Most security engineers can write a useful Semgrep rule in 10 minutes.
The Semgrep playground at semgrep.dev/playground: a working rule is six YAML lines.
If your team expects to write custom rules regularly (enforcing architectural patterns, banning dangerous APIs, codifying security learnings) Semgrep is much less friction.
CI and developer experience
Both tools work as CLI, pre-commit hook, and CI step. Bandit is dead simple to drop in: pip install bandit && bandit -r src/. Semgrep has the same pattern: pip install semgrep && semgrep ci.
Semgrep adds a SaaS dashboard via the AppSec Platform. It is useful for teams that want triage workflows, central exclusion management, and reporting across many repos. Bandit’s reporting story is CLI output and JSON / SARIF files; integration with downstream tools is on you.
For IDE integration, Semgrep ships first-party plugins for VS Code and JetBrains. Bandit relies on third-party IDE wrappers.
Performance
Both are fast on Python codebases. Bandit’s narrow scope (~90 plugins, Python AST) keeps it lean. Semgrep’s general engine adds some overhead per file but scales well to large polyglot repos with rule-set tuning.
For a 100kLOC Python project, both scanners typically complete in seconds to minutes, well within CI budgets.
When to Choose Each
Three questions decide it: language reach first, then custom rules and IDE plugins.
Choose Bandit when
- The project is pure Python and you want a focused Python SAST.
- You want zero-config, drop-in scanning with no SaaS dashboard.
- The team trusts a curated, Python-specialised ruleset.
Choose Semgrep when
- The codebase is polyglot (Python plus JS/TS, Java, Go, etc.).
- You expect to write custom rules to enforce internal patterns.
- IDE-time feedback for developers is part of the requirement.
- You want a SaaS dashboard for centralised triage and reporting.
Choose both when
- Pure Python project where you want Bandit as a Python-specialised second opinion alongside Semgrep’s broader engine.
Related comparisons
- Semgrep vs SonarQube : Custom-rule SAST engine vs all-in-one quality platform.
- Semgrep vs Snyk : SAST engine vs multi-product platform.
- Semgrep vs CodeQL : Two SAST query engines compared.
- SAST vs DAST vs IAST : Where SAST fits in the testing landscape.
Frequently Asked Questions
Is Semgrep better than Bandit for Python?
Is Bandit free?
Can Semgrep replace Bandit entirely for Python?
Which has more rules, Bandit or Semgrep?
How hard is it to write custom rules in Bandit vs Semgrep?

Founder, AppSec Santa
9+ years in application security. Reviews and compares 201 AppSec tools across 12 categories to help teams pick the right solution. More about me →
