Corp-Check

screenshots

Use Corp-Check to identify risks in packages you’d like to include into your precious code. Define rule sets in your build process to prohibit dangerous packages jeopardizing your module and to get warning messages about potentially risky includes.

Understand which included modules might cause trouble in the future, create an overall report about your whole product.

Corp-Check will analyze included packages and dependencies for licensing, versioning and popularity risks. A hidden GPLv2 license might destroy your business. An unreleased alpha version might change so drastically in days that your whole product crashes. An abandoned package might cause serious support troubles just weeks after releasing your software.

Rules

Command Line Interface

npm install corp-check-cli

If you want to use Corp-Check for more than just as a web tool to check packages for risks, you can integrate the CLI module into your build and deployment process to actually prohibit the deployment of risky packages.

The CLI will use the ruleset you define and stop if it encounters a viral license, an unreleased package or an abandoned package will tons of open issues.

Motivation

The Node package management has unpredictable dangers. These dangers mostly stem from that the developers of the packages do not provide proper maintenance. Sometimes they do not keep the versioning rules, and a package might break below a minor or patch upgrade. These troubles are unpredictable, but the probability of that is mostly predictable. For example, if you rely on a package that is never released above 1.0, you probably use a beta version or the maintainer is not enough prudent, and you can not expect a proper maintenance in the future. Popularity should be treated in the same way, which may be a guarantee of the quality.

Even the license should be handled with care, which one is should be a barrier factor to use a package. Notice that not only the direct dependency can carry a breaking license. We also should keep in mind its dependencies license information.

Concept

The principal creed should be:

Every module is just as weak as its weakest dependency

This statement is true likewise for every application, every service, etc.

Corp-Check provides an open-source solution for these problems above. Corp-Check validates a given NPM module or a package.json including dependencies in its entire depth. It has two available interfaces for use:

The basic process

The most appropriate way to checking is installing the examined package with NPM in a working directory, and then discovering the dependencies one by one. Corp-Check installs the dependencies deeply instead of flatly. This way we can keep hereafter the hierarchical information. Thereafter Corp-Check collects the most information about dependencies, which is possible: version, license, etc.

NPM keeps tracking popularity, quality and maintenance attributes in its registry. Corp-Check fetches all of these data and compiles an info packet. This packet is a complete, raw and serializable description about the root package and its dependencies.

This processes above is performed by worker services in isolated docker containers. After this, the worker clears its working directory completely.

Evaluation

Evaluation works in a bit similar recursive way like collecting. Evaluations are made by evaluators. Evaluators are functional separated modules Those can return descriptive ERROR, WARNING and INFO logs for every package in the dependency hierarchy.

Besides evaluators also give a numeric score [0..1], even every package in the hierarchy. These numeric scores will form the final score of the root package. Zero is the worst score, and 1 is the best that can be given, and any intermediate decimal numbers are also accepted.

Every package in the hierarchy has a local final score that are formed by the following method:

score-equation

First the scores - given by the evaluators - are multiplied to each other. That makes the self-score of a package. The final score is made by taking the minimum of the self-score and the root squares of its first direct dependencies' final score. In the equation, A is a free parameter. This makes the method tunable. For now, fix it to 1.

As we can see this scoring algorithm is a recursive algorithm, which has some important considered aspect:

  1. The final score of the root package is also formed by this equation. This is the final score of the entire evaluation.
  2. The root square performs a weakening effect upwards the dependency hierarchy. That increases the dependencies' final score a bit if they are between 0 and 1.
  3. If any evaluator gives 0 score, then the root final score will also be 0.

Notice, that the 0 is a special score. This value is reserved for the errors.

Qualification

Corp-Check gives a nominal qualification for the examined root package. This is determined by the root final score:

  • RECOMMENDED - if the root final score is greater than 0.5
  • ACCEPTED - if the root final score is less then 0.5 and greater than 0
  • REJECTED - if the root final score is 0

Evaluation example

Assume that we have the following dependency hierarchy:

hierarchy

For now, we have the following evaluators:

  • License - checks the license validity for every package
  • Version - checks the version validity for every package
  • Attribute - judges every package by popularity (p), quality (q) and maintenance (m)

And they give the following scores:

A B C D
License score 1 1 1 0
Version score 1 0.5 1 1
Attribute score 0.4 0.3 0.6 0.7

Then the self-score of D is 0 × 1 × 0.7 = 0. Its final score is the same because it does not have any dependency. The self-score of C is 0.6, but its final score is 0, because the minimum of 0.6 and √0 is 0. By following this line of thought we can consider that A also takes zero as the final score. Notice, that the final score of A is the root final score.

We can imagine the zero score as a poison, which kills the entire tree.

zero-effect

The attribute score

NPM gives popularity, quality and maintance attributes for the packages. The Attribute evaluator makes its score by their weighted sum:

npm-scores

Rules of evaluation

The evaluators are tunable by rules. Every evaluator has an own rule configuration, and the collection of these rule configurations form the ruleset within a .json file.

Corp-Check has a corporate ruleset, which is used by default. You can override and modify the primary behavior of Corp-Check evaluations by any slice of these rules. For example, you can specify your preferred licenses in your evaluation, the weight of the attributes of packages, or you can entirely turn off errors by version check. This way you can define your own rules for your project or for your whole company.

Caching

Already we met some primary entities, like:

  • PACKAGE INFO - The collected info about packages after installation. This is a recursive data structure.
  • EVALUATION - This is also a recursive data structure about the evaluation result including every score and logs about the package and its all dependencies.
  • RULESET - The configuration of evaluation.

Corp-Check services are keeping in the cache, the package info and the related evaluations with its ruleset. This makes it possible, that for creating another evaluation with a different ruleset, Corp-Check does not need to collect again the package info. But running twice the same evaluation with the same ruleset provides the same evaluation from the cache.

Of course, cache has the expiration, which ensures, that upgrading deeply nested dependencies can cause change for the complete evaluation, similar to changing the popularity or any other attributes.

Notice, that the cache is bounded to a specified version of an NPM module.

The Corp-Check services have two emphatic expiration timeout:

  • The package attribute values from NPM are cached for a week.
  • An evaluation tied to a specified version and ruleset are cached for 30 days.

Rule configuration

Corp-Check evaluations are made by evaluators. Evaluators are functional separated modules that can return error, warning and info logs, and can give sub-scores to the package. These sub-scores are multiplied to each other, and these multiplied scores constitute the final score of the evaluated package including its dependencies' scores.

Every evaluator is configurable by their rules. They make the entire ruleset. The ruleset is defined in json format:

{
  [evaluatorName]: {
    ... evaluator rules ...
  }
}

Evaluators

License rules

This defines the ruleset of license validation. If there's a not allowed license in any of the dependencies, it yields an error.

The property set is:

  • include: string[] - Defines allowed licenses.
  • exclude: string[] - Unallows specified licenses.
  • licenseRequired: boolean - If true and no license is found in the package, the evaluator throws an error.
  • depth: number - Determines the depth of the evaluation. 0 is the package itself, 1 means the first dependencies, etc. Set it null to interpret as infinity.

Example:

{
  "license": {
    "include": ["MIT"],
    "exclude": ["GPL-2.0"],
    "licenseRequired": true,
    "depth": 3
  }
}

Version rules

This performs the version validation. If an unreleased package is found in the first dependencies it yields an error; while it only sends a warning if it was found in a deeper dependency.

The property set is:

  • minVersion: string[] - Defines the minimum accepted version that is required in a package.
  • isRigorous: boolean - If true, the evaluator yields an error if a package was found with version number less than minVersion.
  • rigorousDepth: number - Determines how rigorous the validation is. 0 means it's only the package itself, 1 means it also inspect the first dependencies, and so on.
  • retributionScore: number - This score is given to the package which is below the minVersion, if the checking is not rigorous.

Example:

{
  "version": {
    "minVersion": "1.0.0",
    "isRigorous": true,
    "rigorousDepth": 1,
    "retributionScore": 0.5
  }
}

NpmScores rules

This provides the popularity, quality and maintenance scores. The final value of the npmScores is calculated using weighted average.

The property set is:

  • qualityWeight: number
  • popularityWeight: number
  • maintenanceWeight: number

Example:

{
  "npmScores": {
    "qualityWeight": 1,
    "popularityWeight": 0.7,
    "maintenanceWeight": 0.5
  }
}

The default corporate ruleset

Find here.

Notes

Keen-eyed developers will realize that some of the dependencies of Corp-Check CLI yield warnings. Thankfully, it happens because of version checks, not licensing ones. This clearly show that while our open-source world is far from being ideal, each and every one of us make what we can to establish a transparent and clear ecosystem. To avoid any problems, Corp-Check CLI still passes the check when you use corp-check-cli as a dependency.

Corp-Check CLI

If you want to use Corp-Check for more than just as a web tool to check packages for risks, you can integrate the CLI module into your build and deployment process to actually prohibit the deployment of risky packages. The CLI will use the ruleset you define and stop if it encounters a viral license, an unreleased package or an abandoned package will tons of open issues.

Install

Install to global using npm:

npm install -g corp-check-cli

Install to project using npm:

npm install --save-dev corp-check-cli

Usage

Validate npm package

You can identify risks in published npm packages with the corp-check npm <package> CLI command. It will let you know how risky the package it is for your project.

corp-check npm express

Validate project

You can create a report about your product (using your package.json) with corp-check <path-to-local-source>. Also you can use your package-lock.json with the --package-lock option. Using the --prod argument will exclude the devDependencies from the validation

corp-check . --package-lock --prod

Npm script

Define your script for corp-check project validation

{
    "scripts": {
        "corp-check": "corp-check ."
    }
}

and you can run with npm

npm run corp-check

Validation rules

Just create a corp-check-rules.json in your project root and you can override the default evaluation rules. With the --rule-set <path> option you can have more custom rules.

corp-check . --rule-set ./my-rules.json

If you want to validate an npm package using your custom rules, you have to enable the --rule-set option

corp-check npm express --rule-set ./my-rules.json

You can read more about custom rules here

Options

    -V, --version             output the version number
    --force, -f               force validation
    --verbose, -v             list all warnings
    --rule-set <ruleSetJson>  validation rule set, default: ./corp-check-rules.json
    --log-level <logLevel>    winston log level, default: warn
    --prod                    skip devDependencies
    --package-lock            use package-lock.json file
    -h, --help                output usage information

Notes

Keen-eyed developers will realize that some of the dependencies of Corp-Check CLI yield warnings. Thankfully, it happens because of version checks, not licensing ones. This clearly show that while our open-source world is far from being ideal, each and every one of us make what we can to establish a transparent and clear ecosystem. To avoid any problems, Corp-Check CLI still passes the check when you use corp-check-cli as a dependency.

Badges

Show the world that your package passes the Corp-Check tests! By putting the "recommended" badge in your package README, you can notify developers that it is safe to use your module: it has proper licensing, it is actually released and you care about its popularity.

How to use

This is an example Recommended Badge for Repatch corp-check status

[![corp-check status](https://api.corp-check.corpjs.com/badge?name=repatch)](https://corp-check.corpjs.com/result?name=repatch)

This is an Accepted sample Badge, meaning warnings have been found but no serious issues: corp-check status

This is how a Rejected sample Badge looks like: corp-check status

Api endpoint for badges:

https://api.corp-check.corpjs.com/badge?name=repatch

Url for the Corp-Check result:

https://corp-check.corpjs.com/result?name=repatch

Usable query parameters

  • scope
  • name
  • version (badge for specific version of module)
https://corp-check.corpjs.com/result?scope=types&name=node&version=8.0.49
https://api.corp-check.corpjs.com/badge?scope=types&name=node&version=8.0.49