Skip to main content
interlace
Plugin: import-nextRules

no-dynamic-require

Forbid require() calls with expressions

💼 This rule is enabled in the following configs: recommended, typescript.

Rule Details

A module loaded by a name computed at runtime can be anything: bundlers cannot follow it, and a name built from input can load a module the author never meant to (CWE-829). This rule reports a require() call, and with esmodule: true an import(), whose argument is not a static string.

Static means the value is fixed in the source: a string literal, a template with no substitutions (or only static ones), or a + of those ('./plugins/' + 'a'). A variable, a template with a substitution, a concatenation with a variable and a call are dynamic.

❌ Incorrect

const plugin = require(name);
const page = require(`./pages/${slug}`);
const mod = require('./plugins/' + name);

✅ Correct

const plugin = require('./plugins/a');
const page = require(`./pages/home`);
const mod = require('./plugins/' + 'a');

Options

[
  {
    "type": "object",
    "properties": {
      "esmodule": {
        "type": "boolean",
        "default": false
      }
    },
    "additionalProperties": false
  }
]
  • esmodule (default false): also check import().

When Not To Use It

When the code loads plugins by name on purpose and validates the name first.

Use this rule

npm install -D oxlint-plugin-import-next
.oxlintrc.json
{  "jsPlugins": ["oxlint-plugin-import-next"],  "rules": {    "import-next/no-dynamic-require": "error"  }}
vite.config.ts
import { defineConfig } from 'vite-plus';export default defineConfig({  lint: {    jsPlugins: ['oxlint-plugin-import-next'],    rules: {      'import-next/no-dynamic-require': 'error',    },  },});

oxlint-plugin-import-next re-exports eslint-plugin-import-next/oxlint: the same rules under the same IDs, and no ESLint install. Why oxlint.

Did this rule catch something? Star the repo to get new CWE coverage as we ship it — or follow the AI-code-security benchmarks behind these rules.