Skip to main content
interlace
Plugin: import-nextRules

require-import-approval

Enforce explicit approval for high-risk package imports

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

Rule Details

A third-party package must be approved before it is used. The user keeps the policy in packages: each entry names a package (axios), a scope (@acme/*) or a prefix (lodash*) with a status of approved, pending or blocked. Every way a package is loaded or re-exported is checked: import, side-effect import, export … from, export * from, require(), import() and TypeScript's import x = require().

A blocked or pending package is reported; with defaultPolicy: 'deny' a package not listed at all is reported too (the default allow lets it through). ignorePatterns exempts packages. The package is matched by name: axios/lib/x is axios, @acme/sdk/x is @acme/sdk.

Never a package: relative and absolute paths, # subpath imports (the package's own files), Node.js builtins (fs, node:fs), and path aliases npm cannot publish under (@/lib: a scope is never empty; ~/lib: ~ is not allowed in a package name).

❌ Incorrect

// { packages: [{ package: 'axios', status: 'blocked' }], defaultPolicy: 'deny' }
import axios from 'axios';
import leftPad from 'left-pad';

✅ Correct

import fs from 'node:fs';
import { x } from '#lib/x';
import helper from './helper';

Options

[
  {
    "type": "object",
    "properties": {
      "packages": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "package": {
              "type": "string"
            },
            "status": {
              "type": "string",
              "enum": [
                "approved",
                "pending",
                "blocked"
              ]
            },
            "reason": {
              "type": "string"
            },
            "alternative": {
              "type": "string"
            },
            "approvedBy": {
              "type": "string"
            },
            "approvedDate": {
              "type": "string"
            }
          },
          "required": [
            "package",
            "status"
          ]
        }
      },
      "defaultPolicy": {
        "type": "string",
        "enum": [
          "allow",
          "deny"
        ],
        "default": "allow"
      },
      "ignorePatterns": {
        "type": "array",
        "items": {
          "type": "string"
        },
        "default": []
      }
    },
    "required": [
      "packages"
    ],
    "additionalProperties": false
  }
]

Implementation

OWASP Foundation

  • Category: A00:2021 - General Security

Use this rule

npm install -D oxlint-plugin-import-next
.oxlintrc.json
{  "jsPlugins": ["oxlint-plugin-import-next"],  "rules": {    "import-next/require-import-approval": "error"  }}
vite.config.ts
import { defineConfig } from 'vite-plus';export default defineConfig({  lint: {    jsPlugins: ['oxlint-plugin-import-next'],    rules: {      'import-next/require-import-approval': '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.