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(defaultfalse): also checkimport().
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{ "jsPlugins": ["oxlint-plugin-import-next"], "rules": { "import-next/no-dynamic-require": "error" }}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.