Sunday, April 5, 2026

Supply Chain Attack Forensics: Artifact Reference

Supply chain attacks are now becoming more common as a vector for compromise.  And can be one of the hardest to investigate.  It is like an insider threat but the insider is software or code in the supply chain. 

Does it leave an artifact trail?  Yes, lets look at package managers, cache, and  logs. This post covers the artifact locations related to supply chain attacks, what forensic data they contain, and how to recover.


Package Manager Attacks

Package Manager Compromise — malicious code injected into PyPI, npm, RubyGems, NuGet, kefile rules, or compiler plugins

Package Manager Artifacts







Python / pip

Malicious PyPI packages typically execute at install time via setup.py, __init__.py, or setup.cfg hooks. The code runs with the installing user's permissions before the developer has reviewed a single line.

Key artifact locations:

Artifact Path Forensic Value
Installed package files ~/.local/lib/python3.x/site-packages/<pkg>/ Recover malicious source — often still on disk post-install
System-wide packages /usr/local/lib/python3.x/dist-packages/ Confirms system-level install vs. virtualenv
pip install log Explicit: pip install --log /tmp/pip.log <pkg> Install timestamp, version resolved, stdout from setup.py
pip cache ~/.cache/pip/ Wheel/sdist files cached at install time — source recovery even if package was yanked from PyPI
virtualenv metadata .venv/lib/python3.x/site-packages/<pkg>-*.dist-info/RECORD Cryptographic record of all files installed by the package
METADATA file <site-packages>/<pkg>-*.dist-info/METADATA Declared maintainer, homepage, version — compare against known-good

pip cache: The pip cache at ~/.cache/pip/ often retains the original wheel or source distribution even after a package has been removed from PyPI by the maintainer or registry. This is a good path to look for looking at malicious code after a takedown. Always image ~/.cache/pip/ 

What to examine in setup.py: Look for encoded payloads, subprocess, os.system, socket, urllib, or requests calls at module import or install time. Legitimate packages do not make outbound network connections during installation.







Node.js / npm and yarn

npm's postinstall lifecycle hook is the primary execution vector. Any package can declare a postinstall script in package.json that runs automatically during npm install — with no user prompt.

Key artifact locations:

Artifact Path Forensic Value
npm debug log ~/.npm/_logs/<timestamp>-debug-*.log Verbose install log: resolved versions, script execution, outbound requests
Installed package source node_modules/<pkg>/ Recover malicious JS — postinstall script often base64-encoded
Package lock package-lock.json or yarn.lock Records exact resolved version + integrity hash at time of install
npm cache ~/.npm/_cacache/ Cached tarballs — recoverable after package takedown
.npmrc Project root or ~/ May reveal custom registry redirects (dependency confusion indicator)

NPM package-lock: package-lock.json records the integrity field — a SHA-512 hash of the exact tarball that was downloaded. If a threat actor compromised a package after a prior clean install, the integrity hash in the lockfile will mismatch the hash of the malicious version. Comparing lockfile hashes against npm's public registry metadata is a fast triage step that doesn't require executing any code.

# Quick integrity check against current installed version
npm audit --json | python3 -m json.tool | grep -A2 "severity"

Other Package Ecosystems

Ecosystem Install Log / Cache Location Execution Vector
RubyGems (gem) ~/.gem/specs/, /var/lib/gems/ extconf.rb, gem extensions compiled at install
NuGet (.NET) %APPDATA%\NuGet\, ~/.nuget/packages/ MSBuild .targets files executed at build time
Maven (Java) ~/.m2/repository/ Plugin execution via pom.xml lifecycle phases
Go modules $GOPATH/pkg/mod/ init() functions; go:generate directives
Cargo (Rust) ~/.cargo/registry/, ~/.cargo/git/ build.rs scripts executed at compile time

Supply chain forensics is an evidence collection problem more than a malware analysis problem. The malicious code often runs once, quickly, and leaves minimal trace. But cache, logs, and package files can be our friend. 


Recent Posts

No comments:

Post a Comment