Initial commit
This commit is contained in:
206
.gitignore
vendored
Normal file
206
.gitignore
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/webstorm+all,node
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=webstorm+all,node
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
### WebStorm+all ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/artifacts
|
||||
# .idea/compiler.xml
|
||||
# .idea/jarRepositories.xml
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
# *.iml
|
||||
# *.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### WebStorm+all Patch ###
|
||||
# Ignores the whole .idea folder and all .iml files
|
||||
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
|
||||
|
||||
.idea/
|
||||
|
||||
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
|
||||
|
||||
*.iml
|
||||
modules.xml
|
||||
.idea/misc.xml
|
||||
*.ipr
|
||||
|
||||
# Sonarlint plugin
|
||||
.idea/sonarlint
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/webstorm+all,node
|
||||
|
||||
src/*.js
|
||||
*.js.map
|
||||
12
CHANGES
Normal file
12
CHANGES
Normal file
@@ -0,0 +1,12 @@
|
||||
Changelog
|
||||
|
||||
=========
|
||||
|
||||
Version 1.0.1
|
||||
|
||||
- feature add endpoint param & MOSEC_ENDPOINT env param
|
||||
- feature change --no-dev to --with-dev
|
||||
|
||||
Version 1.0.0
|
||||
|
||||
- Init
|
||||
13
LICENSE
Normal file
13
LICENSE
Normal file
@@ -0,0 +1,13 @@
|
||||
Copyright 2020 momosecurity.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
21
README.md
Normal file
21
README.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# MOSEC-NODE-PLUGIN
|
||||
|
||||
用于检测 node 项目的第三方依赖组件是否存在安全漏洞。
|
||||
|
||||
该项目是基于 [snyk/resolve-deps](https://github.com/snyk/resolve-deps.git) 的二次开发。
|
||||
|
||||
## 版本支持
|
||||
|
||||
npm >= 5.2.0
|
||||
|
||||
## 使用
|
||||
|
||||
首先运行 [MOSEC-X-PLUGIN Backend](https://github.com/momosecurity/mosec-x-plugin-backend.git)
|
||||
|
||||
#### 无需安装即可使用
|
||||
```
|
||||
> cd your_node_project/
|
||||
> npx github:momosecurity/mosec-node-plugin \
|
||||
--endpoint https://127.0.0.1:9000/api/plugin \
|
||||
--only-provenance
|
||||
```
|
||||
26
index.js
Executable file
26
index.js
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
let program = require("commander");
|
||||
let check = require("./dist/main");
|
||||
let package = require("./package.json");
|
||||
let logger = require("./dist/logger");
|
||||
|
||||
function main() {
|
||||
program
|
||||
.version(package.version)
|
||||
.option('-e, --endpoint <value>', '上报API')
|
||||
.option('-t, --target <path>', '项目所在目录', process.cwd())
|
||||
.option('-s, --severity-level <value>', '威胁等级 [High|Medium|Low]', 'High')
|
||||
.option('--only-provenance', '仅检查直接依赖', false)
|
||||
.option('--with-dev', '包括devDependency', false)
|
||||
.parse(process.argv);
|
||||
|
||||
check
|
||||
.checkProject(program.target, program.endpoint, program.severityLevel, program.onlyProvenance, program.withDev)
|
||||
.catch(function (e) {
|
||||
logger.error(e.message);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
main();
|
||||
2509
package-lock.json
generated
Normal file
2509
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
61
package.json
Normal file
61
package.json
Normal file
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"name": "mosec-node-plugin",
|
||||
"version": "1.0.1",
|
||||
"description": "用于检测Node项目的第三方依赖组件是否存在安全漏洞",
|
||||
"author": "retanoj <mmsrc@immomo.com>",
|
||||
"homepage": "https://github.com/momosecurity/mosec-node-plugin.git",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"package.json",
|
||||
"/dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"build-watch": "tsc -w",
|
||||
"tslint": "tslint --project tsconfig.json --format stylish --exclude **/src/**/*.js",
|
||||
"prepare": "npm run build",
|
||||
"lint": "npm run tslint",
|
||||
"test": "npm run check-tests && npm run lint && tap test/*.test.[jt]s --timeout=60 --node-arg=-r --node-arg=ts-node/register"
|
||||
},
|
||||
"bin": {
|
||||
"mosec": "./index.js"
|
||||
},
|
||||
"keywords": [
|
||||
"security",
|
||||
"dependencies",
|
||||
"vulnerability"
|
||||
],
|
||||
"license": "Apache License 2.0",
|
||||
"devDependencies": {
|
||||
"@types/node": "^6.14.4",
|
||||
"@types/semver": "^5.5.0",
|
||||
"sinon": "^1.17.3",
|
||||
"tap": "^12.6.0",
|
||||
"tap-only": "0.0.5",
|
||||
"ts-node": "^8.1.0",
|
||||
"tslint": "^5.13.1",
|
||||
"typescript": "^3.3.3333"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansicolors": "^0.3.2",
|
||||
"axios": "^0.19.2",
|
||||
"chalk": "^4.1.0",
|
||||
"commander": "^5.1.0",
|
||||
"debug": "^3.2.5",
|
||||
"lodash.assign": "^4.2.0",
|
||||
"lodash.assignin": "^4.2.0",
|
||||
"lodash.clonedeep": "^4.3.0",
|
||||
"lodash.flatten": "^4.4.0",
|
||||
"lru-cache": "^4.0.0",
|
||||
"semver": "^5.5.1",
|
||||
"then-fs": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0",
|
||||
"npm": ">= 5.2.0"
|
||||
}
|
||||
}
|
||||
47
src/dep-types.ts
Normal file
47
src/dep-types.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright 2017 Snyk Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
export = depTypes;
|
||||
|
||||
import { DepType, HasDependencySpecs } from "./types";
|
||||
|
||||
// Dependency types.
|
||||
// We don't call out all of them, only the ones relevant to our behavior.
|
||||
// extraneous means not found in package.json files, prod means not dev ATM
|
||||
function depTypes(depName: string, pkg: HasDependencySpecs) {
|
||||
let type: string | null = null;
|
||||
let from = 'unknown';
|
||||
|
||||
if (pkg.devDependencies && pkg.devDependencies[depName]) {
|
||||
type = depTypes.DEV;
|
||||
from = pkg.devDependencies[depName];
|
||||
}
|
||||
|
||||
// production deps trump all
|
||||
if (pkg.dependencies && pkg.dependencies[depName]) {
|
||||
type = depTypes.PROD;
|
||||
from = pkg.dependencies[depName];
|
||||
}
|
||||
|
||||
return {
|
||||
type: type as string,
|
||||
from: from,
|
||||
};
|
||||
}
|
||||
|
||||
depTypes.EXTRANEOUS = 'extraneous' as DepType;
|
||||
depTypes.OPTIONAL = 'optional' as DepType;
|
||||
depTypes.PROD = 'prod' as DepType;
|
||||
depTypes.DEV = 'dev' as DepType;
|
||||
263
src/deps.ts
Normal file
263
src/deps.ts
Normal file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
Copyright 2017 Snyk Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
export = loadModules;
|
||||
|
||||
import * as depTypes from './dep-types';
|
||||
import * as tryRequire from './try-require';
|
||||
import * as resolve from './pkg-resolve';
|
||||
import * as fs from 'then-fs';
|
||||
import * as _assign from 'lodash.assign';
|
||||
import * as _flatten from 'lodash.flatten';
|
||||
import * as debugModule from 'debug';
|
||||
import * as path from 'path';
|
||||
import * as semver from 'semver';
|
||||
import {AbbreviatedVersion, PackageExpanded, PackageJsonEnriched, DepExpandedDict} from './types';
|
||||
|
||||
const debug = debugModule('mosec:resolve:deps');
|
||||
|
||||
function loadModules(root, depType) {
|
||||
tryRequire.cache.reset(); // reset the package cache on re-run
|
||||
let pkgRoot = root;
|
||||
|
||||
return loadModulesInternal(
|
||||
pkgRoot,
|
||||
depType || null,
|
||||
null,
|
||||
).then(function (tree) {
|
||||
// ensure there's no missing packages our known root deps
|
||||
let missing: Array<Promise<PackageExpanded>> = [];
|
||||
if (tree.__dependencies) {
|
||||
Object.keys(tree.__dependencies).forEach(function (name) {
|
||||
if (!tree.dependencies[name]) {
|
||||
missing.push(resolve.resolvePkg(name, pkgRoot).then(function (dir) {
|
||||
return loadModulesInternal(dir, depTypes.PROD, {
|
||||
from: [tree.name + '@' + tree.version, name],
|
||||
});
|
||||
}).catch(function (e) {
|
||||
if (e.code === 'NO_PACKAGE_FOUND') {
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
if (missing.length) {
|
||||
return Promise.all(missing).then(function (packages) {
|
||||
packages.filter(Boolean).forEach(function (pkg) {
|
||||
pkg.dep = tree.__dependencies[pkg.name];
|
||||
tree.dependencies[pkg.name] = pkg;
|
||||
});
|
||||
return tree;
|
||||
});
|
||||
}
|
||||
|
||||
return tree;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function loadModulesInternal(root, rootDepType, parent): Promise<PackageExpanded> {
|
||||
if (!rootDepType) {
|
||||
rootDepType = depTypes.EXTRANEOUS;
|
||||
}
|
||||
|
||||
if (typeof root !== 'string') {
|
||||
return Promise.reject(new Error('module path must be a string'));
|
||||
}
|
||||
|
||||
let modules;
|
||||
let dir = path.resolve(root, 'package.json');
|
||||
// 1. read package.json for written deps
|
||||
return tryRequire(dir).then(function (pkg: PackageJsonEnriched) {
|
||||
// create root pkg node
|
||||
if (pkg) {
|
||||
let full = pkg.name + '@' + (pkg.version || '0.0.0');
|
||||
modules = {} as PackageExpanded;
|
||||
_assign(modules, {
|
||||
name: pkg.name,
|
||||
version: pkg.version || '0.0.0',
|
||||
license: pkg.license || 'none',
|
||||
depType: rootDepType,
|
||||
hasDevDependencies: !!pkg.devDependencies,
|
||||
full: full,
|
||||
from: (parent || {from: []}).from,
|
||||
__devDependencies: pkg.devDependencies,
|
||||
__dependencies: pkg.dependencies,
|
||||
__filename: pkg.__filename,
|
||||
});
|
||||
|
||||
// allows us to add to work out the full path that the package was
|
||||
// introduced via
|
||||
pkg.from = modules.from.concat(full);
|
||||
pkg.full = modules.full;
|
||||
|
||||
// this is a special case for the root package to get a consistent
|
||||
// from path, so that the complete path (including it's own pkg name)
|
||||
if (modules.from.length === 0) {
|
||||
modules.from.push(full);
|
||||
}
|
||||
} else {
|
||||
throw new Error(dir + ' is not a node project');
|
||||
}
|
||||
modules.dependencies = {};
|
||||
|
||||
// 2. check actual installed deps
|
||||
return fs.readdir(path.resolve(root, 'node_modules')).then(function (dirs) {
|
||||
let res: AbbreviatedVersion[] = dirs.map(function (directory) {
|
||||
// completely ignore `.bin` npm helper dir
|
||||
// ~ can be a symlink to node_modules itself
|
||||
// (https://www.npmjs.com/package/link-tilde)
|
||||
if (['.bin', '.DS_Store', '~'].indexOf(directory) >= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// this is a scoped namespace, and we'd expect to find directories
|
||||
// inside *this* `dir`, so treat differently
|
||||
if (directory.indexOf('@') === 0) {
|
||||
debug('scoped reset on %s', directory);
|
||||
directory = path.resolve(root, 'node_modules', directory);
|
||||
return fs.readdir(directory).then(function (directories) {
|
||||
return Promise.all(directories.map(function (scopedDir) {
|
||||
return tryRequire(path.resolve(directory, scopedDir, 'package.json'));
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
// otherwise try to load a package.json from this node_module dir
|
||||
directory = path.resolve(root, 'node_modules', directory, 'package.json');
|
||||
return tryRequire(directory) as AbbreviatedVersion;
|
||||
});
|
||||
|
||||
return Promise.all(res).then(function (response) {
|
||||
response = _flatten(response).filter(Boolean);
|
||||
|
||||
response.reduce(function (acc, curr) {
|
||||
let license;
|
||||
let licenses = curr.license as any || curr.licenses as any;
|
||||
|
||||
if (Array.isArray(licenses)) {
|
||||
license = licenses.reduce(function (accumulator, current) {
|
||||
accumulator.push((current || {}).type || current);
|
||||
return accumulator;
|
||||
}, []).join('/');
|
||||
} else {
|
||||
license = (licenses || {}).type || licenses;
|
||||
}
|
||||
|
||||
let depInfo = depTypes(curr.name!, pkg);
|
||||
let depType = depInfo.type || rootDepType;
|
||||
let depFrom = depInfo.from;
|
||||
|
||||
let valid = false;
|
||||
if (depFrom) {
|
||||
valid = semver.satisfies(curr.version as string, depFrom);
|
||||
}
|
||||
|
||||
let full = curr.name + '@' + (curr.version || '0.0.0');
|
||||
acc[curr.name!] = {} as PackageExpanded;
|
||||
_assign(acc[curr.name!], {
|
||||
name: curr.name,
|
||||
version: curr.version || null,
|
||||
full: full,
|
||||
valid: valid,
|
||||
depType: depType,
|
||||
license: license || 'none',
|
||||
dep: depFrom || null,
|
||||
from: pkg.from.concat(full),
|
||||
__devDependencies: curr.devDependencies,
|
||||
__dependencies: curr.dependencies,
|
||||
__filename: curr.__filename,
|
||||
});
|
||||
return acc;
|
||||
}, modules.dependencies);
|
||||
|
||||
return modules;
|
||||
});
|
||||
}).then(function (mods) {
|
||||
let deps = Object.keys(mods.dependencies);
|
||||
|
||||
let promises = deps.map(function (dep) {
|
||||
let depType = mods.dependencies[dep].depType;
|
||||
let directory = path.dirname(mods.dependencies[dep].__filename);
|
||||
return loadModulesInternal(directory, depType, pkg);
|
||||
});
|
||||
|
||||
return Promise.all(promises).then(function (res) {
|
||||
res.forEach(function (mod) {
|
||||
mods.dependencies[mod.name].dependencies = mod.dependencies;
|
||||
});
|
||||
|
||||
return mods;
|
||||
});
|
||||
}).catch(function (error) {
|
||||
/* istanbul ignore else */
|
||||
if (error.code === 'ENOENT') {
|
||||
// there's no node_modules directory, that's fine, there's no deps
|
||||
modules.dependencies = {};
|
||||
return modules;
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function simplifyDeps(deps: PackageExpanded, onlyProvenance: boolean, noDev: boolean) {
|
||||
let allowProp = ['name', 'version', 'dependencies', 'from'];
|
||||
|
||||
if (!deps) {
|
||||
return ;
|
||||
}
|
||||
|
||||
// remove extraneous dependencies
|
||||
Object.keys(deps.dependencies).forEach((name) => {
|
||||
if (deps.dependencies[name].depType === depTypes.EXTRANEOUS) {
|
||||
delete deps.dependencies[name];
|
||||
}
|
||||
});
|
||||
|
||||
if (noDev) {
|
||||
// remove dev dependencies
|
||||
Object.keys(deps.dependencies).forEach((name) => {
|
||||
if (deps.dependencies[name].depType === depTypes.DEV) {
|
||||
delete deps.dependencies[name];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (onlyProvenance) {
|
||||
// only check top level dependencies
|
||||
if (deps.from.length > 1) {
|
||||
deps.dependencies = {};
|
||||
}
|
||||
}
|
||||
|
||||
Object.keys(deps).forEach((name) => {
|
||||
if (allowProp.indexOf(name) === -1) {
|
||||
delete deps[name];
|
||||
}
|
||||
});
|
||||
|
||||
if (deps.dependencies) {
|
||||
Object.keys(deps.dependencies).forEach((name) => {
|
||||
simplifyDeps(deps.dependencies[name], onlyProvenance, noDev);
|
||||
});
|
||||
}
|
||||
return deps;
|
||||
}
|
||||
|
||||
loadModules.simplifyDeps = simplifyDeps;
|
||||
34
src/logger.ts
Normal file
34
src/logger.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright 2020 momosecurity.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
export { error, info, warn, log };
|
||||
|
||||
import * as chalk from "chalk";
|
||||
|
||||
function error(msg) {
|
||||
console.error("[MOSEC] %s", chalk.redBright(msg));
|
||||
}
|
||||
|
||||
function info(msg) {
|
||||
console.info("[MOSEC] %s", chalk.greenBright(msg));
|
||||
}
|
||||
|
||||
function warn(msg) {
|
||||
console.warn("[MOSEC] %s", chalk.yellowBright(msg));
|
||||
}
|
||||
|
||||
function log(msg) {
|
||||
console.log("[MOSEC] %s", msg);
|
||||
}
|
||||
125
src/main.ts
Normal file
125
src/main.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
Copyright 2020 momosecurity.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
import set = Reflect.set;
|
||||
|
||||
export { checkProject };
|
||||
|
||||
import * as process from 'process';
|
||||
import * as fs from 'then-fs';
|
||||
import * as path from 'path';
|
||||
import * as logger from './logger';
|
||||
import {SocVulnResponse, Vulnerability} from "./types";
|
||||
|
||||
let axios = require('axios');
|
||||
let util = require('util');
|
||||
let getDeps = require('./deps');
|
||||
|
||||
function statPath(fpath: string) {
|
||||
try {
|
||||
return fs.statSync(fpath);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function printSingleVuln(vuln: Vulnerability) {
|
||||
logger.error(util.format("✗ %s severity vulnerability (%s - %s) found on %s@%s",
|
||||
vuln.severity, vuln.title, vuln.cve, vuln.packageName, vuln.version));
|
||||
|
||||
if (vuln.from) {
|
||||
let fromArr = vuln.from;
|
||||
let fromStr = "";
|
||||
|
||||
fromArr.forEach((fromDep) => {
|
||||
fromStr += fromDep + " > ";
|
||||
});
|
||||
|
||||
fromStr = fromStr.substr(0, fromStr.length - 3);
|
||||
logger.log(util.format("- from: %s", fromStr));
|
||||
}
|
||||
|
||||
if (vuln.target_version.length) {
|
||||
logger.info(util.format("! Fix version %s", JSON.stringify(vuln.target_version)));
|
||||
}
|
||||
|
||||
logger.log('');
|
||||
}
|
||||
|
||||
function checkProject(root: string, endpoint?: string, severity?: string, onlyProvenance?: boolean, withDev?: boolean) {
|
||||
|
||||
let envEndpoint = process.env.MOSEC_ENDPOINT;
|
||||
if (!!envEndpoint) {
|
||||
endpoint = envEndpoint;
|
||||
}
|
||||
if (!endpoint) {
|
||||
return Promise.reject(new Error("endpoint not set. use --endpoint param or MOSEC_ENDPOINT env."));
|
||||
}
|
||||
|
||||
if (statPath(path.resolve(root)) === false) {
|
||||
return Promise.reject(new Error("dir is not exists: " + root));
|
||||
}
|
||||
if (statPath(path.resolve(root, 'package.json')) === false) {
|
||||
return Promise.reject(new Error(root + " is not a node project."));
|
||||
}
|
||||
if (statPath(path.resolve(root, 'node_modules')) === false) {
|
||||
return Promise.reject(new Error("run 'npm install' first, please."));
|
||||
}
|
||||
|
||||
return getDeps(root)
|
||||
.then((deps) => getDeps.simplifyDeps(deps, onlyProvenance || false, withDev || false))
|
||||
.then((deps) => {
|
||||
// feed extra info
|
||||
set(deps, 'type', 'npm');
|
||||
set(deps, 'language', 'javascript');
|
||||
set(deps, 'severityLevel', severity || 'High');
|
||||
|
||||
return axios({
|
||||
method: 'POST',
|
||||
url: endpoint,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
data: deps,
|
||||
timeout: 15 * 1000,
|
||||
}).then((res) => {
|
||||
let responseJson = res.data as SocVulnResponse;
|
||||
|
||||
if (responseJson.ok) {
|
||||
logger.info(
|
||||
util.format("✓ Tested %s dependencies for known vulnerabilities, no vulnerable paths found.",
|
||||
responseJson.dependencyCount));
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
if (responseJson.vulnerabilities) {
|
||||
responseJson.vulnerabilities.forEach((vuln) => {
|
||||
printSingleVuln(vuln);
|
||||
});
|
||||
|
||||
logger.warn(
|
||||
util.format("Tested %s dependencies for known vulnerabilities, found %d vulnerable paths.",
|
||||
responseJson.dependencyCount, responseJson.vulnerabilities.length));
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
if (error.response) {
|
||||
throw new Error("API return data format error.");
|
||||
}
|
||||
});
|
||||
}).catch((error) => {
|
||||
return Promise.reject(error);
|
||||
});
|
||||
}
|
||||
113
src/pkg-resolve.ts
Normal file
113
src/pkg-resolve.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
Copyright 2017 Snyk Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
import set = Reflect.set;
|
||||
|
||||
export { resolvePkg, sync };
|
||||
|
||||
import * as fs from 'then-fs';
|
||||
import * as path from 'path';
|
||||
import * as debugModule from 'debug';
|
||||
|
||||
let debug = debugModule('mosec:resolve');
|
||||
|
||||
function resolvePkg(name, basedir) {
|
||||
if (!basedir) {
|
||||
basedir = process.cwd();
|
||||
}
|
||||
|
||||
let filename = path.resolve(basedir, 'node_modules', name, 'package.json');
|
||||
debug('%s: %s', name, filename);
|
||||
return fs.stat(filename).then(function (stat) {
|
||||
if (stat.isFile()) {
|
||||
return path.dirname(filename);
|
||||
}
|
||||
}).catch(function (error) {
|
||||
debug('%s: not found on %s (root? %s)', name, basedir, isRoot(basedir));
|
||||
if (isRoot(basedir)) {
|
||||
debug('at root');
|
||||
error = new Error('package not found ' + name);
|
||||
error.code = 'NO_PACKAGE_FOUND';
|
||||
throw error;
|
||||
}
|
||||
}).then(function (dir) {
|
||||
if (dir) {
|
||||
debug('%s: FOUND AT %s', name, dir);
|
||||
return dir;
|
||||
}
|
||||
|
||||
debug('%s: cycling down', name);
|
||||
return resolvePkg(name, path.resolve(basedir, '..'));
|
||||
});
|
||||
}
|
||||
|
||||
function sync(name, basedir) {
|
||||
if (!basedir) {
|
||||
basedir = process.cwd();
|
||||
}
|
||||
|
||||
let filename = path.resolve(basedir, 'node_modules', name, 'package.json');
|
||||
debug('%s: %s', name, filename);
|
||||
|
||||
let isFile = function (file) {
|
||||
let stat;
|
||||
try {
|
||||
stat = fs.statSync(file);
|
||||
} catch (error) {
|
||||
if (error && error.code === 'ENOENT') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return stat.isFile() || stat.isFIFO();
|
||||
};
|
||||
|
||||
if (isFile(filename)) {
|
||||
debug('%s: FOUND AT %s', name, filename);
|
||||
return path.dirname(filename);
|
||||
}
|
||||
|
||||
if (isRoot(basedir)) {
|
||||
debug('%s: not found on %s (now at root)', name, filename);
|
||||
let error = new Error('package not found ' + name);
|
||||
set(error, 'code', 'NO_PACKAGE_FOUND');
|
||||
throw error;
|
||||
}
|
||||
|
||||
debug('%s: cycling down', name);
|
||||
return sync(name, path.resolve(basedir, '..'));
|
||||
}
|
||||
|
||||
function isRoot(dir) {
|
||||
let parsed = parse(dir);
|
||||
return parsed.root === parsed.dir && !parsed.base;
|
||||
}
|
||||
|
||||
// FIXME determine whether this would work properly on windows in 0.10
|
||||
function parse(dir) {
|
||||
/* istanbul ignore else */
|
||||
// jscs:disable requireEarlyReturn
|
||||
if (path.parse) {
|
||||
return path.parse(dir);
|
||||
} else {
|
||||
let split = dir.split(path.sep);
|
||||
let root = split[0] + path.sep;
|
||||
return {
|
||||
base: split[1],
|
||||
root: root,
|
||||
dir: dir,
|
||||
};
|
||||
}
|
||||
// jscs:enable requireEarlyReturn
|
||||
}
|
||||
80
src/try-require.ts
Normal file
80
src/try-require.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
Copyright 2017 Snyk Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
export = tryRequire;
|
||||
|
||||
import * as fs from 'then-fs';
|
||||
import * as path from 'path';
|
||||
import * as debugModule from 'debug';
|
||||
import * as cloneDeep from 'lodash.clonedeep';
|
||||
import * as lru from 'lru-cache';
|
||||
let options = { max: 100, maxAge: 1000 * 60 * 60 };
|
||||
let cache = lru(options);
|
||||
|
||||
let debug = debugModule('mosec:resolve:try-require');
|
||||
|
||||
function tryRequire(filename) {
|
||||
let cached = cache.get(filename);
|
||||
if (cached) {
|
||||
let res = cloneDeep(cached);
|
||||
/* istanbul ignore else */
|
||||
if (process.env.TAP) {
|
||||
res.__cached = true;
|
||||
}
|
||||
return Promise.resolve(res);
|
||||
}
|
||||
return fs.readFile(filename, 'utf8').then(function (pkgStr) {
|
||||
let leadingBOM = '';
|
||||
if (pkgStr && pkgStr[0] === '\ufeff') {
|
||||
// String starts with UTF BOM. Remove it so that JSON.parse doesn't
|
||||
// stumble, but remember it for later use.
|
||||
pkgStr = pkgStr.slice(1);
|
||||
leadingBOM = '\ufeff';
|
||||
}
|
||||
|
||||
let pkg = JSON.parse(pkgStr);
|
||||
pkg.leading = leadingBOM + pkgStr.match(/^(\s*){/)[1];
|
||||
pkg.trailing = pkgStr.match(/}(\s*)$/)[1];
|
||||
return pkg;
|
||||
}).catch(function (e) {
|
||||
debug('tryRequire silently failing on %s', e.message);
|
||||
return null;
|
||||
}).then(function (pkg) {
|
||||
if (!pkg) {
|
||||
return pkg;
|
||||
}
|
||||
|
||||
// fixes potential issues later on
|
||||
if (!pkg.devDependencies) {
|
||||
pkg.devDependencies = {};
|
||||
}
|
||||
|
||||
if (!pkg.dependencies) {
|
||||
pkg.dependencies = {};
|
||||
}
|
||||
|
||||
if (!pkg.name) {
|
||||
pkg.name = path.basename(path.dirname(filename));
|
||||
}
|
||||
|
||||
pkg.__filename = filename;
|
||||
return pkg;
|
||||
}).then(function (pkg) {
|
||||
cache.set(filename, pkg);
|
||||
return cloneDeep(pkg);
|
||||
});
|
||||
}
|
||||
|
||||
tryRequire.cache = cache;
|
||||
83
src/types.ts
Normal file
83
src/types.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
Copyright 2017 Snyk Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
export type DepType = 'extraneous' | 'optional'| 'prod' | 'dev';
|
||||
|
||||
export interface DepSpecDict {
|
||||
[name: string]: string;
|
||||
}
|
||||
|
||||
export interface DepExpandedDict {
|
||||
[name: string]: PackageExpanded;
|
||||
}
|
||||
|
||||
export interface AbbreviatedVersion {
|
||||
readonly name: string;
|
||||
readonly version: string;
|
||||
readonly deprecated?: string;
|
||||
readonly dependencies?: {readonly [name: string]: string};
|
||||
readonly devDependencies?: {readonly [name: string]: string};
|
||||
readonly peerDependencies?: {readonly [name: string]: string};
|
||||
readonly directories?: readonly string[];
|
||||
readonly [key: string]: unknown;
|
||||
}
|
||||
|
||||
// Intermediate type used during parsing
|
||||
export interface PackageJsonEnriched extends AbbreviatedVersion {
|
||||
full: string;
|
||||
from: string[];
|
||||
}
|
||||
|
||||
export interface HasDependencySpecs {
|
||||
readonly dependencies?: {readonly [name: string]: string};
|
||||
readonly devDependencies?: {readonly [name: string]: string};
|
||||
}
|
||||
|
||||
// Similar to package-json.AbbreviatedVersion, but with deps expanded
|
||||
export interface PackageExpanded {
|
||||
name: string;
|
||||
version: string;
|
||||
dep: string; // this is the npm version range spec that was resolved to `version`
|
||||
license: string;
|
||||
depType: DepType;
|
||||
hasDevDependencies: boolean;
|
||||
full: string;
|
||||
from: string[];
|
||||
__devDependencies: DepSpecDict;
|
||||
__dependencies: DepSpecDict;
|
||||
__filename: string;
|
||||
devDependencies: DepExpandedDict;
|
||||
dependencies: DepExpandedDict;
|
||||
__used?: boolean;
|
||||
problems?: string[];
|
||||
extraneous?: boolean;
|
||||
}
|
||||
|
||||
export interface Vulnerability {
|
||||
id: string;
|
||||
severity: string;
|
||||
packageName: string;
|
||||
version: string;
|
||||
from: string[];
|
||||
target_version: string[];
|
||||
title: string;
|
||||
cve: string;
|
||||
}
|
||||
|
||||
export interface SocVulnResponse {
|
||||
ok: boolean;
|
||||
dependencyCount: bigint;
|
||||
vulnerabilities: Vulnerability[];
|
||||
}
|
||||
86
test/deps.test.js
Normal file
86
test/deps.test.js
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
Copyright 2017 Snyk Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
let test = require('tap-only');
|
||||
let deps = require('../src/deps');
|
||||
let path = require('path');
|
||||
let npm2fixture = path.resolve(__dirname,
|
||||
'fixtures/bundle/node_modules/snyk-resolve-deps-fixtures',
|
||||
'node_modules/uglify-package');
|
||||
let npm3fixture = path.resolve(__dirname,
|
||||
'fixtures/bundle/node_modules/snyk-resolve-deps-fixtures');
|
||||
|
||||
|
||||
test('deps - npm@3', function (t) {
|
||||
deps(npm3fixture).then(function (res) {
|
||||
t.ok(!!res, 'package loaded');
|
||||
}).catch(t.fail).then(t.end);
|
||||
});
|
||||
|
||||
// fixture uglify-package does not exist, and newer versions of npm care
|
||||
const legacyNpm = Number(
|
||||
require('child_process').execSync('npm -v').toString().split('.', 1)[0]
|
||||
) < 5;
|
||||
|
||||
legacyNpm && test('deps - with uglify-package', function (t) {
|
||||
deps(npm2fixture).then(function (res) {
|
||||
t.equal(res.name, 'uglify-package', 'package name matches');
|
||||
t.type(res.dependencies, 'object', 'has dependencies');
|
||||
t.equal(Object.keys(res.dependencies).length, 3, 'has 3 file dependencies');
|
||||
|
||||
let ugdeep = res.dependencies['ug-deep'];
|
||||
t.equal(ugdeep.name, 'ug-deep', 'ug-deep exists');
|
||||
}).catch(function (e) {
|
||||
t.fail(e.stack);
|
||||
}).then(t.end);
|
||||
});
|
||||
|
||||
legacyNpm && test('deps - with extraFields', function (t) {
|
||||
deps(npm2fixture, null, { extraFields: [ 'main', 'super-bogus-field' ]}).then(function (res) {
|
||||
t.equal(res.main, 'index.js', 'includes extraFields');
|
||||
t.equal(res['super-bogus-field'], null, 'produces null for empty extraFields fields');
|
||||
}).catch(function (e) {
|
||||
t.fail(e.stack);
|
||||
}).then(t.end);
|
||||
});
|
||||
|
||||
test('deps - throws without path', function (t) {
|
||||
deps().then(function () {
|
||||
t.fail('without a path deps should not succeed');
|
||||
}).catch(function (e) {
|
||||
t.type(e, 'Error', 'error received');
|
||||
t.equal(e.message, 'module path must be a string', 'error is correct');
|
||||
}).then(t.end);
|
||||
});
|
||||
|
||||
// See test/fixtures/pkg-yarn-renamed-deps/README.md
|
||||
test('deps - yarn with renamed dep', function (t) {
|
||||
deps('fixtures/pkg-yarn-renamed-deps').then(function (res) {
|
||||
t.equal(res.name, 'pkg-renamed-dep', 'package name matches');
|
||||
t.type(res.dependencies, 'object', 'has dependencies');
|
||||
t.equal(Object.keys(res.dependencies).length, 2, 'has 2 deps');
|
||||
}).catch(function (e) {
|
||||
t.fail(e.stack);
|
||||
}).then(t.end);
|
||||
});
|
||||
|
||||
test('deps - pkg undefined deps', function (t) {
|
||||
deps('fixtures/pkg-undef-deps').then(function (res) {
|
||||
t.equal(res.name, 'pkg-undef-deps', 'package name matches');
|
||||
t.type(res.dependencies, 'object', 'has dependencies');
|
||||
}).catch(function (e) {
|
||||
t.fail(e.stack);
|
||||
}).then(t.end);
|
||||
});
|
||||
15
test/fixtures/bundle/WARNING.md
vendored
Normal file
15
test/fixtures/bundle/WARNING.md
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# WARNING
|
||||
|
||||
`snyk-resolve-deps-fixtures` runs a `postinstall` command which adds
|
||||
orphaned packages. On purpose.
|
||||
|
||||
`npm` is *gagging* to clean this up for you, and will do so if you
|
||||
so much as look at this directory, and randomly anyway.
|
||||
This breaks all the tests in confusing ways. `undefsafe` and `debug`,
|
||||
but of course, you won't see those in the test output.
|
||||
|
||||
As of `6.13.0`, you can re-run the `postinstall`, without breaking
|
||||
anything else, by running `npm i --save-dev snyk-resolve-deps-fixtures`.
|
||||
|
||||
I added it to every `package.json` in the hope that at least one of
|
||||
them would run last, and there wouldn't be a race.
|
||||
2407
test/fixtures/bundle/package-lock.json
generated
vendored
Normal file
2407
test/fixtures/bundle/package-lock.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
21
test/fixtures/bundle/package.json
vendored
Normal file
21
test/fixtures/bundle/package.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "bundle",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"massive-massive-hack-see-warnings": "npm --prefix node_modules/snyk-resolve-deps-fixtures install --no-save --no-safe-dev undefsafe debug",
|
||||
"postinstall": "npm run massive-massive-hack-see-warnings",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"sinon": "7.5.0",
|
||||
"snyk-resolve-deps-fixtures": "^1.1.6",
|
||||
"tap": "12.7.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"snyk-tree": "1.0.0"
|
||||
}
|
||||
}
|
||||
1023
test/fixtures/not-found.json
vendored
Normal file
1023
test/fixtures/not-found.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4839
test/fixtures/oui.json
vendored
Normal file
4839
test/fixtures/oui.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
657
test/fixtures/out.json
vendored
Normal file
657
test/fixtures/out.json
vendored
Normal file
@@ -0,0 +1,657 @@
|
||||
{
|
||||
"name": "snyk-resolve-deps-fixtures",
|
||||
"version": "1.0.11",
|
||||
"license": "UNLICENSED",
|
||||
"depType": "extraneous",
|
||||
"hasDevDependencies": true,
|
||||
"full": "snyk-resolve-deps-fixtures@1.0.11",
|
||||
"dependencies": {
|
||||
"@remy/npm-tree": {
|
||||
"name": "@remy/npm-tree",
|
||||
"version": "1.0.2",
|
||||
"license": "MIT",
|
||||
"depType": "prod",
|
||||
"hasDevDependencies": true,
|
||||
"full": "@remy/npm-tree@1.0.2",
|
||||
"dependencies": {
|
||||
"archy": {
|
||||
"name": "archy",
|
||||
"version": "1.0.0",
|
||||
"full": "archy@1.0.0",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "MIT",
|
||||
"dep": "^1.0.0",
|
||||
"dependencies": {}
|
||||
}
|
||||
},
|
||||
"dep": "^1.0.2"
|
||||
},
|
||||
"@remy/vuln-test": {
|
||||
"name": "@remy/vuln-test",
|
||||
"version": "1.0.1",
|
||||
"full": "@remy/vuln-test@1.0.1",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "ISC",
|
||||
"dep": "^1.0.1",
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"name": "semver",
|
||||
"version": "2.3.2",
|
||||
"full": "semver@2.3.2",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "BSD",
|
||||
"dep": "^2.3.2",
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"dref": {
|
||||
"name": "dref",
|
||||
"version": "0.0.6",
|
||||
"full": "dref@0.0.6",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "none",
|
||||
"dep": "0.0.6",
|
||||
"dependencies": {
|
||||
"structr": {
|
||||
"name": "structr",
|
||||
"version": "0.2.4",
|
||||
"full": "structr@0.2.4",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "none",
|
||||
"dep": "0.2.x",
|
||||
"dependencies": {}
|
||||
},
|
||||
"dref": {
|
||||
"name": "dref",
|
||||
"version": "0.0.6",
|
||||
"full": "dref@0.0.6",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "none",
|
||||
"dep": "0.0.6",
|
||||
"dependencies": {
|
||||
"structr": {
|
||||
"name": "structr",
|
||||
"version": "0.2.4",
|
||||
"full": "structr@0.2.4",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "none",
|
||||
"dep": "0.2.x",
|
||||
"__from": [
|
||||
"snyk-resolve-deps-fixtures",
|
||||
"dref",
|
||||
"structr"
|
||||
],
|
||||
"__devDependencies": {},
|
||||
"__dependencies": {},
|
||||
"__filename": "/Users/remy/Sites/snyk-resolve-deps-npm@2/node_modules/snyk-resolve-deps-fixtures/node_modules/dref/node_modules/structr/package.json",
|
||||
"dependencies": false,
|
||||
"__used": true
|
||||
},
|
||||
"type-component": {
|
||||
"name": "type-component",
|
||||
"version": "0.0.1",
|
||||
"full": "type-component@0.0.1",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "none",
|
||||
"dep": "0.0.x",
|
||||
"__from": [
|
||||
"snyk-resolve-deps-fixtures",
|
||||
"dref",
|
||||
"type-component"
|
||||
],
|
||||
"__devDependencies": {},
|
||||
"__dependencies": {},
|
||||
"__filename": "/Users/remy/Sites/snyk-resolve-deps-npm@2/node_modules/snyk-resolve-deps-fixtures/node_modules/dref/node_modules/type-component/package.json",
|
||||
"dependencies": false,
|
||||
"__used": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"type-component": {
|
||||
"name": "type-component",
|
||||
"version": "0.0.1",
|
||||
"full": "type-component@0.0.1",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "none",
|
||||
"dep": "0.0.x",
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"semver-rs-demo": {
|
||||
"name": "semver-rs-demo",
|
||||
"version": "1.0.0",
|
||||
"full": "semver-rs-demo@1.0.0",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "ISC",
|
||||
"dep": "^1.0.0",
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"name": "semver",
|
||||
"version": "2.3.2",
|
||||
"full": "semver@2.3.2",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "BSD",
|
||||
"dep": "^2.3.2",
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"uglify-package": {
|
||||
"name": "uglify-package",
|
||||
"version": "1.0.0",
|
||||
"full": "uglify-package@1.0.0",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": "/Users/remy/Sites/snyk-resolve-deps-npm@2/node_modules/snyk-resolve-deps-fixtures/node_modules/uglify-package",
|
||||
"license": "ISC",
|
||||
"dep": "*",
|
||||
"dependencies": {
|
||||
"ug-deep": {
|
||||
"name": "ug-deep",
|
||||
"version": "1.0.0",
|
||||
"full": "ug-deep@1.0.0",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": "/Users/remy/Sites/snyk-resolve-deps-npm@2/node_modules/snyk-resolve-deps-fixtures/node_modules/uglify-package/node_modules/ug-deep",
|
||||
"license": "ISC",
|
||||
"dep": "^1.0.0",
|
||||
"dependencies": {
|
||||
"uglify-js": {
|
||||
"name": "uglify-js",
|
||||
"version": "2.4.24",
|
||||
"full": "uglify-js@2.4.24",
|
||||
"valid": false,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "BSD",
|
||||
"dep": null,
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"name": "async",
|
||||
"version": "0.2.10",
|
||||
"full": "async@0.2.10",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "MIT",
|
||||
"dep": "~0.2.6",
|
||||
"dependencies": {}
|
||||
},
|
||||
"source-map": {
|
||||
"name": "source-map",
|
||||
"version": "0.1.34",
|
||||
"full": "source-map@0.1.34",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "BSD",
|
||||
"dep": "0.1.34",
|
||||
"dependencies": {
|
||||
"amdefine": {
|
||||
"name": "amdefine",
|
||||
"version": "1.0.0",
|
||||
"full": "amdefine@1.0.0",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "BSD-3-Clause AND MIT",
|
||||
"dep": ">=0.0.4",
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"uglify-to-browserify": {
|
||||
"name": "uglify-to-browserify",
|
||||
"version": "1.0.2",
|
||||
"full": "uglify-to-browserify@1.0.2",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "MIT",
|
||||
"dep": "~1.0.0",
|
||||
"dependencies": {}
|
||||
},
|
||||
"yargs": {
|
||||
"name": "yargs",
|
||||
"version": "3.5.4",
|
||||
"full": "yargs@3.5.4",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "MIT/X11",
|
||||
"dep": "~3.5.4",
|
||||
"dependencies": {
|
||||
"camelcase": {
|
||||
"name": "camelcase",
|
||||
"version": "1.2.1",
|
||||
"full": "camelcase@1.2.1",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "MIT",
|
||||
"dep": "^1.0.2",
|
||||
"dependencies": {}
|
||||
},
|
||||
"decamelize": {
|
||||
"name": "decamelize",
|
||||
"version": "1.1.2",
|
||||
"full": "decamelize@1.1.2",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "MIT",
|
||||
"dep": "^1.0.0",
|
||||
"dependencies": {
|
||||
"escape-string-regexp": {
|
||||
"name": "escape-string-regexp",
|
||||
"version": "1.0.4",
|
||||
"full": "escape-string-regexp@1.0.4",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "MIT",
|
||||
"dep": "^1.0.4",
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"window-size": {
|
||||
"name": "window-size",
|
||||
"version": "0.1.0",
|
||||
"full": "window-size@0.1.0",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "MIT",
|
||||
"dep": "0.1.0",
|
||||
"dependencies": {}
|
||||
},
|
||||
"wordwrap": {
|
||||
"name": "wordwrap",
|
||||
"version": "0.0.2",
|
||||
"full": "wordwrap@0.0.2",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "MIT/X11",
|
||||
"dep": "0.0.2",
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ug-deep-alt": {
|
||||
"name": "ug-deep-alt",
|
||||
"version": "1.0.0",
|
||||
"full": "ug-deep-alt@1.0.0",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "ISC",
|
||||
"dep": "^1.0.0",
|
||||
"dependencies": {
|
||||
"uglify-js": {
|
||||
"name": "uglify-js",
|
||||
"version": "2.4.24",
|
||||
"full": "uglify-js@2.4.24",
|
||||
"valid": false,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "BSD",
|
||||
"dep": null,
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"name": "async",
|
||||
"version": "0.2.10",
|
||||
"full": "async@0.2.10",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "MIT",
|
||||
"dep": "~0.2.6",
|
||||
"__from": [
|
||||
"snyk-resolve-deps-fixtures",
|
||||
"uglify-package",
|
||||
"uglify-js",
|
||||
"async"
|
||||
],
|
||||
"__devDependencies": {
|
||||
"nodeunit": ">0.0.0",
|
||||
"uglify-js": "1.2.x",
|
||||
"nodelint": ">0.0.0"
|
||||
},
|
||||
"__dependencies": {},
|
||||
"__filename": "/Users/remy/Sites/snyk-resolve-deps-npm@2/node_modules/snyk-resolve-deps-fixtures/node_modules/uglify-package/node_modules/uglify-js/node_modules/async/package.json",
|
||||
"dependencies": false,
|
||||
"__used": true
|
||||
},
|
||||
"source-map": {
|
||||
"name": "source-map",
|
||||
"version": "0.1.34",
|
||||
"full": "source-map@0.1.34",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "BSD",
|
||||
"dep": "0.1.34",
|
||||
"__from": [
|
||||
"snyk-resolve-deps-fixtures",
|
||||
"uglify-package",
|
||||
"uglify-js",
|
||||
"source-map"
|
||||
],
|
||||
"__devDependencies": {
|
||||
"dryice": ">=0.4.8"
|
||||
},
|
||||
"__dependencies": {
|
||||
"amdefine": ">=0.0.4"
|
||||
},
|
||||
"__filename": "/Users/remy/Sites/snyk-resolve-deps-npm@2/node_modules/snyk-resolve-deps-fixtures/node_modules/uglify-package/node_modules/uglify-js/node_modules/source-map/package.json",
|
||||
"dependencies": {
|
||||
"amdefine": {
|
||||
"name": "amdefine",
|
||||
"version": "1.0.0",
|
||||
"full": "amdefine@1.0.0",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "BSD-3-Clause AND MIT",
|
||||
"dep": ">=0.0.4",
|
||||
"__from": [
|
||||
"snyk-resolve-deps-fixtures",
|
||||
"uglify-package",
|
||||
"uglify-js",
|
||||
"source-map",
|
||||
"amdefine"
|
||||
],
|
||||
"__devDependencies": {},
|
||||
"__dependencies": {},
|
||||
"__filename": "/Users/remy/Sites/snyk-resolve-deps-npm@2/node_modules/snyk-resolve-deps-fixtures/node_modules/uglify-package/node_modules/uglify-js/node_modules/source-map/node_modules/amdefine/package.json",
|
||||
"dependencies": false,
|
||||
"__used": true
|
||||
}
|
||||
},
|
||||
"__used": true
|
||||
},
|
||||
"uglify-to-browserify": {
|
||||
"name": "uglify-to-browserify",
|
||||
"version": "1.0.2",
|
||||
"full": "uglify-to-browserify@1.0.2",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "MIT",
|
||||
"dep": "~1.0.0",
|
||||
"__from": [
|
||||
"snyk-resolve-deps-fixtures",
|
||||
"uglify-package",
|
||||
"uglify-js",
|
||||
"uglify-to-browserify"
|
||||
],
|
||||
"__devDependencies": {
|
||||
"uglify-js": "~2.4.0",
|
||||
"source-map": "~0.1.27"
|
||||
},
|
||||
"__dependencies": {},
|
||||
"__filename": "/Users/remy/Sites/snyk-resolve-deps-npm@2/node_modules/snyk-resolve-deps-fixtures/node_modules/uglify-package/node_modules/uglify-js/node_modules/uglify-to-browserify/package.json",
|
||||
"dependencies": false,
|
||||
"__used": true
|
||||
},
|
||||
"yargs": {
|
||||
"name": "yargs",
|
||||
"version": "3.5.4",
|
||||
"full": "yargs@3.5.4",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "MIT/X11",
|
||||
"dep": "~3.5.4",
|
||||
"__from": [
|
||||
"snyk-resolve-deps-fixtures",
|
||||
"uglify-package",
|
||||
"uglify-js",
|
||||
"yargs"
|
||||
],
|
||||
"__devDependencies": {
|
||||
"blanket": "^1.1.6",
|
||||
"chai": "^1.10.0",
|
||||
"coveralls": "^2.11.2",
|
||||
"hashish": "0.0.4",
|
||||
"mocha": "2.1.0",
|
||||
"mocha-lcov-reporter": "0.0.1",
|
||||
"mocoverage": "^1.0.0"
|
||||
},
|
||||
"__dependencies": {
|
||||
"camelcase": "^1.0.2",
|
||||
"decamelize": "^1.0.0",
|
||||
"window-size": "0.1.0",
|
||||
"wordwrap": "0.0.2"
|
||||
},
|
||||
"__filename": "/Users/remy/Sites/snyk-resolve-deps-npm@2/node_modules/snyk-resolve-deps-fixtures/node_modules/uglify-package/node_modules/uglify-js/node_modules/yargs/package.json",
|
||||
"dependencies": {
|
||||
"camelcase": {
|
||||
"name": "camelcase",
|
||||
"version": "1.2.1",
|
||||
"full": "camelcase@1.2.1",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "MIT",
|
||||
"dep": "^1.0.2",
|
||||
"__from": [
|
||||
"snyk-resolve-deps-fixtures",
|
||||
"uglify-package",
|
||||
"uglify-js",
|
||||
"yargs",
|
||||
"camelcase"
|
||||
],
|
||||
"__devDependencies": {
|
||||
"ava": "0.0.4"
|
||||
},
|
||||
"__dependencies": {},
|
||||
"__filename": "/Users/remy/Sites/snyk-resolve-deps-npm@2/node_modules/snyk-resolve-deps-fixtures/node_modules/uglify-package/node_modules/uglify-js/node_modules/yargs/node_modules/camelcase/package.json",
|
||||
"dependencies": false,
|
||||
"__used": true
|
||||
},
|
||||
"decamelize": {
|
||||
"name": "decamelize",
|
||||
"version": "1.1.2",
|
||||
"full": "decamelize@1.1.2",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "MIT",
|
||||
"dep": "^1.0.0",
|
||||
"__from": [
|
||||
"snyk-resolve-deps-fixtures",
|
||||
"uglify-package",
|
||||
"uglify-js",
|
||||
"yargs",
|
||||
"decamelize"
|
||||
],
|
||||
"__devDependencies": {
|
||||
"ava": "*",
|
||||
"xo": "*"
|
||||
},
|
||||
"__dependencies": {
|
||||
"escape-string-regexp": "^1.0.4"
|
||||
},
|
||||
"__filename": "/Users/remy/Sites/snyk-resolve-deps-npm@2/node_modules/snyk-resolve-deps-fixtures/node_modules/uglify-package/node_modules/uglify-js/node_modules/yargs/node_modules/decamelize/package.json",
|
||||
"dependencies": {
|
||||
"escape-string-regexp": {
|
||||
"name": "escape-string-regexp",
|
||||
"version": "1.0.4",
|
||||
"full": "escape-string-regexp@1.0.4",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "MIT",
|
||||
"dep": "^1.0.4",
|
||||
"__from": [
|
||||
"snyk-resolve-deps-fixtures",
|
||||
"uglify-package",
|
||||
"uglify-js",
|
||||
"yargs",
|
||||
"decamelize",
|
||||
"escape-string-regexp"
|
||||
],
|
||||
"__devDependencies": {
|
||||
"ava": "*",
|
||||
"xo": "*"
|
||||
},
|
||||
"__dependencies": {},
|
||||
"__filename": "/Users/remy/Sites/snyk-resolve-deps-npm@2/node_modules/snyk-resolve-deps-fixtures/node_modules/uglify-package/node_modules/uglify-js/node_modules/yargs/node_modules/decamelize/node_modules/escape-string-regexp/package.json",
|
||||
"dependencies": false,
|
||||
"__used": true
|
||||
}
|
||||
},
|
||||
"__used": true
|
||||
},
|
||||
"window-size": {
|
||||
"name": "window-size",
|
||||
"version": "0.1.0",
|
||||
"full": "window-size@0.1.0",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "MIT",
|
||||
"dep": "0.1.0",
|
||||
"__from": [
|
||||
"snyk-resolve-deps-fixtures",
|
||||
"uglify-package",
|
||||
"uglify-js",
|
||||
"yargs",
|
||||
"window-size"
|
||||
],
|
||||
"__devDependencies": {},
|
||||
"__dependencies": {},
|
||||
"__filename": "/Users/remy/Sites/snyk-resolve-deps-npm@2/node_modules/snyk-resolve-deps-fixtures/node_modules/uglify-package/node_modules/uglify-js/node_modules/yargs/node_modules/window-size/package.json",
|
||||
"dependencies": false,
|
||||
"__used": true
|
||||
},
|
||||
"wordwrap": {
|
||||
"name": "wordwrap",
|
||||
"version": "0.0.2",
|
||||
"full": "wordwrap@0.0.2",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "MIT/X11",
|
||||
"dep": "0.0.2",
|
||||
"__from": [
|
||||
"snyk-resolve-deps-fixtures",
|
||||
"uglify-package",
|
||||
"uglify-js",
|
||||
"yargs",
|
||||
"wordwrap"
|
||||
],
|
||||
"__devDependencies": {
|
||||
"expresso": "=0.7.x"
|
||||
},
|
||||
"__dependencies": {},
|
||||
"__filename": "/Users/remy/Sites/snyk-resolve-deps-npm@2/node_modules/snyk-resolve-deps-fixtures/node_modules/uglify-package/node_modules/uglify-js/node_modules/yargs/node_modules/wordwrap/package.json",
|
||||
"dependencies": false,
|
||||
"__used": true
|
||||
}
|
||||
},
|
||||
"__used": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"ug-no-deps": {
|
||||
"name": "ug-no-deps",
|
||||
"version": "1.0.0",
|
||||
"full": "ug-no-deps@1.0.0",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "none",
|
||||
"dep": "*",
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"name": "debug",
|
||||
"version": "2.2.0",
|
||||
"full": "debug@2.2.0",
|
||||
"valid": false,
|
||||
"depType": "dev",
|
||||
"snyk": false,
|
||||
"license": "MIT",
|
||||
"dep": "^2.2.0",
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"name": "ms",
|
||||
"version": "0.7.1",
|
||||
"full": "ms@0.7.1",
|
||||
"valid": true,
|
||||
"depType": "prod",
|
||||
"snyk": false,
|
||||
"license": "none",
|
||||
"dep": "0.7.1",
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"undefsafe": {
|
||||
"name": "undefsafe",
|
||||
"version": "0.0.3 null",
|
||||
"full": "undefsafe@0.0.3",
|
||||
"valid": false,
|
||||
"depType": "extraneous",
|
||||
"snyk": false,
|
||||
"license": "MIT / http://rem.mit-license.org",
|
||||
"dep": null,
|
||||
"__from": [
|
||||
"snyk-resolve-deps-fixtures",
|
||||
"undefsafe"
|
||||
],
|
||||
"__devDependencies": {
|
||||
"mocha": "~1.16.2"
|
||||
},
|
||||
"__dependencies": {},
|
||||
"__filename": "/Users/remy/Sites/snyk-resolve-deps-npm@2/node_modules/snyk-resolve-deps-fixtures/node_modules/undefsafe/package.json",
|
||||
"dependencies": false,
|
||||
"extraneous": true,
|
||||
"problems": [
|
||||
"\u001b[40m\u001b[32mextraneous\u001b[39m\u001b[49m: snyk-resolve-deps-fixtures > undefsafe > undefsafe@0.0.3"
|
||||
]
|
||||
}
|
||||
},
|
||||
"problems": [
|
||||
"missing: ansicolors@^0.3.2, required by @remy/npm-tree@1.0.2",
|
||||
"missing: semantic-release@^4.3.5, required by @remy/npm-tree@1.0.2",
|
||||
"missing: tap@^5.1.1, required by @remy/npm-tree@1.0.2",
|
||||
"\u001b[40m\u001b[32mextraneous\u001b[39m\u001b[49m: snyk-resolve-deps-fixtures > undefsafe > undefsafe@0.0.3"
|
||||
]
|
||||
}
|
||||
5
test/fixtures/pkg-missing-deps/package.json
vendored
Normal file
5
test/fixtures/pkg-missing-deps/package.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "pkg-missing-deps",
|
||||
"version": "1.0.0",
|
||||
"dependencies": { "doesnotexist": "1.0.0" }
|
||||
}
|
||||
6
test/fixtures/pkg-missing-name/package.json
vendored
Normal file
6
test/fixtures/pkg-missing-name/package.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"undefsafe": "^1.0.0"
|
||||
}
|
||||
}
|
||||
7
test/fixtures/pkg-not-install/package.json
vendored
Normal file
7
test/fixtures/pkg-not-install/package.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "pkg-not-install",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"debug": "^4.2.0"
|
||||
}
|
||||
}
|
||||
7
test/fixtures/pkg-undef-deps-with-modules/package.json
vendored
Normal file
7
test/fixtures/pkg-undef-deps-with-modules/package.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "pkg-undef-deps",
|
||||
"version": "0.0.1",
|
||||
"devDependencies": {
|
||||
"debug": "^2.2.0"
|
||||
}
|
||||
}
|
||||
4
test/fixtures/pkg-undef-deps/package.json
vendored
Normal file
4
test/fixtures/pkg-undef-deps/package.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "pkg-undef-deps",
|
||||
"version": "0.0.1"
|
||||
}
|
||||
14
test/fixtures/pkg-yarn-renamed-deps/README.md
vendored
Normal file
14
test/fixtures/pkg-yarn-renamed-deps/README.md
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
Both npm and Yarn support "GitHub URL" kind of dependency:
|
||||
|
||||
"somepackage": "githubuser/somepackage",
|
||||
|
||||
It is possible to actually use a different name for the package:
|
||||
|
||||
"myname": "githubuser/somepackage",
|
||||
|
||||
Npm claims to support that (https://docs.npmjs.com/files/package.json#github-urls), but in practice will just not pull the dependency.
|
||||
|
||||
But Yarn actually allows it: https://yarnpkg.com/lang/en/docs/cli/add/#toc-yarn-add-alias
|
||||
|
||||
This fixture helps to test that we are actually supporting such renamed dependencies
|
||||
during the resolution.
|
||||
8
test/fixtures/pkg-yarn-renamed-deps/package.json
vendored
Normal file
8
test/fixtures/pkg-yarn-renamed-deps/package.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "pkg-renamed-dep",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"githubrenamed": "stevemao/left-pad",
|
||||
"npmrenamed": "npm:ms"
|
||||
}
|
||||
}
|
||||
12
test/fixtures/pkg-yarn-renamed-deps/yarn.lock
vendored
Normal file
12
test/fixtures/pkg-yarn-renamed-deps/yarn.lock
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
githubrenamed@stevemao/left-pad:
|
||||
version "1.3.0"
|
||||
resolved "https://codeload.github.com/stevemao/left-pad/tar.gz/cc0aa707ca1a3158f392a689142d64691bc12a53"
|
||||
|
||||
"npmrenamed@npm:ms":
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
|
||||
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
|
||||
44
test/main.test.js
Normal file
44
test/main.test.js
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright 2017 Snyk Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
let test = require('tap-only');
|
||||
let check = require("../src/main");
|
||||
|
||||
test('main - empty dir', function (t) {
|
||||
check.checkProject('fixtures/empty-dir', 'fake endpoint').then(function (res) {
|
||||
t.fail('empty dir should not succeed', res);
|
||||
}).catch(function (e) {
|
||||
t.type(e, 'Error', 'error received');
|
||||
t.notEqual(e.message.indexOf(' is not a node project'), -1, 'error is correct');
|
||||
}).then(t.end);
|
||||
});
|
||||
|
||||
test('main - none exist dir', function (t) {
|
||||
check.checkProject('fixtures/im_not_exist', 'fake endpoint').then(function (res) {
|
||||
t.fail('none exist dir should not succeed', res);
|
||||
}).catch(function (e) {
|
||||
t.type(e, 'Error', 'error received');
|
||||
t.notEqual(e.message.indexOf('dir is not exists'), -1, 'error is correct');
|
||||
}).then(t.end);
|
||||
});
|
||||
|
||||
test('main - pkg-not-install', function (t) {
|
||||
check.checkProject('fixtures/pkg-not-install', 'fake endpoint').then(function (res) {
|
||||
t.fail('not install pkg dir should not succeed.', res)
|
||||
}).catch(function (e) {
|
||||
t.type(e, 'Error', 'error received');
|
||||
t.notEqual(e.message.indexOf("run 'npm install' first"), -1, 'error is correct')
|
||||
}).then(t.end);
|
||||
});
|
||||
14
test/manual.js
Executable file
14
test/manual.js
Executable file
@@ -0,0 +1,14 @@
|
||||
let resolve = require('../src/deps');
|
||||
|
||||
function main() {
|
||||
let target = process.argv[2];
|
||||
|
||||
resolve(target).then(function (result) {
|
||||
console.log(JSON.stringify(result, null, 2));
|
||||
}).catch(function (error) {
|
||||
console.log('Error:', error.stack);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
main();
|
||||
18
tsconfig.json
Normal file
18
tsconfig.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"pretty": true,
|
||||
"target": "es2015",
|
||||
"lib": [
|
||||
"es2015"
|
||||
],
|
||||
"module": "commonjs",
|
||||
"allowJs": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"noImplicitAny": false // Needed to compile tap and ansi-escapes
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*"
|
||||
]
|
||||
}
|
||||
32
tslint.json
Normal file
32
tslint.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"extends": "tslint:recommended",
|
||||
"rules": {
|
||||
"max-line-length": {
|
||||
"options": [120]
|
||||
},
|
||||
"trailing-comma": [true, {"multiline": "always"}],
|
||||
"triple-equals": true,
|
||||
"curly": true,
|
||||
"indent": [true, "spaces", 4],
|
||||
"interface-name": false,
|
||||
"object-literal-sort-keys": false,
|
||||
"ordered-imports": false,
|
||||
// "quotemark": [true, "single", "avoid-escape", "avoid-template"],
|
||||
"semicolon": [true, "always"],
|
||||
"no-console": [false],
|
||||
"quotemark": [false],
|
||||
"no-default-export": true,
|
||||
"no-var-requires": false,
|
||||
"prefer-const": false,
|
||||
"only-arrow-functions": false,
|
||||
"space-before-function-paren": false,
|
||||
"object-literal-shorthand": false,
|
||||
"prefer-for-of": false
|
||||
},
|
||||
"linterOptions": {
|
||||
"exclude": [
|
||||
"./text/fixtures",
|
||||
"./node_modules"
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user