Key takeaways
- Both bugs come from untrusted input being treated as code.
- Fix SQL injection with parameterized queries, never string concatenation.
- Fix XSS by encoding output by default and avoiding raw innerHTML.
- Defence in depth: validation, least privilege, CSP and HttpOnly cookies.
The shared root cause
Both vulnerabilities appear when an application mixes data and code. User input is meant to be data, but the application places it somewhere the interpreter (the database or the browser) treats it as instructions. Keeping the two strictly separate is the core idea behind every fix below. Injection flaws remain a standard category in the OWASP Top 10, which is a good reading list for any web developer.
SQL injection (SQLi)
SQL injection happens when input is concatenated straight into a database query. Imagine a login that builds this string:
SELECT * FROM users WHERE name = '" + input + "'
An attacker types ' OR '1'='1, the condition becomes always true, and the login is bypassed. Worse variants read or change other tables.
The fix: parameterized queries
Prepared statements send the query structure and the values separately, so input can never change the query’s meaning:
db.query("SELECT * FROM users WHERE name = ?", [input])
Also give the database account only the permissions it needs, hide detailed database errors from users, and validate input types (an ID should be a number). Escaping by hand is fragile; parameters are the reliable answer.
Cross-site scripting (XSS)
XSS happens when user input is shown back in a page as raw HTML instead of text. A malicious comment such as <script>alert(document.cookie)</script> would then run in every visitor’s browser, where it can steal data available to the page, change what users see or act as them.
- Stored XSS: the payload is saved (for example in a comment) and served to many users.
- Reflected XSS: the payload is in a link and bounces back in the response.
- DOM-based XSS: client-side code writes untrusted data into the page, typically through
.innerHTML.
The fix: encode output, prefer text APIs
Use textContent instead of innerHTML, let your template engine escape by default, and only allow rich HTML through a vetted sanitiser with an allow-list. Add a Content-Security-Policy to limit which scripts can run, and mark session cookies HttpOnly and Secure so injected scripts can’t read them.
Quick developer checklist
- Search your code for string-built SQL and replace it with parameters.
- Search for
innerHTML,document.writeandeval, and justify or remove each. - Escape on output, validate on input, and treat all external data as untrusted.
- Ship a CSP and security headers; check them with the HTTP Header Analyzer.
- Keep frameworks and libraries updated.
I use the Code Scanner on the Tools page as a quick first pass for these exact patterns. It is a pattern checker, not a replacement for a proper security review.
Practise legally
Only test for these flaws on systems you own or have written permission to test. Intentionally vulnerable labs are the right place to learn.
Frequently asked questions
Which is more dangerous, SQLi or XSS?
Both are serious. SQL injection targets your data store; XSS targets your users’ browsers. The impact depends on the application.
Do frameworks prevent these automatically?
Modern frameworks and ORMs help a lot by parameterizing queries and escaping output, but unsafe escape hatches (raw queries, raw HTML) still exist.
Is input validation enough?
No. Validation reduces risk but isn’t a complete defence. Parameterized queries and output encoding address the actual cause.
Where can I practise safely?
Use deliberately vulnerable training labs and your own local test projects, never other people’s websites.
Keep reading
A Practical WordPress Hardening Checklist
Most WordPress compromises come from basics being skipped. This checklist covers updates, logins, backups and security headers.
Read article →Password Security in 2026: Why Length Beats Complexity
Why long passphrases and unique passwords protect you better than short, symbol-heavy ones, how entropy works, and the habits that stop most account takeovers.
Read article →Nmap Basics: Reading Your First Scan
Open, closed and filtered ports explained, what -sV adds, how to read your first result and the rule that you only scan what you’re authorised to test.
Read article →