

0 / 2 embers
0 / 3000 xp
click for more info
Complete a lesson to start your streak
click for more info
Still calibrating
click for more info
Not enough gems
Cost: 6 gems
1: Managing Secrets
incomplete
2: Injecting Secrets at Runtime
incomplete
3: Protecting Secrets
incomplete
4: Build Artifacts and Deployment Hygiene
incomplete
5: Limiting Build Context
incomplete
6: Source Code and Config Leaks
incomplete
7: Public File Leaks
incomplete
8: Server-Side Request Forgery
incomplete
9: Defending Against SSRF
incomplete
10: Open Redirects
incomplete
11: Risks of Dependencies
incomplete
12: Auditing Dependencies
incomplete
13: Dependency Maintenance
incomplete
Back
ctrl+,
Next
ctrl+.
This lesson's interactive features are locked, please to keep using them
Modern apps depend on code their teams didn't write... and every dependency brings a tree of transitive dependencies, install scripts, maintainers, and release processes into your security boundary.
A "transitive dependency" is a package that your app doesn't directly depend on, but is a dependency of one of your direct dependencies. A transitive dependency can be several levels deep, and if you're working in TypeScript, you probably have hundreds of them.
An outdated package might have a known vulnerability. A compromised maintainer might publish a malicious release. An install script can read developer or CI environment variables before your app ever runs! That's a lot of trust for one npm install.
A version range in package.json describes which releases the package manager may select:
{
"dependencies": {
"express": "^5.2.1"
}
}
The caret allows compatible updates within the same major version. That doesn't mean every npm ci silently chooses a new release. When a committed package-lock.json is present, npm ci installs the exact locked dependency tree and fails if it disagrees with package.json.
The range mostly matters when the lockfile is created from scratch or deliberately updated. Without a committed lockfile, different installations can resolve different trees. With one, builds are reproducible.
A lockfile makes installation reproducible. It does not make the locked code safe or current.
Before adding a dependency, ask whether its capability is really worth the extra code and attack surface. Good engineers don't solve all their problems with npm install!