Why are you here?
You’ve heard about JavaScript SQL injection attacks before, but you’re not entirely sure what they look like in the wild or if you need to worry about them in the first place. Maybe you’re trying to figure out just how bad it could be.
In short, if you’re building apps using SQL databases, like MySQL and PostgreSQL, you’re at risk—you’re not safe from attack methods plaguing developers and their databases for decades. As a developer, the onus is on you to implement guardrails that protect user data and ensure your underlying infrastructure is never intruded, explored, or commandeered.
All the new tools say they’re helping you, but they just make development more complex.
You can add an object–relational mapper (ORM) like Sequelize and TypeORM to simplify how you work with SQL databases like MySQL and PostgreSQL, but they don’t completely absolve you of risk. Web application firewalls (WAFs) help you block attacks at the networking level, but require expensive infrastructure and constant maintenance. Code-scanners can help you identify obvious flaws, but do far less for the unknown unknowns and lurking zero-day techniques.
We’ll present you with a clear picture of what SQL injection attacks look like, the risk they carry, and the development mistakes that make them possible. Then we’ll do you one better by walking you through installing a global hotfix so you’ll know, with certainty, that your apps are safe.
SQL injection attacks: examples and implications
The most basic definition of an SQL injection attack is when an app allows unvalidated and unsanitized user input to run database queries, allowing an attacker to read the SQL database, modify records, or delete to their heart’s content.
As usual, XKCD illustrates the danger of SQL better than most gloomy scenarios we could dream up:

What does vulnerable JavaScript app look like?
Let’s start with a simple pseudocode example: a JavaScript app with an input element that allows users to search a database of cats. In the example JavaScript code below, the app responds to POST requests on the /cats path to extract the user input from the request body and connects to the database with a query to return all cats with a matching id. The app then displays the cat using the JSON response.
app.post("/cats", (request, response) => {
const query = `SELECT * FROM cats WHERE id = ${request.body.id}`;
connection.query(query, (err, rows) => {
if(err) throw err;
response.json({
data: rows
});
});
});
While this example might look innocuous to those untrained on SQL injection attacks, it’s egregiously vulnerable. Notably, the app does not attempt to validate or sanitize user input for potentially dangerous strings or encoding methods, and concatenates user input directly into the SQL query, which allows attackers multiple opportunities to attack using common SQL injection attack methods that have existed for decades.
Example JavaScript SQL attack payloads
SQL injection hinges on tricking your MySQL or PostgreSQL database into taking action or responding with data outside the expected scope due to how your app generates SQL queries.
The 1=1 is always true attack can return the entire table of cats with tricks like apostrophes or quotation marks, because 1=1
is indeed always TRUE:
- The user inputs:
BOBBY TABLES’ OR 1=’1
- The database executes the SQL query:
SELECT * FROM Users WHERE Cat = BOBBY TABLES OR 1=1;
Similarly, attackers can exploit a = is always true attack to return all cats, because ""=""
is always TRUE:
- The user inputs:
" OR ""="
- The database executes the SQL query:
SELECT * FROM Cats WHERE CatId ="" or ""="";
Attackers will often exploit how databases handle inline comments, and by inserting comments (/* … */)
into a query, they can obfuscate their intent or bypass filters.
- The user inputs:
DR/*hello world*/OP/*sneak attack*/ TABLE Cats;
- The database executes the SQL query:
DROP TABLE Cats;
Another common JavaScript SQL injection strategy is query stacking, which lets attackers start with an innocuous string, then use a semicolon (;) to terminate that statement and begin another containing their injection. Attackers often use query stacking to delete entire databases in one fell swoop with a DROP TABLE command:
- The user inputs:
Bobby; DROP TABLE Cats --
- The app builds its SQL query:
const query = "SELECT * FROM Cats WHERE CatId = " + input;
- The database executes the SQL query:
SELECT * FROM Cats WHERE CatId = BOBBY; DROP TABLE Cats;
What about NoSQL injection attacks?
NoSQL injection attacks are equally dangerous to the security of your app and user data, but only affect tech stacks using databases like MongoDB. The main difference is the style attacks, as SQL and NoSQL queries use entirely unique syntax that doesn’t translate from one category to the other.
If you’re using a SQL database, you’re not at risk of NoSQL injection attacks, and vice versa.
The basic path: manually fixing all your SQL injection vulnerabilities
At this point, you might be less interested in what all the possible injection tricks look like and more interested in how to protect the data you have in MySQL or PostgreSQL.
- Use parameterized queries: SQL has functionality to disconnect the execution of queries and values, protecting the database from injection attacks.With the JavaScript/Node.js example from above, you can employ a placeholder in your SQL query with a question mark (
?
). Theconnection.query()
method then takes the parameter in its second argument, providing the same results in an injection-proof method.
app.post("/cats", (request, response) => {
const query = `SELECT * FROM Cats WHERE id = ?`;
const value = request.body.id;
connection.query(query, value, (err, rows) => {
if(err) throw err;
response.json({
data: rows
});
});
});
- Validate and sanitize user input: While parameterized queries can help protect your SQL database from intrusion and attack, you can also prevent users from entering potentially dangerous strings into your application.
One option is adding open-source libraries for sanitization and validation to your app. For example, you can use validator.js in the JavaScript/Node.js ecosystem to double-check that a user is trying to enter a real email address—not an SQL injection attack—into your sign-up form.
You can also develop custom regex-based validators to perform similar work, but you’ll have an enormously time-consuming and complex road ahead with research and tons of manual testing. Plus, can you really interpret this example regex for email validation?const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
The same idea applies to preventing strings like…’ OR 1-’1.
You can try to research and close down all these opportunities yourself, but you’d probably rather spend your time building new features.
- Deploy WAFs or agent-based security platforms: While these solutions can block SQL attacks before they even touch your app, or at least notify you in real-time as attacks happen, they come with some caveats.
First, they are often expensive and require you to launch new infrastructure on-premises or in the cloud, which is often far more complex than what you signed up for as a developer who just wants to ship to production. Second, they require more manual maintenance to update the ruleset, distracting you from other manual interventions to SQL injection. Finally, they often add more computational load, or redirect all requests through their platform for analysis, adding latency and harming the end-user experience.
The big problem is that opportunities for SQL injection attacks are like weeds—you can cut them all down once using these tools, but you must be constantly vigilant over your entire codebase to ensure they never sprout again.
An alternative path to solving JavaScript SQL injection attacks: Aikido Firewall
Aikido Security recently released Firewall, a free and open-source security engine that autonomously projects you from SQL injection attacks—and a whole lot more.
If you’re not using Node.js, just know that we’ll start supporting other languages and frameworks in the future. You can always subscribe to our product newsletter to hear exactly when Firewall expands beyond the JavaScript world or email us at hello@aikido.dev if you’d like to pitch a specific language.
Testing an app that’s vulnerable to JavaScipt SQL injection
Let’s use a sample app that ships with the open-source repository to showcase how Aikido Firewall works. You’ll also need Docker/Docker Compose to deploy a local MySQL database.
Start by forking the firewall-node repository and cloning said fork to your local workstation.
git clone https://github.com/<YOUR-GITHUB-USERNAME>/firewall-node.gitcd firewall-node
Use Docker to deploy a local MySQL database on port 27015. This docker-compose.yml file also creates s3mock, MongoDB, and PostgreSQL containers as well, as it was created to help the Aikido team test how Firewall blocks various attacks.
docker-compose -f sample-apps/docker-compose.yml up -d
Next, launch the sample app:
node sample-apps/express-mysql2/app.js
Open http://localhost:4000
in your browser to check out the very simple cat app. In the textarea, type in a few cat names and click the Add button. To test SQL injection, you can either click the Test injection link or type the following into the textarea: Kitty'); DELETE FROM cats;-- H
and click Add again. Either way, the app allows you to stack multiple queries together using some sneaky query comments, deleting the entire cats database.
How does this happen? As we warned against earlier, this app simply tacks on any user input at the end of the SQL query, which is inherently unsafe.
const query = `INSERT INTO cats(petname) VALUES ('${name}');`
The consequences might be small here, but it’s not hard to imagine how this oftentimes honest mistake can have disastrous consequences for your production app.
Blocking JavaScript SQL injection with Aikido Firewall
Now let’s look at how quickly our open-source security engine blocks JavaScript SQL injection attacks without manually fixing every database interaction in your code.
If you don’t yet have an Aikido account, go ahead and make one for free. If you already have one, log in and connect your GitHub account. During that process, grant Aikido access to read your fork of the firewall-node
project.
Go to the Firewall dashboard and click Add Service. Give your service a name and once again choose your fork for the firewall-node
project.

Aikido then instructs you on how to install and implement Aikido Firewall. Since we’re using the example app, that work is already done for you, but it’s a helpful reference for how you’d go about bringing our open-source security engine to all your Node.js apps that might be vulnerable to JavaScript SQL injection attacks.

Click the Generate Token button to create a token to let Aikido Firewall securely pass information about blocked SQL injection attacks to the Aikido security platform. Copy the generated token, which starts with AIK_RUNTIME…
, and head back to your terminal to rerun the sample app, only now with Firewall fully enabled in blocking mode:
AIKIDO_TOKEN=<YOUR-AIKIDO-TOKEN> AIKIDO_DEBUG=true AIKIDO_BLOCKING=true node sample-apps/express-mysql2/app.js
Open localhost:4000
and once again invoke the included SQL injection attack. This time, Aikido will block you at the browser, output to your local web server’s logs, and generate a new event. Click that to see comprehensive details about the SQL injection attempt, including the payload and where your app generated the dangerous SQL query.

Instead of worrying about forever protecting your apps against JavaScript SQL injection attacks, both critical and not-yet-seen, Aikido Firewall offers comprehensive blocking and sophisticated observability that keeps you informed about attack sources, common payloads, and potential weak points.
What’s next?
You can install and implement Aikido Firewall in all your Node.js-based applications for free. Our open-source embedded security engine protects your infrastructure and user data against JavaScript SQL injection attacks, command injection, prototype pollution, path traversal, and more to come shortly.
We’re not saying Firewall should replace development best practices for protecting against SQL injection, like using parameterized queries or never trusting user input, but we also know from personal experience that no developer is perfect. No codebase is faultless, and honest mistakes happen all the time.
Think of Firewall as a global hotfix for SQL injection. Unlike custom-developed regex, latency-inducing WAFs, or complex security agents that cost a pretty penny, It does this one job extraordinarily well and with negligible impact—entirely for free.
If you like what you’ve seen, check out our roadmap and give our GitHub repository (https://github.com/AikidoSec/firewall-node) a star. ⭐