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
Install time/Install hook/Deprecated

node_modules/.hooks/ directory

During npm lifecycle events for all packages

Lives in
node_modules/.hooks/ directory
Attacker needs
Filesystem write access
Lifecycle
Install
Startup
your code
Module load
Runtime
REPL

Runs while dependencies download and build. The app has never started.

How it runs

Obscure, and only relevant if you're somehow still on npm 6. npm supported a .hooks/ directory inside node_modules/ that could contain lifecycle scripts. Files there named preinstall, install, postinstall, preuninstall, or postuninstall get executed during the matching lifecycle events for all packages. It's a global lifecycle hook for the entire tree.

mkdir -p node_modules/.hooks
cat > node_modules/.hooks/postinstall <<'EOF'
#!/usr/bin/env sh
echo "*** node_modules/.hooks/postinstall ran ***"
EOF
chmod +x node_modules/.hooks/postinstall
npm install

If an attacker can write to node_modules/.hooks/postinstall, that script runs every time any package is installed. This worked in npm 6-era tooling but does not execute in modern npm (7+, including npm 10). Its obscurity cuts both ways. Most developers don't know it exists, so most security tools don't check for it.

Defend

Use npm 7+ (which ignores this mechanism); restrict write access to node_modules; scan for unexpected .hooks directories in legacy projects.