Yes. A tutorial should pin its dependencies and ship the lockfile, then tell readers to install from that file. Pinning keeps the sample working as libraries change, and it stops a newly published, possibly malicious release from arriving silently the next time someone follows the steps.
What pinning means for a tutorial
A range such as ^4.17.0 means "any compatible version". That is convenient for an application you maintain daily and risky for a tutorial that sits untouched for two years. A pin names exact versions. A lockfile records the full dependency tree, including the packages your packages pull in.
The npm documentation says package-lock.json describes the exact tree that was generated, so later installs produce identical trees regardless of intermediate dependency updates. It also says the file is intended to be committed to source repositories.
Install command matters as much as the file
A lockfile only helps if readers use it. According to the npm documentation for npm ci, the project must already have a package-lock.json or npm-shrinkwrap.json, and if the lock and package.json disagree, the command exits with an error instead of updating the lock. It never writes to package.json or the lock files. That is the behaviour a tutorial wants.
For Python, the pip documentation describes hash-checking mode, enabled with --require-hashes. Hashes are listed per requirement in the requirements file, and the documentation says the mode protects against remote tampering and network issues. It is all or nothing: once any requirement carries a hash, hashes are required for all of them.
| Ecosystem | Pin file | Strict install command |
|---|---|---|
| npm | package-lock.json | npm ci |
| pip | requirements.txt with hashes | pip install --require-hashes -r requirements.txt |
Steps for a tutorial author
- Generate the lockfile from a clean environment and commit it with the sample.
- Replace
npm installin your instructions withnpm ci, and explain in one line why. - For Python, produce a requirements file with hashes and install with the strict flag.
- Pin the language runtime version in the README, since a runtime change breaks samples too.
- Add a dated note at the top: "Tested with these versions on this date." Readers can then judge staleness.
- Revisit the tutorial on a schedule. Pinning freezes you in time, so old pins can carry known advisories. Re-run a scan and bump versions deliberately.
The trade-off to state honestly
Pinning is not free. Pinned samples drift out of date, and a pinned vulnerable version is still vulnerable. The goal is controlled change, not no change. A tutorial that is reviewed twice a year with a scan and a version bump beats one that floats on ranges.
Try it yourself
An accurate dependency inventory is what makes a pin review possible.
Click through it at your own pace, or open it full screen.
Safeguard's dependency scanning and SBOM generation can inventory the versions a sample uses so they can be checked. The free scan is at https://gold.safeguard.sh/scan.
Quick check
Is npm install different from npm ci for readers?
Yes. According to the npm documentation, npm ci requires an existing lockfile and errors if it disagrees with package.json, rather than changing it.
Does pinning make a tutorial secure?
No. It makes change predictable. You still need to scan the pinned versions and update them on a schedule.
Sources
Last reviewed: 19 October 2026.