Exploitable N+1 Queries
Unbounded relation expansion in ORM queries allows attackers to trigger thousands of database queries with a single API request, causing denial of service.
How It Works
N+1 queries occur when an application loads a list of records and then makes a separate query for each record's related data. While this is primarily a performance issue, it becomes a security vulnerability when attackers can control the scope of relation expansion. By requesting deeply nested relations or large datasets through API parameters, an attacker can force the server to execute thousands of queries simultaneously. This overwhelms the database connection pool and can crash the application. GraphQL APIs are especially susceptible because clients control the query depth.
// API endpoint with unbounded includes
app.get('/api/users', async (req, res) => {
const users = await prisma.user.findMany({
include: { posts: { include: { comments: {
include: { author: { include: { posts: true } } }
} } } }
});
res.json(users);
});// Bounded query with pagination and limited depth
app.get('/api/users', async (req, res) => {
const users = await prisma.user.findMany({
take: 20,
select: { id: true, name: true, email: true,
posts: { take: 5, select: { id: true, title: true } }
}
});
res.json(users);
});Real-World Example
In 2023, multiple GraphQL APIs were targeted with query depth attacks. Attackers crafted deeply nested queries that expanded into millions of database operations, taking down production services. GitHub had previously addressed this by implementing query complexity limits on their GraphQL API.
How to Prevent It
- Limit query depth and complexity with tools like graphql-depth-limit
- Always paginate results with take/limit and cursor-based pagination
- Use select instead of include to fetch only needed fields
- Monitor and set alerts for unusual query volumes per request
Affected Technologies
Data Hogo detects this vulnerability automatically.
Scan Your Repo FreeRelated Vulnerabilities
Connection String Exposed
criticalDatabase connection URLs containing usernames and passwords are hardcoded in source code, making credentials accessible to anyone with repo access.
Database Backup Exposed
highDatabase dump files (.sql, .dump, .bak) committed to the repository expose the entire database schema and data, including user credentials and sensitive records.
Raw Queries in ORMs
highUsing raw SQL methods like Prisma's $queryRaw or Sequelize's query() with string interpolation bypasses the ORM's built-in SQL injection protection.
Unsafe Deserialization
highDeserializing untrusted data with libraries like node-serialize or Python's yaml.load allows attackers to execute arbitrary code on the server.