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
What Skylos Sees
Copy
# Caughtcursor.execute("SELECT * FROM users WHERE id = " + user_id)# Misseddef 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.
Copy
# 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 sinkdef 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.
Severity: CRITICAL — Attackers can read, modify, or delete your entire database.
Skylos detects SQL injection across multiple frameworks:
Framework
Dangerous Pattern
Rule ID
Raw Python
cursor.execute(f"...{user_input}...")
SKY-D210
SQLAlchemy
session.execute(text(f"...{user_input}..."))
SKY-D217
Django ORM
Model.objects.raw(f"...{user_input}...")
SKY-D217
Pandas
pd.read_sql(f"...{user_input}...", conn)
SKY-D217
See detection in action
Copy
# Vulnerable - Skylos catches all of these# Direct concatenationcursor.execute("SELECT * FROM users WHERE id = " + user_id)# F-string interpolation cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")# .format() methodcursor.execute("SELECT * FROM users WHERE id = {}".format(user_id))# SQLAlchemy text()from sqlalchemy import textsession.execute(text(f"SELECT * FROM t WHERE x = {val}"))# Django raw()User.objects.raw(f"SELECT * FROM users WHERE name = '{name}'")
Copy
# Safe - parameterized queriescursor.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])
Severity: CRITICAL — Attackers can execute arbitrary commands on your server.
See detection in action
Copy
# Vulnerableos.system(f"convert {user_filename} output.pdf")subprocess.run(f"echo {user_input}", shell=True)# Safe - use list arguments, no shellsubprocess.run(["convert", user_filename, "output.pdf"])subprocess.run(["echo", user_input]) # shell=False by default