If you are comparing Bandit vs CodeQL vs Semgrep for Python, the first thing to know is that these tools are not interchangeable.
They overlap, but the real choice is about workflow:
- Bandit is the simplest Python-first security linter
- CodeQL is the deepest GitHub-native code scanning option in this set
- Semgrep is the most flexible when you want to write or tune custom rules quickly
That is the practical answer.
The short version
| Bandit | CodeQL | Semgrep | |
|---|---|---|---|
| Best for | Lightweight Python security linting | GitHub-native code scanning with richer dataflow | Custom rules and broad security policy coverage |
| Languages | Python | C/C++, C#, Go, Java/Kotlin, JavaScript/TypeScript, Python, Ruby, Rust, Swift, and GitHub Actions workflows | 30+ languages |
| Python setup friction | Low | Low on GitHub with default setup (no workflow file); higher with advanced setup or outside GitHub | Low to medium |
| Customization | Python test plugins | Custom QL queries and query packs (most expressive, steepest learning curve) | YAML pattern and taint rules (fastest to write) |
| GitHub fit | Good, but external | Excellent | Good |
| Dead code detection | No | Limited: Python quality queries for unused imports, unused local and global variables, and unreachable code; no whole-program unused function or class analysis | No |
| Pricing | Free (Apache-2.0) | Free on public repositories; private repositories need GitHub Code Security ($30 per active committer per month, plans) | Community Edition free (LGPL-2.1); hosted Free plan (up to 10 contributors and 10 private repositories, includes cross-file Pro analysis); Teams from $30 per contributor per month; Enterprise custom (pricing) |
| Best team shape | Small Python team | GitHub-heavy engineering org | Security-conscious team that writes custom rules |
What each tool is really trying to do
Bandit
Bandit is the classic Python security linter. It runs fast, focuses on Python AST patterns, and is easy to understand.
Good fit when:
- you want a fast first pass for obvious risky patterns
- your repo is Python-only
- you do not want to invest in a richer rule platform yet
Less ideal when:
- you need deeper dataflow
- you want dead-code detection too
- you need strong custom rule authoring
CodeQL
CodeQL on GitHub is the most GitHub-native option here. If your team already uses GitHub Code Security (part of GitHub Advanced Security) or relies heavily on GitHub code scanning, CodeQL fits naturally.
Good fit when:
- GitHub is your system of record for security findings
- you want query suites and richer code-scanning depth
- you want GitHub to manage scanning (default setup), or can maintain an advanced-setup workflow
Less ideal when:
- you want the simplest setup possible
- you are not centered around GitHub
- you need a dead-code or AI-code workflow, not just code scanning
Semgrep
Semgrep is strongest when the security team or platform team wants to encode policies quickly and iterate on them often.
Good fit when:
- you want custom rules
- you have multiple languages
- you want broad control over how findings are defined
Less ideal when:
- you want a narrow, out-of-the-box Python-only tool
- you want dead-code detection included
- you do not have bandwidth to maintain custom rule logic
Where they differ most for Python teams
1. Setup model
Bandit is the quickest to install:
pip install bandit
bandit -r .
Semgrep is still fairly quick, especially for a default ruleset:
pipx install semgrep
semgrep scan --config p/python .
On GitHub, CodeQL can be turned on with default setup from repository or organization settings, with no workflow file. Advanced setup (your own workflow and query packs) takes more work. CodeQL is free on public repositories; private repositories need GitHub Code Security ($30 per active committer per month, on GitHub Team or Enterprise; see GitHub's security plans).
Outside GitHub, or when you write your own queries, CodeQL asks more of the team.
2. Rule model
Bandit is mostly built around Python-specific security checks.
Semgrep is built around a flexible pattern and rule model.
CodeQL is built around a query language that is more powerful than pattern matching; writing custom queries has the steepest learning curve of the three.
In plain English:
- Bandit is easiest
- Semgrep is easiest to customize
- CodeQL is deepest; custom queries take the most effort to write
3. GitHub workflow fit
If your team already wants findings to live inside GitHub code scanning, CodeQL has the strongest story.
If you just want a Python security scan in any CI system, Bandit and Semgrep are the quickest to run; on GitHub, CodeQL default setup is comparably quick to switch on.
If you want PR checks plus whole-program dead code plus checks aimed at AI-written changes in one local tool, none of these three covers all of it on its own.
What they miss
This is the part most comparison pages skip.
Bandit, CodeQL, and Semgrep all answer the "security scanning" question, and their vendors now ship separate AI-focused products: Semgrep Guardian rescans agent-written code through MCP and hooks (launched 2026-06-23), GitHub Code Quality (generally available since 2026-07-20) adds AI-assisted findings and Python unused-import and unused-variable queries, and Copilot's coding agent validates its own changes with CodeQL and secret scanning. What the three scanners still don't give a Python team on their own:
- framework-aware dead-code detection
- registry-backed checks that an imported package exists and is declared (hallucinated imports)
- a combined workflow where dead code, secrets, risky patterns, and CI hardening sit together
If those are part of your actual requirement, your decision is not just "Bandit or Semgrep or CodeQL." The requirement changed.
Which one should you choose?
Choose Bandit if:
- your team is small
- you want a Python-native security linter fast
- you are okay with a narrower scope
Choose CodeQL if:
- GitHub code scanning is already part of your engineering workflow
- you want GitHub-native query suites and reporting
- your code is on GitHub (default setup) or you can maintain an advanced-setup workflow
Choose Semgrep if:
- you want to write custom rules
- you need broad multi-language coverage
- security policy iteration matters more than minimal setup
Where Skylos fits
Skylos is not a substitute for every CodeQL or Semgrep use case.
It fits when the Python team cares about:
- dead code
- secrets
- risky patterns
- AI-generated code review
- GitHub Actions workflow alignment
That means Skylos often sits in a different comparison bucket: not just "security scanner," but "Python analysis workflow." See the Skylos quick start to run it next to any of the three.
Related comparisons:
The final recommendation
If you want the simplest answer:
- start with Bandit for lightweight Python security linting
- choose CodeQL if GitHub-native code scanning is the center of your workflow
- choose Semgrep if custom rule authoring is the deciding factor
Then reassess whether your actual need also includes dead code, AI-generated code review, or Python-specific workflow coverage. If it does, the comparison should widen beyond traditional SAST alone.