Home / Articles / Software
Software

Open Source Dependencies Are More Than Just npm install: How to Check Packages Before They Enter Your Project

Open source packages can accelerate development, but they also bring new code, scripts, and risks into the project. With a simple check of the source, version, installation scripts, and provenance, the decision to use...

Dependensi Open Source Bukan Sekadar npm install: Cara Memeriksa Paket sebelum Masuk Proyek

A single command like npm install can pull dozens to hundreds of packages into a project. This process often feels safe because the packages are popular, have many downloads, or appear at the top of search results. However, popularity is not proof that a dependency is suitable, maintained, or free from risks.

Dependencies are third-party software components used by our applications. They can help process dates, read files, create interfaces, or connect applications with other services. The problem is that dependencies do not just bring functionality. Packages can also include installation scripts, transitive dependencies, and access to the build environment.

Therefore, choosing an open source package should be treated like selecting components to enter a house: not everything should be suspected, but the origin and necessity still need to be checked.

Don't Just Look at Download Counts

The number of downloads is an initial signal, not a security assessment. A package can be popular but may no longer be maintained. Conversely, a smaller package might come from a reputable organization, have a good release process, and comprehensive documentation.

Before installing a package, check the following:

  • Package name and scope. Ensure the package name is accurate. Fake packages often use names similar to well-known projects.
  • Source repository. Check if the link to GitHub or another platform is available and still active.
  • Last release. An old package that hasn't been updated isn't necessarily dangerous, but it may no longer support the latest runtime versions or security fixes.
  • Number of dependencies. A small package that pulls in dozens of dependencies carries a greater area of risk than a package that does the same with a shorter dependency chain.
  • License. Ensure the license is compatible with how the project will be used, especially for commercial applications.

npm's own documentation advises users to consider package information, including provenance if available, when selecting packages to download. However, this information still needs to be read as part of an audit, not as an automatic safety stamp.

Check What Runs During Installation

One often overlooked part is the lifecycle scripts. npm can run certain scripts when a package is installed, updated, or built. Such scripts are useful for compiling native modules, but they also mean there is code running on the developer's machine or build server.

To see the contents of a package before installing it, take a more cautious approach. For example, download the metadata or view the package.json file from the registry page and its repository. Pay attention to sections like:

{
  "scripts": {
    "preinstall": "...",
    "install": "...",
    "postinstall": "..."
  }
}

The presence of postinstall is not proof that the package is malicious. Many modules use it for legitimate needs. The questions to ask are: why is that script needed, what does it run, and does the project actually require that package?

For projects that do not need installation scripts, teams can evaluate options like npm install --ignore-scripts. However, this option should be tested because some packages do rely on those scripts to complete the build process. Good security does not stop at disabling features; changes must also be tested to avoid creating hidden damage.

Use Lockfiles and Traceable Versions

Files like package-lock.json, yarn.lock, or pnpm-lock.yaml record the concrete versions and sources of packages used by the project. Without a lockfile, installations on developers' laptops and CI servers can yield different version combinations.

Lockfiles are not a guarantee that all code is safe. Their function is simpler and more important: to make installation results repeatable and changes easier to review. If a dependency changes version, that change is visible in a pull request, rather than appearing silently during deployment.

For automated builds, use commands that respect the lockfile, such as npm ci on npm projects. After that, review dependency changes like you would review regular code changes. Ask whether the updates are indeed necessary, whether there are breaking changes, and whether transitive packages—dependencies pulled in by other packages—are also changing.

Provenance Helps Answer “Where Did This Package Come From?”

Provenance is information that links published packages to the source code, commits, and build processes that produced those packages. npm provides provenance information for certain packages and offers the npm audit signatures command to check registry signatures and available attestations.

This information is useful when we want to ensure that a package was indeed built from verifiable sources and published by an authoritative party. But there is an important limitation: provenance does not prove that the contents of the package are free from malicious code. It helps answer the origins and creation process, not replace audits of the code and its behavior.

Provenance answers “built from where and by whom,” not “guaranteed safe for all uses.”

Add Automated Checks in Pull Requests

Manual checks are important, but they can easily be overlooked when teams are racing against deadlines. For projects managed on GitHub, the Dependency Review Action can check dependency changes in pull requests and reject changes based on the severity of vulnerabilities or license rules.

A simple workflow example can be placed in .github/workflows/dependency-review.yml:

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@v4
        with:
          fail-on-severity: high

The version numbers of actions and configurations need to be adjusted according to the official documentation and project policies. The goal is not to block all updates but to make risky changes visible before they enter the main branch.

Practical Checklist Before Adding a Package

  1. Write down the reasons why the package is needed and what feature it will replace.
  2. Ensure the package name, repository, owner, and documentation are consistent.
  3. Check releases, open issues, maintenance activity, and its license.
  4. Look at installation scripts and their transitive dependencies.
  5. Install the version recorded in the lockfile and review the resulting changes.
  6. Check provenance or signatures if available.
  7. Run vulnerability scans regularly, not just once during installation.
  8. Remove dependencies that are no longer used. Unnecessary components still add to maintenance overhead.

What Does This Mean for Us?

Dependency security is not a reason to stop using open source. In fact, because open source has become an essential part of almost all modern applications, the selection process needs to be made more disciplined.

For personal projects, simply start with the habit of checking repositories, reading package.json, using lockfiles, and avoiding installing packages just because their names are similar to internet recommendations. For teams, add automated checks in pull requests and designate who is responsible for reviewing updates.

The ultimate goal is not to make every developer a security auditor. The aim is to transform npm install from a reflexive action into a technical decision that has reasoning, traceability, and clear risk boundaries.

Sources & Further Reading

– Rio Yotto @rioyotto