How to Detect SQL Injection SELECT and XSS Input in Python
A SQL injection SELECT payload like 'UNION SELECT * FROM secrets' can dump an entire table through one unguarded input field. This project builds a Python CLI validator that runs input through two regex pattern sets - one for SQL injection markers, one for XSS - and prints SAFE or UNSAFE with a reason so obvious attacks get caught and logged at the edge.
What the validator catches
The goal is a small Python module, validator.py, that reads a string and prints
SAFE or UNSAFE (with a reason). It runs as a CLI:
python3 validator.py "hello world" # SAFE
python3 validator.py "' UNION SELECT * FROM secrets --" # UNSAFE: sql-injection
python3 validator.py "<script>alert(1)</script>" # UNSAFE: xss
It must flag two attack classes. The SQL injection class covers the classic
markers attackers append to a query: a UNION SELECT that stitches attacker rows
onto a legitimate result set, a tautology like OR 1=1 that makes a WHERE clause
always true, a stacked ; DROP TABLE, and comment terminators (--). The XSS
class covers <script> tags, inline event handlers (onerror=, onload=), and
javascript: URIs.
Why a SQL injection SELECT is dangerous
Consider a search endpoint that builds SQL by string concatenation:
query = "SELECT * FROM products WHERE name = '" + user_input + "'"
If a user submits ' UNION SELECT username, password FROM users --, the query
becomes two SELECTs glued together, and the second one returns the credentials
table. The trailing -- comments out whatever SQL followed. This is why
UNION SELECT and OR 1=1 are the highest-signal tokens to detect - they are the
building blocks of almost every hand-crafted injection.
Step 1 - write the two pattern sets
Compile one case-insensitive regex per attack class. The SQL pattern targets the injection markers directly; the XSS pattern targets the script-execution vectors:
import re, sys
SQLI = re.compile(
r"('|\b)(or|and)\s+\d+=\d+|union\s+select|drop\s+table|insert\s+into"
r"|--\s*$|;\s*--|\bexec\b|\bxp_",
re.IGNORECASE
)
XSS = re.compile(
r"<script|onerror\s*=|onload\s*=|javascript:|<img[^>]+on\w+\s*=",
re.IGNORECASE
)
union\s+select matches UNION SELECT regardless of spacing or case;
(or|and)\s+\d+=\d+ catches OR 1=1 and its variants; ;\s*-- and --\s*$
catch stacked queries and comment terminators.
Step 2 - flag and report
Check SQL first, then XSS, and return a reason so the caller can log which class fired:
def is_safe(text):
if SQLI.search(text):
return False, 'sql-injection'
if XSS.search(text):
return False, 'xss'
return True, None
if __name__ == '__main__':
text = ' '.join(sys.argv[1:])
safe, reason = is_safe(text)
print('SAFE' if safe else f'UNSAFE: {reason}')
Run it against normal input - names, emails, order descriptions - and confirm each
prints SAFE. Order #12345 for Alice and john@example.com must pass through
cleanly; a validator that flags everything is useless.
Where a regex validator fits (and where it does not)
A hand-rolled validator is a useful edge signal - it catches obvious attempts, surfaces them in logs, and stops trivial bots before they reach the app. But it is never the control. The real defenses are:
- Parameterized queries for SQL - the driver sends values separately from the
query text, so
UNION SELECTin a parameter is treated as data, never code. - Output escaping for XSS - HTML-encode user input at render time.
Regex validators are easy to bypass with obfuscation (encoding, comments inside keywords, unicode). Treat this as defense-in-depth and log signal, not a wall.
Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.
Try it in a workspace →What you'll practice
- Writing case-insensitive regex patterns that flag UNION SELECT, OR 1=1, and DROP TABLE
- {'Detecting XSS vectors (script tags, inline event handlers, javascript': 'URIs) with a second pattern set'}
- Building a Python CLI that prints SAFE or UNSAFE with a reason and lets normal input pass
FAQ
How do you detect a SQL injection SELECT attack?
Match the injection markers with a case-insensitive regex: UNION SELECT (which appends attacker rows to a result set), OR 1=1 (a tautology that makes any WHERE clause true), and comment terminators like a trailing double dash. These tokens appear in almost every hand-crafted injection, so flagging them catches obvious attempts at the edge.
What does UNION SELECT do in a SQL injection?
UNION SELECT stitches a second query onto a legitimate one so the response also returns rows the attacker chose - for example dumping a users table through a product search box. It only works when the input is concatenated into the SQL string; parameterized queries neutralize it because the value is sent separately from the query text.
Can a regex input validator stop SQL injection?
A regex validator catches obvious attempts and gives you log signal, but it is not a real defense - it is easy to bypass with encoding or obfuscation. The primary control is parameterized queries, which send input as data the database never parses as SQL. Use the validator as defense-in-depth at the edge.
How do I detect XSS input in Python?
Use a second case-insensitive regex targeting the script-execution vectors: script tags, inline event handlers such as onerror= and onload=, and javascript: URIs. Print an UNSAFE result with an xss reason so the attempt is logged, then rely on output escaping at render time as the actual fix.
Keep learning
Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.
Open the workspace →