/
usr
/
local
/
lib
/
node_modules
/
npm
/
lib
/
utils
/
/usr/local/lib/node_modules/npm/lib/utils
mkdir
upload
Name
Size
Mode
Actions
audit-error.js
1078
0644
edit
dl
rm
auth.js
3288
0644
edit
dl
rm
cmd-list.js
2953
0644
edit
dl
rm
completion.fish
1596
0644
edit
dl
rm
completion.sh
1898
0755
edit
dl
rm
did-you-mean.js
1143
0644
edit
dl
rm
display.js
16760
0644
edit
dl
rm
error-message.js
15775
0644
edit
dl
rm
explain-dep.js
3648
0644
edit
dl
rm
explain-eresolve.js
2582
0644
edit
dl
rm
format-bytes.js
624
0644
edit
dl
rm
format-search-stream.js
4913
0644
edit
dl
rm
format.js
2140
0644
edit
dl
rm
get-identity.js
797
0644
edit
dl
rm
get-workspaces.js
1748
0644
edit
dl
rm
installed-deep.js
1129
0644
edit
dl
rm
installed-shallow.js
583
0644
edit
dl
rm
is-windows.js
177
0644
edit
dl
rm
log-file.js
7860
0644
edit
dl
rm
npm-usage.js
2072
0644
edit
dl
rm
oidc.js
7368
0644
edit
dl
rm
open-url.js
2553
0644
edit
dl
rm
output-error.js
788
0644
edit
dl
rm
ping.js
265
0644
edit
dl
rm
queryable.js
9611
0644
edit
dl
rm
read-user-info.js
2095
0644
edit
dl
rm
reify-finish.js
753
0644
edit
dl
rm
reify-output.js
6475
0644
edit
dl
rm
sbom-cyclonedx.js
5656
0644
edit
dl
rm
sbom-spdx.js
5288
0644
edit
dl
rm
tar.js
3511
0644
edit
dl
rm
timers.js
2120
0644
edit
dl
rm
update-workspaces.js
997
0644
edit
dl
rm
validate-lockfile.js
1023
0644
edit
dl
rm
verify-signatures.js
12499
0644
edit
dl
rm
Edit:
/usr/local/lib/node_modules/npm/lib/utils/sbom-cyclonedx.js
(5656B)
const crypto = require('node:crypto') const parseLicense = require('spdx-expression-parse') const PackageJson = require('@npmcli/package-json') const npa = require('npm-package-arg') const ssri = require('ssri') const CYCLONEDX_SCHEMA = 'http://cyclonedx.org/schema/bom-1.5.schema.json' const CYCLONEDX_FORMAT = 'CycloneDX' const CYCLONEDX_SCHEMA_VERSION = '1.5' const PROP_BUNDLED = 'cdx:npm:package:bundled' const PROP_DEVELOPMENT = 'cdx:npm:package:development' const PROP_EXTRANEOUS = 'cdx:npm:package:extraneous' const PROP_PRIVATE = 'cdx:npm:package:private' const REF_VCS = 'vcs' const REF_WEBSITE = 'website' const REF_ISSUE_TRACKER = 'issue-tracker' const REF_DISTRIBUTION = 'distribution' const ALGO_MAP = { sha1: 'SHA-1', sha256: 'SHA-256', sha384: 'SHA-384', sha512: 'SHA-512', } const cyclonedxOutput = ({ npm, nodes, packageType, packageLockOnly }) => { const rootNode = nodes.find(node => node.isRoot) const childNodes = nodes.filter(node => !node.isRoot && !node.isLink) const uuid = crypto.randomUUID() // Create list of child nodes w/ unique IDs const childNodeMap = new Map() for (const item of childNodes) { const id = toCyclonedxID(item) if (!childNodeMap.has(id)) { childNodeMap.set(id, item) } } const uniqueChildNodes = Array.from(childNodeMap.values()) const deps = [rootNode, ...uniqueChildNodes] .map(node => toCyclonedxDependency(node, nodes)) const bom = { $schema: CYCLONEDX_SCHEMA, bomFormat: CYCLONEDX_FORMAT, specVersion: CYCLONEDX_SCHEMA_VERSION, serialNumber: `urn:uuid:${uuid}`, version: 1, metadata: { timestamp: new Date().toISOString(), lifecycles: [ { phase: packageLockOnly ? 'pre-build' : 'build' }, ], tools: [ { vendor: 'npm', name: 'cli', version: npm.version, }, ], component: toCyclonedxItem(rootNode, { packageType }), }, components: uniqueChildNodes.map(toCyclonedxItem), dependencies: deps, } return bom } const toCyclonedxItem = (node, { packageType }) => { packageType = packageType || 'library' // Calculate purl from package spec let spec = npa(node.pkgid) spec = (spec.type === 'alias') ? spec.subSpec : spec const purl = npa.toPurl(spec) + (isGitNode(node) ? `?vcs_url=${node.resolved}` : '') if (node.package) { const toNormalize = new PackageJson() toNormalize.fromContent(node.package).normalize({ steps: ['normalizeData'] }) node.package = toNormalize.content } let license = node.package?.license if (license) { if (typeof license === 'object') { license = license.type } } else if (Array.isArray(node.package?.licenses)) { license = node.package.licenses .map(l => (typeof l === 'object' ? l.type : l)) .filter(Boolean) .join(' OR ') } let parsedLicense try { parsedLicense = parseLicense(license) } catch { parsedLicense = null } const component = { 'bom-ref': toCyclonedxID(node), type: packageType, name: node.name, version: node.version, scope: (node.optional || node.devOptional) ? 'optional' : 'required', author: (typeof node.package?.author === 'object') ? node.package.author.name : (node.package?.author || undefined), description: node.package?.description || undefined, purl: purl, properties: [], externalReferences: [], } if (node.integrity) { const integrity = ssri.parse(node.integrity, { single: true }) component.hashes = [{ alg: ALGO_MAP[integrity.algorithm] || /* istanbul ignore next */ 'SHA-512', content: integrity.hexDigest(), }] } if (node.dev === true) { component.properties.push(prop(PROP_DEVELOPMENT)) } if (node.package?.private === true) { component.properties.push(prop(PROP_PRIVATE)) } if (node.extraneous === true) { component.properties.push(prop(PROP_EXTRANEOUS)) } if (node.inBundle === true) { component.properties.push(prop(PROP_BUNDLED)) } if (!node.isLink && node.resolved) { component.externalReferences.push(extRef(REF_DISTRIBUTION, node.resolved)) } if (node.package?.repository?.url) { component.externalReferences.push(extRef(REF_VCS, node.package.repository.url)) } if (node.package?.homepage) { component.externalReferences.push(extRef(REF_WEBSITE, node.package.homepage)) } if (node.package?.bugs?.url) { component.externalReferences.push(extRef(REF_ISSUE_TRACKER, node.package.bugs.url)) } // If license is a single SPDX license, use the license field if (parsedLicense?.license) { component.licenses = [{ license: { id: parsedLicense.license } }] // If license is a conjunction, use the expression field } else if (parsedLicense?.conjunction) { component.licenses = [{ expression: license }] } return component } const toCyclonedxDependency = (node, nodes) => { return { ref: toCyclonedxID(node), dependsOn: [...node.edgesOut.values()] // Filter out edges that are linking to nodes not in the list .filter(edge => nodes.find(n => n === edge.to)) .map(edge => toCyclonedxID(edge.to)) .filter(id => id), } } const toCyclonedxID = (node) => `${node.packageName}@${node.version}` const prop = (name) => ({ name, value: 'true' }) const extRef = (type, url) => ({ type, url }) const isGitNode = (node) => { if (!node.resolved) { return } try { const { type } = npa(node.resolved) return type === 'git' || type === 'hosted' } catch { /* istanbul ignore next */ return false } } module.exports = { cyclonedxOutput }
Save
cmd:
run