Dependency integrity
Pin, lock, verify; confusion and typosquats.
Most of your code is other people’s code. Dependency integrity — controlling exactly what you pull in and where it comes from — is where a large share of real supply-chain attacks land, through confusion, typosquatting, and malicious updates.
Pin, lock, and verify
Pin dependencies by cryptographic hash or digest, not just a version string: a version tag can be re-published or a mutable ref moved, but a hash guarantees the exact bytes. A lockfile records the full resolved dependency graph with hashes, so installs are reproducible and any change is visible in review rather than silently pulled in. Verify hashes on install (many ecosystems support a require-hashes mode) so a tampered package is rejected. These simple controls close the "the dependency changed under us" class of attack.
# WEAK: floating version — resolves to whatever is current, unverified.requests>=2.0# STRONG: exact version + hash in a lockfile, verified on install.requests==2.32.3 \--hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6# pip install --require-hashes -r requirements.lock → rejects any mismatch
Confusion, typosquatting, and vetting
Two ecosystem attacks deserve specific defenses. Dependency confusion tricks a resolver into pulling a malicious public package that shares a name with your internal one — defend by scoping/namespacing internal packages and configuring the resolver to prefer your private registry. Typosquatting publishes malicious packages with names close to popular ones — defend with careful review and automation that flags new or unusual dependencies. Beyond that, vet the dependencies you adopt: OpenSSF Scorecard and deps.dev give data-driven signals (signed releases, active maintenance, review practices) so you choose well-run projects rather than abandoned ones.