Git Product home page Git Product logo

lockfile-lint's Introduction

lockfile linting ๐ŸŒˆ

lint lockfiles for improved security and trust policies

main codecov license Security Responsible Disclosure npx lockfile-lint

About

Lockfiles are used as trusted whitelist of resources manifest to fetch packages from. However, keeping track of the changes introduced to lockfiles is not an easy task as they are designed to be consumed by machines ๐Ÿค–.

What happens when someone creates a Pull Request and sneaks a malicious resource package that replaces a real library? ๐Ÿ˜ฑ

Exactly! Lint your lockfiles to ensure they adhere to pre-defined security policies and mitigate this vector of attack.

Why is this important? read: Why npm lockfiles can be a security blindspot for injecting malicious modules

Usage

Easily invoked with npx on any project and lint it:

npx lockfile-lint --path yarn.lock --allowed-hosts npm yarn --validate-https

To lint the npm-shrinkwrap.json file, add the --type npm flag:

npx lockfile-lint --path npm-shrinkwrap.json --type npm --allowed-hosts npm yarn --validate-https

If you get no results, congratulations, the file passes!

If lockfile-lint detects exceptions to the policies it will report them:

carbon

Refer to lockfile-lint for more details on the CLI usage.

You can use lockfile-lint as a standalone CLI tool, or as an API library using the following npm packages:

  • lockfile-lint - a CLI tool that can be easily integrated as a pre-commit hook or part of a CI/build
  • lockfile-lint-api - a library providing a programmatic API

Security Disclaimer

Please be advised of the following security disclaimers that are outside of the control of a lockfile linter:

When you whitelist all hosts from npmjs, yarnpkg, github or other registries you implicitly convey that you trust all the packages originating from these sources. As such, a malicious package can exist in a registry source that you whitelist. Direct dependencies that you should add to a project should be well vetted before adding such as using a tool like npq.

References

FAQ

What about pnpm support?

pnpm doesn't maintain the tarball source of an npm package so unlike yarn, and npm, there's no way to inject an attacker-controlled malicious source file in pnpm-lock.yaml. Other vectors that were explored were to inject new packages into the lockfile (that aren't in package.json) yet pnpm isn't prone to these malicious attempts and would not install them.

If you have witnessed a possible attack vector on pnpm's lockfile, please open an issue with reproducible steps.

How is this different from npm audit?

npm audit is a tool to audit your dependencies for known vulnerabilities. However, it doesn't address the issue of malicious packages being injected into your lockfile. lockfile-lint is a tool that is designed to address this issue.

Author

lockfile-lint ยฉ Liran Tal, Released under the Apache-2.0 License.

lockfile-lint's People

Contributors

abdulhannanali avatar achrinza avatar atgardner avatar bolatovumar avatar drazisil avatar emimuresan avatar ericcornelissen avatar ethankore avatar github-actions[bot] avatar jaanjah avatar jamessingleton avatar jerone avatar jonchurch avatar juanpicado avatar julienw avatar lirantal avatar mathieuaa avatar matthias-ccri avatar mtlewis avatar naugtur avatar pratik97 avatar rheimus avatar richsilv avatar salesh avatar snyk-bot avatar travi avatar xhmikosr avatar xiniria avatar yeikel avatar yoavain avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lockfile-lint's Issues

Exclude unneeded files from the npm packages

Right now the npm packages have many useless files, like _tests_, jsdocs.json and maybe more.

I could make a patch, but being I'm not familiar with your monorepo situation, maybe you should do it. Should be a fairly trivial change.

Bug: only one file checked

Expected Behavior

If there are multiple lockfiles like we use at zurb/foundation-sites, only one will be checked.

Current Behavior

Only one / first found lockfile is checked as it seems.

https://github.com/lirantal/lockfile-lint/blob/master/packages/lockfile-lint-api/src/ParseLockfile.js

Possible Solution

Test all found lockfiles.

Steps to Reproduce (for bugs)

Context

Hard to check all at once. Can be used to change two files and only inject URLs in the second.

Your Environment

  • Library Version used:
  • Node.js version (e.g. Node.js 5.4):
  • Operating System and version (desktop or mobile):

Extra check for incompatible options

Is your feature request related to a problem? Please describe.

#23 (comment)

> nodejs.org@ test:lint:lockfile C:\Users\xmr\Desktop\nodejs.org
> lockfile-lint --allowed-hosts npm github.com --allowed-schemes "https:" "git+https:" --empty-hostname false --validate-https --type npm --path package-lock.json

detected invalid protocol for package: metalsmith-permalinks@git+https://github.com/segmentio/metalsmith-permalinks.git#432843d5823a292b2e47397ba46fd761d03eb9d3
    expected: https:
    actual: git+https:

error: command failed with exit code 1

Describe the solution you'd like

Since the above works without the validate-https flag, maybe there should be some checks in place for potentially incompatible options.

Packages in local filesystem always yield errors when using -s (yarn)

Thanks for releasing this very important tool! There's one small issue preventing us from adopting it:

Expected Behavior

If you add a package from the local filesystem (e.g. yarn add path/to/my/package), an entry is created in yarn.lock corresponding to the package which has no resolved field. I would expect this package to be ignored by lockfile-lint (or at least to have a flag to ignore it), given that the code is already on the host machine, even when the user has specifically requested to validate protocol schemas (or whitelisted allowed schemes some other way).

Current Behavior

ABORTING lockfile lint process due to error exceptions 

Encountered error Invalid URL: undefined in package: "my-local-package@../my-local-package" 

TypeError [ERR_INVALID_URL]: Invalid URL: undefined
    at onParseError (internal/url.js:241:17)
    at new URL (internal/url.js:319:5)
    at ValidateHost.validate (/home/richard/.npm/_npx/31760/lib/node_modules/lockfile-lint/node_modules/lockfile-lint-api/src/validators/ValidateHost.js:30:30)
    at ValidateHostManager (/home/richard/.npm/_npx/31760/lib/node_modules/lockfile-lint/src/validators/index.js:43:20)
    at validators.forEach.validator (/home/richard/.npm/_npx/31760/lib/node_modules/lockfile-lint/src/main.js:35:28)
    at Array.forEach (<anonymous>)
    at Object.runValidators (/home/richard/.npm/_npx/31760/lib/node_modules/lockfile-lint/src/main.js:25:14)
    at Object.<anonymous> (/home/richard/.npm/_npx/31760/lib/node_modules/lockfile-lint/bin/lockfile-lint.js:31:17)
    at Module._compile (internal/modules/cjs/loader.js:778:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10) 

error: command failed with exit code 1 

Possible Solution

Skipping host validation for entries without a resolved field in ValidateHost.js would resolve this, but I'm not sure whether it's acceptable to do so other than behind a flag.

Steps to Reproduce (for bugs)

https://github.com/richsilv/lockfile-lint-bug-example/tree/master

Context

We have a single, common shared library required by a variety of different services, and we find it simpler to copy this package into the local filesystem and install from there when building containers than via a private or self-hosted registry. I can't imagine we're the only people doing this (although I'd be interested to know if I was wrong!). For all other, registry-sourced packages, we would certainly want to validate the protocol.

Your Environment

  • Library Version used: 3.0.5
  • Node.js version (e.g. Node.js 5.4): 10.16.2
  • Operating System and version (desktop or mobile): Ubuntu 18.04

File-based configuration

First off, thanks for this super useful tool.

Is your feature request related to a problem? Please describe.
Sharing lockfile-lint configuration is currently problematic, because the only way to configure it is via command-line arguments. If it were possible to store this configuration in a file, it would allow sharing that file amongst multiple repositories. It would also have the additional benefit of allowing commentary justifying the configuration choices made.

Describe the solution you'd like
The solution should probably use a third-party library for loading config, to allow loading config from multiple conventional sources without a bunch of work.

Describe alternatives you've considered
It would be possible to achieve a similar outcome by passing around scripts that wrap calls to lockfile-lint.

Pnpm support

Is your feature request related to a problem? Please describe.

Support for the @pnpm lockfile linting.

Describe the solution you'd like

I quickly looked over the source here and what I found is that it would be quite easy to add support and it could start from the lockfile-lint-api/src/ParseLockfile.js file.

We could probably use @pnpm/lockfile-file, but I don't see exposed api there for "parsing" there is only methods that accept the path to the lockfile. Here, we need the final "parsed" content of the file. /cc @zkochan

And yet, I'm not sure if that's the only place that changes are needed.

Describe alternatives you've considered

None.

Provide more verbose output on issues found

Is your feature request related to a problem? Please describe.
Currently when an issue is found during a linting script run the information provided on the error is pretty limited, such as:

ABORTING lockfile lint process due to error exceptions
Invalid URL: false
TypeError [ERR_INVALID_URL]: Invalid URL: false
    at onParseError (internal/url.js:240:17)
    at parse (internal/url.js:249:3)

Would be better to provide more verbose information on errors such as the actual package this was detected on and so on.

Check version is actually a proper semver version

This is in regards to my comment here: #53 (comment)

We should check that the version matches a semver version instead of something like file:../lockfile-lint/packages/lockfile-lint/lockfile-lint-3.0.8.tgz

Expected Behavior

lockfile-lint should check that the version is an actual semver version instead of something else.

Current Behavior

It is currently caught with the code in Master, however, with the changes that were required with #53 it will not longer be caught. The reason that it is currently caught is because resolved: depMetadata.resolved ? depMetadata.resolved : depMetadata.version. However, this caused an issue now that we truly go through all dependencies as not all dependencies have a resolved and doing new URL('1.0.0') results in an error from url itself.

Possible Solution

Create a new validator that checks for proper semver version. This would call for a regex pattern but currently eslint-plugin-security's detect-unsafe-regex flags all regex patterns for semver including the ones provided on semver's website.

Steps to Reproduce (for bugs)

  1. Check out the code in #53
  2. Make this line https://github.com/JamesSingleton/lockfile-lint/blob/bugfix/dependency-depth/packages/lockfile-lint-api/src/ParseLockfile.js#L132 resolved: depMetadata.resolved ? depMetadata.resolved : depMetadata.version
  3. In the 3 validator files remove the if statement that surrounds the try...catch...
if (packageMetadata.resolved) {
  try {
    packageResolvedURL = new URL(packageMetadata.resolved)
  } catch (error) {
    throw new PackageError(packageName, error)
  }
}
  1. npm pack lockfile-lint-api
  2. Install that tgx file into lockfile-lint
  3. npm pack lockfile-lint
  4. Install lockfile-lint into a repo
  5. Run lockfile-lint

Context

This will make sure that no locally installed .tgz files in the package-lock.json make it in.

Your Environment

  • Library Version used: ^3.0.8
  • Node.js version (e.g. Node.js 5.4): v12.14.0
  • Operating System and version (desktop or mobile): macOS Mojave v10.14.5

The tests fail because yargs detects the OS' locale

I can do a PR for the issue if you want.

Expected Behavior

The tests should pass when cloning & installing the project.

Current Behavior

They do not.
See:

  CLI tests
    โœ• Running without parameters should display help (94ms)
    โœ• Running without parameters should display a requirement for the p option (85ms)
    โœ• Linting a file that has wrong host should display an error message and use exit code 1 (76ms)
    โœ“ Linting a file that has wrong host should return exit code 1 (74ms)

  โ— CLI tests โ€บ Running without parameters should display help

    expect(received).not.toBe(expected) // Object.is equality

    Expected: not -1

      17 |       expect(output.indexOf('Usage:')).not.toBe(-1)
      18 |       expect(output.indexOf('Options:')).not.toBe(-1)
    > 19 |       expect(output.indexOf('Examples:')).not.toBe(-1)
         |                                               ^
      20 |       done()
      21 |     })
      22 |   })

      at Socket.toBe (__tests__/cli.test.js:19:47)

That's because my locale is set to the french one, and yargs translates the CLI output (at least some of it) (See https://github.com/yargs/yargs/blob/master/docs/api.md#detectlocaleboolean
Your tests rely on the fact that the user has an english locale.

See the output of the npx lockfile-lint -h command:

Usage: lockfile-lint --path <path-to-lockfile> --allowed-hosts yarn npm

Options:
  --version              Affiche le numรฉro de version                  [boolรฉen]
  --help, -h             Affiche de l'aide                             [boolรฉen]
  -p, --path             path to the lockfile     [chaine de caractรจre] [requis]
  -t, --type             lockfile type, options are "npm" or "yarn"
                                                           [chaine de caractรจre]
  -s, --validate-https   validates the use of HTTPS as protocol schema for all
                         resources                                     [boolรฉen]
  -e, --empty-hostname   allows empty hostnames, or set to false if you wish for
                         a stricter policy              [boolรฉen] [dรฉfaut: true]
  -a, --allowed-hosts    validates a whitelist of allowed hosts to be used for
                         resources in the lockfile                     [tableau]
  -o, --allowed-schemes  validates a whitelist of allowed schemes to be used for
                         resources in the lockfile                     [tableau]

Exemples:
  lockfile-lint --path yarn.lock --validate-https
  lockfile-lint --path yarn.lock --validate-https --allowed-hosts npm yarn
  verdaccio
  lockfile-lint --path yarn.lock --allowed-schemes "https:" "git+ssh:"
  --allowed-hosts npm yarn verdaccio

curated by Liran Tal at https://github.com/lirantal/lockfile-lint

Notice the Exemples string

Possible Solution

Adding

.detectLocale(false)

to the lockfile-lint/src.main.js file works.

Steps to Reproduce (for bugs)

Well, I don't know how to set my locale to another, but I guess https://www.tecmint.com/set-system-locales-in-linux/ should help

  1. Clone the project
  2. Install the dependencies
  3. Launch the tests

Context

I was trying to improve the output of the expected protocol; I've tried to analyze one of my project's lockfile and I was surprised at the output (I expected HTTPS, not https:, do you want to a PR for that?)

Your Environment

Ubuntu LTS, french locale

The output of the locale command.

LANG=fr_FR.UTF-8
LANGUAGE=
LC_CTYPE="fr_FR.UTF-8"
LC_NUMERIC="fr_FR.UTF-8"
LC_TIME="fr_FR.UTF-8"
LC_COLLATE="fr_FR.UTF-8"
LC_MONETARY="fr_FR.UTF-8"
LC_MESSAGES="fr_FR.UTF-8"
LC_PAPER="fr_FR.UTF-8"
LC_NAME="fr_FR.UTF-8"
LC_ADDRESS="fr_FR.UTF-8"
LC_TELEPHONE="fr_FR.UTF-8"
LC_MEASUREMENT="fr_FR.UTF-8"
LC_IDENTIFICATION="fr_FR.UTF-8"
LC_ALL=
  • Library Version used: master
  • Node.js version (e.g. Node.js 5.4): 10.16.3
  • Operating System and version (desktop or mobile): Ubuntu LTS

Example 3 from Readme does not work

Expected Behavior

Run examples given in Readme.

Current Behavior

Running example #3 from readme does not work, refers to CLI info. https://github.com/lirantal/lockfile-lint/tree/master/packages/lockfile-lint#example

 lockfile-lint --path yarn.lock --allowed-hosts yarn github.com --validate-https --allowed-schemes "https:" "git+https:"
Usage: lockfile-lint --path <path-to-lockfile> --allowed-hosts yarn npm

Options:
  --version              Show version number                           [boolean]
  --help, -h             Show help                                     [boolean]
  -p, --path             path to the lockfile                [string] [required]
  -t, --type             lockfile type, options are "npm" or "yarn"     [string]
  -s, --validate-https   validates the use of HTTPS as protocol schema for all
                         resources                                     [boolean]
  -e, --empty-hostname   allows empty hostnames, or set to false if you wish for
                         a stricter policy             [boolean] [default: true]
  -a, --allowed-hosts    validates a whitelist of allowed hosts to be used for
                         resources in the lockfile                       [array]
  -o, --allowed-schemes  validates a whitelist of allowed schemes to be used for
                         resources in the lockfile                       [array]
  -u, --allowed-urls     validates a whitelist of allowed URLs to be used for
                         resources in the lockfile                       [array]

Examples:
  lockfile-lint --path yarn.lock --validate-https
  lockfile-lint --path yarn.lock --validate-https --allowed-hosts npm yarn
  verdaccio
  lockfile-lint --path yarn.lock --allowed-schemes "https:" "git+ssh:"
  --allowed-hosts npm yarn verdaccio

curated by Liran Tal at https://github.com/lirantal/lockfile-lint

Arguments o and validate-https are mutually exclusive

Steps to Reproduce (for bugs)

  1. lockfile-lint --path yarn.lock --allowed-hosts yarn github.com --validate-https --allowed-schemes "https:" "git+https:"

Context

Was just playing around with the CLI to see if we can integrate.

Your Environment

  • Library Version used: "4.2.2"
  • Node.js version (e.g. Node.js 5.4): 12.8.1
  • Operating System and version (desktop or mobile): MacOS Catalina

Question: possible false positives

I've read the article about this tool and at first all made sense.

Then, I've looked at the examples and realized that it's simple to trick it to report false positives.

I'll give two scenarios.

1. using the example from the article

  1. the hacker injects link to Github repository (as in the article)
  2. the application already has dependencies pointing to GH
  3. lockfile-lint is used with following options (this is the command taken from examples)
    lockfile-lint --path yarn.lock --allowed-hosts yarn github.com --validate-https --allowed-schemes "https:" "git+https:"
    
  4. lockfile-lint will not report any problems

2. Injecting malicious NPM package

  1. hacker creates a new malicious package (with some random name, it doesn't really matter)
  2. the package is published on NPM
  3. hacker injects link to this package in the lockfile
  4. lockfile-lint will not report any problems (the package is hosted by NPM so it should be fine)

Quick and dirty example of such you can find on followin Gist: https://gist.github.com/radmen/0e9ce8706343db28f68bc7ad97910ed3


By all means, I'm not a security expert. I just wanted to ask - are those scenarios possible? I find them highly possible and thus I think that this tool might give people false sense of security that everything works fine.

lockfile-lint-api@^5.1.3 not published

The version of `[email protected] that should have been published by this commit 12 days ago:
a939b5f

Does not appear to have been.

The new version of lockfile-lint that was published this morning depends on this version, and now fails to install - can you please check this, and publish the required version of lockfile-lint-api

Shrinkwrap has a typo

Expected Behavior

Users should be able to copy "shrinkwrap".

Current Behavior

People copy "shrinkwarp".

Possible Solution

Changing "shrinkwarp" to "shrinkwrap".

Steps to Reproduce (for bugs)

In a project that includes an npm-shrinkwrap.file, copy the npm-shrinkwrap.json example from README.md (npx lockfile-lint --path npm-shrinkwarp.json --type npm --allowed-hosts npm yarn --validate-https) and paste in your CLI.

Context

Not affected really, just trying to help.

Your Environment

Irrelevant.

resolved field change between v5.0.7 and v5.0.10 for API package

Updating to [email protected] the resolved metadata field doesn't always resolve to a URL or undefined (sometimes it's contains a package a version)

The following illustrates the issue:

import { ParseLockfile } from 'lockfile-lint-api';

const packages = new ParseLockfile({
  lockfilePath,
  lockfileType
}).parseSync().object;

const results = Object.entries(packages).map(([packageName, packageMetadata]) => ({
  packageName,
  resolved: packageMetadata.resolved
}))

console.log(results);

Expected Behavior

  • All packages return a URL that looks like (or undefined):
{
  "packageName": "[email protected]",
  "resolved": "https://npm.corp.indeed.com/repository/npm/fsevents/-/fsevents-1.2.11.tgz"
}

Instead, on 5.0.10 some packages return the version only:

{
  "packageName": "[email protected]",
  "resolved": "1.1.1"
}

Seems to happen for any packages that are listed as dependencies of another package which don't contain this information on the package-lock. e.g.:

		"fsevents": {
			"version": "1.2.11",
			"resolved": "https://my.registry.com/repository/npm/fsevents/-/fsevents-1.2.11.tgz",
			"integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==",
			"optional": true,
			"requires": {
				"bindings": "^1.5.0",
				"nan": "^2.12.1",
				"node-pre-gyp": "*"
			},
			"dependencies": {
				"abbrev": {
					"version": "1.1.1",
					"bundled": true,
					"optional": true
				},

Current Behavior

resolved field contains package version when resolved is not available

Possible Solution

  • omit the resolved value when not available

Steps to Reproduce (for bugs)

  1. install 5.0.7
  2. Run snippet above
  3. install 5.0.10
  4. Run snippet above
  5. compare output

Context

  • It makes a little bit harder to filter out packages without registry specified since it has to also account for package versions
  • If this is the culprit it looks like a breaking change

Your Environment

  • Library Version used: [email protected] and [email protected]
  • Node.js version (e.g. Node.js 5.4): Node 12.13.0
  • Operating System and version (desktop or mobile): OSX 10.146 (desktop)

Use allowed url patterns in a single hostname

Is your feature request related to a problem? Please describe.
We have multiple npm repositories served on a single host, release, and dev on different paths. e.g.:
Dev repo: https://artifactory.example.com/npm/DEV/...
Release repo: https://artifactory.example.com/npm/REL/...

I want to enforce release usage.

Describe the solution you'd like
Have a parameter to specify allowed URLs but with wildcard support.
npx lockfile-lint --allowed-url-patterns https://artifactory.example.com/npm/REL/*/prefix

'*' means any char repeated any times.

Describe alternatives you've considered
Instead of a simple glob pattern, regex can be used. But that may be unnecessarily complex as for regex you'll need to escape the URL.

CLI option to report all non-whitelisted URLs used

This looks like a pretty awesome project and something I would like to include in Salus (www.github.com/coinbase/salus) to get better coverage on yarn and npm projects.

Is your feature request related to a problem? Please describe.
Please describe the problem you are trying to solve.

I'd like to get a list of all URLs being used that don't match the whitelist that fails a scan.

Describe the solution you'd like
Please describe the desired behavior.

Instead of returning detected invalid origin for package: <package_name>, I would like to see the URL used in addition to the package name.

Preferably in a JSON format option for easier parsing but I can implement a rudimentary parser on this syntax if outputting in JSON is not going to be supported.

Describe alternatives you've considered
Please describe alternative solutions or features you have considered.

Vulnerability in y18n (prototype pollution)

Expected Behavior

When using npq (your own tool! ๐Ÿ˜‹) to install lockfile-lint, it pointed out that it has 1 vulnerability, according to Snyk's Vuln DB. Actually this vulnerability is a prototype pollution in [email protected], which is a dependency of [email protected]. It is a known vulnerability and it has been fixed a few weeks ago. Updating yargs to the latest version (16.1.1) updates y18n to version 5.0.5 and fixes the issue.

Current Behavior

Vulnerability in dependency.

Possible Solution

Update yargs to version 16.1.1.

Your Environment

  • Library Version used: 4.3.7
  • Node.js version (e.g. Node.js 5.4): 15.2.0
  • Operating System and version (desktop or mobile): macOS Catalina 10.15.7

Support for pnp and npm-shrinkwrap

Is your feature request related to a problem? Please describe.
Currently only package-lock.json and yarn.lock are checked. But npm-shrinkwrap.json is not which gets higher priority than package-lock.json.

https://docs.npmjs.com/cli/shrinkwrap.html

Also add support for Yarn PnP.

Describe the solution you'd like
Support for more lockfile types, especially npm-shrinkwrap.

lockfile-lint does not lint the entire tree for package-lock.json

When running "test:lockfile": "lockfile-lint -p package-lock.json -t npm -a npm -o https: -c -i", it does not check past the first resolved URL for a dependency.

Expected Behavior

lockfile-lint should check the entire tree.

Current Behavior

If we take the below snippet from a package-lock.json and change the semver resolved URL to http or a URL other than registry.npmjs.org, lockfile-lint will not catch this.

"@babel/core": {
  "version": "7.7.5",
  "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.5.tgz",
  "integrity": "sha512-M42+ScN4+1S9iB6f+TL7QBpoQETxbclx+KNoKJABghnKYE+fMzSGqst0BZJc8CpI625bwPwYgUyRvxZ+0mZzpw==",
  "dev": true,
  "requires": {
    "@babel/code-frame": "^7.5.5",
    "@babel/generator": "^7.7.4",
    "@babel/helpers": "^7.7.4",
    "@babel/parser": "^7.7.5",
    "@babel/template": "^7.7.4",
    "@babel/traverse": "^7.7.4",
    "@babel/types": "^7.7.4",
    "convert-source-map": "^1.7.0",
    "debug": "^4.1.0",
    "json5": "^2.1.0",
    "lodash": "^4.17.13",
    "resolve": "^1.3.2",
    "semver": "^5.4.1",
    "source-map": "^0.5.0"
  },
  "dependencies": {
    "semver": {
      "version": "5.7.1",
      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
      "dev": true
    },
    "source-map": {
      "version": "0.5.7",
      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
      "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
      "dev": true
    }
  }
},

Possible Solution

At the moment, my current possible solution is to find and loop over all the resolved URLs.

Steps to Reproduce (for bugs)

  1. If you don't have a project with lockfile-lint in it already, create one and install lockfile-lint
  2. Add a script that uses lockfile-lint (e.x. "test:lockfile": "lockfile-lint -p package-lock.json -t npm -a npm -o https: -c -i")
  3. Go into the package-lock.json and change the resolved URL to a dependency that is under "dependencies"
  4. Run lockfile-lint

Context

I cannot fully lint my entire package-lock.json file due to this.

Your Environment

  • Library Version used: ^3.0.8
  • Node.js version (e.g. Node.js 5.4): v10.13.0
  • Operating System and version (desktop or mobile): macOS Mojave v10.14.5

Yarn v2 support needed

Is your feature request related to a problem? Please describe.

Yarn v2 introduced a new lockfile format that now adheres to YAML. I believe ATM when trying to run lockfile-lint on a project with yarn v2, lockfile-lint tries to use the v1 parser and fails with an error.

ABORTING lockfile lint process due to error exceptions

Unable to parse lockfile "yarn.lock"

SyntaxError: Unknown token: {line: 3, col: 2, type: ''INVALID', value: undefined } 3:2 in lockfile

Describe the solution you'd like

As far as I can tell, yarn v2 does not have an equivalent lockfile parser. But since it adheres to YAML now, I'm wondering if it is possible to just use a parser like yaml and create a small function to transform it like parseNpmLockfile?

Describe alternatives you've considered

None.

Support for github: scheme

Is there plan to support this type of package?

npx lockfile-lint -p package-lock.json -t npm -s -a npm gitlab.com '' -o "https:" "github:"

detected invalid protocol for package: lottie-api@github:bodymovin/lottie-api#793fcfc4d8f2da1b868977c1a2c36eaf696e28c0
expected: https:
actual: github:

Crash when package-lock.json has no dependencies

Expected Behavior

If the package-lock.json file has no dependencies and --validate-https is specified, lockfile-lint should not crash.

Current Behavior

 npx lockfile-lint -p oas-kit/packages/oas-schema-walker/package-lock.json 
npx: installed 56 in 5.789s
 No issues detected 
 npx lockfile-lint --validate-https -p oas-kit/packages/oas-schema-walker/package-lock.json 
npx: installed 56 in 5.635s
ABORTING lockfile lint process due to error exceptions 

Unable to parse npm lockfile "oas-kit/packages/oas-schema-walker/package-lock.json" 

TypeError: Cannot convert undefined or null to object
    at Function.entries (<anonymous>)
    at ParseLockfile._flattenNpmDepsTree (/home/mike/.npm/_npx/131674/lib/node_modules/lockfile-lint/node_modules/lockfile-lint-api/src/ParseLockfile.js:129:49)
    at ParseLockfile.parseNpmLockfile (/home/mike/.npm/_npx/131674/lib/node_modules/lockfile-lint/node_modules/lockfile-lint-api/src/ParseLockfile.js:117:31)
    at ParseLockfile.parseSync (/home/mike/.npm/_npx/131674/lib/node_modules/lockfile-lint/node_modules/lockfile-lint-api/src/ParseLockfile.js:64:27)
    at ValidateHttpsManager (/home/mike/.npm/_npx/131674/lib/node_modules/lockfile-lint/src/validators/index.js:75:27)
    at /home/mike/.npm/_npx/131674/lib/node_modules/lockfile-lint/src/main.js:37:28
    at Array.forEach (<anonymous>)
    at Object.runValidators (/home/mike/.npm/_npx/131674/lib/node_modules/lockfile-lint/src/main.js:27:14)
    at Object.<anonymous> (/home/mike/.npm/_npx/131674/lib/node_modules/lockfile-lint/bin/lockfile-lint.js:54:17)
    at Module._compile (internal/modules/cjs/loader.js:1063:30) 

error: command failed with exit code 1

Possible Solution

Guard against the non-presence of the dependencies property.

Steps to Reproduce (for bugs)

One of the packages in my mono-repo (https://github.com/mermade/oas-kit) has the following package-lock.json

{
  "name": "oas-schema-walker",
  "version": "1.1.5",
  "lockfileVersion": 1
}

Context

I'd like to use lockfile-lint in my projects, but don't want it to crash during CI.

Your Environment

  • Library Version used: 4.3.7
  • Node.js version (e.g. Node.js 5.4): v14.15.1
  • Operating System and version (desktop or mobile): Ubuntu 20.04.1 desktop

"Only yarn supported"?

Hello!

The readme states:

NOTE: currently only yarn's yarn.lock is supported. PRs to support npm's package-lock.json are welcome

This seems like old information, since the lockfile-lint package does support npm lockfiles, though I may be wrong.

So in this issue, I want to ask: is this readme statement correct?

Replace Travis CI with Github Actions

Is your feature request related to a problem? Please describe.
Nope

Describe the solution you'd like
Github Actions are more integrated than Travis CI, so I thought if this is something you'd like to consider

Describe alternatives you've considered
None

Friendlier error message when parsing lock files fails

Is your feature request related to a problem? Please describe.
When parsing files of either npm or yarn lockfile, let's make sure we show a friendly error message instead of the general error exception being thrown.

This is in continuation to #9 and the work landed by @emimuresan in #13

Describe the solution you'd like
This should probably be done at the level of ParseLockfile.js class l

Support multiple paths and/or glob patterns in the CLI

Is your feature request related to a problem? Please describe.

Sort of, if you are trying to use the CLI in a lerna repo it doesn't support glob patterns like
lockfile-lint -p packages/*/package-lock.json -t npm -a npm -o https: -c -i

Describe the solution you'd like

Either support multiple paths or glob patterns.

Describe alternatives you've considered

Writing a script to manually loop over all the packages.

Would you entertain a PR that would accomplish this?

Add "all is good" confirmation when validation succeeds

Is your feature request related to a problem? Please describe.
Currently when you run the validation command and everything succeed you don't get any feedback in the console so it leaves you wondering if validation actually took place.

Describe the solution you'd like
Add some some sort of confirmation message like ๐Ÿ‘ Validation successful if everything passed.

Allow ignoring `dev` dependencies in a lockfile

Is your feature request related to a problem? Please describe.
Allowing to ignore dev related dependencies in a lockfile might be useful due to fs file linking and other related usages.

Provide the actual bad string being used

Is your feature request related to a problem? Please describe.
Right now when the linter fails on an untrusted option found in the lockfile it says which package is it, but it doesn't say what is the actual bad string being used.

For example, an output of lockfile-lint could be:

detected invalid scheme for package: @babel/code-frame@^7.0.0
error: command failed with exit code 1

But it doesn't say what is the string provided as the "scheme" that is found to be invalid, and so it would be a nice DX to also print this information out with regards to the current validators we have.

Describe the solution you'd like
This is probably something we want to fix in the way that the lockfile-lint-api works and provide this information, at which point the CLI package lockfile-lint can then use it.

Tests fail on Windows

yarn run v1.22.0
$ lerna run test
lerna notice cli v3.14.1
lerna info versioning independent
lerna info Executing command in 2 packages: "yarn run test"
lerna info run Ran npm script 'test' in 'lockfile-lint-api' in 2.9s:
$ jest
----------------------------------|----------|----------|----------|----------|-------------------|
File                              |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------------------------------|----------|----------|----------|----------|-------------------|
All files                         |    96.32 |    88.73 |    95.65 |    96.32 |                   |
 lockfile-lint-api                |      100 |      100 |      100 |      100 |                   |
  index.js                        |      100 |      100 |      100 |      100 |                   |
 lockfile-lint-api/src            |      100 |    95.24 |      100 |      100 |                   |
  ParseLockfile.js                |      100 |    95.24 |      100 |      100 |               132 |
 lockfile-lint-api/src/common     |    73.68 |       50 |     87.5 |    73.68 |                   |
  PackageError.js                 |        0 |        0 |        0 |        0 |     3,10,11,12,13 |
  ParsingError.js                 |      100 |    83.33 |      100 |      100 |                26 |
  constants.js                    |      100 |      100 |      100 |      100 |                   |
 lockfile-lint-api/src/validators |      100 |       95 |      100 |      100 |                   |
  ValidateHost.js                 |      100 |      100 |      100 |      100 |                   |
  ValidateHttps.js                |      100 |    88.89 |      100 |      100 |                 8 |
  ValidateScheme.js               |      100 |    92.31 |      100 |      100 |                 6 |
----------------------------------|----------|----------|----------|----------|-------------------|
lerna ERR! yarn run test exited 1 in 'lockfile-lint'
lerna ERR! yarn run test stdout:
$ jest
  console.error src/main.js:44
    detected invalid protocol for package: debug@^4.1.1
        expected: https:
        actual: http:


  console.error src/main.js:44
    detected invalid protocol for package: ms@^2.1.1
        expected: https:
        actual: http:


  console.error src/main.js:44
    detected invalid protocol for package: debug@^4.1.1
        expected: https:
        actual: http:


  console.error src/main.js:44
    detected invalid protocol for package: ms@^2.1.1
        expected: https:
        actual: http:


  console.error src/main.js:44
    detected invalid host(s) for package: debug@^4.1.1
        expected: registry.npmjs.org
        actual: registry.yarnpkg.com


  console.error src/main.js:44
    detected invalid host(s) for package: ms@^2.1.1
        expected: registry.npmjs.org
        actual: registry.yarnpkg.com


  console.error src/main.js:44
    detected invalid host(s) for package: metalsmith-permalinks@github:XhmikosR/metalsmith-permalinks#432843d5823a292b2e47397ba46fd761d03eb9d3-23e3afb87f94f6fbb4a2a4dee0e9ad5ae3345557
        expected: registry.npmjs.org
        actual:


  console.error src/main.js:44
    detected invalid host(s) for package: substitute@https://github.com/segment-boneyard/substitute/archive/0.1.0.tar.gz-cac7fab347605af7808679c31e920d7da07e6b0c
        expected: registry.npmjs.org
        actual: github.com


  console.error src/main.js:44
    detected invalid scheme(s) for package: [email protected]
        expected: https
        actual: https:


  console.error src/main.js:44
    detected invalid scheme(s) for package: ms@git+https://github.com/zeit/ms.git#adf1eb282d29fe3c405d205a3854177b86a97c1f-0f7c6a877d7eeaa579752be37c7fd80b9bd02a4a
        expected: https
        actual: git+https:


  console.error src/main.js:44
    detected invalid scheme(s) for package: debug@^4.1.1
        expected: https
        actual: https:


  console.error src/main.js:44
    detected invalid scheme(s) for package: ms@^2.1.1
        expected: https
        actual: https:


  console.error src/main.js:44
    detected invalid scheme(s) for package: ms@git+https://github.com/zeit/ms#master
        expected: https
        actual: git+https:


----------------|----------|----------|----------|----------|-------------------|
File            |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------------|----------|----------|----------|----------|-------------------|
All files       |    91.49 |    85.71 |      100 |    91.49 |                   |
 src            |    84.62 |    85.71 |      100 |    84.62 |                   |
  cli.js        |        0 |      100 |      100 |        0 |            3,5,52 |
  main.js       |    95.65 |    85.71 |      100 |    95.65 |                28 |
 src/validators |      100 |      100 |      100 |      100 |                   |
  index.js      |      100 |      100 |      100 |      100 |                   |
----------------|----------|----------|----------|----------|-------------------|
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

lerna ERR! yarn run test stderr:
FAIL __tests__/cli.test.js
  CLI tests
    ร— Running without parameters should display help (13ms)
    ร— Running without parameters should display a requirement for the p option (4ms)
    ร— Linting a file that has wrong host should display an error message and use exit code 1 (4ms)
    ร— Linting a file that has wrong host should return exit code 1 (4ms)

  โ— CLI tests โ€บ Running without parameters should display help

    spawn UNKNOWN

       7 | describe('CLI tests', () => {
       8 |   test('Running without parameters should display help', done => {
    >  9 |     const process = childProcess.spawn(cliExecPath, [])
         |                                  ^
      10 |
      11 |     let output = ''
      12 |     process.stderr.on('data', chunk => {

      at Object.spawn (__tests__/cli.test.js:9:34)

  โ— CLI tests โ€บ Running without parameters should display a requirement for the p option

    spawn UNKNOWN

      23 |
      24 |   test('Running without parameters should display a requirement for the p option', done => {
    > 25 |     const process = childProcess.spawn(cliExecPath, [])
         |                                  ^
      26 |
      27 |     let output = ''
      28 |     process.stderr.on('data', chunk => {

      at Object.spawn (__tests__/cli.test.js:25:34)

  โ— CLI tests โ€บ Linting a file that has wrong host should display an error message and use exit code 1

    spawn UNKNOWN

      37 |
      38 |   test('Linting a file that has wrong host should display an error message and use exit code 1', done => {
    > 39 |     const process = childProcess.spawn(cliExecPath, [
         |                                  ^
      40 |       '--type',
      41 |       'yarn',
      42 |       '--path',

      at Object.spawn (__tests__/cli.test.js:39:34)

  โ— CLI tests โ€บ Linting a file that has wrong host should return exit code 1

    spawn UNKNOWN

      67 |
      68 |   test('Linting a file that has wrong host should return exit code 1', done => {
    > 69 |     const process = childProcess.spawn(cliExecPath, [
         |                                  ^
      70 |       '--type',
      71 |       'yarn',
      72 |       '--path',

      at Object.spawn (__tests__/cli.test.js:69:34)

PASS __tests__/main.test.js
  Main CLI logic
    Invoking validators should handle errors and defaults
      โˆš when no validator function is provided expect to fail (16ms)
      โˆš should handle exceptions when validators arent provided for runValidators method (5ms)
    validateHttp
      โˆš a failing validator should return proper validation failed object (2ms)
      โˆš a successful validator should return proper validation object (1ms)
    validateHosts
      โˆš a failing validator should return proper validation failed object (3ms)
      โˆš a failing validator should throw an error if an empty host is not allowed (4ms)
      โˆš a successful validator should return proper validation object (4ms)
    validateSchemes
      โˆš should fail validating allowed schemes for a package-lock.json file (2ms)
      โˆš should succeed validating allowed schemes for a package-lock.json file (2ms)
      โˆš should fail validating allowed schemes for a yarn.lock file (3ms)
      โˆš should succeed validating allowed schemes for a yarn.lock file (1ms)

Test Suites: 1 failed, 1 passed, 2 total
Tests:       4 failed, 11 passed, 15 total
Snapshots:   0 total
Time:        1.771s
Ran all test suites.
error Command failed with exit code 1.

lerna ERR! yarn run test exited 1 in 'lockfile-lint'
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Additional validations

From some quick testing, it appears the following issues are not currently validated:

  1. Ensure every dependencies entry in package-lock.json has an integrity property with a non-empty string.
  2. Ensure the resolved URL package name matches the dependency it should resolve, to prevent substitutions
  3. Ensure the version number within the resolved URL matches the dependency version it should resolve, to prevent down-levelling to introduce bugs

Use log symbols for easier to read output

Is your feature request related to a problem? Please describe.

  1. More friendly and easier to read output.
  2. Also in case of no issues found, a success message should be printed - right now i don't see any message if all is ok.

Describe the solution you'd like
Use something like: https://www.npmjs.com/package/log-symbols

Describe alternatives you've considered
Alternative solution, styling the text: https://www.npmjs.com/package/ansi-colors, though i think the symbols are better.

getting error on build ci/cd

yarn run v1.22.4
$ lockfile-lint --path yarn.lock --allowed-hosts yarn --validate-https
detected invalid host(s) for package: request@cypress-io/request#b5af0d1fa47eec97ba980cde90a13e69a2afcd16
    expected: registry.yarnpkg.com
    actual: codeload.github.com

error: command failed with exit code 1 

error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
##[error]Process completed with exit code 1.

is it false positive? how can I fix it? have tried to clear cache, node_modules and regenerate yarn.lock

Our build pipeline is broken. Please provide an advise.

Add missing unit test coverage for PR #59

Is your feature request related to a problem? Please describe.

PR #59 rushed to get a quick fix out due to a regression introduced in #53 but it missed on adding proper tests coverage for the underlying issue.

Describe the solution you'd like

Add unit tests

Some tests seem to be testing the wrong thing

Four tests in validators.host.test.js test that the validate method does not throw. Instead these tests should be checking the result object equality since validate method never throws.

See this test for example: https://github.com/lirantal/lockfile-lint/blob/master/packages/lockfile-lint-api/__tests__/validators.host.test.js#L45. It does this:

expect(() => {
  validator.validate(['npm'])
}).not.toThrow()

Instead, it should do this:

expect(validator.validate(['npm'])).toEqual({
  type: 'success',
  errors: []
})

Allow tying packages/scopes to a specific host

Is your feature request related to a problem? Please describe.

I was reading this article that discusses a supply chain attack by searching for internal packages within an organisation that don't exist in public npm and using them as a potential attack vector.

I wondered whether this is something lockfile-lint could provide a solution to (although perfectly understandable if it's out of scope), by allowing folks to tie packages or scopes to a specific host.

Describe the solution you'd like

I think this would work similar to the other validators, it would take some form of configuration that allows people to tie a package name or scope to a certain host. Although this would probably be less than ideal to expose as CLI options

I took a look into what it would take to expose just the scope configuration and came up with this
, I think it wouldn't be too much effort to extend it to package names also if you're interested :)

Getting detected invalid host(s) for file: dependencies

Expected Behavior

I have a package.json and therefore also a package-lock.json which contains a reference to a package on the file system using file:. But it complains about the invalid hosts.

Current Behavior

package.json

{
  "dependencies": {
    "some-package": "file:./some-package-2.0.0.tgz"
  }
}

package-lock.json

{
  "dependencies": {
"some-package": {
      "version": "file:some-package-2.0.0.tgz",
      "integrity": "sha512-...."
    }
}
npx lockfile-lint --path package-lock.json --allowed-hosts npm --allowed-schemes "https:" "file:"
npx: installed 31 in 3.219s
detected invalid host(s) for package: some-package@file:some-package-2.0.0.tgz
    expected: registry.npmjs.org
    actual: 

error: command failed with exit code 1 

Possible Solution

Maybe ignore host when using a file: scheme?

Steps to Reproduce (for bugs)

  1. Create package.json with file reference
  2. Install
  3. Run lockfile-lint

Your Environment

  • Library Version used: 2.2.0
  • Node.js version (e.g. Node.js 5.4): 10.7.0
  • Operating System and version (desktop or mobile): macOS 10.15.x

Fixing example mentioned in README.md of lockfile-lint-api

In the README.md example, there is a typo, lockFilePath instead of lockfilePath. To fix another issue, I cloned the project and copied the example to get started but it was not working, so after few minutes I found the reason was the typo :/.

allowed-hosts failing on urls with port and no scheme

Hi there! We've been using lockfile-lint at our company. We have been specifying --allowed-hosts with a domain and port, like this: nexus.example.com:8089. Up until yesterday, this worked fine:

npx lockfile-lint --path package-lock.json --allowed-hosts nexus.example.com:8089 registry.npmjs.org

As of today, the above command results in false positives that look like this:

detected invalid host(s) for package: [email protected]
    expected: ,registry.npmjs.org
    actual: nexus.example.com:8089

(Note the leading comma in the "expected" value. It seems that this CLI argument is being parsed incorrectly?)

Changing nexus.example.com:8089 to https://nexus.example.com:8089 makes it work again.

Expected Behavior

Expected allowed-hosts not to require a scheme.

Current Behavior

When using a port in an allowed-host, it doesn't work unless you use a scheme as well. And if that's a feature not a bug, then the error message could be improved.

Your Environment

  • Library Version used: 4.3.3
  • Node.js version (e.g. Node.js 5.4): 12.9.1, npm 6.12.1
  • Operating System and version (desktop or mobile): linux

Are lockfiles actually a vulnerability?

<Disclaimer>
I am not trying to hack anyone else, just trying to figure out if this a real problem that I need to worry about for my team
</Disclaimer>

I tried following the steps here: https://snyk.io/blog/why-npm-lockfiles-can-be-a-security-blindspot-for-injecting-malicious-modules/

but it doesn't actually result in a vulnerability.

I followed these steps:

  1. Created a malicious fork of the package nprogress for demonstration purposes (nprogres/nprogress@308c38d)

  2. Ran yarn add nprogres/nprogress

  3. Committed yarn.lock but did not change package.json

  4. Did a fresh clone incorporating that commit.

  5. Confirmed that yarn.lock was pointing to the git version of progress

  6. Ran yarn install

Result: yarn used the version from npm not my version

I also tried:

a. bumping the version of nprogress in package.json to 0.2.3 (npm version is 0.2.1) but this didn't work, it says Couldn't find any versions for "nprogress" that matches "^0.2.3"

b. committing package.json - this works but means that it is rather obvious because it has

"nprogress": "nprogres/nprogress" which a human will easily notice

Question:

Is it possible that yarn has patched the vulnerability and will only use git based modules if they are present in package.json? If so, this whole library does not seem relevant any more and the snyk blog post could be archived and this github repo marked as outdated.

invalid protocol when undefined

Expected Behavior

before the new version published today, running lockfile-lint against my projects was passing.

Current Behavior

now seeing several projects failing with lots of failures similar to

detected invalid protocol for package: [email protected]
     expected: https:
     actual: undefined

https://travis-ci.com/travi-org/matt.travi.org/builds/147288295#L340-L2012

not sure if this was intentional with recent changes, but seems unexpected.

Possible Solution

Steps to Reproduce (for bugs)

  1. Clone from https://github.com/travi-org/matt.travi.org
  2. git checkout greenkeeper/lockfile-lint-3.0.10
  3. nvm install
  4. npm install
  5. npm run lint:lockfile

Context

Greenkeeper PRs to several of my projects failed

Your Environment

  • Library Version used: v3.0.10
  • Node.js version (e.g. Node.js 5.4): v10.18.1
  • Operating System and version (desktop or mobile): macOS Catalina 10.15.2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.