Never use eval() or unsafe dynamic code execution
Avoid eval(), new Function(), setTimeout/setInterval with string arguments, and innerHTML with untrusted content — they execute arbitrary code and create critical XSS vulnerabilities.
- eval() executes arbitrary strings as code — any user input passed to it is a critical security hole
- new Function() is equally dangerous and not caught by CSP eval restrictions
- setTimeout('code', delay) and setInterval('code', delay) also evaluate strings — use function references instead
- Use JSON.parse() instead of eval() for parsing JSON
Rule Details
eval() (opens in new tab) and similar dynamic code execution functions such as the Function() constructor (opens in new tab) run arbitrary strings as JavaScript code, creating security vulnerabilities and defeating JavaScript engine optimizations.
Code Example
// ❌ Critical: eval with user input — direct XSS
const userInput = "alert('hacked!')"
eval(userInput) // Executes arbitrary code
// ❌ Critical: new Function is equally dangerous
const fn = new Function('x', 'return ' + userExpression)
// ❌ Bad: string-based timers evaluate code
setTimeout('updateUI()', 1000) // Don't do this
setInterval('fetchData()', 5000) // Don't do this
// ❌ Bad: eval for JSON parsing (historically common, never safe)
const data = eval('(' + jsonString + ')')Why It Matters
eval() and its equivalents are the root cause of some of the most severe XSS vulnerabilities. If any user-controlled string reaches eval(), an attacker can execute arbitrary JavaScript in your users' browsers — stealing sessions, making requests as the user, or redirecting to malicious sites. A strict Content Security Policy adds a browser-level backstop, but there is still no legitimate use case here that cannot be solved more safely.
Safe Alternatives
Parsing Data
// ✅ JSON.parse for JSON data
const data = JSON.parse(jsonString)
// ✅ URL parsing
const params = new URLSearchParams(queryString)
const value = params.get('key')Dynamic Property Access
// ❌ Using eval for dynamic property access
const property = 'username'
const value = eval(`user.${property}`)
// ✅ Use bracket notation
const value = user[property]
// Add validation to ensure only expected properties are accessed
const ALLOWED = ['username', 'email', 'role']
if (ALLOWED.includes(property)) {
const value = user[property]
}Dynamic Dispatch
// ❌ Using eval to call a function by name
const actionName = 'save'
eval(`${actionName}Document()`)
// ✅ Use an explicit dispatch table
const actions = {
save: saveDocument,
load: loadDocument,
export: exportDocument
}
if (actions[actionName]) {
actions[actionName]()
}Timers
// ❌ String-based timers
setTimeout('updateUI()', 1000)
// ✅ Function references
setTimeout(updateUI, 1000)
setTimeout(() => updateUI(), 1000)ESLint Configuration
Use ESLint's no-eval rule (opens in new tab) together with no-new-func and no-implied-eval so these patterns fail in code review and CI rather than in production.
{
"rules": {
"no-eval": "error",
"no-new-func": "error",
"no-implied-eval": "error"
}
}Content Security Policy
Block eval at the browser level with a strict CSP:
Content-Security-Policy: script-src 'self'; object-src 'none'Without 'unsafe-eval', eval() and new Function() will be blocked by the browser.
Exceptions
- A framework default or browser behavior is not an exception by itself; only documented constraints with compensating controls should suppress the finding.
- When a JavaScript pattern looks unsafe but the data is fully constrained, validated, and never attacker-controlled, document that boundary explicitly instead of treating it as implicit.
- If a rule overlaps with a stronger exploit path or runtime failure, fix the issue that most directly enables compromise or user-visible breakage first.
Verification
Automated Checks
- Verify the behavior in the browser after the code change, not only in static analysis.
- Inspect DevTools Network or Performance panels when the rule affects loading or execution order.
- Test the primary user flow and one edge case triggered by the changed script path.
Manual Checks
- Confirm the code still behaves correctly when the feature is delayed, lazy-loaded, or fails.
Use with AI
Copy these prompts to use with your AI assistant, or install the MCP server to use directly from Claude, Cursor, or Windsurf.
Check
Verify implementation
Search this codebase for any use of eval(), new Function(), or setTimeout/setInterval with string arguments.
Fix
Auto-fix issues
Replace eval() calls with safe alternatives: JSON.parse for data, object lookups for dynamic dispatch, and Function references for timers.
Explain
Learn more
Explain why eval() is dangerous, how it enables XSS attacks, and what safe alternatives exist for each use case.
Review
Code review
Review scripts, client components, and browser execution paths related to Never use eval() or unsafe dynamic code execution. Flag exact imports, event handlers, runtime side effects, or blocking operations that violate the rule, and state how the change should be verified in the browser.