Documentation

RCE (Remote Code Execution) Checks

Remote Code Execution vulnerabilities allow attackers to execute arbitrary code on your server. These are the most dangerous security issues and should be fixed immediately.

rce-eval

Severity: Critical

What It Detects

Use of JavaScript's eval() function, which can execute arbitrary code.

Why It's Dangerous

eval() parses and executes a string as JavaScript code. If an attacker can control the input to eval(), they can:

  • Execute any JavaScript code
  • Access environment variables and secrets
  • Read/write files on the system
  • Make network requests to external servers

Example Vulnerable Code

// User input executed as code
const userInput = req.query.expression;
const result = eval(userInput); // DANGEROUS!
 
// Dynamic configuration evaluation
const config = eval(`(${configString})`); // DANGEROUS!

Safe Alternative

// For JSON parsing
const data = JSON.parse(jsonString);
 
// For math expressions
import { evaluate } from 'mathjs';
const result = evaluate(safeExpression);
 
// For configuration
const config = JSON.parse(configString);
// Or use a schema validator
import { z } from 'zod';
const config = configSchema.parse(JSON.parse(configString));

rce-function-constructor

Severity: Critical

What It Detects

Use of the Function constructor, which creates functions from strings.

Why It's Dangerous

new Function() is essentially eval() with extra steps. It compiles a string into executable code, allowing code injection.

Example Vulnerable Code

// Creating function from user input
const userCode = req.body.code;
const fn = new Function('data', userCode); // DANGEROUS!
fn(userData);
 
// Dynamic function generation
const operation = new Function('a', 'b', `return a ${operator} b`);

Safe Alternative

// Use predefined functions
const operations = {
  add: (a, b) => a + b,
  subtract: (a, b) => a - b,
  multiply: (a, b) => a * b,
};
const result = operations[validatedOperator](a, b);
 
// For complex logic, use a safe interpreter
import { VM } from 'vm2';
const vm = new VM({ timeout: 1000 });
const result = vm.run(sanitizedCode);

rce-child-process

Severity: Critical

What It Detects

Use of Node.js child_process module functions including:

  • exec() / execSync()
  • spawn() / spawnSync()
  • execFile() / execFileSync()
  • fork()

Why It's Dangerous

These functions execute system commands. If user input reaches these functions, attackers can:

  • Execute arbitrary shell commands
  • Read sensitive files (cat /etc/passwd)
  • Download and execute malware
  • Establish reverse shells

Example Vulnerable Code

import { exec } from 'child_process';
 
// Command injection via string concatenation
const userDir = req.query.dir;
exec(`ls ${userDir}`, (err, stdout) => {
  // Attacker input: "; rm -rf /"
}); // DANGEROUS!
 
// User-controlled command
const cmd = req.body.command;
exec(cmd); // EXTREMELY DANGEROUS!

Safe Alternative

import { spawn } from 'child_process';
import path from 'path';
 
// Use spawn with array arguments (no shell interpretation)
const safeDir = path.basename(userInput); // Sanitize
const ls = spawn('ls', [safeDir]);
 
// Validate against allowlist
const allowedCommands = ['list', 'status', 'info'];
if (!allowedCommands.includes(userCommand)) {
  throw new Error('Command not allowed');
}
 
// Use libraries instead of shell commands
import fs from 'fs/promises';
const files = await fs.readdir(safeDir);

rce-dynamic-require

Severity: High

What It Detects

Use of require() with a variable or expression, allowing dynamic module loading.

Why It's Dangerous

Dynamic require() can be exploited to:

  • Load arbitrary modules from the filesystem
  • Execute code from unexpected locations
  • Bypass module whitelists

Example Vulnerable Code

// User-controlled module path
const moduleName = req.query.module;
const module = require(moduleName); // DANGEROUS!
 
// Path-based dynamic require
const handler = require(`./handlers/${userAction}`); // DANGEROUS!

Safe Alternative

// Use an allowlist of modules
const allowedModules = {
  'json': require('./handlers/json'),
  'xml': require('./handlers/xml'),
  'csv': require('./handlers/csv'),
};
 
const moduleName = req.query.module;
if (!(moduleName in allowedModules)) {
  throw new Error('Module not allowed');
}
const handler = allowedModules[moduleName];

rce-dynamic-import

Severity: High

What It Detects

Use of dynamic import() with a variable or expression.

Why It's Dangerous

Similar to dynamic require(), but for ES modules. Attackers can:

  • Import arbitrary modules
  • Execute code from remote URLs (in some environments)
  • Bypass security controls

Example Vulnerable Code

// User-controlled import path
const modulePath = req.query.module;
const module = await import(modulePath); // DANGEROUS!
 
// Dynamic plugin loading
const plugin = await import(`./plugins/${userPlugin}`); // DANGEROUS!

Safe Alternative

// Maintain explicit module map
const plugins = {
  'analytics': () => import('./plugins/analytics'),
  'logging': () => import('./plugins/logging'),
  'cache': () => import('./plugins/cache'),
};
 
const pluginName = req.query.plugin;
if (!(pluginName in plugins)) {
  throw new Error('Plugin not found');
}
const plugin = await plugins[pluginName]();

Summary

| Check | Severity | Key Fix | |-------|----------|---------| | rce-eval | Critical | Use JSON.parse() or safe evaluators | | rce-function-constructor | Critical | Use predefined functions or safe VMs | | rce-child-process | Critical | Use spawn with arrays, validate input | | rce-dynamic-require | High | Use explicit module allowlists | | rce-dynamic-import | High | Use explicit import maps |

Next Steps