I built a small Flask and SQLAlchemy demo that intentionally exposed an injection risk in a login flow, then replaced the unsafe pattern with parameterized queries. I verified the fix and outlined additional hardening steps. The lab is expanding to cover more authentication and data validation scenarios. (How to Do SQL Injection Testing & Mitigation)
Demonstrate how unsafe query construction leads to injection
Implement parameterized queries with the ORM
Confirm the fix and reduce error disclosure
Capture guidance developers can adopt immediately
Python, Flask, and SQLAlchemy basics
Local database using SQLite for simplicity
Flask, SQLAlchemy, SQLite
Local testing with a virtual environment
1. Environment and target
Created a Flask app with a simple User model and login route
Used a deliberately unsafe filter to illustrate the risk
2. Testing
Exercised the login form with crafted inputs in a safe, local lab
Observed that the unsafe pattern treated input as part of the query
3. Mitigation
Replaced the dynamic filter with filter_by and .first() to parameterize input
Reduced error verbosity and standardized invalid login responses
4. Additional hardening
Planned password hashing and per-user salts
Added input validation and least privilege database access
Documented safe ORM patterns for queries and updates
5. Verification and docs
Re-tested the login flow to confirm the unsafe input no longer bypasses checks
Wrote a short guide on parameterized queries and common mistakes
Removed an injection path by adopting ORM parameters
Reduced sensitive error output
Created a reference for developers to avoid similar pitfalls
Injection testing in a safe lab
ORM-based query design
Defensive error handling