Eval injection through dynamic require

Eval injection through dynamic require

Description

When user input controls the module name or file path passed to require(), an attacker may cause unintended JavaScript or a malicious module to be loaded and executed. The selected module or file must be accessible and loadable by the server.

Potential impact

  • Malicious code executed on the server
  • Access to sensitive system or source-code information
  • Service disruption caused by loading an unexpected module

Remediation

  • Pass only fixed module names or trusted values to require.
  • If modules or files must be selected dynamically, restrict the choices to an allow-list.
  • Validate input and paths, and limit the functionality exposed through the selected module to what is needed.

Examples

Before

javascript
function loadModule(moduleName) {
  // Pass user input directly to require
  return require(moduleName);
}

After

javascript
function loadModule(moduleName) {
  // Use only module names on the allow-list
  const allowedModules = ['fs', 'path'];
  if (!allowedModules.includes(moduleName)) {
    throw new Error('허용되지 않은 모듈입니다.');
  }
  return require(moduleName);
}

Explanation:

  • Before: The user-controlled moduleName is passed directly to require, allowing an unintended module to be loaded.
  • After: Module names are limited to fs and path, preventing selection of other modules or files. This does not restrict permissions for file operations performed through those modules.

References