Skip to main content
Enable security scanning: skylos . --danger

Why Pattern Matching Fails

Most security scanners use regex patterns to find dangerous code. This approach has a fundamental flaw: it can’t follow data flow.
# Caught
cursor.execute("SELECT * FROM users WHERE id = " + user_id)

# Missed
def get_user(user_id):
    query = build_query(user_id)
    return db.execute(query)

def build_query(uid):
    return f"SELECT * FROM users WHERE id = {uid}"
Pattern matchers only see the execute() call with a variable—they can’t tell if that variable contains user input.

How Taint Analysis Works

Skylos builds a data flow graph for each file, tracking how values propagate from sources (user input) to sinks (dangerous functions).

The Analysis Pipeline


Vulnerability Categories

SQL Injection

Severity: CRITICAL — Attackers can read, modify, or delete your entire database.
Skylos detects SQL injection across multiple frameworks:
FrameworkDangerous PatternRule ID
Raw Pythoncursor.execute(f"...{user_input}...")SKY-D210
SQLAlchemysession.execute(text(f"...{user_input}..."))SKY-D217
Django ORMModel.objects.raw(f"...{user_input}...")SKY-D217
Pandaspd.read_sql(f"...{user_input}...", conn)SKY-D217
# Vulnerable - Skylos catches all of these

# Direct concatenation
cursor.execute("SELECT * FROM users WHERE id = " + user_id)

# F-string interpolation  
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")

# .format() method
cursor.execute("SELECT * FROM users WHERE id = {}".format(user_id))

# SQLAlchemy text()
from sqlalchemy import text
session.execute(text(f"SELECT * FROM t WHERE x = {val}"))

# Django raw()
User.objects.raw(f"SELECT * FROM users WHERE name = '{name}'")
# Safe - parameterized queries
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
session.execute(text("SELECT * FROM t WHERE x = :val"), {"val": val})
User.objects.raw("SELECT * FROM users WHERE name = %s", [name])

Command Injection

Severity: CRITICAL — Attackers can execute arbitrary commands on your server.
# Vulnerable
os.system(f"convert {user_filename} output.pdf")
subprocess.run(f"echo {user_input}", shell=True)

# Safe - use list arguments, no shell
subprocess.run(["convert", user_filename, "output.pdf"])
subprocess.run(["echo", user_input])  # shell=False by default

Server-Side Request Forgery (SSRF)

Severity: CRITICAL — Attackers can access internal services or cloud metadata.
# Vulnerable - user controls the URL
requests.get(user_provided_url)

# Attacker provides: http://169.254.169.254/latest/meta-data/
# -> Accesses AWS instance metadata, potentially leaking credentials

Path Traversal

# Vulnerable
open(f"uploads/{user_filename}", "r")

# Attacker provides: ../../../etc/passwd
# -> Reads sensitive system files

Cross-Site Scripting (XSS)

# Vulnerable - user content rendered as HTML
from markupsafe import Markup
return Markup(f"<div>{user_comment}</div>")

Dangerous Function Detection

Beyond taint analysis, Skylos flags inherently dangerous patterns:
FunctionRiskRule IDSeverity
eval()Arbitrary code executionSKY-D201HIGH
exec()Arbitrary code executionSKY-D202HIGH
pickle.load()Deserialization attackSKY-D203CRITICAL
pickle.loads()Deserialization attackSKY-D204CRITICAL
yaml.load()Code execution without SafeLoaderSKY-D205HIGH
hashlib.md5()Weak cryptographic hashSKY-D206MEDIUM
hashlib.sha1()Weak cryptographic hashSKY-D207MEDIUM
requests.get(verify=False)SSL verification disabledSKY-D208HIGH

Secret Detection

Enable secret scanning: skylos . --secrets
Skylos detects hardcoded credentials that should never be in source code:
ProviderWhat’s DetectedExample Pattern
AWSAccess keysAKIA...
GitHubPersonal access tokensghp_..., gho_...
SlackBot and user tokensxoxb-..., xoxp-...
StripeLive API keyssk_live_..., rk_live_...
GenericCommon variable namesapi_key = "...", password = "..."
──────────────────────── Secrets ────────────────────────
 #  Provider  Message                    Preview           Location
 1  aws       AWS Access Key detected    AKIA****EXAMPLE   config.py:12
 2  stripe    Stripe Live Key detected   sk_live_****xyz   payments.py:8

Comparison: Skylos vs. Other Tools

CapabilitySkylosBanditSemgrepSnyk Code
Taint analysis
Framework awarenessPartial
Dead code detection
Quality metrics
AI-powered fixes
Self-hosted
FreePartialPartial

Integration Example

Block PRs with critical security issues:
# .github/workflows/security.yml
name: Security Scan

on: [pull_request]

jobs:
  skylos-security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      
      - run: pip install skylos
      
      - name: Security Scan
        run: skylos . --danger --secrets --gate
With fail_on_critical = true (default), any CRITICAL finding blocks the PR.

Next Steps