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

setup.py arbitrary code execution

During pip install (build phase)

Lives in
setup.py in source distributions (sdist)
Attacker needs
Supply-chain foothold
Lifecycle
Install
Startup
your code
Module load
Runtime
REPL

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

How it runs

Most Python supply-chain attacks in the wild run through this. When you pip install a package from a source distribution (sdist), pip runs setup.py to build it. And setup.py is a plain Python script. It can download files, open shells, exfiltrate environment variables or install backdoors. All of that happens at install time, before your application ever imports the package.

# setup.py
from setuptools import setup
import os
os.system('echo "You are hacked" > /tmp/pwned.txt')
setup(name="totally-legit-package", version="1.0.0")
pip install ./totally-legit-package

The 2025 PyPI wave used look-alike domains to distribute packages with malicious setup.py files. TeamPCP went further in 2026. They stole maintainer credentials from CI/CD and published backdoored versions of legitimate packages directly. This is why the ecosystem keeps pushing toward wheels and isolated builds. Sdists aren't going away, though.

In the wild

2025 PyPI typosquat wave (pypj.org, pypl.io); TeamPCP compromise of LiteLLM via stolen maintainer creds (2026)

Defend

Prefer wheels over sdists; use PEP 517 isolated builds; pin hashes; build in sandboxed, network-restricted environments.