Lockfile Lint is a tool to defend against Supply Chain Attack by enforcing policies in lock files.
Lockfile Lint has an option --validate-package-names to verify that packages' resolve attribute is not tampered with and match the package name.
The verification is implented in ValidatePackageName.js:
const path = packageResolvedURL.pathname
const packageNameFromResolved = path.split('/-/')[0].slice(1)
const packageNameOnly = this._getPackageNameOnly(packageName)
const expectedURLBeginning = `${packageResolvedURL.origin}/${packageNameOnly}`
const isPassing = packageMetadata.resolved.startsWith(expectedURLBeginning)
if (!isPassing) {
validationResult.errors.push({
message: `detected resolved URL for package with a different name: ${packageNameOnly}\n expected: ${packageNameOnly}\n actual: ${packageNameFromResolved}\n`,
package: packageNameOnly
})The policy can be easily bypassed by extending the package name. For example, for a package commander:
"commander": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
"dev": true
},The policy can be bypassed by changing commander to commander2 in resolved:
"commander": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander2/-/commander-4.1.1.tgz",
"integrity": "...",
"dev": true
},Running lockfile-lint --validate-package-names --allowed-schemes "https:" --allowed-hosts npm will pass and an installation with npm would install commander2 rather than commander, successfully bypassing the policy.
In order to prevent this abuse, the verification should be expanded to:
const expectedURLBeginning = `${packageResolvedURL.origin}/${packageNameOnly}/`