Strengthening Dependency Security: Best Practices for Vulnerability Scanning, Automatic Updates, and OSS License Management

  • github
    github
  • slack
    slack
  • nodejs
    nodejs
  • snyk
    snyk
Published on 2024/01/29

Introduction

In recent years, the use of OSS (open-source software) has expanded rapidly and has become indispensable for improving development efficiency. However, it is also true that incorporating external libraries introduces risks such as vulnerabilities and license violations.
In particular, leaving packages that contain vulnerabilities unattended can threaten the security of the entire project, so proper management is required.

This article focuses on the following points and explains how to improve the security of your project:

  • Introducing automatic scanning with Snyk / Dependabot (regular vulnerability checks)
  • Identifying vulnerabilities in existing packages and proposing updates
  • Designing an appropriate version management strategy for libraries in use
  • Setting up alert notifications for packages containing critical vulnerabilities (Slack / Teams integration)
  • Using npm audit / yarn audit / pnpm audit and creating reports
  • Reducing unnecessary package dependencies to lower attack risk
  • Proper management of OSS licenses (checking for license violations)
  • Checking EOL (End of Life) for libraries used in existing projects
  • Defining security evaluation criteria for newly introduced packages

1. Introducing Automatic Scanning with Snyk / Dependabot

Snyk and Dependabot are tools that automatically detect and fix vulnerabilities in dependencies. By using these tools, you can improve application security and minimize the impact of vulnerabilities.

Introducing and Using Snyk

Snyk is a SaaS-based security tool that scans for vulnerabilities in dependencies and proposes fixes. By integrating it with GitHub, GitLab, etc., you can automatically create pull requests for fixes and greatly reduce the time required for remediation.

Steps

  1. Create a Snyk account and integrate it with GitHub / GitLab / Bitbucket, etc.
  2. Scan the repository and detect vulnerabilities in existing dependencies
  3. Use snyk monitor to run scans regularly
  4. Integrate with CI/CD to automatically run scans at build time

Example) Add to GitHub Actions

name: Snyk Security Scan
on: push
jobs:
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run Snyk Test
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

Steps to Introduce Dependabot

  1. Basic Dependabot features (enable from the GitHub settings screen)

This is provided as “Security updates” and can be easily enabled from the GitHub repository settings.

  • Go to the GitHub repository
  • Settings → Security → Code security and analysis
  • Enable "Dependabot security updates" ✅
    • This integrates with GitHub Security Advisories, and when a critical vulnerability is found in existing dependencies, a PR is automatically created.
  1. Detailed update management using Dependabot’s dependabot.yml

Security updates alone are not suitable for the use case of “automatically updating when a new version is released.” By using .github/dependabot.yml, you can regularly check dependencies and create PRs even when there are no vulnerabilities.

version: 2
updates:
  - package-ecosystem: "npm"  # For npm (also supports yarn, pip, maven, etc.)
    directory: "/"            # Root directory
    schedule:
      interval: "weekly"      # Check weekly (daily, monthly also possible)
    open-pull-requests-limit: 5  # Open up to 5 PRs

2. Identifying Vulnerabilities in Existing Packages and Proposing Updates

Vulnerability scanning for dependencies in a repository can be automated using tools such as Snyk and Dependabot. This allows you to obtain the following information and quickly proceed with vulnerability remediation:

  1. How scanning works
    Snyk and Dependabot analyze package.json and yarn.lock (or package-lock.json) in the repository and check the versions of the libraries you depend on.
    These tools compare against vulnerability databases (CVE, GitHub Advisory Database, etc.) and provide information such as:
  • Known vulnerabilities in dependent packages
  • Affected files or modules
  • Severity: Low / Medium / High / Critical
  • Recommended versions that fix the issue
  • Scope of impact (direct dependency / transitive dependency)
  1. Response flow for the development team
    Running scans
  • Regularly check snyk test and GitHub Dependabot Alerts

    • Integrate scans into the CI/CD pipeline
  • Check the scope of impact

    • Confirm whether it is a direct dependency or a dependency via another library
    • Prioritize items with Critical / High severity
  • Perform updates

    • If possible, update to the recommended version (yarn upgrade / npm update, etc.)
    • Test for compatibility issues
    • Apply changes to the release
  • Continue monitoring

    • Continue regular scans (integrated into CI/CD)
    • Watch vulnerability information (Snyk and GitHub Security Advisories)

Designing an Appropriate Version Management Strategy for Libraries in Use

An appropriate version management strategy for libraries is essential to maintaining project stability and security. The following points are explained in detail.

  1. Understanding and applying Semantic Versioning (SemVer)
    Semantic Versioning (SemVer) is a common rule for library version management. Applying it properly helps minimize the impact of updates.
  • Managed in the format MAJOR.MINOR.PATCH
    • MAJOR: Increased when there are breaking (incompatible) changes
    • MINOR: Increased when new features are added in a backward-compatible way
    • PATCH: Increased for bug fixes (fixes to existing functionality only)
  • Consider the impact of updates
    • ^1.2.3 (caret): Updatable within the 1.x.x range (will not update to 2.0.0)
    • ~1.2.3 (tilde): Updatable within the 1.2.x range (will not update to 1.3.0)
    • 1.2.3 (exact): Use only the specified version
  • Operational examples
    • Carefully consider MAJOR version upgrades when updating libraries
    • Use ^ for dependencies and ~ for devDependencies in package.json to reduce changes in the development environment
  1. Use lock files (package-lock.json / yarn.lock)
    By using lock files, you can achieve consistent version management when installing in different environments.
  • package-lock.json (npm) / yarn.lock (Yarn) record the exact versions of each dependency
  • In team development, commit the lock file to Git to maintain unified versions

Operational examples

  • In CI/CD environments, use npm ci or yarn install --frozen-lockfile to reproduce fixed versions
  • During review, check that the lock file does not contain unintended changes
  1. Regular update checks
    If you neglect library updates, security vulnerabilities and bugs may affect your project. Regular update checks are important.

Automatic checks using tools

  • Dependabot (GitHub): Automatically detects updates to package.json and creates pull requests
  • Snyk: Scans vulnerabilities in dependent libraries and proposes countermeasures
  1. Understand changelogs
    Library updates may introduce API specification changes or incompatibilities. Get into the habit of checking the changelog before updating.
  • Check CHANGELOG.md / GitHub Releases / npm release notes
  • Pay particular attention to major version upgrades (check the impact of breaking changes)
  • Be cautious with versions tagged as canary or beta

Operational examples

  • Test large updates in a separate branch and verify compatibility
  • For updates with a large impact, check issues and documentation in advance and apply them in stages

Setting Alert Notifications for Packages Containing Critical Vulnerabilities (Slack / Teams Integration)

To enable immediate response when vulnerabilities are detected, configure notifications to Slack or Microsoft Teams.

Setting Slack notifications in Snyk

  1. From the Snyk dashboard, go to Integrations
  2. Select Slack and connect your workspace
  3. Configure notification triggers (e.g., High / Critical vulnerabilities)
  4. Confirm that notifications are sent to the specified channel

Notifications via GitHub Actions for Dependabot

  1. Set assignees and reviewers in dependabot.yml
  2. Configure a GitHub Actions workflow with the on: pull_request trigger
  3. Use slack-notify-action to send a notification when a PR is created

This improves the speed from vulnerability discovery to remediation.

Using npm audit / yarn audit / pnpm audit and Creating Reports

How to use npm audit

npm audit analyzes package-lock.json and checks for known security issues.

npm audit

When you run this command, it lists affected packages, vulnerability severity (low, moderate, high, critical), scope of impact, and possible remediation methods.

Automatically fixing vulnerabilities

  • Apply only low-impact updates (compatible updates only)
npm audit fix
  • Force major version upgrades (risky but suitable for immediate resolution)
npm audit fix --force

By running npm audit in your CI/CD pipeline, you can perform continuous security audits.

npm audit --json > audit-report.json

You can parse this JSON report and build a mechanism to raise alerts when security issues occur.

How to use yarn audit

  • Basic usage
    If you are using Yarn, it audits dependencies based on yarn.lock.
yarn audit
  • Outputting a JSON report
    Yarn can also output audit results in JSON format for use in CI/CD.
yarn audit --json > audit-report.json
  • Failing on issues above a certain severity
    You can fail the process when vulnerabilities of a specified level (low / moderate / high / critical) or higher are detected.
yarn audit --level critical

How to use pnpm audit

  • Basic usage
    pnpm audit also performs security checks on dependencies, similar to npm and yarn.
pnpm audit
  • Outputting a JSON report
    You can use this when you want to save and monitor audit results in CI/CD.
pnpm audit --json > audit-report.json
  • Failing the process in CI/CD
    You can use error handling to fail the build when specific vulnerabilities are detected.
pnpm audit --json > audit-report.json || exit 1

Example of automatic auditing in CI/CD

Here is how to use GitHub Actions to run npm audit regularly and send alerts when vulnerabilities are detected.

name: Security Audit

on:
  schedule:
    - cron: '0 0 * * *' # Run every day at 00:00

jobs:
  security-audit:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Install dependencies
        run: npm ci

      - name: Run npm audit
        run: npm audit --json > audit-report.json || exit 1

      - name: Upload audit report
        uses: actions/upload-artifact@v3
        with:
          name: audit-report
          path: audit-report.json

In this configuration, npm audit runs daily, and the GitHub Actions job is set to fail when vulnerabilities are present.

Reducing Unnecessary Dependencies and Lowering Attack Risk

Dependency management is extremely important both from a security perspective and from a project maintenance perspective. Removing unnecessary dependencies provides the following benefits:

Risks of unnecessary dependencies

  • Security risks
    • Dependent packages may contain vulnerabilities
    • The deeper the dependency tree, the higher the chance of including vulnerable versions
    • There is a risk of supply chain attacks (e.g., developer account hijacking) introducing malicious code
  • Increased management costs
    • Package updates and maintenance become more complex
    • An increase in unused packages can negatively affect build time and application performance
    • Dependency conflicts are more likely, increasing debugging costs

How to identify unnecessary dependencies

depcheck is a tool that can identify dependencies that are actually not used in the project.

npx depcheck

When run, it detects the following:

  • Unused dependencies (unused in dependencies)
  • Unused devDependencies (unused in devDependencies)
  • Missing dependencies (dependencies not found)

To manually remove unnecessary dependencies:

npm uninstall <package>

or

yarn remove <package>

Optimizing dependencies

You can optimize the package structure by consolidating duplicate packages.

npm dedupe

Proper Management of OSS Licenses

Proper management of OSS (open-source software) licenses is important for safely using OSS in commercial projects while avoiding legal risks. Details are as follows.

Importance of OSS license management

When using OSS in commercial projects, you need to check the following points:

  • License compatibility
    • Whether the license is allowed for use in your project (e.g., MIT and Apache-2.0 allow commercial use, while GPL-3.0 has strong restrictions)
    • Obligations required by each license (e.g., credit display, obligation to disclose source code)
  • Avoiding license violation risks
    • Violating OSS licenses may result in legal action
    • GPL (GNU General Public License) in particular requires source code disclosure, so it needs special attention
  • Tracking license changes and updates
    • Licenses may change when OSS is updated
    • Regular audits are required

Using npm-license-crawler

npm-license-crawler is a tool that retrieves license information for all packages in node_modules and outputs it in CSV or JSON format.

It has the following characteristics:

  • Fewer deprecation warnings about dependencies than license-checker
  • Easy to output results in JSON or CSV format
  • Can filter by specified licenses
  • Suitable for license audits in CI/CD

Display licenses for all packages

npx npm-license-crawler

Example (output image):

└─ zod@3.23.8
   ├─ licenses: MIT
   ├─ repository: https://github.com/colinhacks/zod
   ├─ licenseUrl: https://github.com/colinhacks/zod/raw/master/LICENSE
   └─ parents: exapmle

Get license information in JSON format

npx npm-license-crawler --json licenses.json

Example (output image):

"zod@3.23.8": {
    "licenses": "MIT",
    "repository": "https://github.com/colinhacks/zod",
    "licenseUrl": "https://github.com/colinhacks/zod/raw/master/LICENSE",
    "parents": "example"
}

Get license information in CSV format

npx npm-license-crawler --csv licenses.csv

Example (output image):

"zod@3.23.8","MIT","https://github.com/colinhacks/zod","https://github.com/colinhacks/zod/raw/master/LICENSE","example"

Checking EOL (End of Life) for Existing Libraries

What is EOL (End of Life)?

EOL (End of Life) refers to the end of development and support for software or libraries. Libraries that have reached EOL carry the following risks:

  • Security risk: newly discovered vulnerabilities will not be fixed
  • Compatibility issues: may become incompatible with newer versions of Node.js or other libraries
  • No more feature additions: no new features or optimization updates

Check current and latest versions of packages in the project

This command lets you check the current and latest versions of packages in your project.

npm outdated

Example output

Package                      Current   Wanted   Latest  Location                                  
@hookform/resolvers            3.9.0   3.10.0    4.1.3  node_modules/@hookform/resolvers          
@types/react                 18.3.11  18.3.18  19.0.10  node_modules/@types/react                 
@types/react-dom              18.3.1   18.3.5   19.0.4  node_modules/@types/react-dom             
class-variance-authority       0.7.0    0.7.1    0.7.1  node_modules/class-variance-authority     
eslint                        8.57.1   8.57.1   9.21.0  node_modules/eslint                       
eslint-config-prettier         9.1.0    9.1.0   10.0.2  node_modules/eslint-config-prettier       
eslint-plugin-prettier         5.2.1    5.2.3    5.2.3  node_modules/eslint-plugin-prettier       
eslint-plugin-tailwindcss     3.17.5   3.18.0   3.18.0  node_modules/eslint-plugin-tailwindcss    
postcss                       8.4.47    8.5.3    8.5.3  node_modules/postcss                      
prettier-plugin-tailwindcss    0.6.8   0.6.11   0.6.11  node_modules/prettier-plugin-tailwindcss  
react                         18.3.1   18.3.1   19.0.0  node_modules/react                        
react-dom                     18.3.1   18.3.1   19.0.0  node_modules/react-dom                    
react-hook-form               7.53.1   7.54.2   7.54.2  node_modules/react-hook-form              
tailwind-merge                 2.5.4    2.6.0    3.0.2  node_modules/tailwind-merge               
tailwindcss                   3.4.14   3.4.17    4.0.9  node_modules/tailwindcss                  
typescript                     5.4.3    5.4.3    5.8.2  node_modules/typescript                   
zod                           3.23.8   3.24.2   3.24.2  node_modules/zod                          

Meaning of each column

  • Current (currently installed version)
  • Wanted (latest version installable within the range in package.json)
  • Latest (latest version available in the registry)

When you see results like the above, you need to take actions such as the following:

  • Minor version updates

    • Run npm update (automatically updates up to the Wanted version)
    • Since the likelihood of breaking changes is low, it is generally safe to apply
  • Major version updates (with caution)

    • react, react-dom, and tailwindcss have major updates, so check the changes
    • Investigate the scope of impact, and if you decide to update, run npx npm-check-updates -u to update package.json, then npm install

How to check if something is EOL

npm outdated and npm-check-updates alone cannot determine whether a library is EOL. Use a combination of the following methods:

  1. Check official documentation and release notes
    Check the library’s official site or GitHub release notes for any “EOL” announcements.

Example: React release notes

https://github.com/facebook/react/releases

Example: Node.js EOL schedule

https://nodejs.org/en/about/releases/

  1. Check activity on the GitHub repository

You can check whether it is being maintained by looking at the commit history and issues on GitHub.

  • Last commit was more than a year ago
  • Issues are left unresolved
  • There is a note such as “This project is no longer maintained”

If you see such signs, the library is likely EOL.

  1. Use npm trends or Libraries.io for investigation
    You can also use tools that show library trends and update frequency.
  • npm trends (compare package popularity)

https://npmtrends.com/

  • Libraries.io (check EOL and update frequency)

https://libraries.io/

What to do with EOL libraries

Consider the following measures when you find a library that has reached EOL.

  1. Check for recommended libraries
    If an official replacement library is recommended, consider migrating to that library.

Example)
moment.js (EOL) → date-fns or luxon

  1. Look for a maintained fork
    For popular libraries, there may be maintained forks. Check the GitHub repository for active forks.

  2. If you absolutely cannot update
    Use npm audit to identify the impact of vulnerabilities and apply manual patches if necessary
    Use package-lock.json to pin problematic versions and limit the scope of impact

Defining Security Evaluation Criteria for Newly Introduced Packages

When introducing new OSS packages, considering the following points can improve safety.

Maintenance status

To ensure the security and quality of an OSS package, it is important that it is properly maintained. Checking the following points helps you decide whether you can use it with confidence.

  • Last updated date
    • Check the last commit in the GitHub repository.
    • If it has not been updated for more than a year, maintenance may have stopped.
  • Status of issues and pull requests
    • Check the Issues tab to see if critical bugs are left unresolved.
    • Check the merge speed of pull requests to see if development is active.
  • Activity of maintainers
    • Check whether core developers are committing regularly.
    • If major maintainers have left, see whether new developers have taken over.

Download count

Packages with many users are more likely to have been thoroughly vetted by the community and may be relatively safe.

  • npm trends

    • With npm trends, you can compare the popularity of multiple packages.
    • Compare with competing packages to make an appropriate choice.
  • npm-stat

    • Use npm-stat to check download counts over a specific period.
    • Also check that there has not been a sudden drop in downloads.

Example) Download trend for React from 2020 to 2024.
Downloads are steadily increasing, so it can be considered a healthy package.

Image from Gyazo

Known vulnerabilities

Before introducing a package, run a security scan to check for known vulnerabilities.

  • npm audit
  • GitHub Dependabot
  • Snyk

Conclusion

When using OSS packages, it is not enough to simply install them; continuous security checks and proper management are essential.
By adopting the automatic scanning with Snyk / Dependabot and the use of npm audit / yarn audit introduced here, you can prevent vulnerabilities in advance and maintain a secure development environment.

In addition, thorough EOL checks and license management for libraries are also important points.
Introducing regular audits and alert notification mechanisms and raising security awareness across the team will lead to long-term stable operations.

To achieve a secure development environment, start implementing the measures you can apply right away.

Xでシェア
Facebookでシェア
LinkedInでシェア

Questions about this article 📝

If you have any questions or feedback about the content, please feel free to contact us.
Go to inquiry form