Skip to content

Instantly share code, notes, and snippets.

@Xavier59
Created April 13, 2025 17:53
Show Gist options
  • Select an option

  • Save Xavier59/881aef04940970dc3e738dcbff64151f to your computer and use it in GitHub Desktop.

Select an option

Save Xavier59/881aef04940970dc3e738dcbff64151f to your computer and use it in GitHub Desktop.
Lockfile Lint incorrectly verifies package name

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}/`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment