lote.guide
esc
  • npm lifecycle scriptsscripts field in package.jsonNode.js
  • setup.py arbitrary code executionsetup.py in source distributions (sdist)Python
  • NODE_OPTIONS preload injectionNODE_OPTIONS environment variable, CLI flags, or .env files loaded via --env-fileNode.js
  • .pth file import execution*.pth files on sys.path (commonly site-packages)Python
  • binding.gyp / node-gyp native compilationbinding.gyp file in the package rootNode.js
  • Corepack (packageManager field)"packageManager" field in package.json, COREPACK_HOME cache directoryNode.js
  • .npmrc registry manipulation.npmrc file (project, user, or global)Node.js
  • overrides / resolutions dependency swapoverrides (npm) or resolutions (Yarn) field in package.jsonNode.js
  • pnpm hooks (pnpmfile.cjs).pnpmfile.cjs in the project rootNode.js
  • .yarnrc.yml plugins and registry.yarnrc.yml in the project rootNode.js
  • pyproject.toml build backendspyproject.toml [build-system] tablePython
  • sitecustomize / usercustomize auto-importsitecustomize.py / usercustomize.py on sys.path (usually site-packages)Python
  • .node native addon loading.node files in node_modules/ (typically under build/Release/ or prebuilds/)Node.js
  • Yarn Plug'n'Play (.pnp.cjs).pnp.cjs in the project rootNode.js
  • __init__.py execution on import__init__.py in any package directory on sys.pathPython
  • .pyc bytecode cache poisoning.pyc files in __pycache__/ directories alongside source modulesPython
  • PYTHONPATH / PYTHONHOME module shadowingPYTHONPATH / PYTHONHOME environment variablesPython
  • npx / npm exec remote executionnpx, npm exec, npm create / npm init (initializer flows)Node.js
  • conftest.py auto-loading (pytest)conftest.py files in any directory pytest traversesPython
  • NODE_PATH environment variableNODE_PATH environment variableNode.js
  • "imports" field (subpath imports)imports field in package.jsonNode.js
  • require.extensions / Module._extensionsrequire.extensions / Module._extensions in any loaded moduleNode.js
  • .egg files and EGG-INFO scripts.egg files in site-packages (registered via easy-install.pth)Python
  • Zip imports (zipimport).zip / .pyz files on sys.path, or passed directly to the interpreterPython
  • PYTHONSTARTUP environment variablePYTHONSTARTUP environment variablePython
  • node_modules/.hooks/ directorynode_modules/.hooks/ directoryNode.js
Node.js
Interpreter startup/Environment variable

NODE_OPTIONS preload injection

Before the main script runs (--require, --import) or during module loading (--experimental-loader)

Lives in
NODE_OPTIONS environment variable, CLI flags, or .env files loaded via --env-file
Attacker needs
Environment control
Lifecycle
Install
Startup
your code
Module load
Runtime
REPL

Runs while the interpreter boots, before your entrypoint.

How it runs

NODE_OPTIONS injects CLI flags into every Node.js process. Set it once and every node invocation on that machine, container, or CI pipeline picks it up. It's the most powerful way to run code implicitly in Node, because it carries several flags that each run code before main.

--require preloads a CommonJS (or, on modern Node, ESM) module before your entrypoint:

export NODE_OPTIONS="--require /tmp/demo.js"
node app.js   # /tmp/demo.js already ran

--import is the dedicated ESM preload flag. --experimental-loader installs a loader hook that intercepts, rewrites, or redirects any import. That makes it a man-in-the-middle for the module system. It can replace fs with a patched version that exfiltrates reads, or inject logging into every import.

--env-file (Node 20.6+) loads env vars from a file before the process initializes. If a .env contains NODE_OPTIONS, the whole preload chain moves out of the environment and into a file most developers consider harmless config:

# .env
NODE_OPTIONS=--require /tmp/evil.js

All of these flow through one variable, and an attacker can chain them, as in NODE_OPTIONS="--require ./cjs-hook.js --import ./esm-hook.mjs --experimental-loader ./loader.mjs". If they can set env vars in your pipeline, Docker image, or .env file, they own every Node process that reads them.

Defend

Scrub NODE_OPTIONS in CI/CD, containers, and service managers; treat .env as code; avoid --env-file in package.json scripts you don't control.