<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/how-orms-still-let-sql-injection-through-and-how-to-close-the-gaps--uwxttxmz8" -->

---
title: How ORMs Still Let SQL Injection Through (and How to...
description: ORMs like Sequelize, Prisma, TypeORM, and Knex automatically parameterize the queries they build, but SQL injection risk resurfaces wherever developers step...
canonical: https://daily.dev/posts/how-orms-still-let-sql-injection-through-and-how-to-close-the-gaps--uwxttxmz8
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: How ORMs Still Let SQL Injection Through (and How to Close the Gaps) | daily.dev
og:description: ORMs like Sequelize, Prisma, TypeORM, and Knex automatically parameterize the queries they build, but SQL injection risk resurfaces wherever developers step...
og:url: https://daily.dev/posts/how-orms-still-let-sql-injection-through-and-how-to-close-the-gaps--uwxttxmz8
og:image: https://api.daily.dev/og/posts/UWxttXmZ8.png
og:image:alt: How ORMs Still Let SQL Injection Through (and How to Close the Gaps)
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# How ORMs Still Let SQL Injection Through (and How to Close the Gaps)

**[freeCodeCamp](https://daily.dev/sources/freecodecamp)** · 10 min read · 64 upvotes · 2 comments

## Summary

ORMs like Sequelize, Prisma, TypeORM, and Knex automatically parameterize the queries they build, but SQL injection risk resurfaces wherever developers step outside that safe path. Four common patterns are covered: raw query escape hatches with string concatenation, identifiers (like dynamic ORDER BY columns) that can't be parameterized and need allowlisting, second-order injection where previously-stored user data gets reused in an unparameterized query, and raw SQL smuggled into ORM calls via functions like Sequelize's literal(). Each pattern includes a vulnerable code example, an explanation of the exploit, and a fixed version using bindings, allowlists, or the ORM's operator API.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://www.freecodecamp.org/news/how-orms-still-let-sql-injection-through-and-how-to-close-the-gaps>

## Questions this post answers

### Can SQL injection still happen even if I'm using an ORM like Sequelize or Prisma?

Yes, ORMs parameterize the queries they build automatically, but injection resurfaces wherever code steps outside that safe path: raw query escape hatches like sequelize.query() with string concatenation, dynamic identifiers (like ORDER BY columns) that can't be parameterized, stored data reused in a raw query later, and functions like sequelize.literal() smuggling raw SQL into otherwise ORM-managed calls.

_daily.dev surfaces practical security writeups for teams auditing ORM code for injection risks._

### How do I safely let users sort a list by a dynamic column in SQL without risking injection?

Use an allowlist of permitted column names rather than passing the user-supplied sort value directly into the ORDER BY clause. Identifiers like column and table names can't be bound as query parameters the way values can, so validating input against a fixed set of allowed columns (e.g. ['created_at', 'name', 'email']) is the only safe approach, not sanitization.

_Developers hardening sortable API endpoints track patterns like this through daily.dev._

### Is data from my own database safe to use in a raw SQL query without parameterizing it again?

No, data is not automatically safe just because it came from your own database. If a value like a username originated from user input at any point upstream, even if it was correctly parameterized when first stored, it remains attacker-controlled and must be parameterized again everywhere it's later used in a query, including admin tools and internal search features.

_daily.dev helps developers stay sharp on second-order injection risks when reusing stored data._

## Community discussion

Top comments from developers on daily.dev.

**@pdfopsdev** · 5 upvotes

> second-order injection is the one that actually bites people in review, since everyone assumes if the value came out of your own DB it's already safe. worth flagging that Sequelize's literal() also slips past most raw-sql greps, so your linter won't catch it even if you're scanning for string concat.

**@ristotoldsep** · 0 upvotes

> ORMs protect you right up until raw SQL says “hold my beer.”

## Similar posts on daily.dev

- [SQL Injection: Why It Persists and How to Prevent It](https://daily.dev/posts/sql-injection-why-it-persists-and-how-to-prevent-it-a5i6fyqpz) · Latest Hacking News · 0 upvotes · 0 comments
- [TypeScript Security From Backend to Browser](https://daily.dev/posts/typescript-security-from-backend-to-browser-o0qrurtty) · JS Dev Space · 0 upvotes · 0 comments
- [Insecure Output Handling: SQL Injection Through LLM Output \(Part 2\)](https://daily.dev/posts/insecure-output-handling-sql-injection-through-llm-output-part-2--yjsmqx40e) · InfoSec Write-ups · 0 upvotes · 0 comments
- [Inside an Oracle Database SQL Injection Attack](https://daily.dev/posts/inside-an-oracle-database-sql-injection-attack-jmtkujhqh) · Huntress Blog · 0 upvotes · 0 comments
- [You Don't Need an ORM](https://daily.dev/posts/you-don-t-need-an-orm-ogsa8bhdq) · ElixirStatus · 89 upvotes · 18 comments

---

Tags: [#nodejs](https://daily.dev/tags/nodejs), [#sql](https://daily.dev/tags/sql), [#appsec](https://daily.dev/tags/appsec)

[View this post on daily.dev](https://daily.dev/posts/how-orms-still-let-sql-injection-through-and-how-to-close-the-gaps--uwxttxmz8)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"How ORMs Still Let SQL Injection Through (and How to Close the Gaps)","url":"https://daily.dev/posts/how-orms-still-let-sql-injection-through-and-how-to-close-the-gaps--uwxttxmz8","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/how-orms-still-let-sql-injection-through-and-how-to-close-the-gaps--uwxttxmz8"},"datePublished":"2026-09-29T14:01:35.052Z","dateModified":"2026-09-29T14:02:01.177Z","description":"ORMs like Sequelize, Prisma, TypeORM, and Knex automatically parameterize the queries they build, but SQL injection risk resurfaces wherever developers step...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/c9f230e2352d94d886c2c389eebb5a33?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/c9f230e2352d94d886c2c389eebb5a33?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"freeCodeCamp","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"freeCodeCamp","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1628412854/logos/freecodecamp","url":"https://daily.dev/sources/freecodecamp"},"commentCount":2,"discussionUrl":"https://daily.dev/posts/how-orms-still-let-sql-injection-through-and-how-to-close-the-gaps--uwxttxmz8","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":64},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":2}],"keywords":"nodejs,sql,appsec","timeRequired":"PT10M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"freeCodeCamp","item":"https://daily.dev/sources/freecodecamp"},{"@type":"ListItem","position":3,"name":"How ORMs Still Let SQL Injection Through (and How to Close the Gaps)"}]}
{"@context":"https://schema.org","@type":"WebPage","@id":"https://daily.dev/posts/how-orms-still-let-sql-injection-through-and-how-to-close-the-gaps--uwxttxmz8","comment":[{"@type":"Comment","text":"second-order injection is the one that actually bites people in review, since everyone assumes if the value came out of your own DB it’s already safe. worth flagging that Sequelize’s literal() also slips past most raw-sql greps, so your linter won’t catch it even if you’re scanning for string concat.","datePublished":"2026-09-29T18:01:18.044Z","url":"https://daily.dev/posts/UWxttXmZ8#c-IkI08AkPZ","author":{"@type":"Person","name":"PDFops","url":"https://daily.dev/pdfopsdev","image":"https://media.daily.dev/image/upload/s---8isRBKc--/f_auto/v1782922291/avatars/avatar_orjMeK8QKaaVZwGq7ScPz?_a=BAMAMicg0"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":5}},{"@type":"Comment","text":"ORMs protect you right up until raw SQL says “hold my beer.”","datePublished":"2026-10-06T10:13:07.106Z","url":"https://daily.dev/posts/UWxttXmZ8#c-ABVx8pBs6","author":{"@type":"Person","name":"Risto Tõldsep","url":"https://daily.dev/ristotoldsep","image":"https://lh3.googleusercontent.com/a/ACg8ocLDWc6mZn0JwNmXXw6WY0L_HJ6pegzRttooC5VgtXESHSj3MNYx=s96-c"}}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/how-orms-still-let-sql-injection-through-and-how-to-close-the-gaps--uwxttxmz8#faq","mainEntity":[{"@type":"Question","name":"Can SQL injection still happen even if I'm using an ORM like Sequelize or Prisma?","acceptedAnswer":{"@type":"Answer","text":"Yes, ORMs parameterize the queries they build automatically, but injection resurfaces wherever code steps outside that safe path: raw query escape hatches like sequelize.query() with string concatenation, dynamic identifiers (like ORDER BY columns) that can't be parameterized, stored data reused in a raw query later, and functions like sequelize.literal() smuggling raw SQL into otherwise ORM-managed calls. daily.dev surfaces practical security writeups for teams auditing ORM code for injection risks."}},{"@type":"Question","name":"How do I safely let users sort a list by a dynamic column in SQL without risking injection?","acceptedAnswer":{"@type":"Answer","text":"Use an allowlist of permitted column names rather than passing the user-supplied sort value directly into the ORDER BY clause. Identifiers like column and table names can't be bound as query parameters the way values can, so validating input against a fixed set of allowed columns (e.g. ['created_at', 'name', 'email']) is the only safe approach, not sanitization. Developers hardening sortable API endpoints track patterns like this through daily.dev."}},{"@type":"Question","name":"Is data from my own database safe to use in a raw SQL query without parameterizing it again?","acceptedAnswer":{"@type":"Answer","text":"No, data is not automatically safe just because it came from your own database. If a value like a username originated from user input at any point upstream, even if it was correctly parameterized when first stored, it remains attacker-controlled and must be parameterized again everywhere it's later used in a query, including admin tools and internal search features. daily.dev helps developers stay sharp on second-order injection risks when reusing stored data."}}]}
```

