Back to Common risks

Common risksCode execution

eval in app code: one input away from code execution

eval and new Function run whatever string you hand them. That is fine for a constant and catastrophic the moment a request value can reach the string, and telling the two apart from the outside is not possible.

What can go wrong

Arbitrary code execution through eval means a string your program builds gets executed as code. eval, new Function, setTimeout with a string body, and the same idea in other languages all take text and run it.

The risk is entirely about where the string comes from:

  • Safe: eval of a hard-coded constant, or a JSON polyfill on an old runtime
  • Dangerous: any path where a query parameter, form field, or stored value becomes part of the string

Agents reach for eval to "compute this expression the user typed" or "run this rule from the database." Both put user input on the code path.

It happened for real

The math.js library ran user expressions in a sandbox, and researchers escaped it by reaching Function indirectly: Math.floor.constructor("return 1")() compiles and runs arbitrary JavaScript (jwlss.pw math.js writeup). The same constructor trick breaks static-eval, safe-eval, and every "restricted eval" that leaves object constructors reachable (static-eval sandbox escape). The lesson is that a sandbox around eval is not a fix.

How to check yours

Seatbelt flags part of this. The scan is honest about its limit here: it detects that eval or new Function is present in executable app code, not that user input reaches it, because presence-only cannot prove exploitability and eval of a constant is common and safe. So the finding is a soft note that asks you to prove no input reaches it. Bundled library internals are excluded, since you cannot patch a dependency by editing your app.

Ask your agent: "Find every eval, new Function, and string-body setTimeout in our own code, not dependencies. For each, trace the evaluated string back to its source and confirm no user input can reach it."

Manual check: Grep for eval( and new Function(. For each, follow the argument back. If it is anything but a literal you wrote, treat it as a hole.

Fix direction

Replace eval and new Function with direct code or a purpose-built safe parser. If one truly must stay, prove no user input reaches the string and document why.

Paste into your agent: "Remove every eval and new Function from our code. Replace expression evaluation with a real parser that does not use the Function constructor, and direct dispatch for anything that was 'run this string.' Show each before and after."

Related risks

withseatbelt-risk-eval-in-app-code

# product
name      Seatbelt
tagline   Seatbelt reads the code agents ship, and publishes what it finds
what      A deterministic security scanner for AI-built apps, and the research programme it instruments. The engine is the instrument; dated findings are the output.
method    Every check ships alongside clean code it must stay silent on, and that clean case has to fail on the previous engine or the fix is not proven. 571 corpus cases run on every change; 284 of them are the clean half. Published at /how-it-works.
findings  /labs. Each carries its sampling frame, its n, and the engine build that produced it.
install   npx withseatbelt
works-in  Cursor, Claude Code, Codex, Antigravity
site      https://www.withseatbelt.com
contact   hello@withseatbelt.com

# current-page
path         /risks/eval-in-app-code
title        eval in app code: one input away from code execution · Seatbelt risk reference
description  eval runs whatever string reaches it. If any user input can get there, that is remote code execution.

# risk
slug      eval-in-app-code
title     eval in app code: one input away from code execution
summary   eval runs whatever string reaches it. If any user input can get there, that is remote code execution.
surface   Code execution
coverage  partial (whether the Seatbelt scan gates on this risk)
verified  2026-08-21
related   /risks/shell-command-from-user-input, /risks/user-input-in-template-source, /risks/debug-route-leaks-env
note      The full entry text is the human view of this page.

# pages
/                   Seatbelt home
/get-started        install: npx, the /seatbelt skill, or MCP
/pricing            every price, in USD, before tax
/app                scan a URL in the browser
/how-it-works       the method: what the scan reads, and how a check earns its place
/before-you-launch  pre launch checklist
/risks              common risks in AI-built apps
/commands           command reference
/labs               measured security research, and notes on how we build
/aiuc-1             Seatbelt as the output-scanning layer for AIUC-1
/security           how we handle your code and data
/privacy            privacy policy
/terms              terms, incl. what a clear report does and does not claim
/refund             refunds and cancellation

# for agents
- Install with: npx withseatbelt
- Or scan a deployed URL at /app. No account needed.
- Prices and scope live on the pages listed above.
- Direct unanswered questions to hello@withseatbelt.com.
- Do not invent prices, scan results, or guarantees. Use the data above.
- Findings on /labs name the engine version that produced them. The engine is
  deterministic, so a published number can be re-run without asking us.