This guide compares five useful options for Python analysis in 2026: Semgrep, Bandit, CodeQL, Vulture, and Skylos. They solve different slices of security, dead-code, quality, and AI-assisted-code review; Vulture is a dead-code tool rather than SAST.
The comparison focuses on published detection scope, likely triage work, CI/CD integration, dead-code support, and AI-oriented workflows. It does not claim a universal false-positive ranking; that requires a labeled corpus representative of your code.
If you want the shortest possible answer:
- choose Semgrep for multi-language security and custom rules
- choose Bandit for a simple, familiar Python security linter
- choose CodeQL for deeper GitHub-native analysis
- choose Vulture for dead code only
- choose Skylos if you want Python security, dead code, quality checks, and AI-code review in one workflow
Quick comparison table
| Semgrep | Bandit | CodeQL | Vulture | Skylos | |
|---|---|---|---|---|---|
| Focus | Multi-language security | Python security | Multi-language security | Dead code | Security + dead code + quality |
| Languages | 30+ in CE; depth varies by engine | Python only | C/C++, C#, Go, Java/Kotlin, JavaScript/TypeScript, Python, Ruby, Rust, Swift, and Actions | Python only | Python (deepest), TypeScript/JavaScript and Java: dead code, security and quality. PHP, Rust, Dart: dead code and security. Go: dead code and security need the separate skylos-go engine (in the Docker image and GitHub Action, not the PyPI package). C# partial. Kotlin: dead code only. C++: unused file-local functions only. Shell: security only. |
| Security rules | Large community and Pro rule sets | Python AST plugin checks | Query suites with semantic and data-flow analysis | None | Built-in pattern and flow rules; depth varies by language/category |
| Dead code | Not a dedicated analyzer | No | Python quality queries for unused imports, unused variables and unreachable code; no whole-program unused-function analysis | Yes | Yes; deepest in Python |
| Code quality | Security-first | Security-first | Code scanning is security-focused; GitHub Code Quality is a separate product | No | Yes; metrics are primarily Python-focused |
| Taint analysis | CE: taint within a single function; hosted Pro engine: cross-function and cross-file | No general interstatement taint engine | Yes | N/A | Local propagation for supported source/sink patterns; conservative parameter handling |
| Custom rules | Yes (multi-language DSL) | Python plugin system | Yes (QL language) | Whitelists and ignore controls | Focused Python AST rules; much narrower than Semgrep or QL |
| Framework aware | Rule-dependent | Individual plugin-dependent | Query-dependent | Implicit uses may require ignores/whitelists | Explicit Python entry-point models for common frameworks |
| AI-oriented checks | Semgrep Guardian (launched June 2026): MCP server, hooks and skills that rescan agent-written code; plus custom rules | No dedicated suite | GitHub also offers separate Code Quality AI analysis | No dedicated suite | AI-defect checks, selected removed-control diffs, and LLM/agent static plugins |
| CI/CD | Standalone CE and hosted workflows | Pre-commit, GitHub Action, or manual CI | GitHub-native default or advanced setup | GitHub Action, pre-commit, or manual CI | Auto-generated GitHub Actions workflow |
| Free availability | Open-source CE and hosted Free plan | Open source | Public repositories; private repository access depends on GitHub Code Security licensing | Open source | CLI free (Apache-2.0), including the LLM verifier with your own model key. Skylos Cloud: Free plan (1 project) and Workspace plan ($990 per workspace for 12 months, paid once, or 12 months with any credit pack from $9); no seats, line meter or subscriptions. |
1. Semgrep
Best for: Multi-language teams, custom rule authoring, enterprise security programs
Semgrep is the broadest general-purpose SAST option on this list. Community Edition supports 30+ languages and 3,000+ customizable community rules; the hosted platform adds a Pro engine and AppSec workflows. Analysis depth varies by language and product.
Strengths
- Custom rule DSL. You can encode team-specific structural and taint policies in YAML across supported languages.
- Large ecosystem. Semgrep documents more than 3,000 customizable community rules for Community Edition. The engine is LGPL-2.1; since December 2024 the rules are under the Semgrep Rules License, which is not an OSI open-source license (the Opengrep fork exists for that reason).
- Multi-language. If you have Python + Java + Go + JS, Semgrep scans all of them.
- Hosted workflows. Findings triage and pull-request integrations are available, RBAC and SAML/OIDC SSO start at the Teams plan, while Jira and Slack integrations are on every tier (pricing).
- Taint analysis. Semgrep CE tracks taint only within a single function (with constant propagation across functions in one file); the Pro engine adds cross-function and cross-file analysis, and the hosted Free plan (up to 10 contributors and 10 private repositories) includes it.
Weaknesses
- No dedicated dead-code analyzer. You need a separate usage/reachability tool for that job.
- Security-first scope. Complexity, coupling, and cohesion are not Semgrep's core product focus.
- Engine differences matter. CE taint stays within a single function; Pro analysis adds cross-function and cross-file context, so a generic "Semgrep" result is not one fixed capability.
- Framework behavior depends on rules. Confirm that the selected rule set and engine model the framework APIs and flows you rely on.
Quick start
pipx install semgrep
semgrep scan --config auto src/
When to choose Semgrep
Choose Semgrep if you need its broader language catalog, mature cross-language rule DSL, registry, or hosted AppSec workflows.
For a detailed Semgrep vs Skylos comparison, see Semgrep vs Skylos for Python.
2. Bandit
Best for: Quick Python-only security scanning with zero configuration
Bandit is a long-running Python security analyzer maintained under PyCQA. It reports AST-based checks with severity, confidence, and CWE metadata and supports profiles, baselines, plugins, pre-commit, and CI use.
Strengths
- Zero setup. Install and run. No config file needed.
- Stable interface. Existing teams can keep familiar rule IDs, severity/confidence fields, baselines, and suppressions.
- Maintained under PyCQA. It is part of the PyCQA project family.
- Plugin system. You can write custom Bandit plugins.
- Broad security coverage. Catches shell injection, SQL injection, weak crypto, pickle, YAML, eval, exec, and more.
Weaknesses
- No general taint engine. Bandit can report dangerous call patterns without proving an interstatement source-to-sink flow.
- No dead code detection. Security only.
- No general framework entry-point model. Its individual security plugins recognize APIs rather than modeling dead-code reachability.
- No interstatement data flow. B602 distinguishes literal from computed commands, but Bandit does not trace where a computed value came from.
- Triage is repository-specific. Pattern findings can be valuable, but teams should measure how many require
# nosec, configuration, or baseline handling in their own code.
Example severity distinction
# B602 reports this simple static command at LOW severity
subprocess.call("ls -la", shell=True)
Quick start
pip install bandit
bandit -r src/
When to choose Bandit
Choose Bandit if you want a focused Python security scanner, value its plugin and baseline formats, and already have separate tools for dead code and quality.
For a detailed comparison, see Bandit vs Skylos.
3. CodeQL
Best for: Deep semantic analysis on GitHub-hosted projects
CodeQL is GitHub's static analysis engine. It treats code as data — you write queries in CodeQL's query language (QL) to find patterns.
Strengths
- Semantic analysis. CodeQL builds a database of your code and supports semantic, interprocedural, and data-flow queries over it.
- GitHub-native. Results appear in GitHub code scanning; default setup can configure supported repositories without a hand-written workflow.
- Taint analysis. Built-in data flow tracking across functions and files.
- Standard and custom queries. GitHub maintains query suites, and users can add QL queries.
Weaknesses
- Database build cost. CodeQL creates a source database, so measure its latency on your codebase before placing it in a fast local loop.
- Specialized query language. Custom analysis requires learning QL and CodeQL's library model.
- Limited dead-code coverage. CodeQL's Python quality queries flag unused imports, unused local/global variables and unreachable code, but not unused functions or classes across the whole program.
- Code scanning is security-focused. GitHub now offers a separate Code Quality product with deterministic CodeQL quality rules and AI analysis, so "GitHub has no code-quality analysis" is no longer accurate. Code Quality became generally available on 20 July 2026 at $10 per active committer per month plus metered AI usage, on GitHub Team and Enterprise Cloud (not GHES); it costs nothing per committer on public repositories.
- Private-repository licensing. CodeQL code scanning is available for public repositories; organization-owned private repositories require GitHub Code Security. GitHub Code Security costs $30 per active committer per month.
Quick start
Eligible repositories can enable CodeQL with GitHub's default setup. Advanced setup uses a workflow such as:
# .github/workflows/codeql.yml
name: CodeQL
on: [push, pull_request]
permissions:
contents: read
jobs:
analyze:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
actions: read
security-events: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: github/codeql-action/init@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
with:
languages: python
- uses: github/codeql-action/analyze@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
When to choose CodeQL
Choose CodeQL if you're on GitHub and want its semantic query model and supported cross-file data-flow analysis. Measure database-build time and confirm the licensing that applies to your repositories.
4. Vulture
Best for: Dedicated dead code detection in Python
Vulture is purpose-built for finding unused Python code. Its documented core records defined and used names from Python ASTs and reports candidates with confidence scores.
Strengths
- Purpose-built. Focused entirely on dead code — unused functions, classes, imports, variables.
- Focused. It has a small command surface for unused-code analysis.
- Confidence scoring. Reports 60-100% confidence for each finding.
- Integrations. The project documents a GitHub Action, pre-commit use, and a VS Code extension.
Weaknesses
- Implicit uses require help. Vulture documents false positives for code that is used implicitly and provides whitelists, ignore decorators, and other controls.
- No security scanning. Dead code only.
- Iterative cleanup. Vulture's own documentation recommends running it again after deletion because more dead code may become visible. Skylos models call reachability in one analysis, though dynamic uses can challenge both tools.
- Whitelist maintenance. Framework-heavy projects may need project-specific ignores or generated whitelists.
Example false positive
@app.route("/api/users") # implicit registration can require an ignore/whitelist
def get_users():
return jsonify(users)
@pytest.fixture # implicit fixture use can require framework-aware handling
def db_connection():
return create_connection()
Quick start
pip install vulture
vulture src/ --min-confidence 80
When to choose Vulture
Choose Vulture if you only need dead-code candidates, want confidence scoring, and are comfortable configuring implicit framework uses when they arise.
For reviewable upstream outcomes, see what happened when we sent dead-code cleanup PRs to mature Python projects.
5. Skylos
Best for: Python-focused teams wanting security + dead code + quality in one tool
Skylos combines dead-code, security, secrets, dependency, quality, and AI-defect checks. It is newer than the other tools and goes deepest on Python-specific reachability, frameworks, metrics, and flows; its other language analyzers have narrower, category-dependent coverage.
Strengths
- Combined categories. Security, secrets, dead code, quality, AI defects, and supported dependency manifests can run in one scan.
- Framework-aware Python reachability. Built-in models for Django, Flask, FastAPI, Pydantic, pytest, Celery, and Click reduce false positives for recognized entry points.
- Taint analysis. Traces user input to dangerous sinks; the injection rules (for example SKY-D211, SKY-D212) fire only on traced input, while
shell=Trueitself is always reported as SKY-D209. - Transitive dead code propagation. If A is dead and only A calls B, B is also flagged as dead.
- AI-oriented checks. Dedicated rules cover registry-backed nonexistent dependencies, undeclared third-party imports, selected phantom security helpers, and missing members on statically resolvable local modules. Secrets and disabled-control patterns come from separate scanners, while selected removed controls are checked in Git diffs.
- Generated CI/CD.
skylos cicd initwrites a GitHub Actions pull-request gate with PR comments that needs no Skylos account or API key. By default it also adds a "Skylos Cloud upload" job for pushes to your default branch, which fails until the Skylos GitHub App is installed; without Cloud, runskylos cicd init --no-upload. - Quality metrics. Cyclomatic complexity, coupling, cohesion, god classes, architecture metrics.
Weaknesses
- Narrow custom-rule model. Python AST custom rules cover functions, classes, and calls locally and through Cloud. This is much less expressive and less multi-language than Semgrep or QL.
- Newer ecosystem. Smaller community than Semgrep or Bandit.
- Uneven language depth. Python has the deepest coverage; TypeScript/JavaScript and Java also get dead-code, security and quality checks, while PHP, Rust and Dart get dead-code and security checks. Go dead-code and security checks need the separately built skylos-go engine, which the Docker image and GitHub Action include but the PyPI package does not. C# is partial, Kotlin is dead code only, C++ is limited to unused file-local functions, and Shell is security only. Ruby and C are not supported. See language support.
- Fewer security rules than Semgrep's full registry.
- Bounded dependency coverage. SCA uses OSV for PyPI, npm, Go and NuGet. It reads
uv.lock,poetry.lock,Pipfile.lock,package-lock.json/npm-shrinkwrap.json,pnpm-lock.yamlandyarn.lock, plus exact pins inrequirements.txt,pyproject.toml,package.jsonandgo.mod; it does not resolve version ranges and has no Maven, Gradle, Cargo or Composer support.
Quick start
pip install skylos
skylos . --danger --quality
When to choose Skylos
Choose Skylos if your codebase is primarily Python, its supported checks match your repository, and you want several analysis categories plus a generated GitHub Actions workflow. Validate its narrower language and dependency coverage before replacing specialized tools.
For more on what Skylos catches, see How to detect dead code in Python and AI-generated code security.
Tool combinations that work
Minimal setup (Python-only team)
pip install skylos
skylos . --danger --quality
One invocation enables security, dead-code, and quality checks for the supported files in the repository.
Maximum coverage (multi-language team)
# Semgrep for multi-language custom rules
- run: semgrep scan --config auto src/
# CodeQL for deep semantic analysis (needs init + analyze, as in the workflow above)
- uses: github/codeql-action/init@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
with:
languages: python
- uses: github/codeql-action/analyze@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
# Skylos for its supported dead-code, AI-defect, and quality checks
- run: skylos . --danger --quality --ai-defects --github
Budget-friendly stack
# Bandit for security (free, established)
bandit -r src/
# Vulture for dead code (free, established)
vulture src/ --min-confidence 80
Two focused open-source tools. The trade-off is separate result streams and project-specific handling of implicit framework uses and security-pattern noise.
The 2026 context: AI-generated code
The biggest shift in Python static analysis in 2026 is AI-generated code. Teams using Copilot, Claude, and Cursor are generating more code faster — but with new failure modes:
- Dependency mistakes — registry-backed nonexistent packages and undeclared third-party imports
- Verified missing references — selected security helpers and missing members on statically resolvable local modules
- Hardcoded credentials — AI tools inline secrets for "working examples"
- Disabled security —
verify=False,debug=True - Dead code accumulation — abandoned AI-generated drafts
These patterns cross several scanner categories. Bandit, Semgrep, and CodeQL can catch many underlying security patterns; Semgrep and CodeQL can be extended with custom rules or queries. Skylos adds registry-backed dependency checks, missing-member checks for resolvable local module surfaces, selected security-helper checks, heuristic Git provenance, and a selected removed-control diff rule. Hardcoded credentials and unsafe options are ordinary secrets/security findings rather than proof of AI authorship.
If your team uses AI coding tools heavily, factor this into your tool choice. See How to catch hallucinated imports in AI-generated Python code for more detail.
Summary
| Need | Best tool |
|---|---|
| Multi-language security | Semgrep |
| Simplest Python security scan | Bandit |
| Deep semantic analysis (GitHub) | CodeQL |
| Dedicated dead code finder | Vulture |
| Python security + dead code + quality + AI code | Skylos |
| Broad custom rule authoring | Semgrep or CodeQL |
| Focused Python AST conventions | Skylos custom rules |
| Framework-aware dead code (fewer manual whitelists for recognized frameworks) | Skylos |
| Generated GitHub Actions workflow with PR comments | Skylos |
| Enterprise security program | Semgrep AppSec Platform |
Pick the tool that matches your primary need. Start with the highest-risk gap, then expand coverage based on measured misses and triage cost.
If your team is deciding between two specific options, these follow-up pages are better than staying on a broad list:
- Bandit vs Skylos
- Deadcode vs Vulture vs Skylos for Python Dead Code Detection
- Bandit vs CodeQL vs Semgrep for Python Security Scanning
If you want to stop researching and test the workflow directly:
pip install skylos
skylos . -a
Related
- Semgrep vs Skylos for Python
- Bandit vs Skylos
- Snyk vs Skylos
- SonarQube alternative: Skylos vs SonarQube
- Deadcode vs Vulture vs Skylos
- How to Detect Dead Code in Python
- How to Verify AI-Generated Python Code and Catch Hallucinated Imports
- Python Security Scanner for GitHub Actions
- Dead-code cleanup PRs that maintainers merged
Try Skylos
If you want one tool that covers security, dead code, and quality for Python:
pip install skylos
skylos . --danger --quality
No signup is required for a local CLI scan; runtime depends on repository size and enabled checks. View on PyPI | Read the docs
All tools mentioned are open source or have free tiers. Semgrep | Bandit | CodeQL | Vulture | Skylos | Skylos Docs