Semgrep is a mature application-security scanner with a broad language matrix, a large community rule registry, and a hosted AppSec platform. Its Community Edition and hosted platform have different analysis depth, so "Semgrep" does not describe one identical feature set.
Skylos is a multi-language, local-first static analysis tool that combines security scanning, dead code detection, secrets, dependency checks, and code quality checks. Its deepest framework and data-flow analysis is in Python; coverage varies by language and category.
This comparison is for Python teams deciding between the two. We'll be straightforward about where each tool is stronger.
The short version
| Semgrep | Skylos | |
|---|---|---|
| Best for | Multi-language teams, custom rule authoring, enterprise security programs | Python-focused teams, dead code detection, AI-generated code scanning |
| Languages | 30+; depth varies by engine and product | 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 scanning | Yes (community and Pro rules; Pro adds cross-file analysis) | Yes; Python, JavaScript/TypeScript and Java have the deepest coverage; Go needs the skylos-go engine; Kotlin and C++ have no security rules |
| Dead code detection | Not a dedicated analyzer | Yes; strongest in Python, with language-specific analyzers elsewhere |
| Code quality metrics | Security-first rather than a general metrics suite | Yes; complexity, coupling, and cohesion are primarily Python-focused |
| Custom rules | Yes (mature, multi-language rule DSL) | Yes (Python AST pattern rules; much narrower than Semgrep) |
| Framework awareness | Rule-dependent | Built-in (Django, Flask, FastAPI, Pydantic, pytest) |
| CI/CD | Yes | Yes (auto-generated workflows) |
| Pricing | Open-source CE plus hosted Free, Teams, and Enterprise plans | CLI free (Apache-2.0). 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. |
The Skylos language row describes files the current CLI analyzes, not equal feature parity in every language. Python has the deepest coverage. TypeScript/JavaScript and Java also get dead-code, security and quality checks; 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# support is partial, Kotlin is dead code only, C++ is limited to unused file-local functions, and Shell is security only.
Where Semgrep is stronger
Multi-language support
Both tools can scan polyglot repositories. Skylos's coverage is tiered by language (see above), plus CI and deployment configuration files. Semgrep still has the broader language catalog, including Ruby, and its current platform publishes per-language distinctions between Community and Pro features. For a mixed-language codebase, compare the exact analyzers and rule coverage you need rather than treating a language checkmark as parity.
Custom rule authoring
Semgrep's rule language is its killer feature. You can write custom rules that match specific patterns in your codebase:
rules:
- id: no-raw-sql-queries
patterns:
- pattern: cursor.execute($QUERY, ...)
- pattern-not: cursor.execute("...", ...)
message: Use parameterized queries instead of string formatting
severity: ERROR
languages: [python]
This is incredibly powerful for teams with domain-specific security requirements. If you need to enforce "never call this internal API without an auth check" or "always use our custom logger instead of print," Semgrep lets you encode those rules.
Skylos does have custom rules, but the scope is smaller. Local/community rules and Cloud-synced organization rules use Python AST patterns for function decorators, class inheritance, and calls. Custom YAML rules (loaded from ~/.skylos/rules/ and run with --quality) also support a basic taint-flow pattern. Skylos custom rules are therefore useful for focused Python conventions, not a substitute for Semgrep's cross-language structural and taint-rule DSL.
Rule ecosystem
Semgrep says its Community Edition includes 3,000+ customizable open-source rules. Its registry covers many languages and frameworks. Since December 2024 those registry rules are published under the Semgrep Rules License, which is not an OSI-approved open-source license; Opengrep is a community fork of the engine (Semgrep's Opengrep FAQ).
Skylos ships a smaller catalog spanning security, reliability, secrets, quality, AI-defect, dependency, CI/CD, and deployment checks. A single rule count would hide the fact that those categories and their language depth differ, so teams should compare the relevant rules (see the Skylos rules reference) and run both tools on representative code.
Enterprise features
Semgrep's hosted plans provide findings triage and PR integrations; its current plan matrix puts RBAC and SAML/OIDC SSO in the Teams and Enterprise tiers, while Jira and Slack integrations are on every tier, including Free. If you're running a security program across many repositories, that mature AppSec operating layer matters.
Where Skylos is stronger
Dead code detection
Semgrep is not a dedicated usage-based dead-code analyzer. Its rules can match code patterns, but dead-symbol reachability is not the product's stated focus.
Skylos detects unused functions, classes, imports, variables, and parameters. More importantly, it does transitive dead code propagation: if function A is dead and it's the only caller of function B, Skylos marks B as dead too.
def process_refund(order_id): # dead — nothing calls this
validated = _validate_refund(order_id) # also dead (transitive)
_send_refund_email(validated) # also dead (transitive)
If usage-based dead-code cleanup is a priority, plan to pair Semgrep with a dedicated dead-code analyzer or use a tool that models symbol reachability.
Framework-aware analysis (out of the box)
Semgrep can understand frameworks, but only through specific rules. If a rule doesn't exist for your framework pattern, Semgrep doesn't know about it.
Skylos has built-in framework visitors for Django, Flask, FastAPI, Pydantic, pytest, Celery, and Click. It understands that @app.route handlers are called via HTTP, @pytest.fixture functions are called by the test runner, and Pydantic model_validator methods are called during validation.
This means fewer false positives out of the box without writing custom rules:
@app.route("/api/users") # Skylos: alive (Flask route)
def get_users(): # Semgrep: n/a (no dead-code analysis)
return jsonify(users)
@pytest.fixture
def db(): # Skylos: alive (pytest fixture)
return create_engine()
Taint analysis for Python
Both tools have taint analysis, but they work differently.
Semgrep Community Edition tracks data flow only within a single function in a single file; the Pro engine adds cross-function and cross-file analysis. Semgrep's current hosted Free plan includes Pro rules and cross-file analysis, so this distinction is about CE versus the hosted engine rather than simply free versus paid.
Skylos's supported Python rules propagate taint through local assignments and expressions from sources such as request.args.get(), input(), and sys.argv to sinks such as subprocess.call(), cursor.execute(), and eval(). They also conservatively treat ordinary function parameters as untrusted; this is not cross-function call-chain analysis:
# Skylos flags this — user input flows to shell command
cmd = request.args.get("command")
subprocess.call(cmd, shell=True) # SKY-D212: Command injection
# Skylos still reports shell=True as SKY-D209, but not tainted command injection
subprocess.call("ls -la", shell=True) # SKY-D209; no SKY-D212
Bandit also reports both shell=True calls as B602 and adjusts severity by command form. Semgrep's behavior depends on the rules and engine selected.
AI-generated code patterns
Skylos separates evidence-backed AI-defect checks from its general security, secrets, and diff-aware checks. Together they cover patterns that often appear in AI-assisted changes:
- Verified missing references — selected phantom security helpers and missing members on statically resolvable local modules
- Dependency evidence — registry-backed nonexistent packages and real third-party imports missing from supported dependency metadata
- Hardcoded credentials — handled by the secrets and quality scanners
- Disabled or removed security controls — handled by ordinary security checks and the Git-diff regression rule
Semgrep can encode many of these patterns with rules, and Semgrep Guardian (launched 2026-06-23) adds MCP, hooks and skills that rescan agent-written code; Semgrep's launch post says it can be installed for free. Skylos's distinction is the combination of ordinary scanning, dedicated hallucination checks, and Git-diff checks for specific removed or downgraded controls. Its Git attribution is heuristic, based on commit authors, emails, messages, and co-author trailers; it does not prove that a particular model wrote a line.
For a deeper look, see our guide on catching hallucinated imports in AI-generated code.
Code quality metrics
Semgrep's core offering is application security rather than a broad code-quality metrics suite. Skylos can report the following Python-oriented quality signals in the same scan:
Skylos includes:
skylos src/ --quality
- Cyclomatic complexity (SKY-Q301)
- Deep nesting detection (SKY-Q302)
- Argument count and function length (SKY-C303, SKY-C304)
- God class detection (SKY-Q501)
- Coupling and cohesion metrics (SKY-Q701, SKY-Q702)
- Advisory architecture metrics (distance from the main sequence, SKY-Q802/Q803; off the gate unless
enforce_iad = true) - Async blocking call detection (SKY-Q401)
If you want one tool that covers security, dead code, and quality, Skylos does all three.
Generated CI setup
Skylos generates a complete GitHub Actions workflow:
skylos cicd init --no-upload
This creates a .github/workflows/skylos.yml pull-request gate with PR scanning, GitHub annotations, PR review comments and a quality-gate step, and needs no Skylos account or API key. By default skylos cicd init also adds a "Skylos Cloud upload" job for pushes to your default branch, which fails until the Skylos GitHub App is installed; --no-upload leaves it out.
Semgrep also documents standalone CE CI configurations and hosted-platform integrations. Skylos's advantage here is the bundled workflow generator, not exclusive access to CI scanning.
Detection comparison: real examples
SQL injection
Semgrep (with the registry audit rule python.django.security.audit.raw-query.avoid-raw-sql, which is not in the default p/django ruleset):
# Semgrep flags this
User.objects.raw("SELECT * FROM users WHERE id = %s" % user_id)
Skylos:
# Skylos flags this (SKY-D211: SQL injection via taint analysis)
query = f"SELECT * FROM users WHERE id = {request.args['id']}"
cursor.execute(query)
# Skylos also has a raw-SQL execution rule (SKY-D217)
User.objects.raw(f"SELECT * FROM users WHERE name = '{name}'")
Both tools can catch SQL injection. Skylos has distinct tainted-SQL and raw-SQL rules; Semgrep supports both search-mode and taint-mode rules, with analysis depth depending on its engine.
Hardcoded secrets
Semgrep: Semgrep Secrets (a paid add-on, see pricing) or the public generic.secrets registry rules flag a hardcoded key only when a rule matches the key's shape; for example, detected-generic-api-key needs a 32–45-character alphanumeric value, so a short placeholder like the one below is not reported:
# Not matched by detected-generic-api-key (too short)
api_key = "sk-1234567890abcdef"
Skylos:
# Skylos flags this in a secrets scan (SKY-S101)
API_KEY = "sk-proj-1234567890abcdef"
Both can catch this category. Exact provider coverage and validation behavior change over time, so compare the current rules against the credential types your organization uses.
Command injection
Semgrep:
# Semgrep flags this (depending on rule)
os.system(user_input)
Skylos:
# Skylos flags this (SKY-D212) — traces user_input from request
user_input = request.form.get("cmd")
subprocess.call(user_input, shell=True)
# Skylos reports shell=True but not tainted command injection here
subprocess.call("git status", shell=True) # SKY-D209; no SKY-D212
Skylos distinguishes its general shell=True warning from the higher-confidence source-to-sink command-injection rule. Semgrep can also use taint rules; compare the selected rule sets and engine rather than assuming one product always has more flow context.
When to use Semgrep
- You need languages or language-specific depth beyond Skylos's current analyzers
- You need custom rules for domain-specific security policies
- You want access to a large rule ecosystem
- You're running a formal security program with triage workflows
- You need team controls (SAML/OIDC SSO and RBAC on Teams and Enterprise)
- Dead code detection is not a priority
When to use Skylos
- Your codebase is primarily Python, or you have a supported polyglot repository and have validated the category depth you need
- You want security + dead code + quality in a single tool
- You use Django, Flask, FastAPI, or Pydantic and want out-of-the-box framework awareness
- Your team uses AI coding tools and wants registry-backed dependency checks plus missing-member checks on resolvable local modules
- You want a generated GitHub Actions workflow with PR inline comments
- You need focused Python AST custom rules and do not require Semgrep's broader cross-language rule DSL
Can you use both?
Yes. Some teams run Semgrep for broad application-security policies and Skylos for dead-code, quality, and AI-defect checks. Both can report overlapping security or custom-rule findings, so deduplicate by rule and fingerprint in CI rather than assuming there will be no overlap.
Quick start
Semgrep
pipx install semgrep
semgrep scan --config auto src/
Skylos
pip install skylos
skylos src/ --danger --quality
Final thoughts
Semgrep is a more mature application-security tool with a larger rule ecosystem and broader language catalog. It remains the stronger starting point when you need its supported languages, rule DSL, or platform workflows.
Skylos goes deepest on Python: call-aware dead-code analysis, framework entry points, built-in security flows, AI-defect checks, and combined security and quality analysis. Its additional language analyzers are real but do not all match that Python depth. If those combined checks match your repository, Skylos is worth evaluating alongside Semgrep.
The honest answer: try both on your codebase and compare the output. That's more useful than any comparison article.
Try Skylos
If you want security, dead code, and quality in one Python-focused tool:
pip install skylos
skylos src/ --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
Related
- Bandit vs CodeQL vs Semgrep for Python
- Bandit vs Skylos
- Snyk vs Skylos
- SonarQube vs Skylos
- Deadcode vs Vulture vs Skylos
- Best Python SAST Tools in 2026
- How to Detect Dead Code in Python
- How to Catch Hallucinated Imports in AI Code
- GitHub Actions Security Scanner
- Python Security Scanner for GitHub Actions
Semgrep Community Edition (LGPL-2.1) and the Skylos CLI are open source; Semgrep's Pro engine, AppSec Platform and registry rules are under other licenses. Semgrep | Skylos | Skylos Docs | Install Skylos