Many software projects are not built from scratch. Web applications, internal services, and even small scripts typically use dozens to thousands of third-party components—from libraries for login, image processing, database connections, to testing tools.
The problem is that dependencies are not just pieces of code that can be installed. Each package carries versions, other dependencies, licenses, and potential security vulnerabilities. When one component changes without proper checks, the application can fail to build, its behavior can change, or new risks can emerge.
The good news is that managing dependencies doesn't have to be complicated. A few simple habits can make projects easier to understand and safer to maintain.
Direct and Indirect Dependencies
Direct dependencies are packages that you intentionally add to the project. For example, a Node.js application installs Express to create a web server.
Meanwhile, indirect dependencies are packages used by other dependencies. You might only add one library, but that library can bring in several additional packages. This chain often makes changes feel surprising.
For instance, you update one library to get a new feature. Behind that update, the versions of parsers, utilities, or network modules also change. The application may still look the same from the outside, but the code being executed is no longer identical to the previous version.
Lockfiles Are Not Trash Files
Files like package-lock.json, yarn.lock, or pnpm-lock.yaml are often considered technical files that can be ignored. In fact, lockfiles record the exact versions and structure of dependencies used by the project.
Npm documentation explains that package-lock.json helps ensure that team members, deployment servers, and CI pipelines install the same dependency tree. Without a lockfile, two people can run npm install at different times and end up with slightly different version combinations.
Therefore, lockfiles should be kept in the repository. Do not delete them just because they are large or their contents seem hard to read. They function like a very detailed shopping list: not just saying "buy flour," but also recording the brand and size actually used.
Use the Appropriate Installation Commands
In CI or deployment pipelines, use commands that respect the contents of the lockfile, such as:
npm ciTo update lockfile metadata without installing the entire contents of node_modules, npm also provides:
npm install --package-lock-onlyThese commands still need to be used with caution. Do not assume all updates are safe just because the installation process succeeded.
Differentiate Between Security Updates and Feature Updates
Not all updates should be treated the same. Patch updates may contain bug fixes, while minor or major updates can bring behavioral changes and compatibility issues.
For critical projects, create a clear update path:
- Security updates: prioritized after their impact is understood.
- Routine updates: scheduled, for example, every week or two weeks.
- Major updates: conducted as planned work with testing and change logs.
A common mistake is waiting too long and then making massive updates in one pull request. This approach makes it difficult for the team to identify which package caused issues. Small changes that are frequently checked are usually easier to roll back.
Check Changes Before Merging Code
Code reviews are not sufficient if attention is only directed at application files. Changes in package.json or the lockfile also need to be reviewed.
Pay attention to the following:
- Are there any new packages that the team is not familiar with?
- Has the version of a package changed significantly more than expected?
- Are production dependencies increasing while features are only for development?
- Has the source of a package changed or is it using an unusual registry?
- Is the license compliant with project needs?
GitHub provides a dependency review feature that can show dependencies that have been added, removed, or updated in a pull request, including known vulnerability information. This feature can also be set up as an automated check through Dependency Review Action.
An example of a simple workflow:
name: Dependency Review
on: [pull_request]
permissions:
contents: read
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/dependency-review-action@v4This configuration is not a substitute for human review. It is more like an automatic fence that helps catch common issues before changes are merged.
Component Inventory Helps During Incidents
When a library is found to have a security vulnerability, the first question is usually simple: “Are we using it?” Without a tidy inventory, the answer may require manual searches across multiple repositories and servers.
This is where the concept of Software Bill of Materials or SBOM comes in handy. CISA describes SBOM as a formal record of the components and dependency relationships that make up a software. Simply put, SBOM is a list of the materials that compose an application.
SBOM does not automatically make software secure. However, it speeds up the impact mapping process. Teams can see the versions of components used, where they are used, and which products need to be updated when issues arise.
What Does This Mean for Us?
For personal projects, you may not yet need to build a complex SBOM system. But the basic habits remain relevant:
- Keep lockfiles in the repository.
- Use consistent runtime and package manager versions.
- Run dependency audits regularly.
- Check changes in the lockfile in every pull request.
- Remove unused dependencies.
- Do not install packages just because their names look similar to popular packages.
For teams, add automated testing, minimum review rules, and dependency monitoring. Tools like Dependabot can create update pull requests, but the decision to merge changes should still consider application testing and business context.
What You Can Do Now
Start with the projects that are deployed most frequently. Ensure the lockfile is tracked by Git, run dependency checks, and then review the last five dependency changes. Does the team know why each package was updated? Are there any old packages that are no longer used?
The goal is not to avoid all third-party dependencies. Open-source libraries and package manager ecosystems actually enable software to be developed faster. The aim is to ensure that every component that enters the project can be seen, tested, and updated for clear reasons.
Fact: lockfiles, dependency reviews, and SBOMs help increase visibility into software components. Analysis: the greatest benefit of these practices is not just preventing security vulnerabilities but also reducing wasted time when builds suddenly differ or a library has issues.
Sources & Further Reading
- npm Docs: package-lock.json
- npm Docs: npm install
- GitHub Docs: Dependency review
- GitHub Docs: Configuring the dependency review action
- CISA: SBOM FAQ
– Rio Yotto @rioyotto
