Skip to main content

Security Analysis

info

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.

What Pattern Matchers See:

# 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.

What Skylos Sees:

# Skylos traces the full data flow:

def get_user(user_id): # Tainted: function parameter
query = build_query(user_id) # Tainted: uses tainted value
return db.execute(query) # ALERT: tainted value reaches sink

def build_query(uid): # Tainted: parameter from tainted caller
return f"SELECT * FROM users WHERE id = {uid}" # Tainted string

Skylos follows the taint through every assignment and function call.


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

warning

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
See detection in action
# 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

warning

Severity: CRITICAL — Attackers can execute arbitrary commands on your server.

See detection in action
# 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)

warning

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

info

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

Rule Reference

See all security rules with examples

Quality Gate

Configure thresholds to block deployments