Welcome to our blog.

A no-BS Docker security checklist for the vulnerability-minded developer
Why are you here?
You want to know the real answer to two questions about Docker security:
Is Docker secure for production use?
Yes and no. Docker uses a security model that relies on namespaces and resource isolation, making the processes within more secure from specific attacks than running your applications directly from a cloud VM or bare metal system.Despite that layer, there are still plenty of ways for attackers to access your container, allowing them to read confidential information, run denial-of-service (DoS) attacks, or even gain root access to the host system.
How can I improve my Docker security (in a not terribly painful way)?
We’ll walk you through the most common and severe Docker vulnerabilities, skipping over the basic recommendations you’ll find all over Google, like using official images and keeping your host up to date.Instead, we’ll lead you directly to new docker options and Dockerfile lines that will make your new default Docker container deployment far more secure than ever.

The no-BS Docker security checklist
Make in-container filesystems read-only
What do you gain?
You prevent an attacker from editing the runtime environment of your Docker container, which could allow them to collect useful information about your infrastructure, gather user data, or conduct a DOS or ransomware attack directly.
How do you set it?
You have two options, either at runtime or within your Docker Compose configuration.
At runtime: docker run --read-only your-app:v1.0.1
In your Docker Compose file:
services:
webapp:
image: your-app:v1.0.1read_only: true
...
Lock privilege escalation
What do you gain?
You keep your Docker container—or an attacker who is mucking about inside said container—from enabling new privileges, even root-level, with setuid or setgid. With more permissive access to your container, an attacker could access credentials in the form of passwords or keys to connected parts of your deployment, like a database.
How do you set it?
Once again, at runtime or within your Docker Compose configuration.
At runtime: docker run --security-opt=no-new-privileges your-app:v1.0.1
In your Docker Compose file:
services:
webapp:
image: your-app:v1.0.1
security_opt:
- no-new-privileges:true
...
Isolate your container-to-container networks
What do you gain?
By default, Docker lets all containers communicate via the docker0 network, which might allow an attacker to move laterally from one compromised container to another. If you have discrete services A
and B
in containers Y
and Z
, and they don’t need to communicate directly, isolating their networks provides the same end-user experience while preventing lateral movement for better Docker security.
How do you set it?
You can specify Docker networks at runtime or within your Docker Compose configuration. However, you first need to create the network:
docker network create your-isolated-network
At runtime, add the --network optio
n: docker run --network your-isolated-network your-app:v1.0.1
Or the equivalent option in your Docker Compose file:
services:
webapp:
image: your-app:v1.0.1
networks:
- your-isolated-network
...
Set a proper non-root user
What do you gain?
The default user within a container is root
, with a uid of 0
. By specifying a distinct user, you prevent an attacker from escalating their privileges to another user that can take action without restrictions, like root, which would override any other Docker security measures you’ve worked hard to implement.
How do you set it?
Create your user during the build process or a runtime. At runtime, you can either create the user for the first time, or override the USER
you already set at build.
During the build process, in your Dockerfile
:
...
RUN groupadd -r your-user
RUN useradd -r -g your-user your-user
USER myuser
...
At runtime: docker run -u your-user your-app:v1.0.1
Drop Linux kernel capabilities
What do you gain?
By default, Docker containers are allowed to use a restricted set of Linux kernel capabilities. You might think the folks at Docker created that restricted set to be completely secure, but many capabilities exist for compatibility and simplicity. For example, default containers can arbitrarily change ownership on files, change their root directory, manipulate process UIDs, and read sockets. By dropping some or all of these capabilities, you minimize the number of attack vectors.
How do you set it?
You can drop capabilities and set new ones at runtime. For example, you could drop all kernel capabilities and allow your container only the capability to change ownership of existing files.
docker run --cap-drop ALL --cap-add CHOWN your-app:v1.0.1
Or for Docker Compose:
services:
webapp:
image: your-app:v1.0.1
cap_drop:
- ALL
cap_add:
- CHOWN
...
Prevent fork bombs
What do you gain?
Fork bombs are a type of DoS attack that infinitely replicates an existing process. First, they reduce performance and restrict resources, which inevitably raises costs and can ultimately crash your containers or the host system. Once a fork bomb has started, there’s no way to stop it other than restarting the container or the host.
How do you set it?
At runtime, you can limit the number of processes (PIDs) your container can create.
docker run --pids-limit 99 your-app:v1.0.1
Or with Docker Compose:
services:
webapp:
image: your-app:v1.0.1
deploy
limits:
pids: 99
Improve Docker security by monitoring your open source dependencies
What do you gain?
The applications you’ve containerized for deployment with Docker likely have a wide tree of dependencies.
How do you set it?
The most “non-BS” way is with Aikido’s open-source dependency scanning. Our continuous monitoring scans projects written in more than a dozen languages based on the presence of lockfiles within your application and delivers an instant overview of vulnerabilities and malware. With automatic triaging that filters out false positives, Aikido gives you remediation advice you can start working with right away… not only after you read a dozen other reference documents and GitHub issues.
At Aikido, we love established open-source projects like Trivy, Syft, and Grype. We also know from experience that using them in isolation isn’t a particularly good developer experience. Under the hood, Aikido enhances these projects with custom rules to bridge gaps and reveal security flaws you wouldn’t be able to find otherwise. Unlike chaining various open-source tools together, Aikido frees you from having to build a scanning script or create a custom job in your CI/CD.

Use only trusted images for Docker security
What do you gain?
Docker Content Trust (DCT) is a system for signing and validating the content and integrity of the official images you pull from Docker registries like Docker Hub. Pulling only images signed by the author gives you more reassurance they haven’t been tampered with to create vulnerabilities in your deployment.
How do you set it?
The easiest way is to set the environment variable on your shell, which prevents you or anyone else from working with untrusted images.
export DOCKER_CONTENT_TRUST=1
docker run ...
Or, you can set the environment variable each time you execute Docker:
DOCKER_CONTENT_TRUST=1 docker run …
Update end-of-life (EOL) runtimes
What do you gain?
One common recommendation for Docker container security is to pin images and dependencies to a specific version instead of latest
. In theory, that prevents you from unknowingly using new images, even ones that have been tampered with, that introduce new vulnerabilities.
How do you set it?
You have some open-source projects available to help you discover EOLs and best prepare. The endoflife.date project (GitHub repository) tracks more than 300 products by aggregating data from multiple sources and making it available via a public API. You have a few options with endoflife.date and similar projects:
- Manually check the project for updates on dependencies your applications rely on and create tickets or issues for required updates.
- Write a script (Bash, Python, etc.) to get the EOL dates of dependencies from the API and run it regularly, like a cron job.
- Incorporate the public API, or that custom script, into your CI platform to fail builds that use a project that’s nearing or reached EOL.
As a developer, we understand that your time is valuable and often limited. This is where Aikido can provide a sense of security—our EOL scanning feature tracks your code and containers, prioritizing runtimes with the most impact and exposure, like Node.js or an Nginx web server. As usual, we not only automate collecting information, but deliver alerts with appropriate severity to inform, not overwhelm you.

Limit container resource usage
What do you gain?
By default, containers have no resource constraints and will use as much memory or CPU as the host’s scheduler. Limiting the resource usage of a specific container can minimize the impact of a DoS attack. Instead of crashing your container or host system due to an Out of Memory Exception, the ongoing DoS attack will “only” negatively impact the end-user experience.
How do you set it?
At runtime, you can use the --memory
and --cpus
option to set limits for memory and CPU usage, respectively. The memory option takes numbers with g for gigabytes and m for megabytes, while the CPU option reflects the limit of dedicated CPUs available for the container and its processes.
docker run --memory="1g" --cpus="2" your-app:v1.0.1
This also works with Docker Compose:
services:
webapp:
image: your-app:v1.0.1
deploy:
limits:
cpus: '2'
memory: 1G
...
Your final command and Compose options for Docker security
By now you’ve seen quite a few Docker security tips and the relevant CLI options or configuration to go along with them, which means you’re either quite excited to implement them or overwhelmed with how to piece them all together. Below, we’ve rolled up all the recommendations into a single command or configuration template, which will help you start deploying more secure Docker containers right away.
Obviously, you’ll want to change some of the options—like the non-root user name, kernel capabilities, resource limits—based on your application’s needs.
export DOCKER_CONTENT_TRUST=1
docker run \
--read-only \
--security-opt=no-new-privileges \
--network your-isolated-network \
--cap-drop ALL
--cap-add CHOWN \
--pids-limit 99 \
--memory="1g" --cpus="2" \
--user=your-user \
... # OTHER OPTIONS GO HERE
your-app:v1.0.1
You might even want to create a drun alias with your host’s shell you can invoke without having to remember all those details.
function drun {
docker run \
--read-only \
--security-opt=no-new-privileges \
--network your-isolated-network \
--cap-drop ALL
--cap-add CHOWN \
--pids-limit 99 \
--memory="1g" --cpus="2" \
--user=your-user \
$1 \
$2
}
Then run your alias like so, with your options and image name: drun -it your-app:v1.0.1
If you’re a Docker Compose kind of person, you can adapt all the same options into a new baseline Docker Compose template you can work from in the future:
services:
webapp:
image: your-app:v1.0.1
read_only: true
security_opt:
- no-new-privileges:true
networks:
- your-isolated-network
cap_drop:
- ALL
cap_add:
- CHOWN
deploy:
limits:
pids: 9
cpus: '2'
memory: 1G
... # OTHER OPTIONS GO HERE
Bonus: Run Docker with rootless containers
When you install Docker on any system, its daemon operates with root-level privileges. Even if you enable all the options above, and prevent privilege escalation within a Docker container, the rest of the container runtime on your host system still has root privileges. That inevitably widens your attack surface.
The solution is rootless containers, which an unprivileged user can create and manage. No root privileges involved means far fewer security issues for your host system.
We wish we could help you use rootless containers with a single option or command, but it’s just not that simple. You can find detailed instructions at the Rootless Containers website, including a how-to guide for Docker.
What’s next for your Docker security?
If you’ve learned anything from this experience, it’s that container security is a long-tail operation. There are always more hardening checklists and deep-dive articles to read about locking down your containers in Docker or its older and often misunderstood cousin, Kubernetes. You can’t possibly aim for faultless container security—creating time in your busy development schedule to address security, and then making incremental improvements based on impact and severity, will go a long way over time.
To help you maximize on that continuous process and prioritize fixes that will meaningfully improve your application security, there’s Aikido. We just raised a $17 million Series A for our “no BS” developer security platform, and we’d love to have you join us.

Sensing and blocking JavaScript SQL injection attacks
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. ⭐

Prisma and PostgreSQL vulnerable to NoSQL injection? A surprising security risk explained
Introduction
Imagine you’re building a blogging web app using Prisma. You write a simple query to authenticate users based on their provided email and password:
1const user = await prisma.user.findFirst({
2 where: { email, password },
3});
Looks harmless, right? But what if an attacker sends password = { "not": "" }
? Instead of returning the User object only when email and password match, the query always returns the User when only the provided email matches.
This vulnerability is known as operator injection, but it’s more commonly referred to as NoSQL injection. What many developers don’t realize is that despite strict model schemas some ORMs are vulnerable to operator injection even when they’re used with a relational database such as PostgreSQL, making it a more widespread risk than expected.
In this post, we’ll explore how operator injection works, demonstrate exploits in Prisma ORM, and discuss how to prevent them.
Understanding Operator Injection
To understand operator injection in ORMs, it’s interesting to first look at NoSQL injection. MongoDB introduced developers to an API for querying data using operators such as $eq
, $lt
and $ne
. When user input is passed blindly to MongoDB's query functions, there exists a risk of NoSQL injection.
Popular ORM libraries for JavaScript started offering a similar API for querying data and now almost all major ORMs support some variation of query operators, even when they don’t support MongoDB. Prisma, Sequelize and TypeORM have all implemented support for query operators for relational databases such as PostgreSQL.
Exploiting Operator Injection in Prisma
Prisma query functions that operate on more than one record typically support query operators and are vulnerable to injection. Example functions include findFirst
, findMany
, updateMany
and deleteMany
. While Prisma does validate the model fields referenced in the query at runtime, operators are a valid input for these functions and therefor aren’t rejected by validation.
One reason why operator injection is easy to exploit in Prisma, is the string-based operators that are offered by the Prisma API. Some ORM libraries have removed support for string-based query operators because they are so easily overlooked by developers and easy to exploit. Instead, they force developers to reference custom objects for operators. As these objects cannot be readily de-serialized from user input, the risk of operation injection is greatly reduced in these libraries.
Not all query functions in Prisma are vulnerable to operator injection. Functions that select or mutate a single database record typically do not support operators and throw a runtime error when an Object is provided. Apart from findUnique, the Prisma update, delete and upsert functions also do not accept operators in their where filter.
1 // This query throws a runtime error:
2 // Argument `email`: Invalid value provided. Expected String, provided Object.
3 const user = await prisma.user.findUnique({
4 where: { email: { not: "" } },
5 });
Best Practices to Prevent Operator Injection
1. Cast User Input to Primitive Data Types
Typically casting input to primitive data types such as strings or numbers suffices to prevent attackers from injecting objects. In the original example, casting would look as follows:
1 const user = await prisma.user.findFirst({
2 where: { email: email.toString(), password: password.toString() },
3 });
2. Validate User Input
While casting is effective, you might want to validate the user input, to ensure that the input meets your business logic requirements.
There are many libraries for server-side validation of user input, such as class-validator, zod and joi. If you’re developing for a web application framework such as NestJS or NextJS, they likely recommend specific methods for user input validation in the controller.
In the original example, zod validation might look as follows:
1import { z } from "zod";
2
3const authInputSchema = z.object({
4 email: z.string().email(),
5 password: z.string().min(8)
6});
7
8const { email, password } = authInputSchema.parse({email: req.params.email, password: req.params.password});
9
10const user = await prisma.user.findFirst({
11 where: { email, password },
12});
3. Keep your ORM updated
Stay updated to benefit from security improvements and fixes. For example, Sequelize disabled string aliases for query operators starting from version 4.12, which significantly reduces susceptibility to operator injection.
Conclusion
Operator injection is a real threat for applications using modern ORMs. The vulnerability stems from the ORM API design and isn’t related to the database type in use. Indeed, even Prisma combined with PostgreSQL may be vulnerable to operator injection. While Prisma offers some built-in protection against operator injection, developers must still practice input validation and sanitization to ensure application security.
Appendix: Prisma schema for User model
1// This is your Prisma schema file,
2// learn more about it in the docs: https://pris.ly/d/prisma-schema
3
4generator client {
5 provider = "prisma-client-js"
6}
7
8datasource db {
9 provider = "postgresql"
10 url = env("DATABASE_URL")
11}
12
13// ...
14
15model User {
16 id Int @id @default(autoincrement())
17 email String @unique
18 password String
19 name String?
20 posts Post[]
21 profile Profile?
22}

Your Client Requires NIS2 Vulnerability Patching. Now What?

TL;DR: The new EU cybersecurity directive, NIS2, is already reshaping how software suppliers do business through stricter vulnerability management requirements in procurement contracts. This shift is gaining momentum, and more companies will need to adapt. Aikido helps automate compliance reporting and vulnerability tracking to meet these new demands. Start your free compliance journey here, or read on to understand what this means for your business.
The Risks of NIS2 Patching Non-Compliance
Picture this: It's 8:33 AM on a Monday. You're triaging your inbox, coffee in hand, mentally preparing for the weekly meeting at 9. Then you see it – the email subject line that makes your stomach drop.
You open the email, you scroll through the usual boilerplate until you find yourself reading – and re-reading – these words:

All software components used for delivering the services must be patched within the following timeframes, depending on the severity of the vulnerability:
- Critical: within 48 hours of the availability of the patch
- High: within one week of the availability of the patch
- Medium: within one month of the availability of the patch
- Low: within three months of the availability of the patch
48 hours for critical vulnerabilities. Not business days. Not "best effort." 48. Hours. Just like that, your Monday turned into a compliance Olympics, and you're competing in every event simultaneously.
These new NIS2 patching requirements aren't just another checkbox – they present a significant operational challenge. Think about it:
- Your team is already stretched thin
- Every new CVE feels like playing security whack-a-mole
- Your deployment windows are tight and getting tighter
- And now you need to document and prove compliance with these aggressive timelines?
Missing these SLAs isn't just about failing an audit: it could mean losing major contracts, facing penalties, or even being cut out of EU markets entirely.
But here's the thing: while other vendors are scrambling to build massive compliance programs and hiring dedicated NIS2 teams, you don't have to.
How to be NIS2 Compliant
We built Aikido specifically for this moment. Our NIS2 compliance is like playing a game on easy mode for these procurement headaches. In literally minutes, you can:
- Generate compliance reports that procurement teams actually accept
- Track your vulnerability SLAs automatically
- Get alerts before you breach any timelines
- Prove your compliance with actual data, not promises
Let's break down exactly what these requirements mean and how you can tackle them without upending your entire 2025 plan.
Sign up for Aikido and get your free NIS2 report in minutes.
What are the Requirements of NIS2?
NIS2 is the EU's latest cybersecurity directive, and it's reshaping how companies handle vulnerability management. EU Member States are transposing NIS2 into national law, often referencing standards like ISO 27001 as a basis for implementation.
Unlike its predecessor, NIS2 covers more industries and imposes stricter requirements – especially around supply chain security. Major enterprises, particularly those in critical sectors, aren't just implementing these requirements internally; they're required to push them down to every vendor in their supply chain.
Read: NIS2: Who is affected?
What does this mean in practice? If you're selling software or services to EU companies, you'll increasingly face procurement requirements that look exactly like the example above. They'll demand specific patch timelines, expect detailed documentation of your vulnerability management process, and require regular compliance reporting. These aren't just checkbox requirements – procurement teams are actively verifying compliance and building these SLAs into contracts.
The most common requirements we're seeing include:
- Defined SLAs for patching vulnerabilities based on severity (the example in the introduction comes from a real procurement doc!)
- Regular vulnerability scanning and reporting
- Documented processes for vulnerability management
- Evidence of compliance through automated tracking
- Regular status updates on remediation efforts
NIS2 Vulnerability Patching Requirements
Let's cut through the legal jargon and focus on what NIS2 actually implies for vulnerability patching. NIS2 itself doesn't prescribe specific patching timeframes. However, it mandates risk management measures, including vulnerability handling and disclosure, which leads to the described SLAs being imposed by software buyers. Here's what procurement teams are looking for:
Response Timeframes
Most enterprises are standardizing on these patch windows:
- Critical vulnerabilities: 48 hours
- High severity: 7 days
- Medium severity: 30 days
- Low severity: 90 days
And yes, these timelines start from when the patch becomes available, not from when you discover it. This means you need to stay on top of vulnerability announcements for every component in your stack.
Documentation Requirements
You'll need to prove three things:
- When you discovered each vulnerability
- When the patch became available
- When you deployed the fix
Without automated tracking, this quickly becomes a full-time job for your security team.
Continuous Monitoring
Gone are the days of quarterly security scans. NIS2 expects:
- Regular vulnerability scanning (most companies interpret this as daily)
- CVEs monitoring for new security advisories
- Active tracking of patch status and SLA compliance
Risk Management
For every vulnerability, you need to:
- Document your severity assessment
- Track remediation progress
- Justify any delays in patching
- Report on compliance with agreed SLAs
This is why we built the NIS2 report in Aikido – it handles all of this automatically. Instead of building spreadsheets and juggling tickets, you get a single dashboard that tracks everything procurement teams want to see.
Implementing with Aikido (Practical Steps)
Here's the thing about compliance frameworks: they're usually a mess of paperwork disconnected from your actual security operations. But it doesn't have to be that way.
Let's say a procurement team asks about your vulnerability management process. Instead of scrambling to create documentation, you simply:
- Connect Aikido to your development pipeline
- Link your cloud infrastructure
- Enable the NIS2 compliance report
- Export the automated evidence of your patching timelines
- Send it off
That's it. No endless documentation sessions. No spreadsheets. No last-minute panics.

What You Get Immediately
- Continuous scanning across nine risk vectors (from dependencies to runtime security)
- Automated evidence collection for your technical controls
- Real-time compliance status for procurement requirements
- Dynamic reporting that maps directly to NIS2 requirements
The best part? It's working exactly where your developers already are: in CI pipelines, code repositories, and cloud environments. While other teams are manually collecting evidence for their ISO 27001 certifications and NIS2 compliance efforts, you're automatically generating compliance reports from your actual security data.
Next Steps
Let’s wrap up in one sentence: you don't need to build a massive compliance program or hire an army of consultants to answer NIS2 compliance inquiries. We recommend the following strategic approach
- Get a clear picture of where you stand (by signing up for a free Aikido account)
- Run your first NIS2 compliance report
- See exactly what needs attention
- Automate the reporting & easily prove to your customer you're ready for NIS2
While your competitors continue to manage their patch documentation through manual processes, you could have automated compliance reporting up and running in minutes. When future procurement inquiries regarding NIS2 requirements arrive, you can proceed with confidence, knowing your compliance infrastructure is firmly in place.
So the next time you see a procurement email with 'NIS2 requirements' in the subject line? Go ahead and take another sip of that coffee. You've got this one in the bag – or should we say, in the mug.

Top 10 AI-powered SAST tools in 2025

In this article, we break down the 10 leaders in AI SAST tools. We explore the core features of each tool and the unique ways they implement AI to enhance security discovery, prioritization and remediation.
What is SAST?
Static Application Security Testing (SAST) is a methodology for analyzing an application's source code, bytecode, or binary to identify vulnerabilities and security flaws early in the software development lifecycle (SDLC). SAST finds vulnerabilities within the source code, which means that it is often the first defense against insecure code.
For more information SAST vs DAST what you need to know
What vulnerabilities does SAST find in your code?
There are many different vulnerabilities SAST can find and it depends on the coding practices used, technology stack and frameworks. Below are some of the most common vulnerabilities a SAST tool will typically uncover.
SQL Injection
Detects improper sanitization of user inputs that could lead to database compromise.
Example Injection Code
# Function to authenticate user
def authenticate_user(username, password):
query = f"SELECT * FROM users WHERE username = '{user}' AND password = '{password}'"
print(f"Executing query: {query}") # For debugging purposes
cursor.execute(query)
return cursor.fetchone()
Cross-Site Scripting (XSS)
Identifies instances where user inputs are incorrectly validated or encoded, allowing injection of malicious scripts.
Example of code vulnerable to XSS
<script>
const params = new URLSearchParams(window.location.search);
const name = params.get('name');
if (name) {
// Directly inserting user input into HTML without sanitization
document.getElementById('greeting').innerHTML = `Hello, ${name}!`;
}
</script>
Buffer Overflows
Highlights areas where improper handling of memory allocation could lead to data corruption or system crashes.
Example code vulnerable to buffer overflow
1#include
2void vulnerableFunction() {
3 char buffer[10]; // A small buffer with space for 10 characters
4
5 printf("Enter some text: ");
6 gets(buffer); // Dangerous function: does not check input size
7
8 printf("You entered: %s\n", buffer);
9}
10
11int main() {
12 vulnerableFunction();
13 return 0;
14}
Insecure Cryptographic Practices
Finds weak encryption algorithms, improper key management, or hardcoded keys.
import hashlib
def store_password(password):
# Weak hashing algorithm (MD5 is broken and unsuitable for passwords)
hashed_password = hashlib.md5(password.encode()).hexdigest()
print(f"Storing hashed password: {hashed_password}")
return hashed_password
SAST tools provide valuable insights, enabling developers to fix issues before they become critical.
How AI is Enhancing SAST Tools
Right now you can’t get away from AI buzz (and BullSh*t). It can be difficult to know exactly how AI is being implemented in security tools. We wanted to compare some of the leaders in AI-powered SAST and explain the different ways these tools are implementing AI to enhance security.
Right now there are three trends with AI as it relates to SAST tools.
- AI to improve vulnerability detection: AI models trained on large datasets of known vulnerabilities improve the accuracy of identifying security issues while reducing false positives.
- AI to create automated prioritization: AI helps rank vulnerabilities based on severity, exploitability, and potential business impact, allowing developers to focus on critical issues first.
- AI to provide automated remediation: AI provides context-aware code fixes or suggestions, speeding up the remediation process and helping developers learn secure coding practices.
Top 10 AI-Powered SAST Tools
Here are 10 industry leaders that are using AI in different ways to enhance the capabilities of traditional SAST (In alphabetical order)
1. Aikido Security SAST | AI AutoFix

Core AI Capability | Auto Remediation (Dashboard + IDE)
Aikido Security uses AI to create code fixes for vulnerabilities discovered by its SAST scanner and can even generate automated pull requests to speed up the remediation process.
Unlike other tools, Aikido does not send your code to a third-party AI model and has a unique method of ensuring your code does not leak through AI models. Aikido creates a sandbox environment of your code, then a purpose-tuned LLM will scan it, and create suggestions which are also scanned again for vulnerabilities. Once the suggested remediation as passed validation, a pull request can be automatically created before finally the Sandbox environment is destroyed. Aikidos AutoFix is also able to give a confidence score on the suggestions it makes to developers to make informed decisions when using AI-generated code.
2. Checkmarx

Core AI Capability | Auto Remediation (IDE only)
Checkmarx SAST tools can provide AI-generated coding suggestions to developers within their IDE. The tool connects to ChatGPT transmits the developer's code to the OpenAI model and retrieves the suggestions. This method makes the process of querying ChatGPT easier but does not add any proprietary processes giving it limited capabilities right now.
WARNING - This use-case sends your proprietary code to OpenAI and may not meet compliance standards.
3. CodeAnt AI

Core AI Capability | Improved Detection (Dashboard)
CodeAnt is a code security and quality tool that entirely uses AI for its discovery of code vulnerabilities and suggested fixes. CodeAnt does not provide documentation on how their AI models work but generally uses AI as their core detection engine, this can slow down detection, particularly in large enterprises.
4. CodeThreat

Core AI Capability | Automated Prioritization (Dashboard)
CodeThreat offers on-premise static code analysis and provides AI-assisted remediation strategies. A core difference is that CodeThreat allows you to integrate your own on-premise AI model into their tool. This has the advantage of not sending data to a third party but means it can only offer genetically trained AI models right now and you need to be running an on-premise AI LLM like ChatGPT.
5. Fortify Static Code Analyzer

Core AI Capability | Improved Prioritization (Dashboard)
Fortify Static Code Analyzer scans source code for vulnerabilities and gives users the option to adjust thresholds when an alert is made for example likeliness of exploitability. Fortifies AI Autoassistant reviews the previous thresholds assigned to vulnerabilities and makes intelligent predictions on what the thresholds for other vulnerabilities should be.
Note: Fortify Static Code Analyzer does not use AI to discover vulnerabilities or suggest fixes for them, instead it uses it to predict administrative settings used in the admin panels.
6. GitHub Advanced Security | CodeQL

Core AI Capability | Auto Remediation (IDE + Dashboard)
GitHub CodeQL is a static code scanner that uses AI to create intelligent auto-remediation in the form of code suggestions. Developers can accept or dismiss the changes via pull requests in GitHub CodeSpaces or from their machine. It's part of GitHub Advanced Security.
7. Qwiet AI | SAST Code

Core AI Capability | Auto Remediation (Dashboard)
Qwiet AI SAST is a rule-based static application security testing tool that leverages AI to auto-suggest remediation advice and code fixes for code vulnerabilities. Its core offering is its three-stage AI agents which Analyze the issue, Suggest a fix, and then validate the fix.
8. Snyk Code | DeepCode

Core AI Capability | Auto Remediation (IDE)
Snyk Code, a developer-focused, real-time SAST tool that can provide code suggestions to developers from within the IDE thanks toDeepCode AI which Snyk acquired. DeepCode AI utilizes multiple AI models and the core selling point is that their models are trained on data curated by top security specialists giving improved confidence in the AI results.
9. Semgrep Code

Core AI Capability | Improved Detection
SemGreps AI assistant, aptly named assistant, uses the context of the code surrounding a potential vulnerability to provide more accurate results and provide recommended code fixes. It can also be used to create rules for SemGrep to enhance its detection based on the prompts you provide.
10. Veracode Fix

Core AI Capability | Auto Remediation
Veracode fix uses AI to suggest changes based on vulnerabilities within code when developers are using the Veracode IDE extension or CLI tool. The main differentiator for Veracode Fix is that their custom-trained model is not trained on code in the wild but on known vulnerabilities within their database. The positive of this will be more confidence in suggested fixes, the negative is that it is more limited in the scenarios that it can suggest code fixes.
How to choose a SAST tool
AI) is a relatively new entrant to the security market, and industry leaders are continuously exploring innovative applications. AI should be viewed as a tool to enhance security systems, rather than as a sole source of truth. It's important to note that AI cannot transform subpar tools into effective ones. To maximize its potential, AI should be integrated with tools that already have a robust foundation and a proven track record.

Snyk vs Aikido Security | G2 Reviews Snyk Alternative
So you’re in the market for application security, perhaps even a Snyk alternative. Whether it’s your first time exploring a code security platform or you’re a seasoned user searching for better options, you’re in the right place.
When developers and businesses evaluate their choices, two names often rise to the top: Aikido Security and Snyk. Both platforms offer comprehensive tools for engineering teams to secure their applications, but how do they really compare? Rather than relying on opinions, let’s turn to the voices that matter most: real users.
Based on verified 3rd-party reviews
This guide is a direct synopsis of verified third-party reviews from G2, the world’s largest trusted software marketplace. Over 100 million professionals rely on G2 annually to make informed software decisions using authentic user feedback. Based on the latest verified user data from G2, we’ll provide a detailed breakdown of Aikido Security vs. Snyk, analyzing features, user experience, pricing, and more.
In addition, you can also read these user reviews directly on G2. Here is the G2 link for Aikido Security and for Snyk, and the direct comparison reviews that compare Aikido as a Snyk alternative.
What is Aikido Security:
Led by serial CTO Willem Delbare, Aikido is the “no bullshit” security platform for developers. After many years using other application security products, Delbare founded Aikido to fix security for CTOs and developers with an all-in-one platform code-to-cloud security platform designed to help engineering teams get security done.
Engineering teams execute faster with Aikido thanks to developer-dedicated features: centralized scans, aggressive false positive reduction, dev-native UX, automatic risk triage, risk bundling, and easy step-by-step risk fixes, including LLM-powered autofixes for 3 different issue types.
TL;DR Aikido makes security simple for SMEs and doable for developers, so companies can win customers, grow up-market, and ace compliance.
What is Snyk:
Snyk is a well-known security company that positions itself as a “developer-oriented” security tool, for teams to identify and fix vulnerabilities in their code, open-source dependencies, and container images. Snyk is an early player in the “shift left” security movement and was founded 10 years ago in Tel Aviv and London and is currently headquartered in Boston, USA.
Aikido vs Snyk Alternative at a Glance
- Aikido Security:
- Rating ⭐️: 4.7
- Market Segments: Small to Mid-Market Businesses
- Entry-Level Pricing: Free
- Snyk:
- Rating ⭐️: 4.5
- Market Segments: Mid-Market to Enterprise
- Entry-Level Pricing: Free
Aikido Security is heavily favored by small to medium-sized businesses, while Snyk has broader adoption among larger mid-market organizations, especially enterprises. Both platforms offer free plans, making them accessible for individual developers and smaller teams.
Category Ranking Overview

User Experience
Ease of Use
- Aikido Security: Rated 9.5, users praise its intuitive interface and streamlined workflows. It’s designed with a developer-first approach, ensuring minimal friction when integrating into existing CI/CD pipelines.
- Snyk: Rated 8.7, while still user-friendly, some reviewers note a steeper learning curve, especially for teams unfamiliar with DevSecOps tools.
Ease of Setup
- Aikido Security: With a score of 9.5, users love Aikido’s quick onboarding process and minimal configuration requirements.
- Snyk: Rated 9.0, setup is straightforward, but users occasionally encounter challenges integrating with less common tools.
Ease of Administration
- Aikido Security: Scoring 9.3, system administrators find it simple to manage teams, permissions, and integrations.
- Snyk: Rated 8.8, administration is effective but can become complex in larger organizations.
Support and Product Direction
Quality of Support
- Aikido Security: With an impressive score of 9.6, users frequently commend the responsive and knowledgeable support team. Most testimonials highlight fast support from Aikido team and founders as a top highlight.
- Snyk: Rated 8.6, support is OK, generally reliable but sometimes slower for free-tier users.
Product Direction
- Aikido Security: Users rank Aikido with a round 10.0 score, reflecting user confidence in its innovative roadmap and consistent feature updates.
- Snyk: Rated 8.7, appreciated for its focus on open source and developer-centric tools but slightly lagging in comprehensive feature rollouts.
Aikido vs Snyk Alternative Feature Comparison
If you are looking for a Snyk alternative, it is important to note the specific production functionalities that each platform offers. While Snyk offers SAST, IaC, Software Composition Analysis, and vulnerability scanning, Aikido offers more functions and features within its all-in-one platform.
While Snyk offers 4 products, Aikido offers 11 products in one security suite, including SAST, DAST, Software Composition Analysis, IaC, container image scanning, secret scanning, malware scanning, API scanning, license risk scanning, local custom scanning, as well as cloud (CSPM) security.

Static Application Security Testing (SAST)
What is it? SAST is a method to identify vulnerabilities in source code before deployment.
- Aikido Security: Rated 8.7, it excels in identifying vulnerabilities in source code and presenting actionable insights.
- Snyk: Rated 7.7, effective but often criticized for generating more false positives compared to competitors.
Dynamic Application Security Testing (DAST)
What is it? DAST is a technique that scans live applications to detect runtime vulnerabilities.
- Aikido Security: Scoring 8.9, users appreciate its ability to identify runtime vulnerabilities with minimal configuration.
- Snyk: Not enough data available to assess DAST capabilities.
Container Security
What is it? Container Security is the process of identifying vulnerabilities in containerized applications and images.
- Aikido Security: Rated 8.4, it provides deep insights into container images and vulnerabilities across registries.
- Snyk: Rated 7.9, strong for basic container scanning but less comprehensive in advanced scenarios.
Software Composition Analysis (SCA)
What is it? SCA is the practice of detecting vulnerabilities in open-source dependencies and third-party libraries.
- Aikido Security: Scoring 8.9, it combines open-source dependency scanning with enhanced malware detection, ensuring robust protection.
- Snyk: Rated 8.0, effective for detecting known vulnerabilities in open-source libraries but less advanced in identifying malicious packages.
Application Security Posture Management (ASPM)
What is it? ASPM is a framework for managing and improving the security posture of applications across their lifecycle.
- Aikido Security: Scored 8.4, praised for its proactive approach to identifying and resolving security risks in application environments.
- Snyk: Not enough data available to assess ASPM capabilities.
Cloud Security Posture Management (CSPM)
What is it? CSPM is a toolset for monitoring and securing cloud environments by identifying misconfigurations and compliance issues.
- Monitors and secures cloud environments by identifying misconfigurations and compliance issues.
- Aikido Security: Rated 7.4, integrates seamlessly into multi-cloud environments, providing clear misconfiguration insights. Aikido CSPM functionality was recently launched and a big facet of our roadmap.
- Snyk: Not enough data is available to evaluate CSPM features. At this time, Snyk does not have CSPM functionality.
Vulnerability Scanner
What is it? A Vulnerability Scanner identifies and evaluates security vulnerabilities in systems and software.
- Aikido Security: Rated 7.9, effective in pinpointing vulnerabilities with clear remediation guidance.
- Snyk: Scored 8.1, valued for its extensive library of known vulnerabilities but criticized for frequent noise in results.
Verified Snyk vs Aikido customer testimonials:
Reviews from verified people that have used both Aikido and Snyk. If you want to hear how Aikido stacks up as a Snyk Alternative, read on below.
Aikido is an “effective and fair-priced solution”
Compared to well known competitors like Snyk, Aikido is much more affordable, more complete and most importantly much better at presenting the vulnerabilities that are actually reaching your systems. They use many popular open source libraries to scan your code, as well as propriatary ones, giving you a good mix

Aikido is “a cheaper Snyk Alternative”
We were looking for a cheaper alternative to Snyk and Aikido fills that role fantastically. Good software, easy UI and most important of all very easy to talk to with feedback.
Everything was really simple to set-up and onboarding of team members a breeze.

Hopefully, this synopsis of G2 user feedback helps to inform your search for an application security platform. If you are interested in testing Aikido, why not launch now?
Get your first scan results in 32 seconds with no credit card and no strings attached, you can even use demo data for extra security. If you want a more personalized walk-through, you can talk to a human or say “hi” on intercom. We respond in seconds 🤝
if(window.strchfSettings === undefined) window.strchfSettings = {};
window.strchfSettings.stats = {url: "https://aikido-security.storychief.io/en/snyk-vs-aikido-security-g2-reviews-snyk-alternative?id=843344305&type=26",title: "Snyk vs Aikido Security | G2 Reviews Snyk Alternative",siteId: "5823",id: "f8908bf0-c824-4f3f-9bc9-22cac096e678"};
(function(d, s, id) {
var js, sjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {window.strchf.update(); return;}
js = d.createElement(s); js.id = id;
js.src = "https://d37oebn0w9ir6a.cloudfront.net/scripts/v0/strchf.js";
js.async = true;
sjs.parentNode.insertBefore(js, sjs);
}(document, 'script', 'storychief-jssdk'))