diff --git a/node_modules/.gitignore b/node_modules/.gitignore index ca0c5fbd69ae3..1a0706de3b8f3 100644 --- a/node_modules/.gitignore +++ b/node_modules/.gitignore @@ -22,6 +22,21 @@ !/@npmcli/installed-package-contents !/@npmcli/map-workspaces !/@npmcli/metavuln-calculator +!/@npmcli/metavuln-calculator/node_modules/ +/@npmcli/metavuln-calculator/node_modules/* +!/@npmcli/metavuln-calculator/node_modules/@sigstore/ +/@npmcli/metavuln-calculator/node_modules/@sigstore/* +!/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle +!/@npmcli/metavuln-calculator/node_modules/@sigstore/core +!/@npmcli/metavuln-calculator/node_modules/@sigstore/sign +!/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf +!/@npmcli/metavuln-calculator/node_modules/@sigstore/verify +!/@npmcli/metavuln-calculator/node_modules/@tufjs/ +/@npmcli/metavuln-calculator/node_modules/@tufjs/* +!/@npmcli/metavuln-calculator/node_modules/@tufjs/models +!/@npmcli/metavuln-calculator/node_modules/pacote +!/@npmcli/metavuln-calculator/node_modules/sigstore +!/@npmcli/metavuln-calculator/node_modules/tuf-js !/@npmcli/name-from-folder !/@npmcli/node-gyp !/@npmcli/package-json diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/LICENSE b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/LICENSE new file mode 100644 index 0000000000000..e9e7c1679a09d --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 The Sigstore Authors + + 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. diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/build.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/build.js new file mode 100644 index 0000000000000..ade736407554c --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/build.js @@ -0,0 +1,100 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.toMessageSignatureBundle = toMessageSignatureBundle; +exports.toDSSEBundle = toDSSEBundle; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const protobuf_specs_1 = require("@sigstore/protobuf-specs"); +const bundle_1 = require("./bundle"); +// Message signature bundle - $case: 'messageSignature' +function toMessageSignatureBundle(options) { + return { + mediaType: options.certificateChain + ? bundle_1.BUNDLE_V02_MEDIA_TYPE + : bundle_1.BUNDLE_V03_MEDIA_TYPE, + content: { + $case: 'messageSignature', + messageSignature: { + messageDigest: { + algorithm: protobuf_specs_1.HashAlgorithm.SHA2_256, + digest: options.digest, + }, + signature: options.signature, + }, + }, + verificationMaterial: toVerificationMaterial(options), + }; +} +// DSSE envelope bundle - $case: 'dsseEnvelope' +function toDSSEBundle(options) { + return { + mediaType: options.certificateChain + ? bundle_1.BUNDLE_V02_MEDIA_TYPE + : bundle_1.BUNDLE_V03_MEDIA_TYPE, + content: { + $case: 'dsseEnvelope', + dsseEnvelope: toEnvelope(options), + }, + verificationMaterial: toVerificationMaterial(options), + }; +} +function toEnvelope(options) { + return { + payloadType: options.artifactType, + payload: options.artifact, + signatures: [toSignature(options)], + }; +} +function toSignature(options) { + return { + keyid: options.keyHint || '', + sig: options.signature, + }; +} +// Verification material +function toVerificationMaterial(options) { + return { + content: toKeyContent(options), + tlogEntries: [], + timestampVerificationData: { rfc3161Timestamps: [] }, + }; +} +function toKeyContent(options) { + if (options.certificate) { + if (options.certificateChain) { + return { + $case: 'x509CertificateChain', + x509CertificateChain: { + certificates: [{ rawBytes: options.certificate }], + }, + }; + } + else { + return { + $case: 'certificate', + certificate: { rawBytes: options.certificate }, + }; + } + } + else { + return { + $case: 'publicKey', + publicKey: { + hint: options.keyHint || '', + }, + }; + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/bundle.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/bundle.js new file mode 100644 index 0000000000000..eb67a0ddc17bb --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/bundle.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BUNDLE_V03_MEDIA_TYPE = exports.BUNDLE_V03_LEGACY_MEDIA_TYPE = exports.BUNDLE_V02_MEDIA_TYPE = exports.BUNDLE_V01_MEDIA_TYPE = void 0; +exports.isBundleWithCertificateChain = isBundleWithCertificateChain; +exports.isBundleWithPublicKey = isBundleWithPublicKey; +exports.isBundleWithMessageSignature = isBundleWithMessageSignature; +exports.isBundleWithDsseEnvelope = isBundleWithDsseEnvelope; +exports.BUNDLE_V01_MEDIA_TYPE = 'application/vnd.dev.sigstore.bundle+json;version=0.1'; +exports.BUNDLE_V02_MEDIA_TYPE = 'application/vnd.dev.sigstore.bundle+json;version=0.2'; +exports.BUNDLE_V03_LEGACY_MEDIA_TYPE = 'application/vnd.dev.sigstore.bundle+json;version=0.3'; +exports.BUNDLE_V03_MEDIA_TYPE = 'application/vnd.dev.sigstore.bundle.v0.3+json'; +// Type guards for bundle variants. +function isBundleWithCertificateChain(b) { + return b.verificationMaterial.content.$case === 'x509CertificateChain'; +} +function isBundleWithPublicKey(b) { + return b.verificationMaterial.content.$case === 'publicKey'; +} +function isBundleWithMessageSignature(b) { + return b.content.$case === 'messageSignature'; +} +function isBundleWithDsseEnvelope(b) { + return b.content.$case === 'dsseEnvelope'; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/error.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/error.js new file mode 100644 index 0000000000000..f84295323b812 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/error.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ValidationError = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +class ValidationError extends Error { + constructor(message, fields) { + super(message); + this.fields = fields; + } +} +exports.ValidationError = ValidationError; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/index.js new file mode 100644 index 0000000000000..1b012acad4d85 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/index.js @@ -0,0 +1,43 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isBundleV01 = exports.assertBundleV02 = exports.assertBundleV01 = exports.assertBundleLatest = exports.assertBundle = exports.envelopeToJSON = exports.envelopeFromJSON = exports.bundleToJSON = exports.bundleFromJSON = exports.ValidationError = exports.isBundleWithPublicKey = exports.isBundleWithMessageSignature = exports.isBundleWithDsseEnvelope = exports.isBundleWithCertificateChain = exports.BUNDLE_V03_MEDIA_TYPE = exports.BUNDLE_V03_LEGACY_MEDIA_TYPE = exports.BUNDLE_V02_MEDIA_TYPE = exports.BUNDLE_V01_MEDIA_TYPE = exports.toMessageSignatureBundle = exports.toDSSEBundle = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +var build_1 = require("./build"); +Object.defineProperty(exports, "toDSSEBundle", { enumerable: true, get: function () { return build_1.toDSSEBundle; } }); +Object.defineProperty(exports, "toMessageSignatureBundle", { enumerable: true, get: function () { return build_1.toMessageSignatureBundle; } }); +var bundle_1 = require("./bundle"); +Object.defineProperty(exports, "BUNDLE_V01_MEDIA_TYPE", { enumerable: true, get: function () { return bundle_1.BUNDLE_V01_MEDIA_TYPE; } }); +Object.defineProperty(exports, "BUNDLE_V02_MEDIA_TYPE", { enumerable: true, get: function () { return bundle_1.BUNDLE_V02_MEDIA_TYPE; } }); +Object.defineProperty(exports, "BUNDLE_V03_LEGACY_MEDIA_TYPE", { enumerable: true, get: function () { return bundle_1.BUNDLE_V03_LEGACY_MEDIA_TYPE; } }); +Object.defineProperty(exports, "BUNDLE_V03_MEDIA_TYPE", { enumerable: true, get: function () { return bundle_1.BUNDLE_V03_MEDIA_TYPE; } }); +Object.defineProperty(exports, "isBundleWithCertificateChain", { enumerable: true, get: function () { return bundle_1.isBundleWithCertificateChain; } }); +Object.defineProperty(exports, "isBundleWithDsseEnvelope", { enumerable: true, get: function () { return bundle_1.isBundleWithDsseEnvelope; } }); +Object.defineProperty(exports, "isBundleWithMessageSignature", { enumerable: true, get: function () { return bundle_1.isBundleWithMessageSignature; } }); +Object.defineProperty(exports, "isBundleWithPublicKey", { enumerable: true, get: function () { return bundle_1.isBundleWithPublicKey; } }); +var error_1 = require("./error"); +Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return error_1.ValidationError; } }); +var serialized_1 = require("./serialized"); +Object.defineProperty(exports, "bundleFromJSON", { enumerable: true, get: function () { return serialized_1.bundleFromJSON; } }); +Object.defineProperty(exports, "bundleToJSON", { enumerable: true, get: function () { return serialized_1.bundleToJSON; } }); +Object.defineProperty(exports, "envelopeFromJSON", { enumerable: true, get: function () { return serialized_1.envelopeFromJSON; } }); +Object.defineProperty(exports, "envelopeToJSON", { enumerable: true, get: function () { return serialized_1.envelopeToJSON; } }); +var validate_1 = require("./validate"); +Object.defineProperty(exports, "assertBundle", { enumerable: true, get: function () { return validate_1.assertBundle; } }); +Object.defineProperty(exports, "assertBundleLatest", { enumerable: true, get: function () { return validate_1.assertBundleLatest; } }); +Object.defineProperty(exports, "assertBundleV01", { enumerable: true, get: function () { return validate_1.assertBundleV01; } }); +Object.defineProperty(exports, "assertBundleV02", { enumerable: true, get: function () { return validate_1.assertBundleV02; } }); +Object.defineProperty(exports, "isBundleV01", { enumerable: true, get: function () { return validate_1.isBundleV01; } }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/serialized.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/serialized.js new file mode 100644 index 0000000000000..be0d2a2d54d09 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/serialized.js @@ -0,0 +1,49 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.envelopeToJSON = exports.envelopeFromJSON = exports.bundleToJSON = exports.bundleFromJSON = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const protobuf_specs_1 = require("@sigstore/protobuf-specs"); +const bundle_1 = require("./bundle"); +const validate_1 = require("./validate"); +const bundleFromJSON = (obj) => { + const bundle = protobuf_specs_1.Bundle.fromJSON(obj); + switch (bundle.mediaType) { + case bundle_1.BUNDLE_V01_MEDIA_TYPE: + (0, validate_1.assertBundleV01)(bundle); + break; + case bundle_1.BUNDLE_V02_MEDIA_TYPE: + (0, validate_1.assertBundleV02)(bundle); + break; + default: + (0, validate_1.assertBundleLatest)(bundle); + break; + } + return bundle; +}; +exports.bundleFromJSON = bundleFromJSON; +const bundleToJSON = (bundle) => { + return protobuf_specs_1.Bundle.toJSON(bundle); +}; +exports.bundleToJSON = bundleToJSON; +const envelopeFromJSON = (obj) => { + return protobuf_specs_1.Envelope.fromJSON(obj); +}; +exports.envelopeFromJSON = envelopeFromJSON; +const envelopeToJSON = (envelope) => { + return protobuf_specs_1.Envelope.toJSON(envelope); +}; +exports.envelopeToJSON = envelopeToJSON; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/utility.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/utility.js new file mode 100644 index 0000000000000..c8ad2e549bdc6 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/utility.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/validate.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/validate.js new file mode 100644 index 0000000000000..21b8b5ee293ba --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/dist/validate.js @@ -0,0 +1,199 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.assertBundle = assertBundle; +exports.assertBundleV01 = assertBundleV01; +exports.isBundleV01 = isBundleV01; +exports.assertBundleV02 = assertBundleV02; +exports.assertBundleLatest = assertBundleLatest; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const error_1 = require("./error"); +// Performs basic validation of a Sigstore bundle to ensure that all required +// fields are populated. This is not a complete validation of the bundle, but +// rather a check that the bundle is in a valid state to be processed by the +// rest of the code. +function assertBundle(b) { + const invalidValues = validateBundleBase(b); + if (invalidValues.length > 0) { + throw new error_1.ValidationError('invalid bundle', invalidValues); + } +} +// Asserts that the given bundle conforms to the v0.1 bundle format. +function assertBundleV01(b) { + const invalidValues = []; + invalidValues.push(...validateBundleBase(b)); + invalidValues.push(...validateInclusionPromise(b)); + if (invalidValues.length > 0) { + throw new error_1.ValidationError('invalid v0.1 bundle', invalidValues); + } +} +// Type guard to determine if Bundle is a v0.1 bundle. +function isBundleV01(b) { + try { + assertBundleV01(b); + return true; + } + catch (e) { + return false; + } +} +// Asserts that the given bundle conforms to the v0.2 bundle format. +function assertBundleV02(b) { + const invalidValues = []; + invalidValues.push(...validateBundleBase(b)); + invalidValues.push(...validateInclusionProof(b)); + if (invalidValues.length > 0) { + throw new error_1.ValidationError('invalid v0.2 bundle', invalidValues); + } +} +// Asserts that the given bundle conforms to the newest (0.3) bundle format. +function assertBundleLatest(b) { + const invalidValues = []; + invalidValues.push(...validateBundleBase(b)); + invalidValues.push(...validateInclusionProof(b)); + invalidValues.push(...validateNoCertificateChain(b)); + if (invalidValues.length > 0) { + throw new error_1.ValidationError('invalid bundle', invalidValues); + } +} +function validateBundleBase(b) { + const invalidValues = []; + // Media type validation + if (b.mediaType === undefined || + (!b.mediaType.match(/^application\/vnd\.dev\.sigstore\.bundle\+json;version=\d\.\d/) && + !b.mediaType.match(/^application\/vnd\.dev\.sigstore\.bundle\.v\d\.\d\+json/))) { + invalidValues.push('mediaType'); + } + // Content-related validation + if (b.content === undefined) { + invalidValues.push('content'); + } + else { + switch (b.content.$case) { + case 'messageSignature': + if (b.content.messageSignature.messageDigest === undefined) { + invalidValues.push('content.messageSignature.messageDigest'); + } + else { + if (b.content.messageSignature.messageDigest.digest.length === 0) { + invalidValues.push('content.messageSignature.messageDigest.digest'); + } + } + if (b.content.messageSignature.signature.length === 0) { + invalidValues.push('content.messageSignature.signature'); + } + break; + case 'dsseEnvelope': + if (b.content.dsseEnvelope.payload.length === 0) { + invalidValues.push('content.dsseEnvelope.payload'); + } + if (b.content.dsseEnvelope.signatures.length !== 1) { + invalidValues.push('content.dsseEnvelope.signatures'); + } + else { + if (b.content.dsseEnvelope.signatures[0].sig.length === 0) { + invalidValues.push('content.dsseEnvelope.signatures[0].sig'); + } + } + break; + } + } + // Verification material-related validation + if (b.verificationMaterial === undefined) { + invalidValues.push('verificationMaterial'); + } + else { + if (b.verificationMaterial.content === undefined) { + invalidValues.push('verificationMaterial.content'); + } + else { + switch (b.verificationMaterial.content.$case) { + case 'x509CertificateChain': + if (b.verificationMaterial.content.x509CertificateChain.certificates + .length === 0) { + invalidValues.push('verificationMaterial.content.x509CertificateChain.certificates'); + } + b.verificationMaterial.content.x509CertificateChain.certificates.forEach((cert, i) => { + if (cert.rawBytes.length === 0) { + invalidValues.push(`verificationMaterial.content.x509CertificateChain.certificates[${i}].rawBytes`); + } + }); + break; + case 'certificate': + if (b.verificationMaterial.content.certificate.rawBytes.length === 0) { + invalidValues.push('verificationMaterial.content.certificate.rawBytes'); + } + break; + } + } + if (b.verificationMaterial.tlogEntries === undefined) { + invalidValues.push('verificationMaterial.tlogEntries'); + } + else { + if (b.verificationMaterial.tlogEntries.length > 0) { + b.verificationMaterial.tlogEntries.forEach((entry, i) => { + if (entry.logId === undefined) { + invalidValues.push(`verificationMaterial.tlogEntries[${i}].logId`); + } + if (entry.kindVersion === undefined) { + invalidValues.push(`verificationMaterial.tlogEntries[${i}].kindVersion`); + } + }); + } + } + } + return invalidValues; +} +// Necessary for V01 bundles +function validateInclusionPromise(b) { + const invalidValues = []; + if (b.verificationMaterial && + b.verificationMaterial.tlogEntries?.length > 0) { + b.verificationMaterial.tlogEntries.forEach((entry, i) => { + if (entry.inclusionPromise === undefined) { + invalidValues.push(`verificationMaterial.tlogEntries[${i}].inclusionPromise`); + } + }); + } + return invalidValues; +} +// Necessary for V02 and later bundles +function validateInclusionProof(b) { + const invalidValues = []; + if (b.verificationMaterial && + b.verificationMaterial.tlogEntries?.length > 0) { + b.verificationMaterial.tlogEntries.forEach((entry, i) => { + if (entry.inclusionProof === undefined) { + invalidValues.push(`verificationMaterial.tlogEntries[${i}].inclusionProof`); + } + else { + if (entry.inclusionProof.checkpoint === undefined) { + invalidValues.push(`verificationMaterial.tlogEntries[${i}].inclusionProof.checkpoint`); + } + } + }); + } + return invalidValues; +} +// Necessary for V03 and later bundles +function validateNoCertificateChain(b) { + const invalidValues = []; + /* istanbul ignore next */ + if (b.verificationMaterial?.content?.$case === 'x509CertificateChain') { + invalidValues.push('verificationMaterial.content.$case'); + } + return invalidValues; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/package.json b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/package.json new file mode 100644 index 0000000000000..ee5d2b92b801a --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle/package.json @@ -0,0 +1,35 @@ +{ + "name": "@sigstore/bundle", + "version": "3.0.0", + "description": "Sigstore bundle type", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "clean": "shx rm -rf dist *.tsbuildinfo", + "build": "tsc --build", + "test": "jest" + }, + "files": [ + "dist", + "store" + ], + "author": "bdehamer@github.com", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "git+https://github.com/sigstore/sigstore-js.git" + }, + "bugs": { + "url": "https://github.com/sigstore/sigstore-js/issues" + }, + "homepage": "https://github.com/sigstore/sigstore-js/tree/main/packages/bundle#readme", + "publishConfig": { + "provenance": true + }, + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.2" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/LICENSE b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/LICENSE new file mode 100644 index 0000000000000..e9e7c1679a09d --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 The Sigstore Authors + + 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. diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/asn1/error.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/asn1/error.js new file mode 100644 index 0000000000000..17d93b0f7e706 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/asn1/error.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ASN1TypeError = exports.ASN1ParseError = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +class ASN1ParseError extends Error { +} +exports.ASN1ParseError = ASN1ParseError; +class ASN1TypeError extends Error { +} +exports.ASN1TypeError = ASN1TypeError; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/asn1/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/asn1/index.js new file mode 100644 index 0000000000000..348b2ea4022e5 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/asn1/index.js @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ASN1Obj = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +var obj_1 = require("./obj"); +Object.defineProperty(exports, "ASN1Obj", { enumerable: true, get: function () { return obj_1.ASN1Obj; } }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/asn1/length.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/asn1/length.js new file mode 100644 index 0000000000000..cb7ebf09dbefa --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/asn1/length.js @@ -0,0 +1,62 @@ +"use strict"; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.decodeLength = decodeLength; +exports.encodeLength = encodeLength; +const error_1 = require("./error"); +// Decodes the length of a DER-encoded ANS.1 element from the supplied stream. +// https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-encoded-length-and-value-bytes +function decodeLength(stream) { + const buf = stream.getUint8(); + // If the most significant bit is UNSET the length is just the value of the + // byte. + if ((buf & 0x80) === 0x00) { + return buf; + } + // Otherwise, the lower 7 bits of the first byte indicate the number of bytes + // that follow to encode the length. + const byteCount = buf & 0x7f; + // Ensure the encoded length can safely fit in a JS number. + if (byteCount > 6) { + throw new error_1.ASN1ParseError('length exceeds 6 byte limit'); + } + // Iterate over the bytes that encode the length. + let len = 0; + for (let i = 0; i < byteCount; i++) { + len = len * 256 + stream.getUint8(); + } + // This is a valid ASN.1 length encoding, but we don't support it. + if (len === 0) { + throw new error_1.ASN1ParseError('indefinite length encoding not supported'); + } + return len; +} +// Translates the supplied value to a DER-encoded length. +function encodeLength(len) { + if (len < 128) { + return Buffer.from([len]); + } + // Bitwise operations on large numbers are not supported in JS, so we need to + // use BigInts. + let val = BigInt(len); + const bytes = []; + while (val > 0n) { + bytes.unshift(Number(val & 255n)); + val = val >> 8n; + } + return Buffer.from([0x80 | bytes.length, ...bytes]); +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/asn1/obj.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/asn1/obj.js new file mode 100644 index 0000000000000..5f9ac9cdbc493 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/asn1/obj.js @@ -0,0 +1,152 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ASN1Obj = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const stream_1 = require("../stream"); +const error_1 = require("./error"); +const length_1 = require("./length"); +const parse_1 = require("./parse"); +const tag_1 = require("./tag"); +class ASN1Obj { + constructor(tag, value, subs) { + this.tag = tag; + this.value = value; + this.subs = subs; + } + // Constructs an ASN.1 object from a Buffer of DER-encoded bytes. + static parseBuffer(buf) { + return parseStream(new stream_1.ByteStream(buf)); + } + toDER() { + const valueStream = new stream_1.ByteStream(); + if (this.subs.length > 0) { + for (const sub of this.subs) { + valueStream.appendView(sub.toDER()); + } + } + else { + valueStream.appendView(this.value); + } + const value = valueStream.buffer; + // Concat tag/length/value + const obj = new stream_1.ByteStream(); + obj.appendChar(this.tag.toDER()); + obj.appendView((0, length_1.encodeLength)(value.length)); + obj.appendView(value); + return obj.buffer; + } + ///////////////////////////////////////////////////////////////////////////// + // Convenience methods for parsing ASN.1 primitives into JS types + // Returns the ASN.1 object's value as a boolean. Throws an error if the + // object is not a boolean. + toBoolean() { + if (!this.tag.isBoolean()) { + throw new error_1.ASN1TypeError('not a boolean'); + } + return (0, parse_1.parseBoolean)(this.value); + } + // Returns the ASN.1 object's value as a BigInt. Throws an error if the + // object is not an integer. + toInteger() { + if (!this.tag.isInteger()) { + throw new error_1.ASN1TypeError('not an integer'); + } + return (0, parse_1.parseInteger)(this.value); + } + // Returns the ASN.1 object's value as an OID string. Throws an error if the + // object is not an OID. + toOID() { + if (!this.tag.isOID()) { + throw new error_1.ASN1TypeError('not an OID'); + } + return (0, parse_1.parseOID)(this.value); + } + // Returns the ASN.1 object's value as a Date. Throws an error if the object + // is not either a UTCTime or a GeneralizedTime. + toDate() { + switch (true) { + case this.tag.isUTCTime(): + return (0, parse_1.parseTime)(this.value, true); + case this.tag.isGeneralizedTime(): + return (0, parse_1.parseTime)(this.value, false); + default: + throw new error_1.ASN1TypeError('not a date'); + } + } + // Returns the ASN.1 object's value as a number[] where each number is the + // value of a bit in the bit string. Throws an error if the object is not a + // bit string. + toBitString() { + if (!this.tag.isBitString()) { + throw new error_1.ASN1TypeError('not a bit string'); + } + return (0, parse_1.parseBitString)(this.value); + } +} +exports.ASN1Obj = ASN1Obj; +///////////////////////////////////////////////////////////////////////////// +// Internal stream parsing functions +function parseStream(stream) { + // Parse tag, length, and value from stream + const tag = new tag_1.ASN1Tag(stream.getUint8()); + const len = (0, length_1.decodeLength)(stream); + const value = stream.slice(stream.position, len); + const start = stream.position; + let subs = []; + // If the object is constructed, parse its children. Sometimes, children + // are embedded in OCTESTRING objects, so we need to check those + // for children as well. + if (tag.constructed) { + subs = collectSubs(stream, len); + } + else if (tag.isOctetString()) { + // Attempt to parse children of OCTETSTRING objects. If anything fails, + // assume the object is not constructed and treat as primitive. + try { + subs = collectSubs(stream, len); + } + catch (e) { + // Fail silently and treat as primitive + } + } + // If there are no children, move stream cursor to the end of the object + if (subs.length === 0) { + stream.seek(start + len); + } + return new ASN1Obj(tag, value, subs); +} +function collectSubs(stream, len) { + // Calculate end of object content + const end = stream.position + len; + // Make sure there are enough bytes left in the stream. This should never + // happen, cause it'll get caught when the stream is sliced in parseStream. + // Leaving as an extra check just in case. + /* istanbul ignore if */ + if (end > stream.length) { + throw new error_1.ASN1ParseError('invalid length'); + } + // Parse all children + const subs = []; + while (stream.position < end) { + subs.push(parseStream(stream)); + } + // When we're done parsing children, we should be at the end of the object + if (stream.position !== end) { + throw new error_1.ASN1ParseError('invalid length'); + } + return subs; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/asn1/parse.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/asn1/parse.js new file mode 100644 index 0000000000000..7fbb42632c60e --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/asn1/parse.js @@ -0,0 +1,124 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.parseInteger = parseInteger; +exports.parseStringASCII = parseStringASCII; +exports.parseTime = parseTime; +exports.parseOID = parseOID; +exports.parseBoolean = parseBoolean; +exports.parseBitString = parseBitString; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const RE_TIME_SHORT_YEAR = /^(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\.\d{3})?Z$/; +const RE_TIME_LONG_YEAR = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\.\d{3})?Z$/; +// Parse a BigInt from the DER-encoded buffer +// https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-integer +function parseInteger(buf) { + let pos = 0; + const end = buf.length; + let val = buf[pos]; + const neg = val > 0x7f; + // Consume any padding bytes + const pad = neg ? 0xff : 0x00; + while (val == pad && ++pos < end) { + val = buf[pos]; + } + // Calculate remaining bytes to read + const len = end - pos; + if (len === 0) + return BigInt(neg ? -1 : 0); + // Handle two's complement for negative numbers + val = neg ? val - 256 : val; + // Parse remaining bytes + let n = BigInt(val); + for (let i = pos + 1; i < end; ++i) { + n = n * BigInt(256) + BigInt(buf[i]); + } + return n; +} +// Parse an ASCII string from the DER-encoded buffer +// https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-basic-types#boolean +function parseStringASCII(buf) { + return buf.toString('ascii'); +} +// Parse a Date from the DER-encoded buffer +// https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.5.1 +function parseTime(buf, shortYear) { + const timeStr = parseStringASCII(buf); + // Parse the time string into matches - captured groups start at index 1 + const m = shortYear + ? RE_TIME_SHORT_YEAR.exec(timeStr) + : RE_TIME_LONG_YEAR.exec(timeStr); + if (!m) { + throw new Error('invalid time'); + } + // Translate dates with a 2-digit year to 4 digits per the spec + if (shortYear) { + let year = Number(m[1]); + year += year >= 50 ? 1900 : 2000; + m[1] = year.toString(); + } + // Translate to ISO8601 format and parse + return new Date(`${m[1]}-${m[2]}-${m[3]}T${m[4]}:${m[5]}:${m[6]}Z`); +} +// Parse an OID from the DER-encoded buffer +// https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-object-identifier +function parseOID(buf) { + let pos = 0; + const end = buf.length; + // Consume first byte which encodes the first two OID components + let n = buf[pos++]; + const first = Math.floor(n / 40); + const second = n % 40; + let oid = `${first}.${second}`; + // Consume remaining bytes + let val = 0; + for (; pos < end; ++pos) { + n = buf[pos]; + val = (val << 7) + (n & 0x7f); + // If the left-most bit is NOT set, then this is the last byte in the + // sequence and we can add the value to the OID and reset the accumulator + if ((n & 0x80) === 0) { + oid += `.${val}`; + val = 0; + } + } + return oid; +} +// Parse a boolean from the DER-encoded buffer +// https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-basic-types#boolean +function parseBoolean(buf) { + return buf[0] !== 0; +} +// Parse a bit string from the DER-encoded buffer +// https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-bit-string +function parseBitString(buf) { + // First byte tell us how many unused bits are in the last byte + const unused = buf[0]; + const start = 1; + const end = buf.length; + const bits = []; + for (let i = start; i < end; ++i) { + const byte = buf[i]; + // The skip value is only used for the last byte + const skip = i === end - 1 ? unused : 0; + // Iterate over each bit in the byte (most significant first) + for (let j = 7; j >= skip; --j) { + // Read the bit and add it to the bit string + bits.push((byte >> j) & 0x01); + } + } + return bits; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/asn1/tag.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/asn1/tag.js new file mode 100644 index 0000000000000..84dd938d049aa --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/asn1/tag.js @@ -0,0 +1,86 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ASN1Tag = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const error_1 = require("./error"); +const UNIVERSAL_TAG = { + BOOLEAN: 0x01, + INTEGER: 0x02, + BIT_STRING: 0x03, + OCTET_STRING: 0x04, + OBJECT_IDENTIFIER: 0x06, + SEQUENCE: 0x10, + SET: 0x11, + PRINTABLE_STRING: 0x13, + UTC_TIME: 0x17, + GENERALIZED_TIME: 0x18, +}; +const TAG_CLASS = { + UNIVERSAL: 0x00, + APPLICATION: 0x01, + CONTEXT_SPECIFIC: 0x02, + PRIVATE: 0x03, +}; +// https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-encoded-tag-bytes +class ASN1Tag { + constructor(enc) { + // Bits 0 through 4 are the tag number + this.number = enc & 0x1f; + // Bit 5 is the constructed bit + this.constructed = (enc & 0x20) === 0x20; + // Bit 6 & 7 are the class + this.class = enc >> 6; + if (this.number === 0x1f) { + throw new error_1.ASN1ParseError('long form tags not supported'); + } + if (this.class === TAG_CLASS.UNIVERSAL && this.number === 0x00) { + throw new error_1.ASN1ParseError('unsupported tag 0x00'); + } + } + isUniversal() { + return this.class === TAG_CLASS.UNIVERSAL; + } + isContextSpecific(num) { + const res = this.class === TAG_CLASS.CONTEXT_SPECIFIC; + return num !== undefined ? res && this.number === num : res; + } + isBoolean() { + return this.isUniversal() && this.number === UNIVERSAL_TAG.BOOLEAN; + } + isInteger() { + return this.isUniversal() && this.number === UNIVERSAL_TAG.INTEGER; + } + isBitString() { + return this.isUniversal() && this.number === UNIVERSAL_TAG.BIT_STRING; + } + isOctetString() { + return this.isUniversal() && this.number === UNIVERSAL_TAG.OCTET_STRING; + } + isOID() { + return (this.isUniversal() && this.number === UNIVERSAL_TAG.OBJECT_IDENTIFIER); + } + isUTCTime() { + return this.isUniversal() && this.number === UNIVERSAL_TAG.UTC_TIME; + } + isGeneralizedTime() { + return this.isUniversal() && this.number === UNIVERSAL_TAG.GENERALIZED_TIME; + } + toDER() { + return this.number | (this.constructed ? 0x20 : 0x00) | (this.class << 6); + } +} +exports.ASN1Tag = ASN1Tag; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/crypto.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/crypto.js new file mode 100644 index 0000000000000..296b5ba43e86a --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/crypto.js @@ -0,0 +1,60 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createPublicKey = createPublicKey; +exports.digest = digest; +exports.verify = verify; +exports.bufferEqual = bufferEqual; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const crypto_1 = __importDefault(require("crypto")); +function createPublicKey(key, type = 'spki') { + if (typeof key === 'string') { + return crypto_1.default.createPublicKey(key); + } + else { + return crypto_1.default.createPublicKey({ key, format: 'der', type: type }); + } +} +function digest(algorithm, ...data) { + const hash = crypto_1.default.createHash(algorithm); + for (const d of data) { + hash.update(d); + } + return hash.digest(); +} +function verify(data, key, signature, algorithm) { + // The try/catch is to work around an issue in Node 14.x where verify throws + // an error in some scenarios if the signature is invalid. + try { + return crypto_1.default.verify(algorithm, data, key, signature); + } + catch (e) { + /* istanbul ignore next */ + return false; + } +} +function bufferEqual(a, b) { + try { + return crypto_1.default.timingSafeEqual(a, b); + } + catch { + /* istanbul ignore next */ + return false; + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/dsse.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/dsse.js new file mode 100644 index 0000000000000..ca7b63630e2ba --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/dsse.js @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.preAuthEncoding = preAuthEncoding; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const PAE_PREFIX = 'DSSEv1'; +// DSSE Pre-Authentication Encoding +function preAuthEncoding(payloadType, payload) { + const prefix = [ + PAE_PREFIX, + payloadType.length, + payloadType, + payload.length, + '', + ].join(' '); + return Buffer.concat([Buffer.from(prefix, 'ascii'), payload]); +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/encoding.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/encoding.js new file mode 100644 index 0000000000000..7113af66db4c2 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/encoding.js @@ -0,0 +1,27 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.base64Encode = base64Encode; +exports.base64Decode = base64Decode; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const BASE64_ENCODING = 'base64'; +const UTF8_ENCODING = 'utf-8'; +function base64Encode(str) { + return Buffer.from(str, UTF8_ENCODING).toString(BASE64_ENCODING); +} +function base64Decode(str) { + return Buffer.from(str, BASE64_ENCODING).toString(UTF8_ENCODING); +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/index.js new file mode 100644 index 0000000000000..ac35e86a8df7d --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/index.js @@ -0,0 +1,56 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.X509SCTExtension = exports.X509Certificate = exports.EXTENSION_OID_SCT = exports.ByteStream = exports.RFC3161Timestamp = exports.pem = exports.json = exports.encoding = exports.dsse = exports.crypto = exports.ASN1Obj = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +var asn1_1 = require("./asn1"); +Object.defineProperty(exports, "ASN1Obj", { enumerable: true, get: function () { return asn1_1.ASN1Obj; } }); +exports.crypto = __importStar(require("./crypto")); +exports.dsse = __importStar(require("./dsse")); +exports.encoding = __importStar(require("./encoding")); +exports.json = __importStar(require("./json")); +exports.pem = __importStar(require("./pem")); +var rfc3161_1 = require("./rfc3161"); +Object.defineProperty(exports, "RFC3161Timestamp", { enumerable: true, get: function () { return rfc3161_1.RFC3161Timestamp; } }); +var stream_1 = require("./stream"); +Object.defineProperty(exports, "ByteStream", { enumerable: true, get: function () { return stream_1.ByteStream; } }); +var x509_1 = require("./x509"); +Object.defineProperty(exports, "EXTENSION_OID_SCT", { enumerable: true, get: function () { return x509_1.EXTENSION_OID_SCT; } }); +Object.defineProperty(exports, "X509Certificate", { enumerable: true, get: function () { return x509_1.X509Certificate; } }); +Object.defineProperty(exports, "X509SCTExtension", { enumerable: true, get: function () { return x509_1.X509SCTExtension; } }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/json.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/json.js new file mode 100644 index 0000000000000..7808d033b98cc --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/json.js @@ -0,0 +1,60 @@ +"use strict"; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.canonicalize = canonicalize; +// JSON canonicalization per https://github.com/cyberphone/json-canonicalization +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function canonicalize(object) { + let buffer = ''; + if (object === null || typeof object !== 'object' || object.toJSON != null) { + // Primitives or toJSONable objects + buffer += JSON.stringify(object); + } + else if (Array.isArray(object)) { + // Array - maintain element order + buffer += '['; + let first = true; + object.forEach((element) => { + if (!first) { + buffer += ','; + } + first = false; + // recursive call + buffer += canonicalize(element); + }); + buffer += ']'; + } + else { + // Object - Sort properties before serializing + buffer += '{'; + let first = true; + Object.keys(object) + .sort() + .forEach((property) => { + if (!first) { + buffer += ','; + } + first = false; + buffer += JSON.stringify(property); + buffer += ':'; + // recursive call + buffer += canonicalize(object[property]); + }); + buffer += '}'; + } + return buffer; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/oid.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/oid.js new file mode 100644 index 0000000000000..ac7a643067ad0 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/oid.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SHA2_HASH_ALGOS = exports.ECDSA_SIGNATURE_ALGOS = void 0; +exports.ECDSA_SIGNATURE_ALGOS = { + '1.2.840.10045.4.3.1': 'sha224', + '1.2.840.10045.4.3.2': 'sha256', + '1.2.840.10045.4.3.3': 'sha384', + '1.2.840.10045.4.3.4': 'sha512', +}; +exports.SHA2_HASH_ALGOS = { + '2.16.840.1.101.3.4.2.1': 'sha256', + '2.16.840.1.101.3.4.2.2': 'sha384', + '2.16.840.1.101.3.4.2.3': 'sha512', +}; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/pem.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/pem.js new file mode 100644 index 0000000000000..f1241d28d586e --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/pem.js @@ -0,0 +1,43 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.toDER = toDER; +exports.fromDER = fromDER; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const PEM_HEADER = /-----BEGIN (.*)-----/; +const PEM_FOOTER = /-----END (.*)-----/; +function toDER(certificate) { + let der = ''; + certificate.split('\n').forEach((line) => { + if (line.match(PEM_HEADER) || line.match(PEM_FOOTER)) { + return; + } + der += line; + }); + return Buffer.from(der, 'base64'); +} +// Translates a DER-encoded buffer into a PEM-encoded string. Standard PEM +// encoding dictates that each certificate should have a trailing newline after +// the footer. +function fromDER(certificate, type = 'CERTIFICATE') { + // Base64-encode the certificate. + const der = certificate.toString('base64'); + // Split the certificate into lines of 64 characters. + const lines = der.match(/.{1,64}/g) || ''; + return [`-----BEGIN ${type}-----`, ...lines, `-----END ${type}-----`] + .join('\n') + .concat('\n'); +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/rfc3161/error.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/rfc3161/error.js new file mode 100644 index 0000000000000..b9b549b0bb323 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/rfc3161/error.js @@ -0,0 +1,21 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RFC3161TimestampVerificationError = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +class RFC3161TimestampVerificationError extends Error { +} +exports.RFC3161TimestampVerificationError = RFC3161TimestampVerificationError; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/rfc3161/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/rfc3161/index.js new file mode 100644 index 0000000000000..b77ecf1c7d50c --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/rfc3161/index.js @@ -0,0 +1,20 @@ +"use strict"; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RFC3161Timestamp = void 0; +var timestamp_1 = require("./timestamp"); +Object.defineProperty(exports, "RFC3161Timestamp", { enumerable: true, get: function () { return timestamp_1.RFC3161Timestamp; } }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/rfc3161/timestamp.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/rfc3161/timestamp.js new file mode 100644 index 0000000000000..3e61fc1a4e169 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/rfc3161/timestamp.js @@ -0,0 +1,201 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RFC3161Timestamp = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const asn1_1 = require("../asn1"); +const crypto = __importStar(require("../crypto")); +const oid_1 = require("../oid"); +const error_1 = require("./error"); +const tstinfo_1 = require("./tstinfo"); +const OID_PKCS9_CONTENT_TYPE_SIGNED_DATA = '1.2.840.113549.1.7.2'; +const OID_PKCS9_CONTENT_TYPE_TSTINFO = '1.2.840.113549.1.9.16.1.4'; +const OID_PKCS9_MESSAGE_DIGEST_KEY = '1.2.840.113549.1.9.4'; +class RFC3161Timestamp { + constructor(asn1) { + this.root = asn1; + } + static parse(der) { + const asn1 = asn1_1.ASN1Obj.parseBuffer(der); + return new RFC3161Timestamp(asn1); + } + get status() { + return this.pkiStatusInfoObj.subs[0].toInteger(); + } + get contentType() { + return this.contentTypeObj.toOID(); + } + get eContentType() { + return this.eContentTypeObj.toOID(); + } + get signingTime() { + return this.tstInfo.genTime; + } + get signerIssuer() { + return this.signerSidObj.subs[0].value; + } + get signerSerialNumber() { + return this.signerSidObj.subs[1].value; + } + get signerDigestAlgorithm() { + const oid = this.signerDigestAlgorithmObj.subs[0].toOID(); + return oid_1.SHA2_HASH_ALGOS[oid]; + } + get signatureAlgorithm() { + const oid = this.signatureAlgorithmObj.subs[0].toOID(); + return oid_1.ECDSA_SIGNATURE_ALGOS[oid]; + } + get signatureValue() { + return this.signatureValueObj.value; + } + get tstInfo() { + // Need to unpack tstInfo from an OCTET STRING + return new tstinfo_1.TSTInfo(this.eContentObj.subs[0].subs[0]); + } + verify(data, publicKey) { + if (!this.timeStampTokenObj) { + throw new error_1.RFC3161TimestampVerificationError('timeStampToken is missing'); + } + // Check for expected ContentInfo content type + if (this.contentType !== OID_PKCS9_CONTENT_TYPE_SIGNED_DATA) { + throw new error_1.RFC3161TimestampVerificationError(`incorrect content type: ${this.contentType}`); + } + // Check for expected encapsulated content type + if (this.eContentType !== OID_PKCS9_CONTENT_TYPE_TSTINFO) { + throw new error_1.RFC3161TimestampVerificationError(`incorrect encapsulated content type: ${this.eContentType}`); + } + // Check that the tstInfo references the correct artifact + this.tstInfo.verify(data); + // Check that the signed message digest matches the tstInfo + this.verifyMessageDigest(); + // Check that the signature is valid for the signed attributes + this.verifySignature(publicKey); + } + verifyMessageDigest() { + // Check that the tstInfo matches the signed data + const tstInfoDigest = crypto.digest(this.signerDigestAlgorithm, this.tstInfo.raw); + const expectedDigest = this.messageDigestAttributeObj.subs[1].subs[0].value; + if (!crypto.bufferEqual(tstInfoDigest, expectedDigest)) { + throw new error_1.RFC3161TimestampVerificationError('signed data does not match tstInfo'); + } + } + verifySignature(key) { + // Encode the signed attributes for verification + const signedAttrs = this.signedAttrsObj.toDER(); + signedAttrs[0] = 0x31; // Change context-specific tag to SET + // Check that the signature is valid for the signed attributes + const verified = crypto.verify(signedAttrs, key, this.signatureValue, this.signatureAlgorithm); + if (!verified) { + throw new error_1.RFC3161TimestampVerificationError('signature verification failed'); + } + } + // https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2 + get pkiStatusInfoObj() { + // pkiStatusInfo is the first element of the timestamp response sequence + return this.root.subs[0]; + } + // https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2 + get timeStampTokenObj() { + // timeStampToken is the first element of the timestamp response sequence + return this.root.subs[1]; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-3 + get contentTypeObj() { + return this.timeStampTokenObj.subs[0]; + } + // https://www.rfc-editor.org/rfc/rfc5652#section-3 + get signedDataObj() { + const obj = this.timeStampTokenObj.subs.find((sub) => sub.tag.isContextSpecific(0x00)); + return obj.subs[0]; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.1 + get encapContentInfoObj() { + return this.signedDataObj.subs[2]; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.1 + get signerInfosObj() { + // SignerInfos is the last element of the signed data sequence + const sd = this.signedDataObj; + return sd.subs[sd.subs.length - 1]; + } + // https://www.rfc-editor.org/rfc/rfc5652#section-5.1 + get signerInfoObj() { + // Only supporting one signer + return this.signerInfosObj.subs[0]; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.2 + get eContentTypeObj() { + return this.encapContentInfoObj.subs[0]; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.2 + get eContentObj() { + return this.encapContentInfoObj.subs[1]; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.3 + get signedAttrsObj() { + const signedAttrs = this.signerInfoObj.subs.find((sub) => sub.tag.isContextSpecific(0x00)); + return signedAttrs; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.3 + get messageDigestAttributeObj() { + const messageDigest = this.signedAttrsObj.subs.find((sub) => sub.subs[0].tag.isOID() && + sub.subs[0].toOID() === OID_PKCS9_MESSAGE_DIGEST_KEY); + return messageDigest; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.3 + get signerSidObj() { + return this.signerInfoObj.subs[1]; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.3 + get signerDigestAlgorithmObj() { + // Signature is the 2nd element of the signerInfoObj object + return this.signerInfoObj.subs[2]; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.3 + get signatureAlgorithmObj() { + // Signature is the 4th element of the signerInfoObj object + return this.signerInfoObj.subs[4]; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.3 + get signatureValueObj() { + // Signature is the 6th element of the signerInfoObj object + return this.signerInfoObj.subs[5]; + } +} +exports.RFC3161Timestamp = RFC3161Timestamp; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/rfc3161/tstinfo.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/rfc3161/tstinfo.js new file mode 100644 index 0000000000000..dc8e4fb339383 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/rfc3161/tstinfo.js @@ -0,0 +1,61 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TSTInfo = void 0; +const crypto = __importStar(require("../crypto")); +const oid_1 = require("../oid"); +const error_1 = require("./error"); +class TSTInfo { + constructor(asn1) { + this.root = asn1; + } + get version() { + return this.root.subs[0].toInteger(); + } + get genTime() { + return this.root.subs[4].toDate(); + } + get messageImprintHashAlgorithm() { + const oid = this.messageImprintObj.subs[0].subs[0].toOID(); + return oid_1.SHA2_HASH_ALGOS[oid]; + } + get messageImprintHashedMessage() { + return this.messageImprintObj.subs[1].value; + } + get raw() { + return this.root.toDER(); + } + verify(data) { + const digest = crypto.digest(this.messageImprintHashAlgorithm, data); + if (!crypto.bufferEqual(digest, this.messageImprintHashedMessage)) { + throw new error_1.RFC3161TimestampVerificationError('message imprint does not match artifact'); + } + } + // https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2 + get messageImprintObj() { + return this.root.subs[2]; + } +} +exports.TSTInfo = TSTInfo; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/stream.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/stream.js new file mode 100644 index 0000000000000..0a24f8582eb23 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/stream.js @@ -0,0 +1,115 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ByteStream = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +class StreamError extends Error { +} +class ByteStream { + constructor(buffer) { + this.start = 0; + if (buffer) { + this.buf = buffer; + this.view = Buffer.from(buffer); + } + else { + this.buf = new ArrayBuffer(0); + this.view = Buffer.from(this.buf); + } + } + get buffer() { + return this.view.subarray(0, this.start); + } + get length() { + return this.view.byteLength; + } + get position() { + return this.start; + } + seek(position) { + this.start = position; + } + // Returns a Buffer containing the specified number of bytes starting at the + // given start position. + slice(start, len) { + const end = start + len; + if (end > this.length) { + throw new StreamError('request past end of buffer'); + } + return this.view.subarray(start, end); + } + appendChar(char) { + this.ensureCapacity(1); + this.view[this.start] = char; + this.start += 1; + } + appendUint16(num) { + this.ensureCapacity(2); + const value = new Uint16Array([num]); + const view = new Uint8Array(value.buffer); + this.view[this.start] = view[1]; + this.view[this.start + 1] = view[0]; + this.start += 2; + } + appendUint24(num) { + this.ensureCapacity(3); + const value = new Uint32Array([num]); + const view = new Uint8Array(value.buffer); + this.view[this.start] = view[2]; + this.view[this.start + 1] = view[1]; + this.view[this.start + 2] = view[0]; + this.start += 3; + } + appendView(view) { + this.ensureCapacity(view.length); + this.view.set(view, this.start); + this.start += view.length; + } + getBlock(size) { + if (size <= 0) { + return Buffer.alloc(0); + } + if (this.start + size > this.view.length) { + throw new Error('request past end of buffer'); + } + const result = this.view.subarray(this.start, this.start + size); + this.start += size; + return result; + } + getUint8() { + return this.getBlock(1)[0]; + } + getUint16() { + const block = this.getBlock(2); + return (block[0] << 8) | block[1]; + } + ensureCapacity(size) { + if (this.start + size > this.view.byteLength) { + const blockSize = ByteStream.BLOCK_SIZE + (size > ByteStream.BLOCK_SIZE ? size : 0); + this.realloc(this.view.byteLength + blockSize); + } + } + realloc(size) { + const newArray = new ArrayBuffer(size); + const newView = Buffer.from(newArray); + // Copy the old buffer into the new one + newView.set(this.view); + this.buf = newArray; + this.view = newView; + } +} +exports.ByteStream = ByteStream; +ByteStream.BLOCK_SIZE = 1024; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/x509/cert.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/x509/cert.js new file mode 100644 index 0000000000000..72ea8e0738bc8 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/x509/cert.js @@ -0,0 +1,230 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.X509Certificate = exports.EXTENSION_OID_SCT = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const asn1_1 = require("../asn1"); +const crypto = __importStar(require("../crypto")); +const oid_1 = require("../oid"); +const pem = __importStar(require("../pem")); +const ext_1 = require("./ext"); +const EXTENSION_OID_SUBJECT_KEY_ID = '2.5.29.14'; +const EXTENSION_OID_KEY_USAGE = '2.5.29.15'; +const EXTENSION_OID_SUBJECT_ALT_NAME = '2.5.29.17'; +const EXTENSION_OID_BASIC_CONSTRAINTS = '2.5.29.19'; +const EXTENSION_OID_AUTHORITY_KEY_ID = '2.5.29.35'; +exports.EXTENSION_OID_SCT = '1.3.6.1.4.1.11129.2.4.2'; +class X509Certificate { + constructor(asn1) { + this.root = asn1; + } + static parse(cert) { + const der = typeof cert === 'string' ? pem.toDER(cert) : cert; + const asn1 = asn1_1.ASN1Obj.parseBuffer(der); + return new X509Certificate(asn1); + } + get tbsCertificate() { + return this.tbsCertificateObj; + } + get version() { + // version number is the first element of the version context specific tag + const ver = this.versionObj.subs[0].toInteger(); + return `v${(ver + BigInt(1)).toString()}`; + } + get serialNumber() { + return this.serialNumberObj.value; + } + get notBefore() { + // notBefore is the first element of the validity sequence + return this.validityObj.subs[0].toDate(); + } + get notAfter() { + // notAfter is the second element of the validity sequence + return this.validityObj.subs[1].toDate(); + } + get issuer() { + return this.issuerObj.value; + } + get subject() { + return this.subjectObj.value; + } + get publicKey() { + return this.subjectPublicKeyInfoObj.toDER(); + } + get signatureAlgorithm() { + const oid = this.signatureAlgorithmObj.subs[0].toOID(); + return oid_1.ECDSA_SIGNATURE_ALGOS[oid]; + } + get signatureValue() { + // Signature value is a bit string, so we need to skip the first byte + return this.signatureValueObj.value.subarray(1); + } + get subjectAltName() { + const ext = this.extSubjectAltName; + return ext?.uri || /* istanbul ignore next */ ext?.rfc822Name; + } + get extensions() { + // The extension list is the first (and only) element of the extensions + // context specific tag + /* istanbul ignore next */ + const extSeq = this.extensionsObj?.subs[0]; + /* istanbul ignore next */ + return extSeq?.subs || []; + } + get extKeyUsage() { + const ext = this.findExtension(EXTENSION_OID_KEY_USAGE); + return ext ? new ext_1.X509KeyUsageExtension(ext) : undefined; + } + get extBasicConstraints() { + const ext = this.findExtension(EXTENSION_OID_BASIC_CONSTRAINTS); + return ext ? new ext_1.X509BasicConstraintsExtension(ext) : undefined; + } + get extSubjectAltName() { + const ext = this.findExtension(EXTENSION_OID_SUBJECT_ALT_NAME); + return ext ? new ext_1.X509SubjectAlternativeNameExtension(ext) : undefined; + } + get extAuthorityKeyID() { + const ext = this.findExtension(EXTENSION_OID_AUTHORITY_KEY_ID); + return ext ? new ext_1.X509AuthorityKeyIDExtension(ext) : undefined; + } + get extSubjectKeyID() { + const ext = this.findExtension(EXTENSION_OID_SUBJECT_KEY_ID); + return ext + ? new ext_1.X509SubjectKeyIDExtension(ext) + : /* istanbul ignore next */ undefined; + } + get extSCT() { + const ext = this.findExtension(exports.EXTENSION_OID_SCT); + return ext ? new ext_1.X509SCTExtension(ext) : undefined; + } + get isCA() { + const ca = this.extBasicConstraints?.isCA || false; + // If the KeyUsage extension is present, keyCertSign must be set + if (this.extKeyUsage) { + return ca && this.extKeyUsage.keyCertSign; + } + // TODO: test coverage for this case + /* istanbul ignore next */ + return ca; + } + extension(oid) { + const ext = this.findExtension(oid); + return ext ? new ext_1.X509Extension(ext) : undefined; + } + verify(issuerCertificate) { + // Use the issuer's public key if provided, otherwise use the subject's + const publicKey = issuerCertificate?.publicKey || this.publicKey; + const key = crypto.createPublicKey(publicKey); + return crypto.verify(this.tbsCertificate.toDER(), key, this.signatureValue, this.signatureAlgorithm); + } + validForDate(date) { + return this.notBefore <= date && date <= this.notAfter; + } + equals(other) { + return this.root.toDER().equals(other.root.toDER()); + } + // Creates a copy of the certificate with a new buffer + clone() { + const der = this.root.toDER(); + const clone = Buffer.alloc(der.length); + der.copy(clone); + return X509Certificate.parse(clone); + } + findExtension(oid) { + // Find the extension with the given OID. The OID will always be the first + // element of the extension sequence + return this.extensions.find((ext) => ext.subs[0].toOID() === oid); + } + ///////////////////////////////////////////////////////////////////////////// + // The following properties use the documented x509 structure to locate the + // desired ASN.1 object + // https://www.rfc-editor.org/rfc/rfc5280#section-4.1 + // https://www.rfc-editor.org/rfc/rfc5280#section-4.1.1.1 + get tbsCertificateObj() { + // tbsCertificate is the first element of the certificate sequence + return this.root.subs[0]; + } + // https://www.rfc-editor.org/rfc/rfc5280#section-4.1.1.2 + get signatureAlgorithmObj() { + // signatureAlgorithm is the second element of the certificate sequence + return this.root.subs[1]; + } + // https://www.rfc-editor.org/rfc/rfc5280#section-4.1.1.3 + get signatureValueObj() { + // signatureValue is the third element of the certificate sequence + return this.root.subs[2]; + } + // https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.1 + get versionObj() { + // version is the first element of the tbsCertificate sequence + return this.tbsCertificateObj.subs[0]; + } + // https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.2 + get serialNumberObj() { + // serialNumber is the second element of the tbsCertificate sequence + return this.tbsCertificateObj.subs[1]; + } + // https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.4 + get issuerObj() { + // issuer is the fourth element of the tbsCertificate sequence + return this.tbsCertificateObj.subs[3]; + } + // https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.5 + get validityObj() { + // version is the fifth element of the tbsCertificate sequence + return this.tbsCertificateObj.subs[4]; + } + // https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.6 + get subjectObj() { + // subject is the sixth element of the tbsCertificate sequence + return this.tbsCertificateObj.subs[5]; + } + // https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.7 + get subjectPublicKeyInfoObj() { + // subjectPublicKeyInfo is the seventh element of the tbsCertificate sequence + return this.tbsCertificateObj.subs[6]; + } + // Extensions can't be located by index because their position varies. Instead, + // we need to find the extensions context specific tag + // https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.9 + get extensionsObj() { + return this.tbsCertificateObj.subs.find((sub) => sub.tag.isContextSpecific(0x03)); + } +} +exports.X509Certificate = X509Certificate; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/x509/ext.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/x509/ext.js new file mode 100644 index 0000000000000..1d481261b0aa6 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/x509/ext.js @@ -0,0 +1,145 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.X509SCTExtension = exports.X509SubjectKeyIDExtension = exports.X509AuthorityKeyIDExtension = exports.X509SubjectAlternativeNameExtension = exports.X509KeyUsageExtension = exports.X509BasicConstraintsExtension = exports.X509Extension = void 0; +const stream_1 = require("../stream"); +const sct_1 = require("./sct"); +// https://www.rfc-editor.org/rfc/rfc5280#section-4.1 +class X509Extension { + constructor(asn1) { + this.root = asn1; + } + get oid() { + return this.root.subs[0].toOID(); + } + get critical() { + // The critical field is optional and will be the second element of the + // extension sequence if present. Default to false if not present. + return this.root.subs.length === 3 ? this.root.subs[1].toBoolean() : false; + } + get value() { + return this.extnValueObj.value; + } + get valueObj() { + return this.extnValueObj; + } + get extnValueObj() { + // The extnValue field will be the last element of the extension sequence + return this.root.subs[this.root.subs.length - 1]; + } +} +exports.X509Extension = X509Extension; +// https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.9 +class X509BasicConstraintsExtension extends X509Extension { + get isCA() { + return this.sequence.subs[0]?.toBoolean() ?? false; + } + get pathLenConstraint() { + return this.sequence.subs.length > 1 + ? this.sequence.subs[1].toInteger() + : undefined; + } + // The extnValue field contains a single sequence wrapping the isCA and + // pathLenConstraint. + get sequence() { + return this.extnValueObj.subs[0]; + } +} +exports.X509BasicConstraintsExtension = X509BasicConstraintsExtension; +// https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.3 +class X509KeyUsageExtension extends X509Extension { + get digitalSignature() { + return this.bitString[0] === 1; + } + get keyCertSign() { + return this.bitString[5] === 1; + } + get crlSign() { + return this.bitString[6] === 1; + } + // The extnValue field contains a single bit string which is a bit mask + // indicating which key usages are enabled. + get bitString() { + return this.extnValueObj.subs[0].toBitString(); + } +} +exports.X509KeyUsageExtension = X509KeyUsageExtension; +// https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.6 +class X509SubjectAlternativeNameExtension extends X509Extension { + get rfc822Name() { + return this.findGeneralName(0x01)?.value.toString('ascii'); + } + get uri() { + return this.findGeneralName(0x06)?.value.toString('ascii'); + } + // Retrieve the value of an otherName with the given OID. + otherName(oid) { + const otherName = this.findGeneralName(0x00); + if (otherName === undefined) { + return undefined; + } + // The otherName is a sequence containing an OID and a value. + // Need to check that the OID matches the one we're looking for. + const otherNameOID = otherName.subs[0].toOID(); + if (otherNameOID !== oid) { + return undefined; + } + // The otherNameValue is a sequence containing the actual value. + const otherNameValue = otherName.subs[1]; + return otherNameValue.subs[0].value.toString('ascii'); + } + findGeneralName(tag) { + return this.generalNames.find((gn) => gn.tag.isContextSpecific(tag)); + } + // The extnValue field contains a sequence of GeneralNames. + get generalNames() { + return this.extnValueObj.subs[0].subs; + } +} +exports.X509SubjectAlternativeNameExtension = X509SubjectAlternativeNameExtension; +// https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.1 +class X509AuthorityKeyIDExtension extends X509Extension { + get keyIdentifier() { + return this.findSequenceMember(0x00)?.value; + } + findSequenceMember(tag) { + return this.sequence.subs.find((el) => el.tag.isContextSpecific(tag)); + } + // The extnValue field contains a single sequence wrapping the keyIdentifier + get sequence() { + return this.extnValueObj.subs[0]; + } +} +exports.X509AuthorityKeyIDExtension = X509AuthorityKeyIDExtension; +// https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.2 +class X509SubjectKeyIDExtension extends X509Extension { + get keyIdentifier() { + return this.extnValueObj.subs[0].value; + } +} +exports.X509SubjectKeyIDExtension = X509SubjectKeyIDExtension; +// https://www.rfc-editor.org/rfc/rfc6962#section-3.3 +class X509SCTExtension extends X509Extension { + constructor(asn1) { + super(asn1); + } + get signedCertificateTimestamps() { + const buf = this.extnValueObj.subs[0].value; + const stream = new stream_1.ByteStream(buf); + // The overall list length is encoded in the first two bytes -- note this + // is the length of the list in bytes, NOT the number of SCTs in the list + const end = stream.getUint16() + 2; + const sctList = []; + while (stream.position < end) { + // Read the length of the next SCT + const sctLength = stream.getUint16(); + // Slice out the bytes for the next SCT and parse it + const sct = stream.getBlock(sctLength); + sctList.push(sct_1.SignedCertificateTimestamp.parse(sct)); + } + if (stream.position !== end) { + throw new Error('SCT list length does not match actual length'); + } + return sctList; + } +} +exports.X509SCTExtension = X509SCTExtension; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/x509/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/x509/index.js new file mode 100644 index 0000000000000..cdd77e58f37d5 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/x509/index.js @@ -0,0 +1,23 @@ +"use strict"; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.X509SCTExtension = exports.X509Certificate = exports.EXTENSION_OID_SCT = void 0; +var cert_1 = require("./cert"); +Object.defineProperty(exports, "EXTENSION_OID_SCT", { enumerable: true, get: function () { return cert_1.EXTENSION_OID_SCT; } }); +Object.defineProperty(exports, "X509Certificate", { enumerable: true, get: function () { return cert_1.X509Certificate; } }); +var ext_1 = require("./ext"); +Object.defineProperty(exports, "X509SCTExtension", { enumerable: true, get: function () { return ext_1.X509SCTExtension; } }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/x509/sct.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/x509/sct.js new file mode 100644 index 0000000000000..1603059c0d1ac --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/dist/x509/sct.js @@ -0,0 +1,141 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SignedCertificateTimestamp = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const crypto = __importStar(require("../crypto")); +const stream_1 = require("../stream"); +class SignedCertificateTimestamp { + constructor(options) { + this.version = options.version; + this.logID = options.logID; + this.timestamp = options.timestamp; + this.extensions = options.extensions; + this.hashAlgorithm = options.hashAlgorithm; + this.signatureAlgorithm = options.signatureAlgorithm; + this.signature = options.signature; + } + get datetime() { + return new Date(Number(this.timestamp.readBigInt64BE())); + } + // Returns the hash algorithm used to generate the SCT's signature. + // https://www.rfc-editor.org/rfc/rfc5246#section-7.4.1.4.1 + get algorithm() { + switch (this.hashAlgorithm) { + /* istanbul ignore next */ + case 0: + return 'none'; + /* istanbul ignore next */ + case 1: + return 'md5'; + /* istanbul ignore next */ + case 2: + return 'sha1'; + /* istanbul ignore next */ + case 3: + return 'sha224'; + case 4: + return 'sha256'; + /* istanbul ignore next */ + case 5: + return 'sha384'; + /* istanbul ignore next */ + case 6: + return 'sha512'; + /* istanbul ignore next */ + default: + return 'unknown'; + } + } + verify(preCert, key) { + // Assemble the digitally-signed struct (the data over which the signature + // was generated). + // https://www.rfc-editor.org/rfc/rfc6962#section-3.2 + const stream = new stream_1.ByteStream(); + stream.appendChar(this.version); + stream.appendChar(0x00); // SignatureType = certificate_timestamp(0) + stream.appendView(this.timestamp); + stream.appendUint16(0x01); // LogEntryType = precert_entry(1) + stream.appendView(preCert); + stream.appendUint16(this.extensions.byteLength); + /* istanbul ignore next - extensions are very uncommon */ + if (this.extensions.byteLength > 0) { + stream.appendView(this.extensions); + } + return crypto.verify(stream.buffer, key, this.signature, this.algorithm); + } + // Parses a SignedCertificateTimestamp from a buffer. SCTs are encoded using + // TLS encoding which means the fields and lengths of most fields are + // specified as part of the SCT and TLS specs. + // https://www.rfc-editor.org/rfc/rfc6962#section-3.2 + // https://www.rfc-editor.org/rfc/rfc5246#section-7.4.1.4.1 + static parse(buf) { + const stream = new stream_1.ByteStream(buf); + // Version - enum { v1(0), (255) } + const version = stream.getUint8(); + // Log ID - struct { opaque key_id[32]; } + const logID = stream.getBlock(32); + // Timestamp - uint64 + const timestamp = stream.getBlock(8); + // Extensions - opaque extensions<0..2^16-1>; + const extenstionLength = stream.getUint16(); + const extensions = stream.getBlock(extenstionLength); + // Hash algo - enum { sha256(4), . . . (255) } + const hashAlgorithm = stream.getUint8(); + // Signature algo - enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } + const signatureAlgorithm = stream.getUint8(); + // Signature - opaque signature<0..2^16-1>; + const sigLength = stream.getUint16(); + const signature = stream.getBlock(sigLength); + // Check that we read the entire buffer + if (stream.position !== buf.length) { + throw new Error('SCT buffer length mismatch'); + } + return new SignedCertificateTimestamp({ + version, + logID, + timestamp, + extensions, + hashAlgorithm, + signatureAlgorithm, + signature, + }); + } +} +exports.SignedCertificateTimestamp = SignedCertificateTimestamp; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/package.json b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/package.json new file mode 100644 index 0000000000000..af5dd281ac90e --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core/package.json @@ -0,0 +1,31 @@ +{ + "name": "@sigstore/core", + "version": "2.0.0", + "description": "Base library for Sigstore", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "clean": "shx rm -rf dist *.tsbuildinfo", + "build": "tsc --build", + "test": "jest" + }, + "files": [ + "dist" + ], + "author": "bdehamer@github.com", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "git+https://github.com/sigstore/sigstore-js.git" + }, + "bugs": { + "url": "https://github.com/sigstore/sigstore-js/issues" + }, + "homepage": "https://github.com/sigstore/sigstore-js/tree/main/packages/core#readme", + "publishConfig": { + "provenance": true + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/LICENSE b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/LICENSE new file mode 100644 index 0000000000000..e9e7c1679a09d --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 The Sigstore Authors + + 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. diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/bundler/base.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/bundler/base.js new file mode 100644 index 0000000000000..61d5eba4568a3 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/bundler/base.js @@ -0,0 +1,50 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BaseBundleBuilder = void 0; +// BaseBundleBuilder is a base class for BundleBuilder implementations. It +// provides a the basic wokflow for signing and witnessing an artifact. +// Subclasses must implement the `package` method to assemble a valid bundle +// with the generated signature and verification material. +class BaseBundleBuilder { + constructor(options) { + this.signer = options.signer; + this.witnesses = options.witnesses; + } + // Executes the signing/witnessing process for the given artifact. + async create(artifact) { + const signature = await this.prepare(artifact).then((blob) => this.signer.sign(blob)); + const bundle = await this.package(artifact, signature); + // Invoke all of the witnesses in parallel + const verificationMaterials = await Promise.all(this.witnesses.map((witness) => witness.testify(bundle.content, publicKey(signature.key)))); + // Collect the verification material from all of the witnesses + const tlogEntryList = []; + const timestampList = []; + verificationMaterials.forEach(({ tlogEntries, rfc3161Timestamps }) => { + tlogEntryList.push(...(tlogEntries ?? [])); + timestampList.push(...(rfc3161Timestamps ?? [])); + }); + // Merge the collected verification material into the bundle + bundle.verificationMaterial.tlogEntries = tlogEntryList; + bundle.verificationMaterial.timestampVerificationData = { + rfc3161Timestamps: timestampList, + }; + return bundle; + } + // Override this function to apply any pre-signing transformations to the + // artifact. The returned buffer will be signed by the signer. The default + // implementation simply returns the artifact data. + async prepare(artifact) { + return artifact.data; + } +} +exports.BaseBundleBuilder = BaseBundleBuilder; +// Extracts the public key from a KeyMaterial. Returns either the public key +// or the certificate, depending on the type of key material. +function publicKey(key) { + switch (key.$case) { + case 'publicKey': + return key.publicKey; + case 'x509Certificate': + return key.certificate; + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/bundler/bundle.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/bundler/bundle.js new file mode 100644 index 0000000000000..ed32286ad88ef --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/bundler/bundle.js @@ -0,0 +1,71 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.toMessageSignatureBundle = toMessageSignatureBundle; +exports.toDSSEBundle = toDSSEBundle; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const sigstore = __importStar(require("@sigstore/bundle")); +const util_1 = require("../util"); +// Helper functions for assembling the parts of a Sigstore bundle +// Message signature bundle - $case: 'messageSignature' +function toMessageSignatureBundle(artifact, signature) { + const digest = util_1.crypto.digest('sha256', artifact.data); + return sigstore.toMessageSignatureBundle({ + digest, + signature: signature.signature, + certificate: signature.key.$case === 'x509Certificate' + ? util_1.pem.toDER(signature.key.certificate) + : undefined, + keyHint: signature.key.$case === 'publicKey' ? signature.key.hint : undefined, + certificateChain: true, + }); +} +// DSSE envelope bundle - $case: 'dsseEnvelope' +function toDSSEBundle(artifact, signature, certificateChain) { + return sigstore.toDSSEBundle({ + artifact: artifact.data, + artifactType: artifact.type, + signature: signature.signature, + certificate: signature.key.$case === 'x509Certificate' + ? util_1.pem.toDER(signature.key.certificate) + : undefined, + keyHint: signature.key.$case === 'publicKey' ? signature.key.hint : undefined, + certificateChain, + }); +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/bundler/dsse.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/bundler/dsse.js new file mode 100644 index 0000000000000..86046ba8f3013 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/bundler/dsse.js @@ -0,0 +1,46 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DSSEBundleBuilder = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const util_1 = require("../util"); +const base_1 = require("./base"); +const bundle_1 = require("./bundle"); +// BundleBuilder implementation for DSSE wrapped attestations +class DSSEBundleBuilder extends base_1.BaseBundleBuilder { + constructor(options) { + super(options); + this.certificateChain = options.certificateChain ?? false; + } + // DSSE requires the artifact to be pre-encoded with the payload type + // before the signature is generated. + async prepare(artifact) { + const a = artifactDefaults(artifact); + return util_1.dsse.preAuthEncoding(a.type, a.data); + } + // Packages the artifact and signature into a DSSE bundle + async package(artifact, signature) { + return (0, bundle_1.toDSSEBundle)(artifactDefaults(artifact), signature, this.certificateChain); + } +} +exports.DSSEBundleBuilder = DSSEBundleBuilder; +// Defaults the artifact type to an empty string if not provided +function artifactDefaults(artifact) { + return { + ...artifact, + type: artifact.type ?? '', + }; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/bundler/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/bundler/index.js new file mode 100644 index 0000000000000..d67c8c324a4f0 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/bundler/index.js @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MessageSignatureBundleBuilder = exports.DSSEBundleBuilder = void 0; +var dsse_1 = require("./dsse"); +Object.defineProperty(exports, "DSSEBundleBuilder", { enumerable: true, get: function () { return dsse_1.DSSEBundleBuilder; } }); +var message_1 = require("./message"); +Object.defineProperty(exports, "MessageSignatureBundleBuilder", { enumerable: true, get: function () { return message_1.MessageSignatureBundleBuilder; } }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/bundler/message.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/bundler/message.js new file mode 100644 index 0000000000000..e3991f42bab93 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/bundler/message.js @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MessageSignatureBundleBuilder = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const base_1 = require("./base"); +const bundle_1 = require("./bundle"); +// BundleBuilder implementation for raw message signatures +class MessageSignatureBundleBuilder extends base_1.BaseBundleBuilder { + constructor(options) { + super(options); + } + async package(artifact, signature) { + return (0, bundle_1.toMessageSignatureBundle)(artifact, signature); + } +} +exports.MessageSignatureBundleBuilder = MessageSignatureBundleBuilder; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/error.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/error.js new file mode 100644 index 0000000000000..d28f1913cc77e --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/error.js @@ -0,0 +1,39 @@ +"use strict"; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.InternalError = void 0; +exports.internalError = internalError; +const error_1 = require("./external/error"); +class InternalError extends Error { + constructor({ code, message, cause, }) { + super(message); + this.name = this.constructor.name; + this.cause = cause; + this.code = code; + } +} +exports.InternalError = InternalError; +function internalError(err, code, message) { + if (err instanceof error_1.HTTPError) { + message += ` - ${err.message}`; + } + throw new InternalError({ + code: code, + message: message, + cause: err, + }); +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/external/error.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/external/error.js new file mode 100644 index 0000000000000..a6a65adebb176 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/external/error.js @@ -0,0 +1,26 @@ +"use strict"; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.HTTPError = void 0; +class HTTPError extends Error { + constructor({ status, message, location, }) { + super(`(${status}) ${message}`); + this.statusCode = status; + this.location = location; + } +} +exports.HTTPError = HTTPError; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/external/fetch.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/external/fetch.js new file mode 100644 index 0000000000000..116090f3c641e --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/external/fetch.js @@ -0,0 +1,98 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.fetchWithRetry = fetchWithRetry; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const http2_1 = require("http2"); +const make_fetch_happen_1 = __importDefault(require("make-fetch-happen")); +const proc_log_1 = require("proc-log"); +const promise_retry_1 = __importDefault(require("promise-retry")); +const util_1 = require("../util"); +const error_1 = require("./error"); +const { HTTP2_HEADER_LOCATION, HTTP2_HEADER_CONTENT_TYPE, HTTP2_HEADER_USER_AGENT, HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_TOO_MANY_REQUESTS, HTTP_STATUS_REQUEST_TIMEOUT, } = http2_1.constants; +async function fetchWithRetry(url, options) { + return (0, promise_retry_1.default)(async (retry, attemptNum) => { + const method = options.method || 'POST'; + const headers = { + [HTTP2_HEADER_USER_AGENT]: util_1.ua.getUserAgent(), + ...options.headers, + }; + const response = await (0, make_fetch_happen_1.default)(url, { + method, + headers, + body: options.body, + timeout: options.timeout, + retry: false, // We're handling retries ourselves + }).catch((reason) => { + proc_log_1.log.http('fetch', `${method} ${url} attempt ${attemptNum} failed with ${reason}`); + return retry(reason); + }); + if (response.ok) { + return response; + } + else { + const error = await errorFromResponse(response); + proc_log_1.log.http('fetch', `${method} ${url} attempt ${attemptNum} failed with ${response.status}`); + if (retryable(response.status)) { + return retry(error); + } + else { + throw error; + } + } + }, retryOpts(options.retry)); +} +// Translate a Response into an HTTPError instance. This will attempt to parse +// the response body for a message, but will default to the statusText if none +// is found. +const errorFromResponse = async (response) => { + let message = response.statusText; + const location = response.headers.get(HTTP2_HEADER_LOCATION) || undefined; + const contentType = response.headers.get(HTTP2_HEADER_CONTENT_TYPE); + // If response type is JSON, try to parse the body for a message + if (contentType?.includes('application/json')) { + try { + const body = await response.json(); + message = body.message || message; + } + catch (e) { + // ignore + } + } + return new error_1.HTTPError({ + status: response.status, + message: message, + location: location, + }); +}; +// Determine if a status code is retryable. This includes 5xx errors, 408, and +// 429. +const retryable = (status) => [HTTP_STATUS_REQUEST_TIMEOUT, HTTP_STATUS_TOO_MANY_REQUESTS].includes(status) || status >= HTTP_STATUS_INTERNAL_SERVER_ERROR; +// Normalize the retry options to the format expected by promise-retry +const retryOpts = (retry) => { + if (typeof retry === 'boolean') { + return { retries: retry ? 1 : 0 }; + } + else if (typeof retry === 'number') { + return { retries: retry }; + } + else { + return { retries: 0, ...retry }; + } +}; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/external/fulcio.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/external/fulcio.js new file mode 100644 index 0000000000000..de6a1ad9f9e79 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/external/fulcio.js @@ -0,0 +1,41 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Fulcio = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const fetch_1 = require("./fetch"); +/** + * Fulcio API client. + */ +class Fulcio { + constructor(options) { + this.options = options; + } + async createSigningCertificate(request) { + const { baseURL, retry, timeout } = this.options; + const url = `${baseURL}/api/v2/signingCert`; + const response = await (0, fetch_1.fetchWithRetry)(url, { + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(request), + timeout, + retry, + }); + return response.json(); + } +} +exports.Fulcio = Fulcio; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/external/rekor.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/external/rekor.js new file mode 100644 index 0000000000000..bb59a126e032f --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/external/rekor.js @@ -0,0 +1,80 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Rekor = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const fetch_1 = require("./fetch"); +/** + * Rekor API client. + */ +class Rekor { + constructor(options) { + this.options = options; + } + /** + * Create a new entry in the Rekor log. + * @param propsedEntry {ProposedEntry} Data to create a new entry + * @returns {Promise} The created entry + */ + async createEntry(propsedEntry) { + const { baseURL, timeout, retry } = this.options; + const url = `${baseURL}/api/v1/log/entries`; + const response = await (0, fetch_1.fetchWithRetry)(url, { + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + body: JSON.stringify(propsedEntry), + timeout, + retry, + }); + const data = await response.json(); + return entryFromResponse(data); + } + /** + * Get an entry from the Rekor log. + * @param uuid {string} The UUID of the entry to retrieve + * @returns {Promise} The retrieved entry + */ + async getEntry(uuid) { + const { baseURL, timeout, retry } = this.options; + const url = `${baseURL}/api/v1/log/entries/${uuid}`; + const response = await (0, fetch_1.fetchWithRetry)(url, { + method: 'GET', + headers: { + Accept: 'application/json', + }, + timeout, + retry, + }); + const data = await response.json(); + return entryFromResponse(data); + } +} +exports.Rekor = Rekor; +// Unpack the response from the Rekor API into a more convenient format. +function entryFromResponse(data) { + const entries = Object.entries(data); + if (entries.length != 1) { + throw new Error('Received multiple entries in Rekor response'); + } + // Grab UUID and entry data from the response + const [uuid, entry] = entries[0]; + return { + ...entry, + uuid, + }; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/external/tsa.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/external/tsa.js new file mode 100644 index 0000000000000..a948ba9cca2c7 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/external/tsa.js @@ -0,0 +1,38 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TimestampAuthority = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const fetch_1 = require("./fetch"); +class TimestampAuthority { + constructor(options) { + this.options = options; + } + async createTimestamp(request) { + const { baseURL, timeout, retry } = this.options; + const url = `${baseURL}/api/v1/timestamp`; + const response = await (0, fetch_1.fetchWithRetry)(url, { + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(request), + timeout, + retry, + }); + return response.buffer(); + } +} +exports.TimestampAuthority = TimestampAuthority; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/identity/ci.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/identity/ci.js new file mode 100644 index 0000000000000..d79133952b605 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/identity/ci.js @@ -0,0 +1,73 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CIContextProvider = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const make_fetch_happen_1 = __importDefault(require("make-fetch-happen")); +// Collection of all the CI-specific providers we have implemented +const providers = [getGHAToken, getEnv]; +/** + * CIContextProvider is a composite identity provider which will iterate + * over all of the CI-specific providers and return the token from the first + * one that resolves. + */ +class CIContextProvider { + /* istanbul ignore next */ + constructor(audience = 'sigstore') { + this.audience = audience; + } + // Invoke all registered ProviderFuncs and return the value of whichever one + // resolves first. + async getToken() { + return Promise.any(providers.map((getToken) => getToken(this.audience))).catch(() => Promise.reject('CI: no tokens available')); + } +} +exports.CIContextProvider = CIContextProvider; +/** + * getGHAToken can retrieve an OIDC token when running in a GitHub Actions + * workflow + */ +async function getGHAToken(audience) { + // Check to see if we're running in GitHub Actions + if (!process.env.ACTIONS_ID_TOKEN_REQUEST_URL || + !process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN) { + return Promise.reject('no token available'); + } + // Construct URL to request token w/ appropriate audience + const url = new URL(process.env.ACTIONS_ID_TOKEN_REQUEST_URL); + url.searchParams.append('audience', audience); + const response = await (0, make_fetch_happen_1.default)(url.href, { + retry: 2, + headers: { + Accept: 'application/json', + Authorization: `Bearer ${process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN}`, + }, + }); + return response.json().then((data) => data.value); +} +/** + * getEnv can retrieve an OIDC token from an environment variable. + * This matches the behavior of https://github.com/sigstore/cosign/tree/main/pkg/providers/envvar + */ +async function getEnv() { + if (!process.env.SIGSTORE_ID_TOKEN) { + return Promise.reject('no token available'); + } + return process.env.SIGSTORE_ID_TOKEN; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/identity/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/identity/index.js new file mode 100644 index 0000000000000..1c1223b443fab --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/identity/index.js @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CIContextProvider = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +var ci_1 = require("./ci"); +Object.defineProperty(exports, "CIContextProvider", { enumerable: true, get: function () { return ci_1.CIContextProvider; } }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/identity/provider.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/identity/provider.js new file mode 100644 index 0000000000000..c8ad2e549bdc6 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/identity/provider.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/index.js new file mode 100644 index 0000000000000..383b76083361b --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/index.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TSAWitness = exports.RekorWitness = exports.DEFAULT_REKOR_URL = exports.FulcioSigner = exports.DEFAULT_FULCIO_URL = exports.CIContextProvider = exports.InternalError = exports.MessageSignatureBundleBuilder = exports.DSSEBundleBuilder = void 0; +var bundler_1 = require("./bundler"); +Object.defineProperty(exports, "DSSEBundleBuilder", { enumerable: true, get: function () { return bundler_1.DSSEBundleBuilder; } }); +Object.defineProperty(exports, "MessageSignatureBundleBuilder", { enumerable: true, get: function () { return bundler_1.MessageSignatureBundleBuilder; } }); +var error_1 = require("./error"); +Object.defineProperty(exports, "InternalError", { enumerable: true, get: function () { return error_1.InternalError; } }); +var identity_1 = require("./identity"); +Object.defineProperty(exports, "CIContextProvider", { enumerable: true, get: function () { return identity_1.CIContextProvider; } }); +var signer_1 = require("./signer"); +Object.defineProperty(exports, "DEFAULT_FULCIO_URL", { enumerable: true, get: function () { return signer_1.DEFAULT_FULCIO_URL; } }); +Object.defineProperty(exports, "FulcioSigner", { enumerable: true, get: function () { return signer_1.FulcioSigner; } }); +var witness_1 = require("./witness"); +Object.defineProperty(exports, "DEFAULT_REKOR_URL", { enumerable: true, get: function () { return witness_1.DEFAULT_REKOR_URL; } }); +Object.defineProperty(exports, "RekorWitness", { enumerable: true, get: function () { return witness_1.RekorWitness; } }); +Object.defineProperty(exports, "TSAWitness", { enumerable: true, get: function () { return witness_1.TSAWitness; } }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/signer/fulcio/ca.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/signer/fulcio/ca.js new file mode 100644 index 0000000000000..f01703cfab564 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/signer/fulcio/ca.js @@ -0,0 +1,59 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CAClient = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const error_1 = require("../../error"); +const fulcio_1 = require("../../external/fulcio"); +class CAClient { + constructor(options) { + this.fulcio = new fulcio_1.Fulcio({ + baseURL: options.fulcioBaseURL, + retry: options.retry, + timeout: options.timeout, + }); + } + async createSigningCertificate(identityToken, publicKey, challenge) { + const request = toCertificateRequest(identityToken, publicKey, challenge); + try { + const resp = await this.fulcio.createSigningCertificate(request); + // Account for the fact that the response may contain either a + // signedCertificateEmbeddedSct or a signedCertificateDetachedSct. + const cert = resp.signedCertificateEmbeddedSct + ? resp.signedCertificateEmbeddedSct + : resp.signedCertificateDetachedSct; + return cert.chain.certificates; + } + catch (err) { + (0, error_1.internalError)(err, 'CA_CREATE_SIGNING_CERTIFICATE_ERROR', 'error creating signing certificate'); + } + } +} +exports.CAClient = CAClient; +function toCertificateRequest(identityToken, publicKey, challenge) { + return { + credentials: { + oidcIdentityToken: identityToken, + }, + publicKeyRequest: { + publicKey: { + algorithm: 'ECDSA', + content: publicKey, + }, + proofOfPossession: challenge.toString('base64'), + }, + }; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/signer/fulcio/ephemeral.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/signer/fulcio/ephemeral.js new file mode 100644 index 0000000000000..481aa5c3579a2 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/signer/fulcio/ephemeral.js @@ -0,0 +1,45 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.EphemeralSigner = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const crypto_1 = __importDefault(require("crypto")); +const EC_KEYPAIR_TYPE = 'ec'; +const P256_CURVE = 'P-256'; +// Signer implementation which uses an ephemeral keypair to sign artifacts. +// The private key lives only in memory and is tied to the lifetime of the +// EphemeralSigner instance. +class EphemeralSigner { + constructor() { + this.keypair = crypto_1.default.generateKeyPairSync(EC_KEYPAIR_TYPE, { + namedCurve: P256_CURVE, + }); + } + async sign(data) { + const signature = crypto_1.default.sign(null, data, this.keypair.privateKey); + const publicKey = this.keypair.publicKey + .export({ format: 'pem', type: 'spki' }) + .toString('ascii'); + return { + signature: signature, + key: { $case: 'publicKey', publicKey }, + }; + } +} +exports.EphemeralSigner = EphemeralSigner; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/signer/fulcio/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/signer/fulcio/index.js new file mode 100644 index 0000000000000..89a432548d2b4 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/signer/fulcio/index.js @@ -0,0 +1,87 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.FulcioSigner = exports.DEFAULT_FULCIO_URL = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const error_1 = require("../../error"); +const util_1 = require("../../util"); +const ca_1 = require("./ca"); +const ephemeral_1 = require("./ephemeral"); +exports.DEFAULT_FULCIO_URL = 'https://fulcio.sigstore.dev'; +// Signer implementation which can be used to decorate another signer +// with a Fulcio-issued signing certificate for the signer's public key. +// Must be instantiated with an identity provider which can provide a JWT +// which represents the identity to be bound to the signing certificate. +class FulcioSigner { + constructor(options) { + this.ca = new ca_1.CAClient({ + ...options, + fulcioBaseURL: options.fulcioBaseURL || /* istanbul ignore next */ exports.DEFAULT_FULCIO_URL, + }); + this.identityProvider = options.identityProvider; + this.keyHolder = options.keyHolder || new ephemeral_1.EphemeralSigner(); + } + async sign(data) { + // Retrieve identity token from the supplied identity provider + const identityToken = await this.getIdentityToken(); + // Extract challenge claim from OIDC token + let subject; + try { + subject = util_1.oidc.extractJWTSubject(identityToken); + } + catch (err) { + throw new error_1.InternalError({ + code: 'IDENTITY_TOKEN_PARSE_ERROR', + message: `invalid identity token: ${identityToken}`, + cause: err, + }); + } + // Construct challenge value by signing the subject claim + const challenge = await this.keyHolder.sign(Buffer.from(subject)); + if (challenge.key.$case !== 'publicKey') { + throw new error_1.InternalError({ + code: 'CA_CREATE_SIGNING_CERTIFICATE_ERROR', + message: 'unexpected format for signing key', + }); + } + // Create signing certificate + const certificates = await this.ca.createSigningCertificate(identityToken, challenge.key.publicKey, challenge.signature); + // Generate artifact signature + const signature = await this.keyHolder.sign(data); + // Specifically returning only the first certificate in the chain + // as the key. + return { + signature: signature.signature, + key: { + $case: 'x509Certificate', + certificate: certificates[0], + }, + }; + } + async getIdentityToken() { + try { + return await this.identityProvider.getToken(); + } + catch (err) { + throw new error_1.InternalError({ + code: 'IDENTITY_TOKEN_READ_ERROR', + message: 'error retrieving identity token', + cause: err, + }); + } + } +} +exports.FulcioSigner = FulcioSigner; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/signer/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/signer/index.js new file mode 100644 index 0000000000000..e2087767b81c1 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/signer/index.js @@ -0,0 +1,22 @@ +"use strict"; +/* istanbul ignore file */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.FulcioSigner = exports.DEFAULT_FULCIO_URL = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +var fulcio_1 = require("./fulcio"); +Object.defineProperty(exports, "DEFAULT_FULCIO_URL", { enumerable: true, get: function () { return fulcio_1.DEFAULT_FULCIO_URL; } }); +Object.defineProperty(exports, "FulcioSigner", { enumerable: true, get: function () { return fulcio_1.FulcioSigner; } }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/signer/signer.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/signer/signer.js new file mode 100644 index 0000000000000..b92c54183375d --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/signer/signer.js @@ -0,0 +1,17 @@ +"use strict"; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/types/fetch.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/types/fetch.js new file mode 100644 index 0000000000000..c8ad2e549bdc6 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/types/fetch.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/util/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/util/index.js new file mode 100644 index 0000000000000..f467c9150c348 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/util/index.js @@ -0,0 +1,49 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ua = exports.oidc = exports.pem = exports.json = exports.encoding = exports.dsse = exports.crypto = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +var core_1 = require("@sigstore/core"); +Object.defineProperty(exports, "crypto", { enumerable: true, get: function () { return core_1.crypto; } }); +Object.defineProperty(exports, "dsse", { enumerable: true, get: function () { return core_1.dsse; } }); +Object.defineProperty(exports, "encoding", { enumerable: true, get: function () { return core_1.encoding; } }); +Object.defineProperty(exports, "json", { enumerable: true, get: function () { return core_1.json; } }); +Object.defineProperty(exports, "pem", { enumerable: true, get: function () { return core_1.pem; } }); +exports.oidc = __importStar(require("./oidc")); +exports.ua = __importStar(require("./ua")); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/util/oidc.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/util/oidc.js new file mode 100644 index 0000000000000..37c5b168ee12e --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/util/oidc.js @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.extractJWTSubject = extractJWTSubject; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const core_1 = require("@sigstore/core"); +function extractJWTSubject(jwt) { + const parts = jwt.split('.', 3); + const payload = JSON.parse(core_1.encoding.base64Decode(parts[1])); + switch (payload.iss) { + case 'https://accounts.google.com': + case 'https://oauth2.sigstore.dev/auth': + return payload.email; + default: + return payload.sub; + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/util/ua.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/util/ua.js new file mode 100644 index 0000000000000..b15ff2070fb9f --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/util/ua.js @@ -0,0 +1,32 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getUserAgent = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const os_1 = __importDefault(require("os")); +// Format User-Agent: / () +// source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent +const getUserAgent = () => { + const packageVersion = require('../../package.json').version; + const nodeVersion = process.version; + const platformName = os_1.default.platform(); + const archName = os_1.default.arch(); + return `sigstore-js/${packageVersion} (Node ${nodeVersion}) (${platformName}/${archName})`; +}; +exports.getUserAgent = getUserAgent; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/index.js new file mode 100644 index 0000000000000..72677c399caa7 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/index.js @@ -0,0 +1,24 @@ +"use strict"; +/* istanbul ignore file */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TSAWitness = exports.RekorWitness = exports.DEFAULT_REKOR_URL = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +var tlog_1 = require("./tlog"); +Object.defineProperty(exports, "DEFAULT_REKOR_URL", { enumerable: true, get: function () { return tlog_1.DEFAULT_REKOR_URL; } }); +Object.defineProperty(exports, "RekorWitness", { enumerable: true, get: function () { return tlog_1.RekorWitness; } }); +var tsa_1 = require("./tsa"); +Object.defineProperty(exports, "TSAWitness", { enumerable: true, get: function () { return tsa_1.TSAWitness; } }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/tlog/client.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/tlog/client.js new file mode 100644 index 0000000000000..22c895f2ca7ed --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/tlog/client.js @@ -0,0 +1,61 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TLogClient = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const error_1 = require("../../error"); +const error_2 = require("../../external/error"); +const rekor_1 = require("../../external/rekor"); +class TLogClient { + constructor(options) { + this.fetchOnConflict = options.fetchOnConflict ?? false; + this.rekor = new rekor_1.Rekor({ + baseURL: options.rekorBaseURL, + retry: options.retry, + timeout: options.timeout, + }); + } + async createEntry(proposedEntry) { + let entry; + try { + entry = await this.rekor.createEntry(proposedEntry); + } + catch (err) { + // If the entry already exists, fetch it (if enabled) + if (entryExistsError(err) && this.fetchOnConflict) { + // Grab the UUID of the existing entry from the location header + /* istanbul ignore next */ + const uuid = err.location.split('/').pop() || ''; + try { + entry = await this.rekor.getEntry(uuid); + } + catch (err) { + (0, error_1.internalError)(err, 'TLOG_FETCH_ENTRY_ERROR', 'error fetching tlog entry'); + } + } + else { + (0, error_1.internalError)(err, 'TLOG_CREATE_ENTRY_ERROR', 'error creating tlog entry'); + } + } + return entry; + } +} +exports.TLogClient = TLogClient; +function entryExistsError(value) { + return (value instanceof error_2.HTTPError && + value.statusCode === 409 && + value.location !== undefined); +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/tlog/entry.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/tlog/entry.js new file mode 100644 index 0000000000000..bb1c68e914b90 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/tlog/entry.js @@ -0,0 +1,140 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.toProposedEntry = toProposedEntry; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const bundle_1 = require("@sigstore/bundle"); +const util_1 = require("../../util"); +const SHA256_ALGORITHM = 'sha256'; +function toProposedEntry(content, publicKey, +// TODO: Remove this parameter once have completely switched to 'dsse' entries +entryType = 'dsse') { + switch (content.$case) { + case 'dsseEnvelope': + // TODO: Remove this conditional once have completely ditched "intoto" entries + if (entryType === 'intoto') { + return toProposedIntotoEntry(content.dsseEnvelope, publicKey); + } + return toProposedDSSEEntry(content.dsseEnvelope, publicKey); + case 'messageSignature': + return toProposedHashedRekordEntry(content.messageSignature, publicKey); + } +} +// Returns a properly formatted Rekor "hashedrekord" entry for the given digest +// and signature +function toProposedHashedRekordEntry(messageSignature, publicKey) { + const hexDigest = messageSignature.messageDigest.digest.toString('hex'); + const b64Signature = messageSignature.signature.toString('base64'); + const b64Key = util_1.encoding.base64Encode(publicKey); + return { + apiVersion: '0.0.1', + kind: 'hashedrekord', + spec: { + data: { + hash: { + algorithm: SHA256_ALGORITHM, + value: hexDigest, + }, + }, + signature: { + content: b64Signature, + publicKey: { + content: b64Key, + }, + }, + }, + }; +} +// Returns a properly formatted Rekor "dsse" entry for the given DSSE envelope +// and signature +function toProposedDSSEEntry(envelope, publicKey) { + const envelopeJSON = JSON.stringify((0, bundle_1.envelopeToJSON)(envelope)); + const encodedKey = util_1.encoding.base64Encode(publicKey); + return { + apiVersion: '0.0.1', + kind: 'dsse', + spec: { + proposedContent: { + envelope: envelopeJSON, + verifiers: [encodedKey], + }, + }, + }; +} +// Returns a properly formatted Rekor "intoto" entry for the given DSSE +// envelope and signature +function toProposedIntotoEntry(envelope, publicKey) { + // Calculate the value for the payloadHash field in the Rekor entry + const payloadHash = util_1.crypto + .digest(SHA256_ALGORITHM, envelope.payload) + .toString('hex'); + // Calculate the value for the hash field in the Rekor entry + const envelopeHash = calculateDSSEHash(envelope, publicKey); + // Collect values for re-creating the DSSE envelope. + // Double-encode payload and signature cause that's what Rekor expects + const payload = util_1.encoding.base64Encode(envelope.payload.toString('base64')); + const sig = util_1.encoding.base64Encode(envelope.signatures[0].sig.toString('base64')); + const keyid = envelope.signatures[0].keyid; + const encodedKey = util_1.encoding.base64Encode(publicKey); + // Create the envelope portion of the entry. Note the inclusion of the + // publicKey in the signature struct is not a standard part of a DSSE + // envelope, but is required by Rekor. + const dsse = { + payloadType: envelope.payloadType, + payload: payload, + signatures: [{ sig, publicKey: encodedKey }], + }; + // If the keyid is an empty string, Rekor seems to remove it altogether. We + // need to do the same here so that we can properly recreate the entry for + // verification. + if (keyid.length > 0) { + dsse.signatures[0].keyid = keyid; + } + return { + apiVersion: '0.0.2', + kind: 'intoto', + spec: { + content: { + envelope: dsse, + hash: { algorithm: SHA256_ALGORITHM, value: envelopeHash }, + payloadHash: { algorithm: SHA256_ALGORITHM, value: payloadHash }, + }, + }, + }; +} +// Calculates the hash of a DSSE envelope for inclusion in a Rekor entry. +// There is no standard way to do this, so the scheme we're using as as +// follows: +// * payload is base64 encoded +// * signature is base64 encoded (only the first signature is used) +// * keyid is included ONLY if it is NOT an empty string +// * The resulting JSON is canonicalized and hashed to a hex string +function calculateDSSEHash(envelope, publicKey) { + const dsse = { + payloadType: envelope.payloadType, + payload: envelope.payload.toString('base64'), + signatures: [ + { sig: envelope.signatures[0].sig.toString('base64'), publicKey }, + ], + }; + // If the keyid is an empty string, Rekor seems to remove it altogether. + if (envelope.signatures[0].keyid.length > 0) { + dsse.signatures[0].keyid = envelope.signatures[0].keyid; + } + return util_1.crypto + .digest(SHA256_ALGORITHM, util_1.json.canonicalize(dsse)) + .toString('hex'); +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/tlog/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/tlog/index.js new file mode 100644 index 0000000000000..6197b09d4cdd9 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/tlog/index.js @@ -0,0 +1,82 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RekorWitness = exports.DEFAULT_REKOR_URL = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const util_1 = require("../../util"); +const client_1 = require("./client"); +const entry_1 = require("./entry"); +exports.DEFAULT_REKOR_URL = 'https://rekor.sigstore.dev'; +class RekorWitness { + constructor(options) { + this.entryType = options.entryType; + this.tlog = new client_1.TLogClient({ + ...options, + rekorBaseURL: options.rekorBaseURL || /* istanbul ignore next */ exports.DEFAULT_REKOR_URL, + }); + } + async testify(content, publicKey) { + const proposedEntry = (0, entry_1.toProposedEntry)(content, publicKey, this.entryType); + const entry = await this.tlog.createEntry(proposedEntry); + return toTransparencyLogEntry(entry); + } +} +exports.RekorWitness = RekorWitness; +function toTransparencyLogEntry(entry) { + const logID = Buffer.from(entry.logID, 'hex'); + // Parse entry body so we can extract the kind and version. + const bodyJSON = util_1.encoding.base64Decode(entry.body); + const entryBody = JSON.parse(bodyJSON); + const promise = entry?.verification?.signedEntryTimestamp + ? inclusionPromise(entry.verification.signedEntryTimestamp) + : undefined; + const proof = entry?.verification?.inclusionProof + ? inclusionProof(entry.verification.inclusionProof) + : undefined; + const tlogEntry = { + logIndex: entry.logIndex.toString(), + logId: { + keyId: logID, + }, + integratedTime: entry.integratedTime.toString(), + kindVersion: { + kind: entryBody.kind, + version: entryBody.apiVersion, + }, + inclusionPromise: promise, + inclusionProof: proof, + canonicalizedBody: Buffer.from(entry.body, 'base64'), + }; + return { + tlogEntries: [tlogEntry], + }; +} +function inclusionPromise(promise) { + return { + signedEntryTimestamp: Buffer.from(promise, 'base64'), + }; +} +function inclusionProof(proof) { + return { + logIndex: proof.logIndex.toString(), + treeSize: proof.treeSize.toString(), + rootHash: Buffer.from(proof.rootHash, 'hex'), + hashes: proof.hashes.map((h) => Buffer.from(h, 'hex')), + checkpoint: { + envelope: proof.checkpoint, + }, + }; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/tsa/client.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/tsa/client.js new file mode 100644 index 0000000000000..754de3748dbb3 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/tsa/client.js @@ -0,0 +1,46 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TSAClient = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const error_1 = require("../../error"); +const tsa_1 = require("../../external/tsa"); +const util_1 = require("../../util"); +const SHA256_ALGORITHM = 'sha256'; +class TSAClient { + constructor(options) { + this.tsa = new tsa_1.TimestampAuthority({ + baseURL: options.tsaBaseURL, + retry: options.retry, + timeout: options.timeout, + }); + } + async createTimestamp(signature) { + const request = { + artifactHash: util_1.crypto + .digest(SHA256_ALGORITHM, signature) + .toString('base64'), + hashAlgorithm: SHA256_ALGORITHM, + }; + try { + return await this.tsa.createTimestamp(request); + } + catch (err) { + (0, error_1.internalError)(err, 'TSA_CREATE_TIMESTAMP_ERROR', 'error creating timestamp'); + } + } +} +exports.TSAClient = TSAClient; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/tsa/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/tsa/index.js new file mode 100644 index 0000000000000..d4f5c7c859d10 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/tsa/index.js @@ -0,0 +1,44 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TSAWitness = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const client_1 = require("./client"); +class TSAWitness { + constructor(options) { + this.tsa = new client_1.TSAClient({ + tsaBaseURL: options.tsaBaseURL, + retry: options.retry, + timeout: options.timeout, + }); + } + async testify(content) { + const signature = extractSignature(content); + const timestamp = await this.tsa.createTimestamp(signature); + return { + rfc3161Timestamps: [{ signedTimestamp: timestamp }], + }; + } +} +exports.TSAWitness = TSAWitness; +function extractSignature(content) { + switch (content.$case) { + case 'dsseEnvelope': + return content.dsseEnvelope.signatures[0].sig; + case 'messageSignature': + return content.messageSignature.signature; + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/witness.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/witness.js new file mode 100644 index 0000000000000..c8ad2e549bdc6 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/dist/witness/witness.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/package.json b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/package.json new file mode 100644 index 0000000000000..fe05e8dc2d73a --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/package.json @@ -0,0 +1,46 @@ +{ + "name": "@sigstore/sign", + "version": "3.0.0", + "description": "Sigstore signing library", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "clean": "shx rm -rf dist *.tsbuildinfo", + "build": "tsc --build", + "test": "jest" + }, + "files": [ + "dist" + ], + "author": "bdehamer@github.com", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "git+https://github.com/sigstore/sigstore-js.git" + }, + "bugs": { + "url": "https://github.com/sigstore/sigstore-js/issues" + }, + "homepage": "https://github.com/sigstore/sigstore-js/tree/main/packages/sign#readme", + "publishConfig": { + "provenance": true + }, + "devDependencies": { + "@sigstore/jest": "^0.0.0", + "@sigstore/mock": "^0.8.0", + "@sigstore/rekor-types": "^3.0.0", + "@types/make-fetch-happen": "^10.0.4", + "@types/promise-retry": "^1.1.6" + }, + "dependencies": { + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0", + "@sigstore/protobuf-specs": "^0.3.2", + "make-fetch-happen": "^14.0.1", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/LICENSE b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/LICENSE new file mode 100644 index 0000000000000..e9e7c1679a09d --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 The Sigstore Authors + + 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. diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/dist/appdata.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/dist/appdata.js new file mode 100644 index 0000000000000..06a8143e70da2 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/dist/appdata.js @@ -0,0 +1,43 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.appDataPath = appDataPath; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const os_1 = __importDefault(require("os")); +const path_1 = __importDefault(require("path")); +function appDataPath(name) { + const homedir = os_1.default.homedir(); + switch (process.platform) { + /* istanbul ignore next */ + case 'darwin': { + const appSupport = path_1.default.join(homedir, 'Library', 'Application Support'); + return path_1.default.join(appSupport, name); + } + /* istanbul ignore next */ + case 'win32': { + const localAppData = process.env.LOCALAPPDATA || path_1.default.join(homedir, 'AppData', 'Local'); + return path_1.default.join(localAppData, name, 'Data'); + } + /* istanbul ignore next */ + default: { + const localData = process.env.XDG_DATA_HOME || path_1.default.join(homedir, '.local', 'share'); + return path_1.default.join(localData, name); + } + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/dist/client.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/dist/client.js new file mode 100644 index 0000000000000..328f49e40dbbd --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/dist/client.js @@ -0,0 +1,111 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TUFClient = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const fs_1 = __importDefault(require("fs")); +const path_1 = __importDefault(require("path")); +const tuf_js_1 = require("tuf-js"); +const _1 = require("."); +const target_1 = require("./target"); +const TARGETS_DIR_NAME = 'targets'; +class TUFClient { + constructor(options) { + const url = new URL(options.mirrorURL); + const repoName = encodeURIComponent(url.host + url.pathname.replace(/\/$/, '')); + const cachePath = path_1.default.join(options.cachePath, repoName); + initTufCache(cachePath); + seedCache({ + cachePath, + mirrorURL: options.mirrorURL, + tufRootPath: options.rootPath, + forceInit: options.forceInit, + }); + this.updater = initClient({ + mirrorURL: options.mirrorURL, + cachePath, + forceCache: options.forceCache, + retry: options.retry, + timeout: options.timeout, + }); + } + async refresh() { + return this.updater.refresh(); + } + getTarget(targetName) { + return (0, target_1.readTarget)(this.updater, targetName); + } +} +exports.TUFClient = TUFClient; +// Initializes the TUF cache directory structure including the initial +// root.json file. If the cache directory does not exist, it will be +// created. If the targets directory does not exist, it will be created. +// If the root.json file does not exist, it will be copied from the +// rootPath argument. +function initTufCache(cachePath) { + const targetsPath = path_1.default.join(cachePath, TARGETS_DIR_NAME); + if (!fs_1.default.existsSync(cachePath)) { + fs_1.default.mkdirSync(cachePath, { recursive: true }); + } + if (!fs_1.default.existsSync(targetsPath)) { + fs_1.default.mkdirSync(targetsPath); + } +} +// Populates the TUF cache with the initial root.json file. If the root.json +// file does not exist (or we're forcing re-initialization), copy it from either +// the rootPath argument or from one of the repo seeds. +function seedCache({ cachePath, mirrorURL, tufRootPath, forceInit, }) { + const cachedRootPath = path_1.default.join(cachePath, 'root.json'); + // If the root.json file does not exist (or we're forcing re-initialization), + // populate it either from the supplied rootPath or from one of the repo seeds. + if (!fs_1.default.existsSync(cachedRootPath) || forceInit) { + if (tufRootPath) { + fs_1.default.copyFileSync(tufRootPath, cachedRootPath); + } + else { + const seeds = require('../seeds.json'); + const repoSeed = seeds[mirrorURL]; + if (!repoSeed) { + throw new _1.TUFError({ + code: 'TUF_INIT_CACHE_ERROR', + message: `No root.json found for mirror: ${mirrorURL}`, + }); + } + fs_1.default.writeFileSync(cachedRootPath, Buffer.from(repoSeed['root.json'], 'base64')); + // Copy any seed targets into the cache + Object.entries(repoSeed.targets).forEach(([targetName, target]) => { + fs_1.default.writeFileSync(path_1.default.join(cachePath, TARGETS_DIR_NAME, targetName), Buffer.from(target, 'base64')); + }); + } + } +} +function initClient(options) { + const config = { + fetchTimeout: options.timeout, + fetchRetry: options.retry, + }; + return new tuf_js_1.Updater({ + metadataBaseUrl: options.mirrorURL, + targetBaseUrl: `${options.mirrorURL}/targets`, + metadataDir: options.cachePath, + targetDir: path_1.default.join(options.cachePath, TARGETS_DIR_NAME), + forceCache: options.forceCache, + config, + }); +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/dist/error.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/dist/error.js new file mode 100644 index 0000000000000..e13971b289ff2 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/dist/error.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TUFError = void 0; +class TUFError extends Error { + constructor({ code, message, cause, }) { + super(message); + this.code = code; + this.cause = cause; + this.name = this.constructor.name; + } +} +exports.TUFError = TUFError; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/dist/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/dist/index.js new file mode 100644 index 0000000000000..2af5de93ec5d2 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/dist/index.js @@ -0,0 +1,56 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TUFError = exports.DEFAULT_MIRROR_URL = void 0; +exports.getTrustedRoot = getTrustedRoot; +exports.initTUF = initTUF; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const protobuf_specs_1 = require("@sigstore/protobuf-specs"); +const appdata_1 = require("./appdata"); +const client_1 = require("./client"); +exports.DEFAULT_MIRROR_URL = 'https://tuf-repo-cdn.sigstore.dev'; +const DEFAULT_CACHE_DIR = 'sigstore-js'; +const DEFAULT_RETRY = { retries: 2 }; +const DEFAULT_TIMEOUT = 5000; +const TRUSTED_ROOT_TARGET = 'trusted_root.json'; +async function getTrustedRoot( +/* istanbul ignore next */ +options = {}) { + const client = createClient(options); + const trustedRoot = await client.getTarget(TRUSTED_ROOT_TARGET); + return protobuf_specs_1.TrustedRoot.fromJSON(JSON.parse(trustedRoot)); +} +async function initTUF( +/* istanbul ignore next */ +options = {}) { + const client = createClient(options); + return client.refresh().then(() => client); +} +// Create a TUF client with default options +function createClient(options) { + /* istanbul ignore next */ + return new client_1.TUFClient({ + cachePath: options.cachePath || (0, appdata_1.appDataPath)(DEFAULT_CACHE_DIR), + rootPath: options.rootPath, + mirrorURL: options.mirrorURL || exports.DEFAULT_MIRROR_URL, + retry: options.retry ?? DEFAULT_RETRY, + timeout: options.timeout ?? DEFAULT_TIMEOUT, + forceCache: options.forceCache ?? false, + forceInit: options.forceInit ?? options.force ?? false, + }); +} +var error_1 = require("./error"); +Object.defineProperty(exports, "TUFError", { enumerable: true, get: function () { return error_1.TUFError; } }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/dist/target.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/dist/target.js new file mode 100644 index 0000000000000..5c6675bdfbf5f --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/dist/target.js @@ -0,0 +1,79 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.readTarget = readTarget; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const fs_1 = __importDefault(require("fs")); +const error_1 = require("./error"); +// Downloads and returns the specified target from the provided TUF Updater. +async function readTarget(tuf, targetPath) { + const path = await getTargetPath(tuf, targetPath); + return new Promise((resolve, reject) => { + fs_1.default.readFile(path, 'utf-8', (err, data) => { + if (err) { + reject(new error_1.TUFError({ + code: 'TUF_READ_TARGET_ERROR', + message: `error reading target ${path}`, + cause: err, + })); + } + else { + resolve(data); + } + }); + }); +} +// Returns the local path to the specified target. If the target is not yet +// cached locally, the provided TUF Updater will be used to download and +// cache the target. +async function getTargetPath(tuf, target) { + let targetInfo; + try { + targetInfo = await tuf.getTargetInfo(target); + } + catch (err) { + throw new error_1.TUFError({ + code: 'TUF_REFRESH_METADATA_ERROR', + message: 'error refreshing TUF metadata', + cause: err, + }); + } + if (!targetInfo) { + throw new error_1.TUFError({ + code: 'TUF_FIND_TARGET_ERROR', + message: `target ${target} not found`, + }); + } + let path = await tuf.findCachedTarget(targetInfo); + // An empty path here means the target has not been cached locally, or is + // out of date. In either case, we need to download it. + if (!path) { + try { + path = await tuf.downloadTarget(targetInfo); + } + catch (err) { + throw new error_1.TUFError({ + code: 'TUF_DOWNLOAD_TARGET_ERROR', + message: `error downloading target ${path}`, + cause: err, + }); + } + } + return path; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/package.json b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/package.json new file mode 100644 index 0000000000000..808689dfddf92 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/package.json @@ -0,0 +1,41 @@ +{ + "name": "@sigstore/tuf", + "version": "3.0.0", + "description": "Client for the Sigstore TUF repository", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "clean": "shx rm -rf dist *.tsbuildinfo", + "build": "tsc --build", + "test": "jest" + }, + "files": [ + "dist", + "seeds.json" + ], + "author": "bdehamer@github.com", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "git+https://github.com/sigstore/sigstore-js.git" + }, + "bugs": { + "url": "https://github.com/sigstore/sigstore-js/issues" + }, + "homepage": "https://github.com/sigstore/sigstore-js/tree/main/packages/tuf#readme", + "publishConfig": { + "provenance": true + }, + "devDependencies": { + "@sigstore/jest": "^0.0.0", + "@tufjs/repo-mock": "^3.0.1", + "@types/make-fetch-happen": "^10.0.4" + }, + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.2", + "tuf-js": "^3.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/seeds.json b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/seeds.json new file mode 100644 index 0000000000000..d1d3c6b5c4604 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf/seeds.json @@ -0,0 +1 @@ +{"https://tuf-repo-cdn.sigstore.dev":{"root.json":"ewogInNpZ25hdHVyZXMiOiBbCiAgewogICAia2V5aWQiOiAiNmYyNjAwODlkNTkyM2RhZjIwMTY2Y2E2NTdjNTQzYWY2MTgzNDZhYjk3MTg4NGE5OTk2MmIwMTk4OGJiZTBjMyIsCiAgICJzaWciOiAiMzA0NjAyMjEwMDhhYjFmNmYxN2Q0ZjllNmQ3ZGNmMWM4ODkxMmI2YjUzY2MxMDM4ODY0NGFlMWYwOWJjMzdhMDgyY2QwNjAwM2UwMjIxMDBlMTQ1ZWY0YzdiNzgyZDRlODEwN2I1MzQzN2U2NjlkMDQ3Njg5MmNlOTk5OTAzYWUzM2QxNDQ0ODM2Njk5NmU3IgogIH0sCiAgewogICAia2V5aWQiOiAiZTcxYTU0ZDU0MzgzNWJhODZhZGFkOTQ2MDM3OWM3NjQxZmI4NzI2ZDE2NGVhNzY2ODAxYTFjNTIyYWJhN2VhMiIsCiAgICJzaWciOiAiMzA0NTAyMjEwMGM3NjhiMmY4NmRhOTk1NjkwMTljMTYwYTA4MWRhNTRhZTM2YzM0YzBhMzEyMGQzY2I2OWI1M2I3ZDExMzc1OGUwMjIwNGY2NzE1MThmNjE3YjIwZDQ2NTM3ZmFlNmMzYjYzYmFlODkxM2Y0ZjE5NjIxNTYxMDVjYzRmMDE5YWMzNWM2YSIKICB9LAogIHsKICAgImtleWlkIjogIjIyZjRjYWVjNmQ4ZTZmOTU1NWFmNjZiM2Q0YzNjYjA2YTNiYjIzZmRjN2UzOWM5MTZjNjFmNDYyZTZmNTJiMDYiLAogICAic2lnIjogIjMwNDUwMjIxMDBiNDQzNGU2OTk1ZDM2OGQyM2U3NDc1OWFjZDBjYjkwMTNjODNhNWQzNTExZjBmOTk3ZWM1NGM0NTZhZTQzNTBhMDIyMDE1YjBlMjY1ZDE4MmQyYjYxZGM3NGUxNTVkOThiM2MzZmJlNTY0YmEwNTI4NmFhMTRjOGRmMDJjOWI3NTY1MTYiCiAgfSwKICB7CiAgICJrZXlpZCI6ICI2MTY0MzgzODEyNWI0NDBiNDBkYjY5NDJmNWNiNWEzMWMwZGMwNDM2ODMxNmViMmFhYTU4Yjk1OTA0YTU4MjIyIiwKICAgInNpZyI6ICIzMDQ1MDIyMTAwODJjNTg0MTFkOTg5ZWI5Zjg2MTQxMDg1N2Q0MjM4MTU5MGVjOTQyNGRiZGFhNTFlNzhlZDEzNTE1NDMxOTA0ZTAyMjAxMTgxODVkYTZhNmMyOTQ3MTMxYzE3Nzk3ZTJiYjc2MjBjZTI2ZTVmMzAxZDFjZWFjNWYyYTdlNThmOWRjZjJlIgogIH0sCiAgewogICAia2V5aWQiOiAiYTY4N2U1YmY0ZmFiODJiMGVlNThkNDZlMDVjOTUzNTE0NWEyYzlhZmI0NThmNDNkNDJiNDVjYTBmZGNlMmE3MCIsCiAgICJzaWciOiAiMzA0NjAyMjEwMGM3ODUxMzg1NGNhZTljMzJlYWE2Yjg4ZTE4OTEyZjQ4MDA2YzI3NTdhMjU4ZjkxNzMxMmNhYmE3NTk0OGViOWUwMjIxMDBkOWUxYjRjZTBhZGZlOWZkMmUyMTQ4ZDdmYTI3YTJmNDBiYTExMjJiZDY5ZGE3NjEyZDhkMTc3NmIwMTNjOTFkIgogIH0sCiAgewogICAia2V5aWQiOiAiZmRmYTgzYTA3YjVhODM1ODliODdkZWQ0MWY3N2YzOWQyMzJhZDkxZjdjY2U1Mjg2OGRhY2QwNmJhMDg5ODQ5ZiIsCiAgICJzaWciOiAiMzA0NTAyMjA1NjQ4M2EyZDVkOWVhOWNlYzZlMTFlYWRmYjMzYzQ4NGI2MTQyOThmYWNhMTVhY2YxYzQzMWIxMWVkN2Y3MzRjMDIyMTAwZDBjMWQ3MjZhZjkyYTg3ZTRlNjY0NTljYTVhZGYzOGEwNWI0NGUxZjk0MzE4NDIzZjk1NGJhZThiY2E1YmIyZSIKICB9LAogIHsKICAgImtleWlkIjogImUyZjU5YWNiOTQ4ODUxOTQwN2UxOGNiZmM5MzI5NTEwYmUwM2MwNGFjYTk5MjlkMmYwMzAxMzQzZmVjODU1MjMiLAogICAic2lnIjogIjMwNDYwMjIxMDBkMDA0ZGU4ODAyNGMzMmRjNTY1M2E5ZjQ4NDNjZmM1MjE1NDI3MDQ4YWQ5NjAwZDJjZjljOTY5ZTZlZGZmM2QyMDIyMTAwZDllYmI3OThmNWZjNjZhZjEwODk5ZGVjZTAxNGE4NjI4Y2NmM2M1NDAyY2Q0YTQyNzAyMDc0NzJmOGY2ZTcxMiIKICB9LAogIHsKICAgImtleWlkIjogIjNjMzQ0YWEwNjhmZDRjYzRlODdkYzUwYjYxMmMwMjQzMWZiYzc3MWU5NTAwMzk5MzY4M2EyYjBiZjI2MGNmMGUiLAogICAic2lnIjogIjMwNDYwMjIxMDBiN2IwOTk5NmM0NWNhMmQ0YjA1NjAzZTU2YmFlZmEyOTcxOGEwYjcxMTQ3Y2Y4YzZlNjYzNDliYWE2MTQ3N2RmMDIyMTAwYzRkYTgwYzcxN2I0ZmE3YmJhMGZkNWM3MmRhOGEwNDk5MzU4YjAxMzU4YjIzMDlmNDFkMTQ1NmVhMWU3ZTFkOSIKICB9LAogIHsKICAgImtleWlkIjogImVjODE2Njk3MzRlMDE3OTk2YzViODVmM2QwMmMzZGUxZGQ0NjM3YTE1MjAxOWZlMWFmMTI1ZDJmOTM2OGI5NWUiLAogICAic2lnIjogIjMwNDYwMjIxMDBiZTk3ODJjMzA3NDRlNDExYTgyZmE4NWI1MTM4ZDYwMWNlMTQ4YmMxOTI1OGFlYzY0ZTdlYzI0NDc4ZjM4ODEyMDIyMTAwY2FlZjYzZGNhZjFhNGI5YTUwMGQzYmQwZTNmMTY0ZWMxOGYxYjYzZDdhOTQ2MGQ5YWNhYjEwNjZkYjBmMDE2ZCIKICB9LAogIHsKICAgImtleWlkIjogIjFlMWQ2NWNlOThiMTBhZGRhZDQ3NjRmZWJmN2RkYTJkMDQzNmIzZDNhMzg5MzU3OWMwZGRkYWVhMjBlNTQ4NDkiLAogICAic2lnIjogIjMwNDUwMjIwNzQ2ZWMzZjg1MzRjZTU1NTMxZDBkMDFmZjY0OTY0ZWY0NDBkMWU3ZDJjNGMxNDI0MDliOGU5NzY5ZjFhZGE2ZjAyMjEwMGUzYjkyOWZjZDkzZWExOGZlYWEwODI1ODg3YTcyMTA0ODk4NzlhNjY3ODBjMDdhODNmNGJkNDZlMmYwOWFiM2IiCiAgfQogXSwKICJzaWduZWQiOiB7CiAgIl90eXBlIjogInJvb3QiLAogICJjb25zaXN0ZW50X3NuYXBzaG90IjogdHJ1ZSwKICAiZXhwaXJlcyI6ICIyMDI1LTAyLTE5VDA4OjA0OjMyWiIsCiAgImtleXMiOiB7CiAgICIyMmY0Y2FlYzZkOGU2Zjk1NTVhZjY2YjNkNGMzY2IwNmEzYmIyM2ZkYzdlMzljOTE2YzYxZjQ2MmU2ZjUyYjA2IjogewogICAgImtleWlkX2hhc2hfYWxnb3JpdGhtcyI6IFsKICAgICAic2hhMjU2IiwKICAgICAic2hhNTEyIgogICAgXSwKICAgICJrZXl0eXBlIjogImVjZHNhIiwKICAgICJrZXl2YWwiOiB7CiAgICAgInB1YmxpYyI6ICItLS0tLUJFR0lOIFBVQkxJQyBLRVktLS0tLVxuTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFekJ6Vk9tSENQb2pNVkxTSTM2NFdpaVY4TlByRFxuNklnUnhWbGlza3ovdit5M0pFUjVtY1ZHY09ObGlEY1dNQzVKMmxmSG1qUE5QaGI0SDd4bThMemZTQT09XG4tLS0tLUVORCBQVUJMSUMgS0VZLS0tLS1cbiIKICAgIH0sCiAgICAic2NoZW1lIjogImVjZHNhLXNoYTItbmlzdHAyNTYiLAogICAgIngtdHVmLW9uLWNpLWtleW93bmVyIjogIkBzYW50aWFnb3RvcnJlcyIKICAgfSwKICAgIjYxNjQzODM4MTI1YjQ0MGI0MGRiNjk0MmY1Y2I1YTMxYzBkYzA0MzY4MzE2ZWIyYWFhNThiOTU5MDRhNTgyMjIiOiB7CiAgICAia2V5aWRfaGFzaF9hbGdvcml0aG1zIjogWwogICAgICJzaGEyNTYiLAogICAgICJzaGE1MTIiCiAgICBdLAogICAgImtleXR5cGUiOiAiZWNkc2EiLAogICAgImtleXZhbCI6IHsKICAgICAicHVibGljIjogIi0tLS0tQkVHSU4gUFVCTElDIEtFWS0tLS0tXG5NRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVpbmlrU3NBUW1Za05lSDVlWXEvQ25JekxhYWNPXG54bFNhYXdRRE93cUt5L3RDcXhxNXh4UFNKYzIxSzRXSWhzOUd5T2tLZnp1ZVkzR0lMemNNSlo0Y1d3PT1cbi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLVxuIgogICAgfSwKICAgICJzY2hlbWUiOiAiZWNkc2Etc2hhMi1uaXN0cDI1NiIsCiAgICAieC10dWYtb24tY2kta2V5b3duZXIiOiAiQGJvYmNhbGxhd2F5IgogICB9LAogICAiNmYyNjAwODlkNTkyM2RhZjIwMTY2Y2E2NTdjNTQzYWY2MTgzNDZhYjk3MTg4NGE5OTk2MmIwMTk4OGJiZTBjMyI6IHsKICAgICJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCiAgICAgInNoYTI1NiIsCiAgICAgInNoYTUxMiIKICAgIF0sCiAgICAia2V5dHlwZSI6ICJlY2RzYSIsCiAgICAia2V5dmFsIjogewogICAgICJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXk4WEtzbWhCWURJOEpjMEd3ekJ4ZUtheDBjbTVcblNUS0VVNjVIUEZ1blVuNDFzVDhwaTBGak00SWtIei9ZVW13bUxVTzBXdDdseGhqNkJrTElLNHFZQXc9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCiAgICB9LAogICAgInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKICAgICJ4LXR1Zi1vbi1jaS1rZXlvd25lciI6ICJAZGxvcmVuYyIKICAgfSwKICAgIjcyNDdmMGRiYWQ4NWIxNDdlMTg2M2JhZGU3NjEyNDNjYzc4NWRjYjdhYTQxMGU3MTA1ZGQzZDJiNjFhMzZkMmMiOiB7CiAgICAia2V5aWRfaGFzaF9hbGdvcml0aG1zIjogWwogICAgICJzaGEyNTYiLAogICAgICJzaGE1MTIiCiAgICBdLAogICAgImtleXR5cGUiOiAiZWNkc2EiLAogICAgImtleXZhbCI6IHsKICAgICAicHVibGljIjogIi0tLS0tQkVHSU4gUFVCTElDIEtFWS0tLS0tXG5NRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVXUmlHcjUraiszSjVTc0grWnRyNW5FMkgyd083XG5CVituTzNzOTNnTGNhMThxVE96SFkxb1d5QUdEeWtNU3NHVFVCU3Q5RCtBbjBLZktzRDJtZlNNNDJRPT1cbi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLVxuIgogICAgfSwKICAgICJzY2hlbWUiOiAiZWNkc2Etc2hhMi1uaXN0cDI1NiIsCiAgICAieC10dWYtb24tY2ktb25saW5lLXVyaSI6ICJnY3BrbXM6Ly9wcm9qZWN0cy9zaWdzdG9yZS1yb290LXNpZ25pbmcvbG9jYXRpb25zL2dsb2JhbC9rZXlSaW5ncy9yb290L2NyeXB0b0tleXMvdGltZXN0YW1wIgogICB9LAogICAiYTY4N2U1YmY0ZmFiODJiMGVlNThkNDZlMDVjOTUzNTE0NWEyYzlhZmI0NThmNDNkNDJiNDVjYTBmZGNlMmE3MCI6IHsKICAgICJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCiAgICAgInNoYTI1NiIsCiAgICAgInNoYTUxMiIKICAgIF0sCiAgICAia2V5dHlwZSI6ICJlY2RzYSIsCiAgICAia2V5dmFsIjogewogICAgICJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTBnaHJoOTJMdzFZcjNpZEdWNVdxQ3RNREI4Q3hcbitEOGhkQzR3MlpMTklwbFZSb1ZHTHNrWWEzZ2hlTXlPamlKOGtQaTE1YVEyLy83UCtvajdVdkpQR3c9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCiAgICB9LAogICAgInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKICAgICJ4LXR1Zi1vbi1jaS1rZXlvd25lciI6ICJAam9zaHVhZ2wiCiAgIH0sCiAgICJlNzFhNTRkNTQzODM1YmE4NmFkYWQ5NDYwMzc5Yzc2NDFmYjg3MjZkMTY0ZWE3NjY4MDFhMWM1MjJhYmE3ZWEyIjogewogICAgImtleWlkX2hhc2hfYWxnb3JpdGhtcyI6IFsKICAgICAic2hhMjU2IiwKICAgICAic2hhNTEyIgogICAgXSwKICAgICJrZXl0eXBlIjogImVjZHNhIiwKICAgICJrZXl2YWwiOiB7CiAgICAgInB1YmxpYyI6ICItLS0tLUJFR0lOIFBVQkxJQyBLRVktLS0tLVxuTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFRVhzejNTWlhGYjhqTVY0Mmo2cEpseWpialI4S1xuTjNCd29jZXhxNkxNSWI1cXNXS09RdkxOMTZOVWVmTGM0SHN3T291bVJzVlZhYWpTcFFTNmZvYmtSdz09XG4tLS0tLUVORCBQVUJMSUMgS0VZLS0tLS1cbiIKICAgIH0sCiAgICAic2NoZW1lIjogImVjZHNhLXNoYTItbmlzdHAyNTYiLAogICAgIngtdHVmLW9uLWNpLWtleW93bmVyIjogIkBtbm02NzgiCiAgIH0KICB9LAogICJyb2xlcyI6IHsKICAgInJvb3QiOiB7CiAgICAia2V5aWRzIjogWwogICAgICI2ZjI2MDA4OWQ1OTIzZGFmMjAxNjZjYTY1N2M1NDNhZjYxODM0NmFiOTcxODg0YTk5OTYyYjAxOTg4YmJlMGMzIiwKICAgICAiZTcxYTU0ZDU0MzgzNWJhODZhZGFkOTQ2MDM3OWM3NjQxZmI4NzI2ZDE2NGVhNzY2ODAxYTFjNTIyYWJhN2VhMiIsCiAgICAgIjIyZjRjYWVjNmQ4ZTZmOTU1NWFmNjZiM2Q0YzNjYjA2YTNiYjIzZmRjN2UzOWM5MTZjNjFmNDYyZTZmNTJiMDYiLAogICAgICI2MTY0MzgzODEyNWI0NDBiNDBkYjY5NDJmNWNiNWEzMWMwZGMwNDM2ODMxNmViMmFhYTU4Yjk1OTA0YTU4MjIyIiwKICAgICAiYTY4N2U1YmY0ZmFiODJiMGVlNThkNDZlMDVjOTUzNTE0NWEyYzlhZmI0NThmNDNkNDJiNDVjYTBmZGNlMmE3MCIKICAgIF0sCiAgICAidGhyZXNob2xkIjogMwogICB9LAogICAic25hcHNob3QiOiB7CiAgICAia2V5aWRzIjogWwogICAgICI3MjQ3ZjBkYmFkODViMTQ3ZTE4NjNiYWRlNzYxMjQzY2M3ODVkY2I3YWE0MTBlNzEwNWRkM2QyYjYxYTM2ZDJjIgogICAgXSwKICAgICJ0aHJlc2hvbGQiOiAxLAogICAgIngtdHVmLW9uLWNpLWV4cGlyeS1wZXJpb2QiOiAzNjUwLAogICAgIngtdHVmLW9uLWNpLXNpZ25pbmctcGVyaW9kIjogMzY1CiAgIH0sCiAgICJ0YXJnZXRzIjogewogICAgImtleWlkcyI6IFsKICAgICAiNmYyNjAwODlkNTkyM2RhZjIwMTY2Y2E2NTdjNTQzYWY2MTgzNDZhYjk3MTg4NGE5OTk2MmIwMTk4OGJiZTBjMyIsCiAgICAgImU3MWE1NGQ1NDM4MzViYTg2YWRhZDk0NjAzNzljNzY0MWZiODcyNmQxNjRlYTc2NjgwMWExYzUyMmFiYTdlYTIiLAogICAgICIyMmY0Y2FlYzZkOGU2Zjk1NTVhZjY2YjNkNGMzY2IwNmEzYmIyM2ZkYzdlMzljOTE2YzYxZjQ2MmU2ZjUyYjA2IiwKICAgICAiNjE2NDM4MzgxMjViNDQwYjQwZGI2OTQyZjVjYjVhMzFjMGRjMDQzNjgzMTZlYjJhYWE1OGI5NTkwNGE1ODIyMiIsCiAgICAgImE2ODdlNWJmNGZhYjgyYjBlZTU4ZDQ2ZTA1Yzk1MzUxNDVhMmM5YWZiNDU4ZjQzZDQyYjQ1Y2EwZmRjZTJhNzAiCiAgICBdLAogICAgInRocmVzaG9sZCI6IDMKICAgfSwKICAgInRpbWVzdGFtcCI6IHsKICAgICJrZXlpZHMiOiBbCiAgICAgIjcyNDdmMGRiYWQ4NWIxNDdlMTg2M2JhZGU3NjEyNDNjYzc4NWRjYjdhYTQxMGU3MTA1ZGQzZDJiNjFhMzZkMmMiCiAgICBdLAogICAgInRocmVzaG9sZCI6IDEsCiAgICAieC10dWYtb24tY2ktZXhwaXJ5LXBlcmlvZCI6IDcsCiAgICAieC10dWYtb24tY2ktc2lnbmluZy1wZXJpb2QiOiA0CiAgIH0KICB9LAogICJzcGVjX3ZlcnNpb24iOiAiMS4wIiwKICAidmVyc2lvbiI6IDEwLAogICJ4LXR1Zi1vbi1jaS1leHBpcnktcGVyaW9kIjogMTgyLAogICJ4LXR1Zi1vbi1jaS1zaWduaW5nLXBlcmlvZCI6IDMxCiB9Cn0=","targets":{"trusted_root.json":"ewogICJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLmRldi5zaWdzdG9yZS50cnVzdGVkcm9vdCtqc29uO3ZlcnNpb249MC4xIiwKICAidGxvZ3MiOiBbCiAgICB7CiAgICAgICJiYXNlVXJsIjogImh0dHBzOi8vcmVrb3Iuc2lnc3RvcmUuZGV2IiwKICAgICAgImhhc2hBbGdvcml0aG0iOiAiU0hBMl8yNTYiLAogICAgICAicHVibGljS2V5IjogewogICAgICAgICJyYXdCeXRlcyI6ICJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUUyRzJZKzJ0YWJkVFY1QmNHaUJJeDBhOWZBRndya0JibUxTR3RrczRMM3FYNnlZWTB6dWZCbmhDOFVyL2l5NTVHaFdQLzlBL2JZMkxoQzMwTTkrUll0dz09IiwKICAgICAgICAia2V5RGV0YWlscyI6ICJQS0lYX0VDRFNBX1AyNTZfU0hBXzI1NiIsCiAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgInN0YXJ0IjogIjIwMjEtMDEtMTJUMTE6NTM6MjcuMDAwWiIKICAgICAgICB9CiAgICAgIH0sCiAgICAgICJsb2dJZCI6IHsKICAgICAgICAia2V5SWQiOiAid05JOWF0UUdseitWV2ZPNkxSeWdINFFVZlkvOFc0UkZ3aVQ1aTVXUmdCMD0iCiAgICAgIH0KICAgIH0KICBdLAogICJjZXJ0aWZpY2F0ZUF1dGhvcml0aWVzIjogWwogICAgewogICAgICAic3ViamVjdCI6IHsKICAgICAgICAib3JnYW5pemF0aW9uIjogInNpZ3N0b3JlLmRldiIsCiAgICAgICAgImNvbW1vbk5hbWUiOiAic2lnc3RvcmUiCiAgICAgIH0sCiAgICAgICJ1cmkiOiAiaHR0cHM6Ly9mdWxjaW8uc2lnc3RvcmUuZGV2IiwKICAgICAgImNlcnRDaGFpbiI6IHsKICAgICAgICAiY2VydGlmaWNhdGVzIjogWwogICAgICAgICAgewogICAgICAgICAgICAicmF3Qnl0ZXMiOiAiTUlJQitEQ0NBWDZnQXdJQkFnSVROVmtEWm9DaW9mUERzeTdkZm02Z2VMYnVoekFLQmdncWhrak9QUVFEQXpBcU1SVXdFd1lEVlFRS0V3eHphV2R6ZEc5eVpTNWtaWFl4RVRBUEJnTlZCQU1UQ0hOcFozTjBiM0psTUI0WERUSXhNRE13TnpBek1qQXlPVm9YRFRNeE1ESXlNekF6TWpBeU9Wb3dLakVWTUJNR0ExVUVDaE1NYzJsbmMzUnZjbVV1WkdWMk1SRXdEd1lEVlFRREV3aHphV2R6ZEc5eVpUQjJNQkFHQnlxR1NNNDlBZ0VHQlN1QkJBQWlBMklBQkxTeUE3SWk1aytwTk84WkVXWTB5bGVtV0Rvd09rTmEza0wrR1pFNVo1R1dlaEw5L0E5YlJOQTNSYnJzWjVpMEpjYXN0YVJMN1NwNWZwL2pENWR4cWMvVWRUVm5sdlMxNmFuKzJZZnN3ZS9RdUxvbFJVQ3JjT0UyKzJpQTUrdHpkNk5tTUdRd0RnWURWUjBQQVFIL0JBUURBZ0VHTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFFd0hRWURWUjBPQkJZRUZNakZIUUJCbWlRcE1sRWs2dzJ1U3UxS0J0UHNNQjhHQTFVZEl3UVlNQmFBRk1qRkhRQkJtaVFwTWxFazZ3MnVTdTFLQnRQc01Bb0dDQ3FHU000OUJBTURBMmdBTUdVQ01IOGxpV0pmTXVpNnZYWEJoakRnWTRNd3NsbU4vVEp4VmUvODNXckZvbXdtTmYwNTZ5MVg0OEY5YzRtM2Ezb3pYQUl4QUtqUmF5NS9hai9qc0tLR0lrbVFhdGpJOHV1cEhyLytDeEZ2YUpXbXBZcU5rTERHUlUrOW9yemg1aEkyUnJjdWFRPT0iCiAgICAgICAgICB9CiAgICAgICAgXQogICAgICB9LAogICAgICAidmFsaWRGb3IiOiB7CiAgICAgICAgInN0YXJ0IjogIjIwMjEtMDMtMDdUMDM6MjA6MjkuMDAwWiIsCiAgICAgICAgImVuZCI6ICIyMDIyLTEyLTMxVDIzOjU5OjU5Ljk5OVoiCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJzdWJqZWN0IjogewogICAgICAgICJvcmdhbml6YXRpb24iOiAic2lnc3RvcmUuZGV2IiwKICAgICAgICAiY29tbW9uTmFtZSI6ICJzaWdzdG9yZSIKICAgICAgfSwKICAgICAgInVyaSI6ICJodHRwczovL2Z1bGNpby5zaWdzdG9yZS5kZXYiLAogICAgICAiY2VydENoYWluIjogewogICAgICAgICJjZXJ0aWZpY2F0ZXMiOiBbCiAgICAgICAgICB7CiAgICAgICAgICAgICJyYXdCeXRlcyI6ICJNSUlDR2pDQ0FhR2dBd0lCQWdJVUFMblZpVmZuVTBickphc21Sa0hybi9VbmZhUXdDZ1lJS29aSXpqMEVBd013S2pFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNUkV3RHdZRFZRUURFd2h6YVdkemRHOXlaVEFlRncweU1qQTBNVE15TURBMk1UVmFGdzB6TVRFd01EVXhNelUyTlRoYU1EY3hGVEFUQmdOVkJBb1RESE5wWjNOMGIzSmxMbVJsZGpFZU1Cd0dBMVVFQXhNVmMybG5jM1J2Y21VdGFXNTBaWEp0WldScFlYUmxNSFl3RUFZSEtvWkl6ajBDQVFZRks0RUVBQ0lEWWdBRThSVlMveXNIK05PdnVEWnlQSVp0aWxnVUY5TmxhcllwQWQ5SFAxdkJCSDFVNUNWNzdMU1M3czBaaUg0bkU3SHY3cHRTNkx2dlIvU1RrNzk4TFZnTXpMbEo0SGVJZkYzdEhTYWV4TGNZcFNBU3Ixa1MwTi9SZ0JKei85aldDaVhubzNzd2VUQU9CZ05WSFE4QkFmOEVCQU1DQVFZd0V3WURWUjBsQkF3d0NnWUlLd1lCQlFVSEF3TXdFZ1lEVlIwVEFRSC9CQWd3QmdFQi93SUJBREFkQmdOVkhRNEVGZ1FVMzlQcHoxWWtFWmI1cU5qcEtGV2l4aTRZWkQ4d0h3WURWUjBqQkJnd0ZvQVVXTUFlWDVGRnBXYXBlc3lRb1pNaTBDckZ4Zm93Q2dZSUtvWkl6ajBFQXdNRFp3QXdaQUl3UENzUUs0RFlpWllEUElhRGk1SEZLbmZ4WHg2QVNTVm1FUmZzeW5ZQmlYMlg2U0pSblpVODQvOURaZG5GdnZ4bUFqQk90NlFwQmxjNEovMER4dmtUQ3FwY2x2emlMNkJDQ1BuamRsSUIzUHUzQnhzUG15Z1VZN0lpMnpiZENkbGlpb3c9IgogICAgICAgICAgfSwKICAgICAgICAgIHsKICAgICAgICAgICAgInJhd0J5dGVzIjogIk1JSUI5ekNDQVh5Z0F3SUJBZ0lVQUxaTkFQRmR4SFB3amVEbG9Ed3lZQ2hBTy80d0NnWUlLb1pJemowRUF3TXdLakVWTUJNR0ExVUVDaE1NYzJsbmMzUnZjbVV1WkdWMk1SRXdEd1lEVlFRREV3aHphV2R6ZEc5eVpUQWVGdzB5TVRFd01EY3hNelUyTlRsYUZ3MHpNVEV3TURVeE16VTJOVGhhTUNveEZUQVRCZ05WQkFvVERITnBaM04wYjNKbExtUmxkakVSTUE4R0ExVUVBeE1JYzJsbmMzUnZjbVV3ZGpBUUJnY3Foa2pPUFFJQkJnVXJnUVFBSWdOaUFBVDdYZUZUNHJiM1BRR3dTNElhanRMazMvT2xucGdhbmdhQmNsWXBzWUJyNWkrNHluQjA3Y2ViM0xQME9JT1pkeGV4WDY5YzVpVnV5SlJRK0h6MDV5aStVRjN1QldBbEhwaVM1c2gwK0gyR0hFN1NYcmsxRUM1bTFUcjE5TDlnZzkyall6QmhNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUll3QjVma1VXbFpxbDZ6SkNoa3lMUUtzWEYrakFmQmdOVkhTTUVHREFXZ0JSWXdCNWZrVVdsWnFsNnpKQ2hreUxRS3NYRitqQUtCZ2dxaGtqT1BRUURBd05wQURCbUFqRUFqMW5IZVhacCsxM05XQk5hK0VEc0RQOEcxV1dnMXRDTVdQL1dIUHFwYVZvMGpoc3dlTkZaZ1NzMGVFN3dZSTRxQWpFQTJXQjlvdDk4c0lrb0YzdlpZZGQzL1Z0V0I1YjlUTk1lYTdJeC9zdEo1VGZjTExlQUJMRTRCTkpPc1E0dm5CSEoiCiAgICAgICAgICB9CiAgICAgICAgXQogICAgICB9LAogICAgICAidmFsaWRGb3IiOiB7CiAgICAgICAgInN0YXJ0IjogIjIwMjItMDQtMTNUMjA6MDY6MTUuMDAwWiIKICAgICAgfQogICAgfQogIF0sCiAgImN0bG9ncyI6IFsKICAgIHsKICAgICAgImJhc2VVcmwiOiAiaHR0cHM6Ly9jdGZlLnNpZ3N0b3JlLmRldi90ZXN0IiwKICAgICAgImhhc2hBbGdvcml0aG0iOiAiU0hBMl8yNTYiLAogICAgICAicHVibGljS2V5IjogewogICAgICAgICJyYXdCeXRlcyI6ICJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUViZndSK1JKdWRYc2NnUkJScEtYMVhGRHkzUHl1ZER4ei9TZm5SaTFmVDhla3BmQmQyTzF1b3o3anIzWjhuS3p4QTY5RVVRK2VGQ0ZJM3pldWJQV1U3dz09IiwKICAgICAgICAia2V5RGV0YWlscyI6ICJQS0lYX0VDRFNBX1AyNTZfU0hBXzI1NiIsCiAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgInN0YXJ0IjogIjIwMjEtMDMtMTRUMDA6MDA6MDAuMDAwWiIsCiAgICAgICAgICAiZW5kIjogIjIwMjItMTAtMzFUMjM6NTk6NTkuOTk5WiIKICAgICAgICB9CiAgICAgIH0sCiAgICAgICJsb2dJZCI6IHsKICAgICAgICAia2V5SWQiOiAiQ0dDUzhDaFMvMmhGMGRGcko0U2NSV2NZckJZOXd6alNiZWE4SWdZMmIzST0iCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJiYXNlVXJsIjogImh0dHBzOi8vY3RmZS5zaWdzdG9yZS5kZXYvMjAyMiIsCiAgICAgICJoYXNoQWxnb3JpdGhtIjogIlNIQTJfMjU2IiwKICAgICAgInB1YmxpY0tleSI6IHsKICAgICAgICAicmF3Qnl0ZXMiOiAiTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFaVBTbEZpMENtRlRmRWpDVXFGOUh1Q0VjWVhOS0FhWWFsSUptQlo4eXllelBqVHFoeHJLQnBNbmFvY1Z0TEpCSTFlTTN1WG5RelFHQUpkSjRnczlGeXc9PSIsCiAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICJ2YWxpZEZvciI6IHsKICAgICAgICAgICJzdGFydCI6ICIyMDIyLTEwLTIwVDAwOjAwOjAwLjAwMFoiCiAgICAgICAgfQogICAgICB9LAogICAgICAibG9nSWQiOiB7CiAgICAgICAgImtleUlkIjogIjNUMHdhc2JIRVRKakdSNGNtV2MzQXFKS1hyamVQSzMvaDRweWdDOHA3bzQ9IgogICAgICB9CiAgICB9CiAgXSwKICAidGltZXN0YW1wQXV0aG9yaXRpZXMiOiBbCiAgICB7CiAgICAgICJzdWJqZWN0IjogewogICAgICAgICJvcmdhbml6YXRpb24iOiAiR2l0SHViLCBJbmMuIiwKICAgICAgICAiY29tbW9uTmFtZSI6ICJJbnRlcm5hbCBTZXJ2aWNlcyBSb290IgogICAgICB9LAogICAgICAiY2VydENoYWluIjogewogICAgICAgICJjZXJ0aWZpY2F0ZXMiOiBbCiAgICAgICAgICB7CiAgICAgICAgICAgICJyYXdCeXRlcyI6ICJNSUlCM0RDQ0FXS2dBd0lCQWdJVWNoa05zSDM2WGEwNGIxTHFJYytxcjlEVmVjTXdDZ1lJS29aSXpqMEVBd013TWpFVk1CTUdBMVVFQ2hNTVIybDBTSFZpTENCSmJtTXVNUmt3RndZRFZRUURFeEJVVTBFZ2FXNTBaWEp0WldScFlYUmxNQjRYRFRJek1EUXhOREF3TURBd01Gb1hEVEkwTURReE16QXdNREF3TUZvd01qRVZNQk1HQTFVRUNoTU1SMmwwU0hWaUxDQkpibU11TVJrd0Z3WURWUVFERXhCVVUwRWdWR2x0WlhOMFlXMXdhVzVuTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFVUQ1Wk5iU3FZTWQ2cjhxcE9PRVg5aWJHblpUOUdzdVhPaHIvZjhVOUZKdWdCR0V4S1lwNDBPVUxTMGVyalpXN3hWOXhWNTJObkpmNU9lRHE0ZTVaS3FOV01GUXdEZ1lEVlIwUEFRSC9CQVFEQWdlQU1CTUdBMVVkSlFRTU1Bb0dDQ3NHQVFVRkJ3TUlNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqQkJnd0ZvQVVhVzFSdWRPZ1Z0MGxlcVkwV0tZYnVQcjQ3d0F3Q2dZSUtvWkl6ajBFQXdNRGFBQXdaUUl3YlVIOUh2RDRlakNaSk9XUW5xQWxrcVVSbGx2dTlNOCtWcUxiaVJLK3pTZlpDWndzaWxqUm44TVFRUlNrWEVFNUFqRUFnK1Z4cXRvamZWZnU4RGh6emhDeDlHS0VUYkpIYjE5aVY3Mm1NS1ViREFGbXpaNmJROGI1NFpiOHRpZHk1YVdlIgogICAgICAgICAgfSwKICAgICAgICAgIHsKICAgICAgICAgICAgInJhd0J5dGVzIjogIk1JSUNFRENDQVpXZ0F3SUJBZ0lVWDhaTzVRWFA3dk40ZE1RNWU5c1UzbnViOE9nd0NnWUlLb1pJemowRUF3TXdPREVWTUJNR0ExVUVDaE1NUjJsMFNIVmlMQ0JKYm1NdU1SOHdIUVlEVlFRREV4WkpiblJsY201aGJDQlRaWEoyYVdObGN5QlNiMjkwTUI0WERUSXpNRFF4TkRBd01EQXdNRm9YRFRJNE1EUXhNakF3TURBd01Gb3dNakVWTUJNR0ExVUVDaE1NUjJsMFNIVmlMQ0JKYm1NdU1Sa3dGd1lEVlFRREV4QlVVMEVnYVc1MFpYSnRaV1JwWVhSbE1IWXdFQVlIS29aSXpqMENBUVlGSzRFRUFDSURZZ0FFdk1MWS9kVFZidklKWUFOQXVzekV3Sm5RRTFsbGZ0eW55TUtJTWhoNDhIbXFiVnI1eWd5YnpzTFJMVktiQldPZFoyMWFlSnorZ1ppeXRaZXRxY3lGOVdsRVI1TkVNZjZKVjdaTm9qUXB4SHE0UkhHb0dTY2VRdi9xdlRpWnhFREtvMll3WkRBT0JnTlZIUThCQWY4RUJBTUNBUVl3RWdZRFZSMFRBUUgvQkFnd0JnRUIvd0lCQURBZEJnTlZIUTRFRmdRVWFXMVJ1ZE9nVnQwbGVxWTBXS1lidVByNDd3QXdId1lEVlIwakJCZ3dGb0FVOU5ZWWxvYm5BRzRjMC9xanh5SC9scS93eitRd0NnWUlLb1pJemowRUF3TURhUUF3WmdJeEFLMUIxODV5Z0NySVlGbElzM0dqc3dqbndTTUc2TFk4d29MVmRha0tEWnhWYThmOGNxTXMxRGhjeEowKzA5dzk1UUl4QU8rdEJ6Wms3dmpVSjlpSmdENFI2WldUeFFXS3FObTc0ak85OW8rbzlzdjRGSS9TWlRaVEZ5TW4wSUpFSGRObXlBPT0iCiAgICAgICAgICB9LAogICAgICAgICAgewogICAgICAgICAgICAicmF3Qnl0ZXMiOiAiTUlJQjlEQ0NBWHFnQXdJQkFnSVVhL0pBa2RVaks0SlV3c3F0YWlSSkdXaHFMU293Q2dZSUtvWkl6ajBFQXdNd09ERVZNQk1HQTFVRUNoTU1SMmwwU0hWaUxDQkpibU11TVI4d0hRWURWUVFERXhaSmJuUmxjbTVoYkNCVFpYSjJhV05sY3lCU2IyOTBNQjRYRFRJek1EUXhOREF3TURBd01Gb1hEVE16TURReE1UQXdNREF3TUZvd09ERVZNQk1HQTFVRUNoTU1SMmwwU0hWaUxDQkpibU11TVI4d0hRWURWUVFERXhaSmJuUmxjbTVoYkNCVFpYSjJhV05sY3lCU2IyOTBNSFl3RUFZSEtvWkl6ajBDQVFZRks0RUVBQ0lEWWdBRWY5akZBWHh6NGt4NjhBSFJNT2tGQmhmbERjTVR2emFYejR4L0ZDY1hqSi8xcUVLb24vcVBJR25hVVJza0R0eU5iTkRPcGVKVERERnF0NDhpTVBybnpweDZJWndxZW1mVUpONHhCRVpmemErcFl0L2l5b2QrOXRacjIwUlJXU3YvbzBVd1F6QU9CZ05WSFE4QkFmOEVCQU1DQVFZd0VnWURWUjBUQVFIL0JBZ3dCZ0VCL3dJQkFqQWRCZ05WSFE0RUZnUVU5TllZbG9ibkFHNGMwL3FqeHlIL2xxL3d6K1F3Q2dZSUtvWkl6ajBFQXdNRGFBQXdaUUl4QUxaTFo4QmdSWHpLeExNTU45VklsTytlNGhyQm5OQmdGN3R6N0hucm93djJOZXRaRXJJQUNLRnltQmx2V0R2dE1BSXdaTytraTZzc1ExYnNabzk4TzhtRUFmMk5aN2lpQ2dERFUwVndqZWNvNnp5ZWgwekJUczkvN2dWNkFITlE1M3hEIgogICAgICAgICAgfQogICAgICAgIF0KICAgICAgfSwKICAgICAgInZhbGlkRm9yIjogewogICAgICAgICJzdGFydCI6ICIyMDIzLTA0LTE0VDAwOjAwOjAwLjAwMFoiCiAgICAgIH0KICAgIH0KICBdCn0K","registry.npmjs.org%2Fkeys.json":"ewogICAgImtleXMiOiBbCiAgICAgICAgewogICAgICAgICAgICAia2V5SWQiOiAiU0hBMjU2OmpsM2J3c3d1ODBQampva0NnaDBvMnc1YzJVNExoUUFFNTdnajljejFrekEiLAogICAgICAgICAgICAia2V5VXNhZ2UiOiAibnBtOnNpZ25hdHVyZXMiLAogICAgICAgICAgICAicHVibGljS2V5IjogewogICAgICAgICAgICAgICAgInJhd0J5dGVzIjogIk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTFPbGIzek1BRkZ4WEtIaUlrUU81Y0ozWWhsNWk2VVBwK0lodXRlQkpidUhjQTVVb2dLbzBFV3RsV3dXNktTYUtvVE5FWUw3SmxDUWlWbmtoQmt0VWdnPT0iLAogICAgICAgICAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgICAgICAgICAgICJzdGFydCI6ICIxOTk5LTAxLTAxVDAwOjAwOjAwLjAwMFoiCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgICAgImtleUlkIjogIlNIQTI1NjpqbDNid3N3dTgwUGpqb2tDZ2gwbzJ3NWMyVTRMaFFBRTU3Z2o5Y3oxa3pBIiwKICAgICAgICAgICAgImtleVVzYWdlIjogIm5wbTphdHRlc3RhdGlvbnMiLAogICAgICAgICAgICAicHVibGljS2V5IjogewogICAgICAgICAgICAgICAgInJhd0J5dGVzIjogIk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTFPbGIzek1BRkZ4WEtIaUlrUU81Y0ozWWhsNWk2VVBwK0lodXRlQkpidUhjQTVVb2dLbzBFV3RsV3dXNktTYUtvVE5FWUw3SmxDUWlWbmtoQmt0VWdnPT0iLAogICAgICAgICAgICAgICAgImtleURldGFpbHMiOiAiUEtJWF9FQ0RTQV9QMjU2X1NIQV8yNTYiLAogICAgICAgICAgICAgICAgInZhbGlkRm9yIjogewogICAgICAgICAgICAgICAgICAgICJzdGFydCI6ICIyMDIyLTEyLTAxVDAwOjAwOjAwLjAwMFoiCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICBdCn0K"}}} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/bundle/dsse.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/bundle/dsse.js new file mode 100644 index 0000000000000..1033fc422aba0 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/bundle/dsse.js @@ -0,0 +1,43 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DSSESignatureContent = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const core_1 = require("@sigstore/core"); +class DSSESignatureContent { + constructor(env) { + this.env = env; + } + compareDigest(digest) { + return core_1.crypto.bufferEqual(digest, core_1.crypto.digest('sha256', this.env.payload)); + } + compareSignature(signature) { + return core_1.crypto.bufferEqual(signature, this.signature); + } + verifySignature(key) { + return core_1.crypto.verify(this.preAuthEncoding, key, this.signature); + } + get signature() { + return this.env.signatures.length > 0 + ? this.env.signatures[0].sig + : Buffer.from(''); + } + // DSSE Pre-Authentication Encoding + get preAuthEncoding() { + return core_1.dsse.preAuthEncoding(this.env.payloadType, this.env.payload); + } +} +exports.DSSESignatureContent = DSSESignatureContent; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/bundle/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/bundle/index.js new file mode 100644 index 0000000000000..4287d8032b75f --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/bundle/index.js @@ -0,0 +1,57 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.toSignedEntity = toSignedEntity; +exports.signatureContent = signatureContent; +const core_1 = require("@sigstore/core"); +const dsse_1 = require("./dsse"); +const message_1 = require("./message"); +function toSignedEntity(bundle, artifact) { + const { tlogEntries, timestampVerificationData } = bundle.verificationMaterial; + const timestamps = []; + for (const entry of tlogEntries) { + timestamps.push({ + $case: 'transparency-log', + tlogEntry: entry, + }); + } + for (const ts of timestampVerificationData?.rfc3161Timestamps ?? []) { + timestamps.push({ + $case: 'timestamp-authority', + timestamp: core_1.RFC3161Timestamp.parse(ts.signedTimestamp), + }); + } + return { + signature: signatureContent(bundle, artifact), + key: key(bundle), + tlogEntries, + timestamps, + }; +} +function signatureContent(bundle, artifact) { + switch (bundle.content.$case) { + case 'dsseEnvelope': + return new dsse_1.DSSESignatureContent(bundle.content.dsseEnvelope); + case 'messageSignature': + return new message_1.MessageSignatureContent(bundle.content.messageSignature, artifact); + } +} +function key(bundle) { + switch (bundle.verificationMaterial.content.$case) { + case 'publicKey': + return { + $case: 'public-key', + hint: bundle.verificationMaterial.content.publicKey.hint, + }; + case 'x509CertificateChain': + return { + $case: 'certificate', + certificate: core_1.X509Certificate.parse(bundle.verificationMaterial.content.x509CertificateChain + .certificates[0].rawBytes), + }; + case 'certificate': + return { + $case: 'certificate', + certificate: core_1.X509Certificate.parse(bundle.verificationMaterial.content.certificate.rawBytes), + }; + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/bundle/message.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/bundle/message.js new file mode 100644 index 0000000000000..836148c68a8b6 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/bundle/message.js @@ -0,0 +1,36 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MessageSignatureContent = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const core_1 = require("@sigstore/core"); +class MessageSignatureContent { + constructor(messageSignature, artifact) { + this.signature = messageSignature.signature; + this.messageDigest = messageSignature.messageDigest.digest; + this.artifact = artifact; + } + compareSignature(signature) { + return core_1.crypto.bufferEqual(signature, this.signature); + } + compareDigest(digest) { + return core_1.crypto.bufferEqual(digest, this.messageDigest); + } + verifySignature(key) { + return core_1.crypto.verify(this.artifact, key, this.signature); + } +} +exports.MessageSignatureContent = MessageSignatureContent; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/error.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/error.js new file mode 100644 index 0000000000000..6cb1cd4121343 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/error.js @@ -0,0 +1,32 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.PolicyError = exports.VerificationError = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +class BaseError extends Error { + constructor({ code, message, cause, }) { + super(message); + this.code = code; + this.cause = cause; + this.name = this.constructor.name; + } +} +class VerificationError extends BaseError { +} +exports.VerificationError = VerificationError; +class PolicyError extends BaseError { +} +exports.PolicyError = PolicyError; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/index.js new file mode 100644 index 0000000000000..3222876fcd68b --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/index.js @@ -0,0 +1,28 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Verifier = exports.toTrustMaterial = exports.VerificationError = exports.PolicyError = exports.toSignedEntity = void 0; +/* istanbul ignore file */ +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +var bundle_1 = require("./bundle"); +Object.defineProperty(exports, "toSignedEntity", { enumerable: true, get: function () { return bundle_1.toSignedEntity; } }); +var error_1 = require("./error"); +Object.defineProperty(exports, "PolicyError", { enumerable: true, get: function () { return error_1.PolicyError; } }); +Object.defineProperty(exports, "VerificationError", { enumerable: true, get: function () { return error_1.VerificationError; } }); +var trust_1 = require("./trust"); +Object.defineProperty(exports, "toTrustMaterial", { enumerable: true, get: function () { return trust_1.toTrustMaterial; } }); +var verifier_1 = require("./verifier"); +Object.defineProperty(exports, "Verifier", { enumerable: true, get: function () { return verifier_1.Verifier; } }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/key/certificate.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/key/certificate.js new file mode 100644 index 0000000000000..a916de0e51e71 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/key/certificate.js @@ -0,0 +1,205 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CertificateChainVerifier = void 0; +exports.verifyCertificateChain = verifyCertificateChain; +const error_1 = require("../error"); +const trust_1 = require("../trust"); +function verifyCertificateChain(leaf, certificateAuthorities) { + // Filter list of trusted CAs to those which are valid for the given + // leaf certificate. + const cas = (0, trust_1.filterCertAuthorities)(certificateAuthorities, { + start: leaf.notBefore, + end: leaf.notAfter, + }); + /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ + let error; + for (const ca of cas) { + try { + const verifier = new CertificateChainVerifier({ + trustedCerts: ca.certChain, + untrustedCert: leaf, + }); + return verifier.verify(); + } + catch (err) { + error = err; + } + } + // If we failed to verify the certificate chain for all of the trusted + // CAs, throw the last error we encountered. + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'Failed to verify certificate chain', + cause: error, + }); +} +class CertificateChainVerifier { + constructor(opts) { + this.untrustedCert = opts.untrustedCert; + this.trustedCerts = opts.trustedCerts; + this.localCerts = dedupeCertificates([ + ...opts.trustedCerts, + opts.untrustedCert, + ]); + } + verify() { + // Construct certificate path from leaf to root + const certificatePath = this.sort(); + // Perform validation checks on each certificate in the path + this.checkPath(certificatePath); + // Return verified certificate path + return certificatePath; + } + sort() { + const leafCert = this.untrustedCert; + // Construct all possible paths from the leaf + let paths = this.buildPaths(leafCert); + // Filter for paths which contain a trusted certificate + paths = paths.filter((path) => path.some((cert) => this.trustedCerts.includes(cert))); + if (paths.length === 0) { + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'no trusted certificate path found', + }); + } + // Find the shortest of possible paths + /* istanbul ignore next */ + const path = paths.reduce((prev, curr) => prev.length < curr.length ? prev : curr); + // Construct chain from shortest path + // Removes the last certificate in the path, which will be a second copy + // of the root certificate given that the root is self-signed. + return [leafCert, ...path].slice(0, -1); + } + // Recursively build all possible paths from the leaf to the root + buildPaths(certificate) { + const paths = []; + const issuers = this.findIssuer(certificate); + if (issuers.length === 0) { + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'no valid certificate path found', + }); + } + for (let i = 0; i < issuers.length; i++) { + const issuer = issuers[i]; + // Base case - issuer is self + if (issuer.equals(certificate)) { + paths.push([certificate]); + continue; + } + // Recursively build path for the issuer + const subPaths = this.buildPaths(issuer); + // Construct paths by appending the issuer to each subpath + for (let j = 0; j < subPaths.length; j++) { + paths.push([issuer, ...subPaths[j]]); + } + } + return paths; + } + // Return all possible issuers for the given certificate + findIssuer(certificate) { + let issuers = []; + let keyIdentifier; + // Exit early if the certificate is self-signed + if (certificate.subject.equals(certificate.issuer)) { + if (certificate.verify()) { + return [certificate]; + } + } + // If the certificate has an authority key identifier, use that + // to find the issuer + if (certificate.extAuthorityKeyID) { + keyIdentifier = certificate.extAuthorityKeyID.keyIdentifier; + // TODO: Add support for authorityCertIssuer/authorityCertSerialNumber + // though Fulcio doesn't appear to use these + } + // Find possible issuers by comparing the authorityKeyID/subjectKeyID + // or issuer/subject. Potential issuers are added to the result array. + this.localCerts.forEach((possibleIssuer) => { + if (keyIdentifier) { + if (possibleIssuer.extSubjectKeyID) { + if (possibleIssuer.extSubjectKeyID.keyIdentifier.equals(keyIdentifier)) { + issuers.push(possibleIssuer); + } + return; + } + } + // Fallback to comparing certificate issuer and subject if + // subjectKey/authorityKey extensions are not present + if (possibleIssuer.subject.equals(certificate.issuer)) { + issuers.push(possibleIssuer); + } + }); + // Remove any issuers which fail to verify the certificate + issuers = issuers.filter((issuer) => { + try { + return certificate.verify(issuer); + } + catch (ex) { + /* istanbul ignore next - should never error */ + return false; + } + }); + return issuers; + } + checkPath(path) { + /* istanbul ignore if */ + if (path.length < 1) { + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'certificate chain must contain at least one certificate', + }); + } + // Ensure that all certificates beyond the leaf are CAs + const validCAs = path.slice(1).every((cert) => cert.isCA); + if (!validCAs) { + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'intermediate certificate is not a CA', + }); + } + // Certificate's issuer must match the subject of the next certificate + // in the chain + for (let i = path.length - 2; i >= 0; i--) { + /* istanbul ignore if */ + if (!path[i].issuer.equals(path[i + 1].subject)) { + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'incorrect certificate name chaining', + }); + } + } + // Check pathlength constraints + for (let i = 0; i < path.length; i++) { + const cert = path[i]; + // If the certificate is a CA, check the path length + if (cert.extBasicConstraints?.isCA) { + const pathLength = cert.extBasicConstraints.pathLenConstraint; + // The path length, if set, indicates how many intermediate + // certificates (NOT including the leaf) are allowed to follow. The + // pathLength constraint of any intermediate CA certificate MUST be + // greater than or equal to it's own depth in the chain (with an + // adjustment for the leaf certificate) + if (pathLength !== undefined && pathLength < i - 1) { + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'path length constraint exceeded', + }); + } + } + } + } +} +exports.CertificateChainVerifier = CertificateChainVerifier; +// Remove duplicate certificates from the array +function dedupeCertificates(certs) { + for (let i = 0; i < certs.length; i++) { + for (let j = i + 1; j < certs.length; j++) { + if (certs[i].equals(certs[j])) { + certs.splice(j, 1); + j--; + } + } + } + return certs; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/key/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/key/index.js new file mode 100644 index 0000000000000..cc894aab95a5d --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/key/index.js @@ -0,0 +1,72 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyPublicKey = verifyPublicKey; +exports.verifyCertificate = verifyCertificate; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const core_1 = require("@sigstore/core"); +const error_1 = require("../error"); +const certificate_1 = require("./certificate"); +const sct_1 = require("./sct"); +const OID_FULCIO_ISSUER_V1 = '1.3.6.1.4.1.57264.1.1'; +const OID_FULCIO_ISSUER_V2 = '1.3.6.1.4.1.57264.1.8'; +function verifyPublicKey(hint, timestamps, trustMaterial) { + const key = trustMaterial.publicKey(hint); + timestamps.forEach((timestamp) => { + if (!key.validFor(timestamp)) { + throw new error_1.VerificationError({ + code: 'PUBLIC_KEY_ERROR', + message: `Public key is not valid for timestamp: ${timestamp.toISOString()}`, + }); + } + }); + return { key: key.publicKey }; +} +function verifyCertificate(leaf, timestamps, trustMaterial) { + // Check that leaf certificate chains to a trusted CA + const path = (0, certificate_1.verifyCertificateChain)(leaf, trustMaterial.certificateAuthorities); + // Check that ALL certificates are valid for ALL of the timestamps + const validForDate = timestamps.every((timestamp) => path.every((cert) => cert.validForDate(timestamp))); + if (!validForDate) { + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'certificate is not valid or expired at the specified date', + }); + } + return { + scts: (0, sct_1.verifySCTs)(path[0], path[1], trustMaterial.ctlogs), + signer: getSigner(path[0]), + }; +} +function getSigner(cert) { + let issuer; + const issuerExtension = cert.extension(OID_FULCIO_ISSUER_V2); + /* istanbul ignore next */ + if (issuerExtension) { + issuer = issuerExtension.valueObj.subs?.[0]?.value.toString('ascii'); + } + else { + issuer = cert.extension(OID_FULCIO_ISSUER_V1)?.value.toString('ascii'); + } + const identity = { + extensions: { issuer }, + subjectAlternativeName: cert.subjectAltName, + }; + return { + key: core_1.crypto.createPublicKey(cert.publicKey), + identity, + }; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/key/sct.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/key/sct.js new file mode 100644 index 0000000000000..8eca48738096e --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/key/sct.js @@ -0,0 +1,78 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifySCTs = verifySCTs; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const core_1 = require("@sigstore/core"); +const error_1 = require("../error"); +const trust_1 = require("../trust"); +function verifySCTs(cert, issuer, ctlogs) { + let extSCT; + // Verifying the SCT requires that we remove the SCT extension and + // re-encode the TBS structure to DER -- this value is part of the data + // over which the signature is calculated. Since this is a destructive action + // we create a copy of the certificate so we can remove the SCT extension + // without affecting the original certificate. + const clone = cert.clone(); + // Intentionally not using the findExtension method here because we want to + // remove the the SCT extension from the certificate before calculating the + // PreCert structure + for (let i = 0; i < clone.extensions.length; i++) { + const ext = clone.extensions[i]; + if (ext.subs[0].toOID() === core_1.EXTENSION_OID_SCT) { + extSCT = new core_1.X509SCTExtension(ext); + // Remove the extension from the certificate + clone.extensions.splice(i, 1); + break; + } + } + // No SCT extension found to verify + if (!extSCT) { + return []; + } + // Found an SCT extension but it has no SCTs + /* istanbul ignore if -- too difficult to fabricate test case for this */ + if (extSCT.signedCertificateTimestamps.length === 0) { + return []; + } + // Construct the PreCert structure + // https://www.rfc-editor.org/rfc/rfc6962#section-3.2 + const preCert = new core_1.ByteStream(); + // Calculate hash of the issuer's public key + const issuerId = core_1.crypto.digest('sha256', issuer.publicKey); + preCert.appendView(issuerId); + // Re-encodes the certificate to DER after removing the SCT extension + const tbs = clone.tbsCertificate.toDER(); + preCert.appendUint24(tbs.length); + preCert.appendView(tbs); + // Calculate and return the verification results for each SCT + return extSCT.signedCertificateTimestamps.map((sct) => { + // Find the ctlog instance that corresponds to the SCT's logID + const validCTLogs = (0, trust_1.filterTLogAuthorities)(ctlogs, { + logID: sct.logID, + targetDate: sct.datetime, + }); + // See if the SCT is valid for any of the CT logs + const verified = validCTLogs.some((log) => sct.verify(preCert.buffer, log.publicKey)); + if (!verified) { + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'SCT verification failed', + }); + } + return sct.logID; + }); +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/policy.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/policy.js new file mode 100644 index 0000000000000..f5960cf047b84 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/policy.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifySubjectAlternativeName = verifySubjectAlternativeName; +exports.verifyExtensions = verifyExtensions; +const error_1 = require("./error"); +function verifySubjectAlternativeName(policyIdentity, signerIdentity) { + if (signerIdentity === undefined || !signerIdentity.match(policyIdentity)) { + throw new error_1.PolicyError({ + code: 'UNTRUSTED_SIGNER_ERROR', + message: `certificate identity error - expected ${policyIdentity}, got ${signerIdentity}`, + }); + } +} +function verifyExtensions(policyExtensions, signerExtensions = {}) { + let key; + for (key in policyExtensions) { + if (signerExtensions[key] !== policyExtensions[key]) { + throw new error_1.PolicyError({ + code: 'UNTRUSTED_SIGNER_ERROR', + message: `invalid certificate extension - expected ${key}=${policyExtensions[key]}, got ${key}=${signerExtensions[key]}`, + }); + } + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/shared.types.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/shared.types.js new file mode 100644 index 0000000000000..c8ad2e549bdc6 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/shared.types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/timestamp/checkpoint.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/timestamp/checkpoint.js new file mode 100644 index 0000000000000..46619b675f886 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/timestamp/checkpoint.js @@ -0,0 +1,157 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyCheckpoint = verifyCheckpoint; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const core_1 = require("@sigstore/core"); +const error_1 = require("../error"); +const trust_1 = require("../trust"); +// Separator between the note and the signatures in a checkpoint +const CHECKPOINT_SEPARATOR = '\n\n'; +// Checkpoint signatures are of the following form: +// "– \n" +// where: +// - the prefix is an emdash (U+2014). +// - gives a human-readable representation of the signing ID. +// - is the first 4 bytes of the SHA256 hash of the +// associated public key followed by the signature bytes. +const SIGNATURE_REGEX = /\u2014 (\S+) (\S+)\n/g; +// Verifies the checkpoint value in the given tlog entry. There are two steps +// to the verification: +// 1. Verify that all signatures in the checkpoint can be verified against a +// trusted public key +// 2. Verify that the root hash in the checkpoint matches the root hash in the +// inclusion proof +// See: https://github.com/transparency-dev/formats/blob/main/log/README.md +function verifyCheckpoint(entry, tlogs) { + // Filter tlog instances to just those which were valid at the time of the + // entry + const validTLogs = (0, trust_1.filterTLogAuthorities)(tlogs, { + targetDate: new Date(Number(entry.integratedTime) * 1000), + }); + const inclusionProof = entry.inclusionProof; + const signedNote = SignedNote.fromString(inclusionProof.checkpoint.envelope); + const checkpoint = LogCheckpoint.fromString(signedNote.note); + // Verify that the signatures in the checkpoint are all valid + if (!verifySignedNote(signedNote, validTLogs)) { + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROOF_ERROR', + message: 'invalid checkpoint signature', + }); + } + // Verify that the root hash from the checkpoint matches the root hash in the + // inclusion proof + if (!core_1.crypto.bufferEqual(checkpoint.logHash, inclusionProof.rootHash)) { + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROOF_ERROR', + message: 'root hash mismatch', + }); + } +} +// Verifies the signatures in the SignedNote. For each signature, the +// corresponding transparency log is looked up by the key hint and the +// signature is verified against the public key in the transparency log. +// Throws an error if any of the signatures are invalid. +function verifySignedNote(signedNote, tlogs) { + const data = Buffer.from(signedNote.note, 'utf-8'); + return signedNote.signatures.every((signature) => { + // Find the transparency log instance with the matching key hint + const tlog = tlogs.find((tlog) => core_1.crypto.bufferEqual(tlog.logID.subarray(0, 4), signature.keyHint)); + if (!tlog) { + return false; + } + return core_1.crypto.verify(data, tlog.publicKey, signature.signature); + }); +} +// SignedNote represents a signed note from a transparency log checkpoint. Consists +// of a body (or note) and one more signatures calculated over the body. See +// https://github.com/transparency-dev/formats/blob/main/log/README.md#signed-envelope +class SignedNote { + constructor(note, signatures) { + this.note = note; + this.signatures = signatures; + } + // Deserialize a SignedNote from a string + static fromString(envelope) { + if (!envelope.includes(CHECKPOINT_SEPARATOR)) { + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROOF_ERROR', + message: 'missing checkpoint separator', + }); + } + // Split the note into the header and the data portions at the separator + const split = envelope.indexOf(CHECKPOINT_SEPARATOR); + const header = envelope.slice(0, split + 1); + const data = envelope.slice(split + CHECKPOINT_SEPARATOR.length); + // Find all the signature lines in the data portion + const matches = data.matchAll(SIGNATURE_REGEX); + // Parse each of the matched signature lines into the name and signature. + // The first four bytes of the signature are the key hint (should match the + // first four bytes of the log ID), and the rest is the signature itself. + const signatures = Array.from(matches, (match) => { + const [, name, signature] = match; + const sigBytes = Buffer.from(signature, 'base64'); + if (sigBytes.length < 5) { + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROOF_ERROR', + message: 'malformed checkpoint signature', + }); + } + return { + name, + keyHint: sigBytes.subarray(0, 4), + signature: sigBytes.subarray(4), + }; + }); + if (signatures.length === 0) { + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROOF_ERROR', + message: 'no signatures found in checkpoint', + }); + } + return new SignedNote(header, signatures); + } +} +// LogCheckpoint represents a transparency log checkpoint. Consists of the +// following: +// - origin: the name of the transparency log +// - logSize: the size of the log at the time of the checkpoint +// - logHash: the root hash of the log at the time of the checkpoint +// - rest: the rest of the checkpoint body, which is a list of log entries +// See: +// https://github.com/transparency-dev/formats/blob/main/log/README.md#checkpoint-body +class LogCheckpoint { + constructor(origin, logSize, logHash, rest) { + this.origin = origin; + this.logSize = logSize; + this.logHash = logHash; + this.rest = rest; + } + static fromString(note) { + const lines = note.trimEnd().split('\n'); + if (lines.length < 3) { + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROOF_ERROR', + message: 'too few lines in checkpoint header', + }); + } + const origin = lines[0]; + const logSize = BigInt(lines[1]); + const rootHash = Buffer.from(lines[2], 'base64'); + const rest = lines.slice(3); + return new LogCheckpoint(origin, logSize, rootHash, rest); + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/timestamp/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/timestamp/index.js new file mode 100644 index 0000000000000..56e948de19338 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/timestamp/index.js @@ -0,0 +1,46 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyTSATimestamp = verifyTSATimestamp; +exports.verifyTLogTimestamp = verifyTLogTimestamp; +const error_1 = require("../error"); +const checkpoint_1 = require("./checkpoint"); +const merkle_1 = require("./merkle"); +const set_1 = require("./set"); +const tsa_1 = require("./tsa"); +function verifyTSATimestamp(timestamp, data, timestampAuthorities) { + (0, tsa_1.verifyRFC3161Timestamp)(timestamp, data, timestampAuthorities); + return { + type: 'timestamp-authority', + logID: timestamp.signerSerialNumber, + timestamp: timestamp.signingTime, + }; +} +function verifyTLogTimestamp(entry, tlogAuthorities) { + let inclusionVerified = false; + if (isTLogEntryWithInclusionPromise(entry)) { + (0, set_1.verifyTLogSET)(entry, tlogAuthorities); + inclusionVerified = true; + } + if (isTLogEntryWithInclusionProof(entry)) { + (0, merkle_1.verifyMerkleInclusion)(entry); + (0, checkpoint_1.verifyCheckpoint)(entry, tlogAuthorities); + inclusionVerified = true; + } + if (!inclusionVerified) { + throw new error_1.VerificationError({ + code: 'TLOG_MISSING_INCLUSION_ERROR', + message: 'inclusion could not be verified', + }); + } + return { + type: 'transparency-log', + logID: entry.logId.keyId, + timestamp: new Date(Number(entry.integratedTime) * 1000), + }; +} +function isTLogEntryWithInclusionPromise(entry) { + return entry.inclusionPromise !== undefined; +} +function isTLogEntryWithInclusionProof(entry) { + return entry.inclusionProof !== undefined; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/timestamp/merkle.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/timestamp/merkle.js new file mode 100644 index 0000000000000..f57cae42002bd --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/timestamp/merkle.js @@ -0,0 +1,104 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyMerkleInclusion = verifyMerkleInclusion; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const core_1 = require("@sigstore/core"); +const error_1 = require("../error"); +const RFC6962_LEAF_HASH_PREFIX = Buffer.from([0x00]); +const RFC6962_NODE_HASH_PREFIX = Buffer.from([0x01]); +function verifyMerkleInclusion(entry) { + const inclusionProof = entry.inclusionProof; + const logIndex = BigInt(inclusionProof.logIndex); + const treeSize = BigInt(inclusionProof.treeSize); + if (logIndex < 0n || logIndex >= treeSize) { + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROOF_ERROR', + message: `invalid index: ${logIndex}`, + }); + } + // Figure out which subset of hashes corresponds to the inner and border + // nodes + const { inner, border } = decompInclProof(logIndex, treeSize); + if (inclusionProof.hashes.length !== inner + border) { + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROOF_ERROR', + message: 'invalid hash count', + }); + } + const innerHashes = inclusionProof.hashes.slice(0, inner); + const borderHashes = inclusionProof.hashes.slice(inner); + // The entry's hash is the leaf hash + const leafHash = hashLeaf(entry.canonicalizedBody); + // Chain the hashes belonging to the inner and border portions + const calculatedHash = chainBorderRight(chainInner(leafHash, innerHashes, logIndex), borderHashes); + // Calculated hash should match the root hash in the inclusion proof + if (!core_1.crypto.bufferEqual(calculatedHash, inclusionProof.rootHash)) { + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROOF_ERROR', + message: 'calculated root hash does not match inclusion proof', + }); + } +} +// Breaks down inclusion proof for a leaf at the specified index in a tree of +// the specified size. The split point is where paths to the index leaf and +// the (size - 1) leaf diverge. Returns lengths of the bottom and upper proof +// parts. +function decompInclProof(index, size) { + const inner = innerProofSize(index, size); + const border = onesCount(index >> BigInt(inner)); + return { inner, border }; +} +// Computes a subtree hash for a node on or below the tree's right border. +// Assumes the provided proof hashes are ordered from lower to higher levels +// and seed is the initial hash of the node specified by the index. +function chainInner(seed, hashes, index) { + return hashes.reduce((acc, h, i) => { + if ((index >> BigInt(i)) & BigInt(1)) { + return hashChildren(h, acc); + } + else { + return hashChildren(acc, h); + } + }, seed); +} +// Computes a subtree hash for nodes along the tree's right border. +function chainBorderRight(seed, hashes) { + return hashes.reduce((acc, h) => hashChildren(h, acc), seed); +} +function innerProofSize(index, size) { + return bitLength(index ^ (size - BigInt(1))); +} +// Counts the number of ones in the binary representation of the given number. +// https://en.wikipedia.org/wiki/Hamming_weight +function onesCount(num) { + return num.toString(2).split('1').length - 1; +} +// Returns the number of bits necessary to represent an integer in binary. +function bitLength(n) { + if (n === 0n) { + return 0; + } + return n.toString(2).length; +} +// Hashing logic according to RFC6962. +// https://datatracker.ietf.org/doc/html/rfc6962#section-2 +function hashChildren(left, right) { + return core_1.crypto.digest('sha256', RFC6962_NODE_HASH_PREFIX, left, right); +} +function hashLeaf(leaf) { + return core_1.crypto.digest('sha256', RFC6962_LEAF_HASH_PREFIX, leaf); +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/timestamp/set.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/timestamp/set.js new file mode 100644 index 0000000000000..5d3f47bb88746 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/timestamp/set.js @@ -0,0 +1,60 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyTLogSET = verifyTLogSET; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const core_1 = require("@sigstore/core"); +const error_1 = require("../error"); +const trust_1 = require("../trust"); +// Verifies the SET for the given entry against the list of trusted +// transparency logs. Returns true if the SET can be verified against at least +// one of the trusted logs; otherwise, returns false. +function verifyTLogSET(entry, tlogs) { + // Filter the list of tlog instances to only those which might be able to + // verify the SET + const validTLogs = (0, trust_1.filterTLogAuthorities)(tlogs, { + logID: entry.logId.keyId, + targetDate: new Date(Number(entry.integratedTime) * 1000), + }); + // Check to see if we can verify the SET against any of the valid tlogs + const verified = validTLogs.some((tlog) => { + // Re-create the original Rekor verification payload + const payload = toVerificationPayload(entry); + // Canonicalize the payload and turn into a buffer for verification + const data = Buffer.from(core_1.json.canonicalize(payload), 'utf8'); + // Extract the SET from the tlog entry + const signature = entry.inclusionPromise.signedEntryTimestamp; + return core_1.crypto.verify(data, tlog.publicKey, signature); + }); + if (!verified) { + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROMISE_ERROR', + message: 'inclusion promise could not be verified', + }); + } +} +// Returns a properly formatted "VerificationPayload" for one of the +// transaction log entires in the given bundle which can be used for SET +// verification. +function toVerificationPayload(entry) { + const { integratedTime, logIndex, logId, canonicalizedBody } = entry; + return { + body: canonicalizedBody.toString('base64'), + integratedTime: Number(integratedTime), + logIndex: Number(logIndex), + logID: logId.keyId.toString('hex'), + }; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/timestamp/tsa.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/timestamp/tsa.js new file mode 100644 index 0000000000000..70388cd06c52d --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/timestamp/tsa.js @@ -0,0 +1,73 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyRFC3161Timestamp = verifyRFC3161Timestamp; +const core_1 = require("@sigstore/core"); +const error_1 = require("../error"); +const certificate_1 = require("../key/certificate"); +const trust_1 = require("../trust"); +function verifyRFC3161Timestamp(timestamp, data, timestampAuthorities) { + const signingTime = timestamp.signingTime; + // Filter for CAs which were valid at the time of signing + timestampAuthorities = (0, trust_1.filterCertAuthorities)(timestampAuthorities, { + start: signingTime, + end: signingTime, + }); + // Filter for CAs which match serial and issuer embedded in the timestamp + timestampAuthorities = filterCAsBySerialAndIssuer(timestampAuthorities, { + serialNumber: timestamp.signerSerialNumber, + issuer: timestamp.signerIssuer, + }); + // Check that we can verify the timestamp with AT LEAST ONE of the remaining + // CAs + const verified = timestampAuthorities.some((ca) => { + try { + verifyTimestampForCA(timestamp, data, ca); + return true; + } + catch (e) { + return false; + } + }); + if (!verified) { + throw new error_1.VerificationError({ + code: 'TIMESTAMP_ERROR', + message: 'timestamp could not be verified', + }); + } +} +function verifyTimestampForCA(timestamp, data, ca) { + const [leaf, ...cas] = ca.certChain; + const signingKey = core_1.crypto.createPublicKey(leaf.publicKey); + const signingTime = timestamp.signingTime; + // Verify the certificate chain for the provided CA + try { + new certificate_1.CertificateChainVerifier({ + untrustedCert: leaf, + trustedCerts: cas, + }).verify(); + } + catch (e) { + throw new error_1.VerificationError({ + code: 'TIMESTAMP_ERROR', + message: 'invalid certificate chain', + }); + } + // Check that all of the CA certs were valid at the time of signing + const validAtSigningTime = ca.certChain.every((cert) => cert.validForDate(signingTime)); + if (!validAtSigningTime) { + throw new error_1.VerificationError({ + code: 'TIMESTAMP_ERROR', + message: 'timestamp was signed with an expired certificate', + }); + } + // Check that the signing certificate's key can be used to verify the + // timestamp signature. + timestamp.verify(data, signingKey); +} +// Filters the list of CAs to those which have a leaf signing certificate which +// matches the given serial number and issuer. +function filterCAsBySerialAndIssuer(timestampAuthorities, criteria) { + return timestampAuthorities.filter((ca) => ca.certChain.length > 0 && + core_1.crypto.bufferEqual(ca.certChain[0].serialNumber, criteria.serialNumber) && + core_1.crypto.bufferEqual(ca.certChain[0].issuer, criteria.issuer)); +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/tlog/dsse.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/tlog/dsse.js new file mode 100644 index 0000000000000..d71ed8c6e7ad9 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/tlog/dsse.js @@ -0,0 +1,57 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyDSSETLogBody = verifyDSSETLogBody; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const error_1 = require("../error"); +// Compare the given intoto tlog entry to the given bundle +function verifyDSSETLogBody(tlogEntry, content) { + switch (tlogEntry.apiVersion) { + case '0.0.1': + return verifyDSSE001TLogBody(tlogEntry, content); + default: + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: `unsupported dsse version: ${tlogEntry.apiVersion}`, + }); + } +} +// Compare the given dsse v0.0.1 tlog entry to the given DSSE envelope. +function verifyDSSE001TLogBody(tlogEntry, content) { + // Ensure the bundle's DSSE only contains a single signature + if (tlogEntry.spec.signatures?.length !== 1) { + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: 'signature count mismatch', + }); + } + const tlogSig = tlogEntry.spec.signatures[0].signature; + // Ensure that the signature in the bundle's DSSE matches tlog entry + if (!content.compareSignature(Buffer.from(tlogSig, 'base64'))) + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: 'tlog entry signature mismatch', + }); + // Ensure the digest of the bundle's DSSE payload matches the digest in the + // tlog entry + const tlogHash = tlogEntry.spec.payloadHash?.value || ''; + if (!content.compareDigest(Buffer.from(tlogHash, 'hex'))) { + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: 'DSSE payload hash mismatch', + }); + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/tlog/hashedrekord.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/tlog/hashedrekord.js new file mode 100644 index 0000000000000..c4aa345b57ba7 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/tlog/hashedrekord.js @@ -0,0 +1,51 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyHashedRekordTLogBody = verifyHashedRekordTLogBody; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const error_1 = require("../error"); +// Compare the given hashedrekord tlog entry to the given bundle +function verifyHashedRekordTLogBody(tlogEntry, content) { + switch (tlogEntry.apiVersion) { + case '0.0.1': + return verifyHashedrekord001TLogBody(tlogEntry, content); + default: + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: `unsupported hashedrekord version: ${tlogEntry.apiVersion}`, + }); + } +} +// Compare the given hashedrekord v0.0.1 tlog entry to the given message +// signature +function verifyHashedrekord001TLogBody(tlogEntry, content) { + // Ensure that the bundles message signature matches the tlog entry + const tlogSig = tlogEntry.spec.signature.content || ''; + if (!content.compareSignature(Buffer.from(tlogSig, 'base64'))) { + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: 'signature mismatch', + }); + } + // Ensure that the bundle's message digest matches the tlog entry + const tlogDigest = tlogEntry.spec.data.hash?.value || ''; + if (!content.compareDigest(Buffer.from(tlogDigest, 'hex'))) { + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: 'digest mismatch', + }); + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/tlog/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/tlog/index.js new file mode 100644 index 0000000000000..da235360c594a --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/tlog/index.js @@ -0,0 +1,47 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyTLogBody = verifyTLogBody; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const error_1 = require("../error"); +const dsse_1 = require("./dsse"); +const hashedrekord_1 = require("./hashedrekord"); +const intoto_1 = require("./intoto"); +// Verifies that the given tlog entry matches the supplied signature content. +function verifyTLogBody(entry, sigContent) { + const { kind, version } = entry.kindVersion; + const body = JSON.parse(entry.canonicalizedBody.toString('utf8')); + if (kind !== body.kind || version !== body.apiVersion) { + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: `kind/version mismatch - expected: ${kind}/${version}, received: ${body.kind}/${body.apiVersion}`, + }); + } + switch (body.kind) { + case 'dsse': + return (0, dsse_1.verifyDSSETLogBody)(body, sigContent); + case 'intoto': + return (0, intoto_1.verifyIntotoTLogBody)(body, sigContent); + case 'hashedrekord': + return (0, hashedrekord_1.verifyHashedRekordTLogBody)(body, sigContent); + /* istanbul ignore next */ + default: + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: `unsupported kind: ${kind}`, + }); + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/tlog/intoto.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/tlog/intoto.js new file mode 100644 index 0000000000000..9096ae9418cc3 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/tlog/intoto.js @@ -0,0 +1,62 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyIntotoTLogBody = verifyIntotoTLogBody; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const error_1 = require("../error"); +// Compare the given intoto tlog entry to the given bundle +function verifyIntotoTLogBody(tlogEntry, content) { + switch (tlogEntry.apiVersion) { + case '0.0.2': + return verifyIntoto002TLogBody(tlogEntry, content); + default: + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: `unsupported intoto version: ${tlogEntry.apiVersion}`, + }); + } +} +// Compare the given intoto v0.0.2 tlog entry to the given DSSE envelope. +function verifyIntoto002TLogBody(tlogEntry, content) { + // Ensure the bundle's DSSE contains a single signature + if (tlogEntry.spec.content.envelope.signatures?.length !== 1) { + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: 'signature count mismatch', + }); + } + // Signature is double-base64-encoded in the tlog entry + const tlogSig = base64Decode(tlogEntry.spec.content.envelope.signatures[0].sig); + // Ensure that the signature in the bundle's DSSE matches tlog entry + if (!content.compareSignature(Buffer.from(tlogSig, 'base64'))) { + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: 'tlog entry signature mismatch', + }); + } + // Ensure the digest of the bundle's DSSE payload matches the digest in the + // tlog entry + const tlogHash = tlogEntry.spec.content.payloadHash?.value || ''; + if (!content.compareDigest(Buffer.from(tlogHash, 'hex'))) { + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: 'DSSE payload hash mismatch', + }); + } +} +function base64Decode(str) { + return Buffer.from(str, 'base64').toString('utf-8'); +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/trust/filter.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/trust/filter.js new file mode 100644 index 0000000000000..880a16cf1940e --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/trust/filter.js @@ -0,0 +1,23 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.filterCertAuthorities = filterCertAuthorities; +exports.filterTLogAuthorities = filterTLogAuthorities; +function filterCertAuthorities(certAuthorities, criteria) { + return certAuthorities.filter((ca) => { + return (ca.validFor.start <= criteria.start && ca.validFor.end >= criteria.end); + }); +} +// Filter the list of tlog instances to only those which match the given log +// ID and have public keys which are valid for the given integrated time. +function filterTLogAuthorities(tlogAuthorities, criteria) { + return tlogAuthorities.filter((tlog) => { + // If we're filtering by log ID and the log IDs don't match, we can't use + // this tlog + if (criteria.logID && !tlog.logID.equals(criteria.logID)) { + return false; + } + // Check that the integrated time is within the validFor range + return (tlog.validFor.start <= criteria.targetDate && + criteria.targetDate <= tlog.validFor.end); + }); +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/trust/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/trust/index.js new file mode 100644 index 0000000000000..bfab2eb4f9975 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/trust/index.js @@ -0,0 +1,86 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.filterTLogAuthorities = exports.filterCertAuthorities = void 0; +exports.toTrustMaterial = toTrustMaterial; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const core_1 = require("@sigstore/core"); +const protobuf_specs_1 = require("@sigstore/protobuf-specs"); +const error_1 = require("../error"); +const BEGINNING_OF_TIME = new Date(0); +const END_OF_TIME = new Date(8640000000000000); +var filter_1 = require("./filter"); +Object.defineProperty(exports, "filterCertAuthorities", { enumerable: true, get: function () { return filter_1.filterCertAuthorities; } }); +Object.defineProperty(exports, "filterTLogAuthorities", { enumerable: true, get: function () { return filter_1.filterTLogAuthorities; } }); +function toTrustMaterial(root, keys) { + const keyFinder = typeof keys === 'function' ? keys : keyLocator(keys); + return { + certificateAuthorities: root.certificateAuthorities.map(createCertAuthority), + timestampAuthorities: root.timestampAuthorities.map(createCertAuthority), + tlogs: root.tlogs.map(createTLogAuthority), + ctlogs: root.ctlogs.map(createTLogAuthority), + publicKey: keyFinder, + }; +} +function createTLogAuthority(tlogInstance) { + const keyDetails = tlogInstance.publicKey.keyDetails; + const keyType = keyDetails === protobuf_specs_1.PublicKeyDetails.PKCS1_RSA_PKCS1V5 || + keyDetails === protobuf_specs_1.PublicKeyDetails.PKIX_RSA_PKCS1V5 || + keyDetails === protobuf_specs_1.PublicKeyDetails.PKIX_RSA_PKCS1V15_2048_SHA256 || + keyDetails === protobuf_specs_1.PublicKeyDetails.PKIX_RSA_PKCS1V15_3072_SHA256 || + keyDetails === protobuf_specs_1.PublicKeyDetails.PKIX_RSA_PKCS1V15_4096_SHA256 + ? 'pkcs1' + : 'spki'; + return { + logID: tlogInstance.logId.keyId, + publicKey: core_1.crypto.createPublicKey(tlogInstance.publicKey.rawBytes, keyType), + validFor: { + start: tlogInstance.publicKey.validFor?.start || BEGINNING_OF_TIME, + end: tlogInstance.publicKey.validFor?.end || END_OF_TIME, + }, + }; +} +function createCertAuthority(ca) { + /* istanbul ignore next */ + return { + certChain: ca.certChain.certificates.map((cert) => { + return core_1.X509Certificate.parse(cert.rawBytes); + }), + validFor: { + start: ca.validFor?.start || BEGINNING_OF_TIME, + end: ca.validFor?.end || END_OF_TIME, + }, + }; +} +function keyLocator(keys) { + return (hint) => { + const key = (keys || {})[hint]; + if (!key) { + throw new error_1.VerificationError({ + code: 'PUBLIC_KEY_ERROR', + message: `key not found: ${hint}`, + }); + } + return { + publicKey: core_1.crypto.createPublicKey(key.rawBytes), + validFor: (date) => { + /* istanbul ignore next */ + return ((key.validFor?.start || BEGINNING_OF_TIME) <= date && + (key.validFor?.end || END_OF_TIME) >= date); + }, + }; + }; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/trust/trust.types.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/trust/trust.types.js new file mode 100644 index 0000000000000..c8ad2e549bdc6 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/trust/trust.types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/verifier.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/verifier.js new file mode 100644 index 0000000000000..829727cd1d40a --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/dist/verifier.js @@ -0,0 +1,141 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Verifier = void 0; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const util_1 = require("util"); +const error_1 = require("./error"); +const key_1 = require("./key"); +const policy_1 = require("./policy"); +const timestamp_1 = require("./timestamp"); +const tlog_1 = require("./tlog"); +class Verifier { + constructor(trustMaterial, options = {}) { + this.trustMaterial = trustMaterial; + this.options = { + ctlogThreshold: options.ctlogThreshold ?? 1, + tlogThreshold: options.tlogThreshold ?? 1, + tsaThreshold: options.tsaThreshold ?? 0, + }; + } + verify(entity, policy) { + const timestamps = this.verifyTimestamps(entity); + const signer = this.verifySigningKey(entity, timestamps); + this.verifyTLogs(entity); + this.verifySignature(entity, signer); + if (policy) { + this.verifyPolicy(policy, signer.identity || {}); + } + return signer; + } + // Checks that all of the timestamps in the entity are valid and returns them + verifyTimestamps(entity) { + let tlogCount = 0; + let tsaCount = 0; + const timestamps = entity.timestamps.map((timestamp) => { + switch (timestamp.$case) { + case 'timestamp-authority': + tsaCount++; + return (0, timestamp_1.verifyTSATimestamp)(timestamp.timestamp, entity.signature.signature, this.trustMaterial.timestampAuthorities); + case 'transparency-log': + tlogCount++; + return (0, timestamp_1.verifyTLogTimestamp)(timestamp.tlogEntry, this.trustMaterial.tlogs); + } + }); + // Check for duplicate timestamps + if (containsDupes(timestamps)) { + throw new error_1.VerificationError({ + code: 'TIMESTAMP_ERROR', + message: 'duplicate timestamp', + }); + } + if (tlogCount < this.options.tlogThreshold) { + throw new error_1.VerificationError({ + code: 'TIMESTAMP_ERROR', + message: `expected ${this.options.tlogThreshold} tlog timestamps, got ${tlogCount}`, + }); + } + if (tsaCount < this.options.tsaThreshold) { + throw new error_1.VerificationError({ + code: 'TIMESTAMP_ERROR', + message: `expected ${this.options.tsaThreshold} tsa timestamps, got ${tsaCount}`, + }); + } + return timestamps.map((t) => t.timestamp); + } + // Checks that the signing key is valid for all of the the supplied timestamps + // and returns the signer. + verifySigningKey({ key }, timestamps) { + switch (key.$case) { + case 'public-key': { + return (0, key_1.verifyPublicKey)(key.hint, timestamps, this.trustMaterial); + } + case 'certificate': { + const result = (0, key_1.verifyCertificate)(key.certificate, timestamps, this.trustMaterial); + /* istanbul ignore next - no fixture */ + if (containsDupes(result.scts)) { + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'duplicate SCT', + }); + } + if (result.scts.length < this.options.ctlogThreshold) { + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: `expected ${this.options.ctlogThreshold} SCTs, got ${result.scts.length}`, + }); + } + return result.signer; + } + } + } + // Checks that the tlog entries are valid for the supplied content + verifyTLogs({ signature: content, tlogEntries }) { + tlogEntries.forEach((entry) => (0, tlog_1.verifyTLogBody)(entry, content)); + } + // Checks that the signature is valid for the supplied content + verifySignature(entity, signer) { + if (!entity.signature.verifySignature(signer.key)) { + throw new error_1.VerificationError({ + code: 'SIGNATURE_ERROR', + message: 'signature verification failed', + }); + } + } + verifyPolicy(policy, identity) { + // Check the subject alternative name of the signer matches the policy + if (policy.subjectAlternativeName) { + (0, policy_1.verifySubjectAlternativeName)(policy.subjectAlternativeName, identity.subjectAlternativeName); + } + // Check that the extensions of the signer match the policy + if (policy.extensions) { + (0, policy_1.verifyExtensions)(policy.extensions, identity.extensions); + } + } +} +exports.Verifier = Verifier; +// Checks for duplicate items in the array. Objects are compared using +// deep equality. +function containsDupes(arr) { + for (let i = 0; i < arr.length; i++) { + for (let j = i + 1; j < arr.length; j++) { + if ((0, util_1.isDeepStrictEqual)(arr[i], arr[j])) { + return true; + } + } + } + return false; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/package.json b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/package.json new file mode 100644 index 0000000000000..edf72b8bfd968 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify/package.json @@ -0,0 +1,36 @@ +{ + "name": "@sigstore/verify", + "version": "2.0.0", + "description": "Verification of Sigstore signatures", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "clean": "shx rm -rf dist *.tsbuildinfo", + "build": "tsc --build", + "test": "jest" + }, + "files": [ + "dist" + ], + "author": "bdehamer@github.com", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "git+https://github.com/sigstore/sigstore-js.git" + }, + "bugs": { + "url": "https://github.com/sigstore/sigstore-js/issues" + }, + "homepage": "https://github.com/sigstore/sigstore-js/tree/main/packages/verify#readme", + "publishConfig": { + "provenance": true + }, + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.2", + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/LICENSE b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/LICENSE new file mode 100644 index 0000000000000..420700f5d3765 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 GitHub and the TUF Contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/base.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/base.js new file mode 100644 index 0000000000000..85e45d8fc1151 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/base.js @@ -0,0 +1,92 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Signed = exports.MetadataKind = void 0; +exports.isMetadataKind = isMetadataKind; +const util_1 = __importDefault(require("util")); +const error_1 = require("./error"); +const utils_1 = require("./utils"); +const SPECIFICATION_VERSION = ['1', '0', '31']; +var MetadataKind; +(function (MetadataKind) { + MetadataKind["Root"] = "root"; + MetadataKind["Timestamp"] = "timestamp"; + MetadataKind["Snapshot"] = "snapshot"; + MetadataKind["Targets"] = "targets"; +})(MetadataKind || (exports.MetadataKind = MetadataKind = {})); +function isMetadataKind(value) { + return (typeof value === 'string' && + Object.values(MetadataKind).includes(value)); +} +/*** + * A base class for the signed part of TUF metadata. + * + * Objects with base class Signed are usually included in a ``Metadata`` object + * on the signed attribute. This class provides attributes and methods that + * are common for all TUF metadata types (roles). + */ +class Signed { + constructor(options) { + this.specVersion = options.specVersion || SPECIFICATION_VERSION.join('.'); + const specList = this.specVersion.split('.'); + if (!(specList.length === 2 || specList.length === 3) || + !specList.every((item) => isNumeric(item))) { + throw new error_1.ValueError('Failed to parse specVersion'); + } + // major version must match + if (specList[0] != SPECIFICATION_VERSION[0]) { + throw new error_1.ValueError('Unsupported specVersion'); + } + this.expires = options.expires; + this.version = options.version; + this.unrecognizedFields = options.unrecognizedFields || {}; + } + equals(other) { + if (!(other instanceof Signed)) { + return false; + } + return (this.specVersion === other.specVersion && + this.expires === other.expires && + this.version === other.version && + util_1.default.isDeepStrictEqual(this.unrecognizedFields, other.unrecognizedFields)); + } + isExpired(referenceTime) { + if (!referenceTime) { + referenceTime = new Date(); + } + return referenceTime >= new Date(this.expires); + } + static commonFieldsFromJSON(data) { + const { spec_version, expires, version, ...rest } = data; + if (!utils_1.guard.isDefined(spec_version)) { + throw new error_1.ValueError('spec_version is not defined'); + } + else if (typeof spec_version !== 'string') { + throw new TypeError('spec_version must be a string'); + } + if (!utils_1.guard.isDefined(expires)) { + throw new error_1.ValueError('expires is not defined'); + } + else if (!(typeof expires === 'string')) { + throw new TypeError('expires must be a string'); + } + if (!utils_1.guard.isDefined(version)) { + throw new error_1.ValueError('version is not defined'); + } + else if (!(typeof version === 'number')) { + throw new TypeError('version must be a number'); + } + return { + specVersion: spec_version, + expires, + version, + unrecognizedFields: rest, + }; + } +} +exports.Signed = Signed; +function isNumeric(str) { + return !isNaN(Number(str)); +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/delegations.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/delegations.js new file mode 100644 index 0000000000000..7165f1e244393 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/delegations.js @@ -0,0 +1,115 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Delegations = void 0; +const util_1 = __importDefault(require("util")); +const error_1 = require("./error"); +const key_1 = require("./key"); +const role_1 = require("./role"); +const utils_1 = require("./utils"); +/** + * A container object storing information about all delegations. + * + * Targets roles that are trusted to provide signed metadata files + * describing targets with designated pathnames and/or further delegations. + */ +class Delegations { + constructor(options) { + this.keys = options.keys; + this.unrecognizedFields = options.unrecognizedFields || {}; + if (options.roles) { + if (Object.keys(options.roles).some((roleName) => role_1.TOP_LEVEL_ROLE_NAMES.includes(roleName))) { + throw new error_1.ValueError('Delegated role name conflicts with top-level role name'); + } + } + this.succinctRoles = options.succinctRoles; + this.roles = options.roles; + } + equals(other) { + if (!(other instanceof Delegations)) { + return false; + } + return (util_1.default.isDeepStrictEqual(this.keys, other.keys) && + util_1.default.isDeepStrictEqual(this.roles, other.roles) && + util_1.default.isDeepStrictEqual(this.unrecognizedFields, other.unrecognizedFields) && + util_1.default.isDeepStrictEqual(this.succinctRoles, other.succinctRoles)); + } + *rolesForTarget(targetPath) { + if (this.roles) { + for (const role of Object.values(this.roles)) { + if (role.isDelegatedPath(targetPath)) { + yield { role: role.name, terminating: role.terminating }; + } + } + } + else if (this.succinctRoles) { + yield { + role: this.succinctRoles.getRoleForTarget(targetPath), + terminating: true, + }; + } + } + toJSON() { + const json = { + keys: keysToJSON(this.keys), + ...this.unrecognizedFields, + }; + if (this.roles) { + json.roles = rolesToJSON(this.roles); + } + else if (this.succinctRoles) { + json.succinct_roles = this.succinctRoles.toJSON(); + } + return json; + } + static fromJSON(data) { + const { keys, roles, succinct_roles, ...unrecognizedFields } = data; + let succinctRoles; + if (utils_1.guard.isObject(succinct_roles)) { + succinctRoles = role_1.SuccinctRoles.fromJSON(succinct_roles); + } + return new Delegations({ + keys: keysFromJSON(keys), + roles: rolesFromJSON(roles), + unrecognizedFields, + succinctRoles, + }); + } +} +exports.Delegations = Delegations; +function keysToJSON(keys) { + return Object.entries(keys).reduce((acc, [keyId, key]) => ({ + ...acc, + [keyId]: key.toJSON(), + }), {}); +} +function rolesToJSON(roles) { + return Object.values(roles).map((role) => role.toJSON()); +} +function keysFromJSON(data) { + if (!utils_1.guard.isObjectRecord(data)) { + throw new TypeError('keys is malformed'); + } + return Object.entries(data).reduce((acc, [keyID, keyData]) => ({ + ...acc, + [keyID]: key_1.Key.fromJSON(keyID, keyData), + }), {}); +} +function rolesFromJSON(data) { + let roleMap; + if (utils_1.guard.isDefined(data)) { + if (!utils_1.guard.isObjectArray(data)) { + throw new TypeError('roles is malformed'); + } + roleMap = data.reduce((acc, role) => { + const delegatedRole = role_1.DelegatedRole.fromJSON(role); + return { + ...acc, + [delegatedRole.name]: delegatedRole, + }; + }, {}); + } + return roleMap; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/error.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/error.js new file mode 100644 index 0000000000000..ba80698747ba0 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/error.js @@ -0,0 +1,27 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.UnsupportedAlgorithmError = exports.CryptoError = exports.LengthOrHashMismatchError = exports.UnsignedMetadataError = exports.RepositoryError = exports.ValueError = void 0; +// An error about insufficient values +class ValueError extends Error { +} +exports.ValueError = ValueError; +// An error with a repository's state, such as a missing file. +// It covers all exceptions that come from the repository side when +// looking from the perspective of users of metadata API or ngclient. +class RepositoryError extends Error { +} +exports.RepositoryError = RepositoryError; +// An error about metadata object with insufficient threshold of signatures. +class UnsignedMetadataError extends RepositoryError { +} +exports.UnsignedMetadataError = UnsignedMetadataError; +// An error while checking the length and hash values of an object. +class LengthOrHashMismatchError extends RepositoryError { +} +exports.LengthOrHashMismatchError = LengthOrHashMismatchError; +class CryptoError extends Error { +} +exports.CryptoError = CryptoError; +class UnsupportedAlgorithmError extends CryptoError { +} +exports.UnsupportedAlgorithmError = UnsupportedAlgorithmError; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/file.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/file.js new file mode 100644 index 0000000000000..b35fe5950bbb7 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/file.js @@ -0,0 +1,183 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TargetFile = exports.MetaFile = void 0; +const crypto_1 = __importDefault(require("crypto")); +const util_1 = __importDefault(require("util")); +const error_1 = require("./error"); +const utils_1 = require("./utils"); +// A container with information about a particular metadata file. +// +// This class is used for Timestamp and Snapshot metadata. +class MetaFile { + constructor(opts) { + if (opts.version <= 0) { + throw new error_1.ValueError('Metafile version must be at least 1'); + } + if (opts.length !== undefined) { + validateLength(opts.length); + } + this.version = opts.version; + this.length = opts.length; + this.hashes = opts.hashes; + this.unrecognizedFields = opts.unrecognizedFields || {}; + } + equals(other) { + if (!(other instanceof MetaFile)) { + return false; + } + return (this.version === other.version && + this.length === other.length && + util_1.default.isDeepStrictEqual(this.hashes, other.hashes) && + util_1.default.isDeepStrictEqual(this.unrecognizedFields, other.unrecognizedFields)); + } + verify(data) { + // Verifies that the given data matches the expected length. + if (this.length !== undefined) { + if (data.length !== this.length) { + throw new error_1.LengthOrHashMismatchError(`Expected length ${this.length} but got ${data.length}`); + } + } + // Verifies that the given data matches the supplied hashes. + if (this.hashes) { + Object.entries(this.hashes).forEach(([key, value]) => { + let hash; + try { + hash = crypto_1.default.createHash(key); + } + catch (e) { + throw new error_1.LengthOrHashMismatchError(`Hash algorithm ${key} not supported`); + } + const observedHash = hash.update(data).digest('hex'); + if (observedHash !== value) { + throw new error_1.LengthOrHashMismatchError(`Expected hash ${value} but got ${observedHash}`); + } + }); + } + } + toJSON() { + const json = { + version: this.version, + ...this.unrecognizedFields, + }; + if (this.length !== undefined) { + json.length = this.length; + } + if (this.hashes) { + json.hashes = this.hashes; + } + return json; + } + static fromJSON(data) { + const { version, length, hashes, ...rest } = data; + if (typeof version !== 'number') { + throw new TypeError('version must be a number'); + } + if (utils_1.guard.isDefined(length) && typeof length !== 'number') { + throw new TypeError('length must be a number'); + } + if (utils_1.guard.isDefined(hashes) && !utils_1.guard.isStringRecord(hashes)) { + throw new TypeError('hashes must be string keys and values'); + } + return new MetaFile({ + version, + length, + hashes, + unrecognizedFields: rest, + }); + } +} +exports.MetaFile = MetaFile; +// Container for info about a particular target file. +// +// This class is used for Target metadata. +class TargetFile { + constructor(opts) { + validateLength(opts.length); + this.length = opts.length; + this.path = opts.path; + this.hashes = opts.hashes; + this.unrecognizedFields = opts.unrecognizedFields || {}; + } + get custom() { + const custom = this.unrecognizedFields['custom']; + if (!custom || Array.isArray(custom) || !(typeof custom === 'object')) { + return {}; + } + return custom; + } + equals(other) { + if (!(other instanceof TargetFile)) { + return false; + } + return (this.length === other.length && + this.path === other.path && + util_1.default.isDeepStrictEqual(this.hashes, other.hashes) && + util_1.default.isDeepStrictEqual(this.unrecognizedFields, other.unrecognizedFields)); + } + async verify(stream) { + let observedLength = 0; + // Create a digest for each hash algorithm + const digests = Object.keys(this.hashes).reduce((acc, key) => { + try { + acc[key] = crypto_1.default.createHash(key); + } + catch (e) { + throw new error_1.LengthOrHashMismatchError(`Hash algorithm ${key} not supported`); + } + return acc; + }, {}); + // Read stream chunk by chunk + for await (const chunk of stream) { + // Keep running tally of stream length + observedLength += chunk.length; + // Append chunk to each digest + Object.values(digests).forEach((digest) => { + digest.update(chunk); + }); + } + // Verify length matches expected value + if (observedLength !== this.length) { + throw new error_1.LengthOrHashMismatchError(`Expected length ${this.length} but got ${observedLength}`); + } + // Verify each digest matches expected value + Object.entries(digests).forEach(([key, value]) => { + const expected = this.hashes[key]; + const actual = value.digest('hex'); + if (actual !== expected) { + throw new error_1.LengthOrHashMismatchError(`Expected hash ${expected} but got ${actual}`); + } + }); + } + toJSON() { + return { + length: this.length, + hashes: this.hashes, + ...this.unrecognizedFields, + }; + } + static fromJSON(path, data) { + const { length, hashes, ...rest } = data; + if (typeof length !== 'number') { + throw new TypeError('length must be a number'); + } + if (!utils_1.guard.isStringRecord(hashes)) { + throw new TypeError('hashes must have string keys and values'); + } + return new TargetFile({ + length, + path, + hashes, + unrecognizedFields: rest, + }); + } +} +exports.TargetFile = TargetFile; +// Check that supplied length if valid +function validateLength(length) { + if (length < 0) { + throw new error_1.ValueError('Length must be at least 0'); + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/index.js new file mode 100644 index 0000000000000..a4dc783659f04 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/index.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Timestamp = exports.Targets = exports.Snapshot = exports.Signature = exports.Root = exports.Metadata = exports.Key = exports.TargetFile = exports.MetaFile = exports.ValueError = exports.MetadataKind = void 0; +var base_1 = require("./base"); +Object.defineProperty(exports, "MetadataKind", { enumerable: true, get: function () { return base_1.MetadataKind; } }); +var error_1 = require("./error"); +Object.defineProperty(exports, "ValueError", { enumerable: true, get: function () { return error_1.ValueError; } }); +var file_1 = require("./file"); +Object.defineProperty(exports, "MetaFile", { enumerable: true, get: function () { return file_1.MetaFile; } }); +Object.defineProperty(exports, "TargetFile", { enumerable: true, get: function () { return file_1.TargetFile; } }); +var key_1 = require("./key"); +Object.defineProperty(exports, "Key", { enumerable: true, get: function () { return key_1.Key; } }); +var metadata_1 = require("./metadata"); +Object.defineProperty(exports, "Metadata", { enumerable: true, get: function () { return metadata_1.Metadata; } }); +var root_1 = require("./root"); +Object.defineProperty(exports, "Root", { enumerable: true, get: function () { return root_1.Root; } }); +var signature_1 = require("./signature"); +Object.defineProperty(exports, "Signature", { enumerable: true, get: function () { return signature_1.Signature; } }); +var snapshot_1 = require("./snapshot"); +Object.defineProperty(exports, "Snapshot", { enumerable: true, get: function () { return snapshot_1.Snapshot; } }); +var targets_1 = require("./targets"); +Object.defineProperty(exports, "Targets", { enumerable: true, get: function () { return targets_1.Targets; } }); +var timestamp_1 = require("./timestamp"); +Object.defineProperty(exports, "Timestamp", { enumerable: true, get: function () { return timestamp_1.Timestamp; } }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/key.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/key.js new file mode 100644 index 0000000000000..5e55b09d7c6dd --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/key.js @@ -0,0 +1,85 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Key = void 0; +const util_1 = __importDefault(require("util")); +const error_1 = require("./error"); +const utils_1 = require("./utils"); +const key_1 = require("./utils/key"); +// A container class representing the public portion of a Key. +class Key { + constructor(options) { + const { keyID, keyType, scheme, keyVal, unrecognizedFields } = options; + this.keyID = keyID; + this.keyType = keyType; + this.scheme = scheme; + this.keyVal = keyVal; + this.unrecognizedFields = unrecognizedFields || {}; + } + // Verifies the that the metadata.signatures contains a signature made with + // this key and is correctly signed. + verifySignature(metadata) { + const signature = metadata.signatures[this.keyID]; + if (!signature) + throw new error_1.UnsignedMetadataError('no signature for key found in metadata'); + if (!this.keyVal.public) + throw new error_1.UnsignedMetadataError('no public key found'); + const publicKey = (0, key_1.getPublicKey)({ + keyType: this.keyType, + scheme: this.scheme, + keyVal: this.keyVal.public, + }); + const signedData = metadata.signed.toJSON(); + try { + if (!utils_1.crypto.verifySignature(signedData, publicKey, signature.sig)) { + throw new error_1.UnsignedMetadataError(`failed to verify ${this.keyID} signature`); + } + } + catch (error) { + if (error instanceof error_1.UnsignedMetadataError) { + throw error; + } + throw new error_1.UnsignedMetadataError(`failed to verify ${this.keyID} signature`); + } + } + equals(other) { + if (!(other instanceof Key)) { + return false; + } + return (this.keyID === other.keyID && + this.keyType === other.keyType && + this.scheme === other.scheme && + util_1.default.isDeepStrictEqual(this.keyVal, other.keyVal) && + util_1.default.isDeepStrictEqual(this.unrecognizedFields, other.unrecognizedFields)); + } + toJSON() { + return { + keytype: this.keyType, + scheme: this.scheme, + keyval: this.keyVal, + ...this.unrecognizedFields, + }; + } + static fromJSON(keyID, data) { + const { keytype, scheme, keyval, ...rest } = data; + if (typeof keytype !== 'string') { + throw new TypeError('keytype must be a string'); + } + if (typeof scheme !== 'string') { + throw new TypeError('scheme must be a string'); + } + if (!utils_1.guard.isStringRecord(keyval)) { + throw new TypeError('keyval must be a string record'); + } + return new Key({ + keyID, + keyType: keytype, + scheme, + keyVal: keyval, + unrecognizedFields: rest, + }); + } +} +exports.Key = Key; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/metadata.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/metadata.js new file mode 100644 index 0000000000000..389d2504e0b53 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/metadata.js @@ -0,0 +1,160 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Metadata = void 0; +const canonical_json_1 = require("@tufjs/canonical-json"); +const util_1 = __importDefault(require("util")); +const base_1 = require("./base"); +const error_1 = require("./error"); +const root_1 = require("./root"); +const signature_1 = require("./signature"); +const snapshot_1 = require("./snapshot"); +const targets_1 = require("./targets"); +const timestamp_1 = require("./timestamp"); +const utils_1 = require("./utils"); +/*** + * A container for signed TUF metadata. + * + * Provides methods to convert to and from json, read and write to and + * from JSON and to create and verify metadata signatures. + * + * ``Metadata[T]`` is a generic container type where T can be any one type of + * [``Root``, ``Timestamp``, ``Snapshot``, ``Targets``]. The purpose of this + * is to allow static type checking of the signed attribute in code using + * Metadata:: + * + * root_md = Metadata[Root].fromJSON("root.json") + * # root_md type is now Metadata[Root]. This means signed and its + * # attributes like consistent_snapshot are now statically typed and the + * # types can be verified by static type checkers and shown by IDEs + * + * Using a type constraint is not required but not doing so means T is not a + * specific type so static typing cannot happen. Note that the type constraint + * ``[Root]`` is not validated at runtime (as pure annotations are not available + * then). + * + * Apart from ``expires`` all of the arguments to the inner constructors have + * reasonable default values for new metadata. + */ +class Metadata { + constructor(signed, signatures, unrecognizedFields) { + this.signed = signed; + this.signatures = signatures || {}; + this.unrecognizedFields = unrecognizedFields || {}; + } + sign(signer, append = true) { + const bytes = Buffer.from((0, canonical_json_1.canonicalize)(this.signed.toJSON())); + const signature = signer(bytes); + if (!append) { + this.signatures = {}; + } + this.signatures[signature.keyID] = signature; + } + verifyDelegate(delegatedRole, delegatedMetadata) { + let role; + let keys = {}; + switch (this.signed.type) { + case base_1.MetadataKind.Root: + keys = this.signed.keys; + role = this.signed.roles[delegatedRole]; + break; + case base_1.MetadataKind.Targets: + if (!this.signed.delegations) { + throw new error_1.ValueError(`No delegations found for ${delegatedRole}`); + } + keys = this.signed.delegations.keys; + if (this.signed.delegations.roles) { + role = this.signed.delegations.roles[delegatedRole]; + } + else if (this.signed.delegations.succinctRoles) { + if (this.signed.delegations.succinctRoles.isDelegatedRole(delegatedRole)) { + role = this.signed.delegations.succinctRoles; + } + } + break; + default: + throw new TypeError('invalid metadata type'); + } + if (!role) { + throw new error_1.ValueError(`no delegation found for ${delegatedRole}`); + } + const signingKeys = new Set(); + role.keyIDs.forEach((keyID) => { + const key = keys[keyID]; + // If we dont' have the key, continue checking other keys + if (!key) { + return; + } + try { + key.verifySignature(delegatedMetadata); + signingKeys.add(key.keyID); + } + catch (error) { + // continue + } + }); + if (signingKeys.size < role.threshold) { + throw new error_1.UnsignedMetadataError(`${delegatedRole} was signed by ${signingKeys.size}/${role.threshold} keys`); + } + } + equals(other) { + if (!(other instanceof Metadata)) { + return false; + } + return (this.signed.equals(other.signed) && + util_1.default.isDeepStrictEqual(this.signatures, other.signatures) && + util_1.default.isDeepStrictEqual(this.unrecognizedFields, other.unrecognizedFields)); + } + toJSON() { + const signatures = Object.values(this.signatures).map((signature) => { + return signature.toJSON(); + }); + return { + signatures, + signed: this.signed.toJSON(), + ...this.unrecognizedFields, + }; + } + static fromJSON(type, data) { + const { signed, signatures, ...rest } = data; + if (!utils_1.guard.isDefined(signed) || !utils_1.guard.isObject(signed)) { + throw new TypeError('signed is not defined'); + } + if (type !== signed._type) { + throw new error_1.ValueError(`expected '${type}', got ${signed['_type']}`); + } + if (!utils_1.guard.isObjectArray(signatures)) { + throw new TypeError('signatures is not an array'); + } + let signedObj; + switch (type) { + case base_1.MetadataKind.Root: + signedObj = root_1.Root.fromJSON(signed); + break; + case base_1.MetadataKind.Timestamp: + signedObj = timestamp_1.Timestamp.fromJSON(signed); + break; + case base_1.MetadataKind.Snapshot: + signedObj = snapshot_1.Snapshot.fromJSON(signed); + break; + case base_1.MetadataKind.Targets: + signedObj = targets_1.Targets.fromJSON(signed); + break; + default: + throw new TypeError('invalid metadata type'); + } + const sigMap = {}; + // Ensure that each signature is unique + signatures.forEach((sigData) => { + const sig = signature_1.Signature.fromJSON(sigData); + if (sigMap[sig.keyID]) { + throw new error_1.ValueError(`multiple signatures found for keyid: ${sig.keyID}`); + } + sigMap[sig.keyID] = sig; + }); + return new Metadata(signedObj, sigMap, rest); + } +} +exports.Metadata = Metadata; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/role.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/role.js new file mode 100644 index 0000000000000..f7ddbc6fe3f38 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/role.js @@ -0,0 +1,299 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SuccinctRoles = exports.DelegatedRole = exports.Role = exports.TOP_LEVEL_ROLE_NAMES = void 0; +const crypto_1 = __importDefault(require("crypto")); +const minimatch_1 = require("minimatch"); +const util_1 = __importDefault(require("util")); +const error_1 = require("./error"); +const utils_1 = require("./utils"); +exports.TOP_LEVEL_ROLE_NAMES = [ + 'root', + 'targets', + 'snapshot', + 'timestamp', +]; +/** + * Container that defines which keys are required to sign roles metadata. + * + * Role defines how many keys are required to successfully sign the roles + * metadata, and which keys are accepted. + */ +class Role { + constructor(options) { + const { keyIDs, threshold, unrecognizedFields } = options; + if (hasDuplicates(keyIDs)) { + throw new error_1.ValueError('duplicate key IDs found'); + } + if (threshold < 1) { + throw new error_1.ValueError('threshold must be at least 1'); + } + this.keyIDs = keyIDs; + this.threshold = threshold; + this.unrecognizedFields = unrecognizedFields || {}; + } + equals(other) { + if (!(other instanceof Role)) { + return false; + } + return (this.threshold === other.threshold && + util_1.default.isDeepStrictEqual(this.keyIDs, other.keyIDs) && + util_1.default.isDeepStrictEqual(this.unrecognizedFields, other.unrecognizedFields)); + } + toJSON() { + return { + keyids: this.keyIDs, + threshold: this.threshold, + ...this.unrecognizedFields, + }; + } + static fromJSON(data) { + const { keyids, threshold, ...rest } = data; + if (!utils_1.guard.isStringArray(keyids)) { + throw new TypeError('keyids must be an array'); + } + if (typeof threshold !== 'number') { + throw new TypeError('threshold must be a number'); + } + return new Role({ + keyIDs: keyids, + threshold, + unrecognizedFields: rest, + }); + } +} +exports.Role = Role; +function hasDuplicates(array) { + return new Set(array).size !== array.length; +} +/** + * A container with information about a delegated role. + * + * A delegation can happen in two ways: + * - ``paths`` is set: delegates targets matching any path pattern in ``paths`` + * - ``pathHashPrefixes`` is set: delegates targets whose target path hash + * starts with any of the prefixes in ``pathHashPrefixes`` + * + * ``paths`` and ``pathHashPrefixes`` are mutually exclusive: both cannot be + * set, at least one of them must be set. + */ +class DelegatedRole extends Role { + constructor(opts) { + super(opts); + const { name, terminating, paths, pathHashPrefixes } = opts; + this.name = name; + this.terminating = terminating; + if (opts.paths && opts.pathHashPrefixes) { + throw new error_1.ValueError('paths and pathHashPrefixes are mutually exclusive'); + } + this.paths = paths; + this.pathHashPrefixes = pathHashPrefixes; + } + equals(other) { + if (!(other instanceof DelegatedRole)) { + return false; + } + return (super.equals(other) && + this.name === other.name && + this.terminating === other.terminating && + util_1.default.isDeepStrictEqual(this.paths, other.paths) && + util_1.default.isDeepStrictEqual(this.pathHashPrefixes, other.pathHashPrefixes)); + } + isDelegatedPath(targetFilepath) { + if (this.paths) { + return this.paths.some((pathPattern) => isTargetInPathPattern(targetFilepath, pathPattern)); + } + if (this.pathHashPrefixes) { + const hasher = crypto_1.default.createHash('sha256'); + const pathHash = hasher.update(targetFilepath).digest('hex'); + return this.pathHashPrefixes.some((pathHashPrefix) => pathHash.startsWith(pathHashPrefix)); + } + return false; + } + toJSON() { + const json = { + ...super.toJSON(), + name: this.name, + terminating: this.terminating, + }; + if (this.paths) { + json.paths = this.paths; + } + if (this.pathHashPrefixes) { + json.path_hash_prefixes = this.pathHashPrefixes; + } + return json; + } + static fromJSON(data) { + const { keyids, threshold, name, terminating, paths, path_hash_prefixes, ...rest } = data; + if (!utils_1.guard.isStringArray(keyids)) { + throw new TypeError('keyids must be an array of strings'); + } + if (typeof threshold !== 'number') { + throw new TypeError('threshold must be a number'); + } + if (typeof name !== 'string') { + throw new TypeError('name must be a string'); + } + if (typeof terminating !== 'boolean') { + throw new TypeError('terminating must be a boolean'); + } + if (utils_1.guard.isDefined(paths) && !utils_1.guard.isStringArray(paths)) { + throw new TypeError('paths must be an array of strings'); + } + if (utils_1.guard.isDefined(path_hash_prefixes) && + !utils_1.guard.isStringArray(path_hash_prefixes)) { + throw new TypeError('path_hash_prefixes must be an array of strings'); + } + return new DelegatedRole({ + keyIDs: keyids, + threshold, + name, + terminating, + paths, + pathHashPrefixes: path_hash_prefixes, + unrecognizedFields: rest, + }); + } +} +exports.DelegatedRole = DelegatedRole; +// JS version of Ruby's Array#zip +const zip = (a, b) => a.map((k, i) => [k, b[i]]); +function isTargetInPathPattern(target, pattern) { + const targetParts = target.split('/'); + const patternParts = pattern.split('/'); + if (patternParts.length != targetParts.length) { + return false; + } + return zip(targetParts, patternParts).every(([targetPart, patternPart]) => (0, minimatch_1.minimatch)(targetPart, patternPart)); +} +/** + * Succinctly defines a hash bin delegation graph. + * + * A ``SuccinctRoles`` object describes a delegation graph that covers all + * targets, distributing them uniformly over the delegated roles (i.e. bins) + * in the graph. + * + * The total number of bins is 2 to the power of the passed ``bit_length``. + * + * Bin names are the concatenation of the passed ``name_prefix`` and a + * zero-padded hex representation of the bin index separated by a hyphen. + * + * The passed ``keyids`` and ``threshold`` is used for each bin, and each bin + * is 'terminating'. + * + * For details: https://github.com/theupdateframework/taps/blob/master/tap15.md + */ +class SuccinctRoles extends Role { + constructor(opts) { + super(opts); + const { bitLength, namePrefix } = opts; + if (bitLength <= 0 || bitLength > 32) { + throw new error_1.ValueError('bitLength must be between 1 and 32'); + } + this.bitLength = bitLength; + this.namePrefix = namePrefix; + // Calculate the suffix_len value based on the total number of bins in + // hex. If bit_length = 10 then number_of_bins = 1024 or bin names will + // have a suffix between "000" and "3ff" in hex and suffix_len will be 3 + // meaning the third bin will have a suffix of "003". + this.numberOfBins = Math.pow(2, bitLength); + // suffix_len is calculated based on "number_of_bins - 1" as the name + // of the last bin contains the number "number_of_bins -1" as a suffix. + this.suffixLen = (this.numberOfBins - 1).toString(16).length; + } + equals(other) { + if (!(other instanceof SuccinctRoles)) { + return false; + } + return (super.equals(other) && + this.bitLength === other.bitLength && + this.namePrefix === other.namePrefix); + } + /*** + * Calculates the name of the delegated role responsible for 'target_filepath'. + * + * The target at path ''target_filepath' is assigned to a bin by casting + * the left-most 'bit_length' of bits of the file path hash digest to + * int, using it as bin index between 0 and '2**bit_length - 1'. + * + * Args: + * target_filepath: URL path to a target file, relative to a base + * targets URL. + */ + getRoleForTarget(targetFilepath) { + const hasher = crypto_1.default.createHash('sha256'); + const hasherBuffer = hasher.update(targetFilepath).digest(); + // can't ever need more than 4 bytes (32 bits). + const hashBytes = hasherBuffer.subarray(0, 4); + // Right shift hash bytes, so that we only have the leftmost + // bit_length bits that we care about. + const shiftValue = 32 - this.bitLength; + const binNumber = hashBytes.readUInt32BE() >>> shiftValue; + // Add zero padding if necessary and cast to hex the suffix. + const suffix = binNumber.toString(16).padStart(this.suffixLen, '0'); + return `${this.namePrefix}-${suffix}`; + } + *getRoles() { + for (let i = 0; i < this.numberOfBins; i++) { + const suffix = i.toString(16).padStart(this.suffixLen, '0'); + yield `${this.namePrefix}-${suffix}`; + } + } + /*** + * Determines whether the given ``role_name`` is in one of + * the delegated roles that ``SuccinctRoles`` represents. + * + * Args: + * role_name: The name of the role to check against. + */ + isDelegatedRole(roleName) { + const desiredPrefix = this.namePrefix + '-'; + if (!roleName.startsWith(desiredPrefix)) { + return false; + } + const suffix = roleName.slice(desiredPrefix.length, roleName.length); + if (suffix.length != this.suffixLen) { + return false; + } + // make sure the suffix is a hex string + if (!suffix.match(/^[0-9a-fA-F]+$/)) { + return false; + } + const num = parseInt(suffix, 16); + return 0 <= num && num < this.numberOfBins; + } + toJSON() { + const json = { + ...super.toJSON(), + bit_length: this.bitLength, + name_prefix: this.namePrefix, + }; + return json; + } + static fromJSON(data) { + const { keyids, threshold, bit_length, name_prefix, ...rest } = data; + if (!utils_1.guard.isStringArray(keyids)) { + throw new TypeError('keyids must be an array of strings'); + } + if (typeof threshold !== 'number') { + throw new TypeError('threshold must be a number'); + } + if (typeof bit_length !== 'number') { + throw new TypeError('bit_length must be a number'); + } + if (typeof name_prefix !== 'string') { + throw new TypeError('name_prefix must be a string'); + } + return new SuccinctRoles({ + keyIDs: keyids, + threshold, + bitLength: bit_length, + namePrefix: name_prefix, + unrecognizedFields: rest, + }); + } +} +exports.SuccinctRoles = SuccinctRoles; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/root.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/root.js new file mode 100644 index 0000000000000..36d0ef0f186d1 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/root.js @@ -0,0 +1,116 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Root = void 0; +const util_1 = __importDefault(require("util")); +const base_1 = require("./base"); +const error_1 = require("./error"); +const key_1 = require("./key"); +const role_1 = require("./role"); +const utils_1 = require("./utils"); +/** + * A container for the signed part of root metadata. + * + * The top-level role and metadata file signed by the root keys. + * This role specifies trusted keys for all other top-level roles, which may further delegate trust. + */ +class Root extends base_1.Signed { + constructor(options) { + super(options); + this.type = base_1.MetadataKind.Root; + this.keys = options.keys || {}; + this.consistentSnapshot = options.consistentSnapshot ?? true; + if (!options.roles) { + this.roles = role_1.TOP_LEVEL_ROLE_NAMES.reduce((acc, role) => ({ + ...acc, + [role]: new role_1.Role({ keyIDs: [], threshold: 1 }), + }), {}); + } + else { + const roleNames = new Set(Object.keys(options.roles)); + if (!role_1.TOP_LEVEL_ROLE_NAMES.every((role) => roleNames.has(role))) { + throw new error_1.ValueError('missing top-level role'); + } + this.roles = options.roles; + } + } + addKey(key, role) { + if (!this.roles[role]) { + throw new error_1.ValueError(`role ${role} does not exist`); + } + if (!this.roles[role].keyIDs.includes(key.keyID)) { + this.roles[role].keyIDs.push(key.keyID); + } + this.keys[key.keyID] = key; + } + equals(other) { + if (!(other instanceof Root)) { + return false; + } + return (super.equals(other) && + this.consistentSnapshot === other.consistentSnapshot && + util_1.default.isDeepStrictEqual(this.keys, other.keys) && + util_1.default.isDeepStrictEqual(this.roles, other.roles)); + } + toJSON() { + return { + _type: this.type, + spec_version: this.specVersion, + version: this.version, + expires: this.expires, + keys: keysToJSON(this.keys), + roles: rolesToJSON(this.roles), + consistent_snapshot: this.consistentSnapshot, + ...this.unrecognizedFields, + }; + } + static fromJSON(data) { + const { unrecognizedFields, ...commonFields } = base_1.Signed.commonFieldsFromJSON(data); + const { keys, roles, consistent_snapshot, ...rest } = unrecognizedFields; + if (typeof consistent_snapshot !== 'boolean') { + throw new TypeError('consistent_snapshot must be a boolean'); + } + return new Root({ + ...commonFields, + keys: keysFromJSON(keys), + roles: rolesFromJSON(roles), + consistentSnapshot: consistent_snapshot, + unrecognizedFields: rest, + }); + } +} +exports.Root = Root; +function keysToJSON(keys) { + return Object.entries(keys).reduce((acc, [keyID, key]) => ({ ...acc, [keyID]: key.toJSON() }), {}); +} +function rolesToJSON(roles) { + return Object.entries(roles).reduce((acc, [roleName, role]) => ({ ...acc, [roleName]: role.toJSON() }), {}); +} +function keysFromJSON(data) { + let keys; + if (utils_1.guard.isDefined(data)) { + if (!utils_1.guard.isObjectRecord(data)) { + throw new TypeError('keys must be an object'); + } + keys = Object.entries(data).reduce((acc, [keyID, keyData]) => ({ + ...acc, + [keyID]: key_1.Key.fromJSON(keyID, keyData), + }), {}); + } + return keys; +} +function rolesFromJSON(data) { + let roles; + if (utils_1.guard.isDefined(data)) { + if (!utils_1.guard.isObjectRecord(data)) { + throw new TypeError('roles must be an object'); + } + roles = Object.entries(data).reduce((acc, [roleName, roleData]) => ({ + ...acc, + [roleName]: role_1.Role.fromJSON(roleData), + }), {}); + } + return roles; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/signature.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/signature.js new file mode 100644 index 0000000000000..33eb204eb0835 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/signature.js @@ -0,0 +1,38 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Signature = void 0; +/** + * A container class containing information about a signature. + * + * Contains a signature and the keyid uniquely identifying the key used + * to generate the signature. + * + * Provide a `fromJSON` method to create a Signature from a JSON object. + */ +class Signature { + constructor(options) { + const { keyID, sig } = options; + this.keyID = keyID; + this.sig = sig; + } + toJSON() { + return { + keyid: this.keyID, + sig: this.sig, + }; + } + static fromJSON(data) { + const { keyid, sig } = data; + if (typeof keyid !== 'string') { + throw new TypeError('keyid must be a string'); + } + if (typeof sig !== 'string') { + throw new TypeError('sig must be a string'); + } + return new Signature({ + keyID: keyid, + sig: sig, + }); + } +} +exports.Signature = Signature; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/snapshot.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/snapshot.js new file mode 100644 index 0000000000000..e90ea8e729e4e --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/snapshot.js @@ -0,0 +1,71 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Snapshot = void 0; +const util_1 = __importDefault(require("util")); +const base_1 = require("./base"); +const file_1 = require("./file"); +const utils_1 = require("./utils"); +/** + * A container for the signed part of snapshot metadata. + * + * Snapshot contains information about all target Metadata files. + * A top-level role that specifies the latest versions of all targets metadata files, + * and hence the latest versions of all targets (including any dependencies between them) on the repository. + */ +class Snapshot extends base_1.Signed { + constructor(opts) { + super(opts); + this.type = base_1.MetadataKind.Snapshot; + this.meta = opts.meta || { 'targets.json': new file_1.MetaFile({ version: 1 }) }; + } + equals(other) { + if (!(other instanceof Snapshot)) { + return false; + } + return super.equals(other) && util_1.default.isDeepStrictEqual(this.meta, other.meta); + } + toJSON() { + return { + _type: this.type, + meta: metaToJSON(this.meta), + spec_version: this.specVersion, + version: this.version, + expires: this.expires, + ...this.unrecognizedFields, + }; + } + static fromJSON(data) { + const { unrecognizedFields, ...commonFields } = base_1.Signed.commonFieldsFromJSON(data); + const { meta, ...rest } = unrecognizedFields; + return new Snapshot({ + ...commonFields, + meta: metaFromJSON(meta), + unrecognizedFields: rest, + }); + } +} +exports.Snapshot = Snapshot; +function metaToJSON(meta) { + return Object.entries(meta).reduce((acc, [path, metadata]) => ({ + ...acc, + [path]: metadata.toJSON(), + }), {}); +} +function metaFromJSON(data) { + let meta; + if (utils_1.guard.isDefined(data)) { + if (!utils_1.guard.isObjectRecord(data)) { + throw new TypeError('meta field is malformed'); + } + else { + meta = Object.entries(data).reduce((acc, [path, metadata]) => ({ + ...acc, + [path]: file_1.MetaFile.fromJSON(metadata), + }), {}); + } + } + return meta; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/targets.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/targets.js new file mode 100644 index 0000000000000..54bd8f8c554af --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/targets.js @@ -0,0 +1,92 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Targets = void 0; +const util_1 = __importDefault(require("util")); +const base_1 = require("./base"); +const delegations_1 = require("./delegations"); +const file_1 = require("./file"); +const utils_1 = require("./utils"); +// Container for the signed part of targets metadata. +// +// Targets contains verifying information about target files and also delegates +// responsible to other Targets roles. +class Targets extends base_1.Signed { + constructor(options) { + super(options); + this.type = base_1.MetadataKind.Targets; + this.targets = options.targets || {}; + this.delegations = options.delegations; + } + addTarget(target) { + this.targets[target.path] = target; + } + equals(other) { + if (!(other instanceof Targets)) { + return false; + } + return (super.equals(other) && + util_1.default.isDeepStrictEqual(this.targets, other.targets) && + util_1.default.isDeepStrictEqual(this.delegations, other.delegations)); + } + toJSON() { + const json = { + _type: this.type, + spec_version: this.specVersion, + version: this.version, + expires: this.expires, + targets: targetsToJSON(this.targets), + ...this.unrecognizedFields, + }; + if (this.delegations) { + json.delegations = this.delegations.toJSON(); + } + return json; + } + static fromJSON(data) { + const { unrecognizedFields, ...commonFields } = base_1.Signed.commonFieldsFromJSON(data); + const { targets, delegations, ...rest } = unrecognizedFields; + return new Targets({ + ...commonFields, + targets: targetsFromJSON(targets), + delegations: delegationsFromJSON(delegations), + unrecognizedFields: rest, + }); + } +} +exports.Targets = Targets; +function targetsToJSON(targets) { + return Object.entries(targets).reduce((acc, [path, target]) => ({ + ...acc, + [path]: target.toJSON(), + }), {}); +} +function targetsFromJSON(data) { + let targets; + if (utils_1.guard.isDefined(data)) { + if (!utils_1.guard.isObjectRecord(data)) { + throw new TypeError('targets must be an object'); + } + else { + targets = Object.entries(data).reduce((acc, [path, target]) => ({ + ...acc, + [path]: file_1.TargetFile.fromJSON(path, target), + }), {}); + } + } + return targets; +} +function delegationsFromJSON(data) { + let delegations; + if (utils_1.guard.isDefined(data)) { + if (!utils_1.guard.isObject(data)) { + throw new TypeError('delegations must be an object'); + } + else { + delegations = delegations_1.Delegations.fromJSON(data); + } + } + return delegations; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/timestamp.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/timestamp.js new file mode 100644 index 0000000000000..9880c4c9fc254 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/timestamp.js @@ -0,0 +1,58 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Timestamp = void 0; +const base_1 = require("./base"); +const file_1 = require("./file"); +const utils_1 = require("./utils"); +/** + * A container for the signed part of timestamp metadata. + * + * A top-level that specifies the latest version of the snapshot role metadata file, + * and hence the latest versions of all metadata and targets on the repository. + */ +class Timestamp extends base_1.Signed { + constructor(options) { + super(options); + this.type = base_1.MetadataKind.Timestamp; + this.snapshotMeta = options.snapshotMeta || new file_1.MetaFile({ version: 1 }); + } + equals(other) { + if (!(other instanceof Timestamp)) { + return false; + } + return super.equals(other) && this.snapshotMeta.equals(other.snapshotMeta); + } + toJSON() { + return { + _type: this.type, + spec_version: this.specVersion, + version: this.version, + expires: this.expires, + meta: { 'snapshot.json': this.snapshotMeta.toJSON() }, + ...this.unrecognizedFields, + }; + } + static fromJSON(data) { + const { unrecognizedFields, ...commonFields } = base_1.Signed.commonFieldsFromJSON(data); + const { meta, ...rest } = unrecognizedFields; + return new Timestamp({ + ...commonFields, + snapshotMeta: snapshotMetaFromJSON(meta), + unrecognizedFields: rest, + }); + } +} +exports.Timestamp = Timestamp; +function snapshotMetaFromJSON(data) { + let snapshotMeta; + if (utils_1.guard.isDefined(data)) { + const snapshotData = data['snapshot.json']; + if (!utils_1.guard.isDefined(snapshotData) || !utils_1.guard.isObject(snapshotData)) { + throw new TypeError('missing snapshot.json in meta'); + } + else { + snapshotMeta = file_1.MetaFile.fromJSON(snapshotData); + } + } + return snapshotMeta; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/utils/guard.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/utils/guard.js new file mode 100644 index 0000000000000..911e8475986bb --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/utils/guard.js @@ -0,0 +1,32 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isDefined = isDefined; +exports.isObject = isObject; +exports.isStringArray = isStringArray; +exports.isObjectArray = isObjectArray; +exports.isStringRecord = isStringRecord; +exports.isObjectRecord = isObjectRecord; +function isDefined(val) { + return val !== undefined; +} +function isObject(value) { + return typeof value === 'object' && value !== null; +} +function isStringArray(value) { + return Array.isArray(value) && value.every((v) => typeof v === 'string'); +} +function isObjectArray(value) { + return Array.isArray(value) && value.every(isObject); +} +function isStringRecord(value) { + return (typeof value === 'object' && + value !== null && + Object.keys(value).every((k) => typeof k === 'string') && + Object.values(value).every((v) => typeof v === 'string')); +} +function isObjectRecord(value) { + return (typeof value === 'object' && + value !== null && + Object.keys(value).every((k) => typeof k === 'string') && + Object.values(value).every((v) => typeof v === 'object' && v !== null)); +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/utils/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/utils/index.js new file mode 100644 index 0000000000000..872aae28049c9 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/utils/index.js @@ -0,0 +1,28 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.crypto = exports.guard = void 0; +exports.guard = __importStar(require("./guard")); +exports.crypto = __importStar(require("./verify")); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/utils/key.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/utils/key.js new file mode 100644 index 0000000000000..3c3ec07f1425a --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/utils/key.js @@ -0,0 +1,142 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getPublicKey = getPublicKey; +const crypto_1 = __importDefault(require("crypto")); +const error_1 = require("../error"); +const oid_1 = require("./oid"); +const ASN1_TAG_SEQUENCE = 0x30; +const ANS1_TAG_BIT_STRING = 0x03; +const NULL_BYTE = 0x00; +const OID_EDDSA = '1.3.101.112'; +const OID_EC_PUBLIC_KEY = '1.2.840.10045.2.1'; +const OID_EC_CURVE_P256V1 = '1.2.840.10045.3.1.7'; +const PEM_HEADER = '-----BEGIN PUBLIC KEY-----'; +function getPublicKey(keyInfo) { + switch (keyInfo.keyType) { + case 'rsa': + return getRSAPublicKey(keyInfo); + case 'ed25519': + return getED25519PublicKey(keyInfo); + case 'ecdsa': + case 'ecdsa-sha2-nistp256': + case 'ecdsa-sha2-nistp384': + return getECDCSAPublicKey(keyInfo); + default: + throw new error_1.UnsupportedAlgorithmError(`Unsupported key type: ${keyInfo.keyType}`); + } +} +function getRSAPublicKey(keyInfo) { + // Only support PEM-encoded RSA keys + if (!keyInfo.keyVal.startsWith(PEM_HEADER)) { + throw new error_1.CryptoError('Invalid key format'); + } + const key = crypto_1.default.createPublicKey(keyInfo.keyVal); + switch (keyInfo.scheme) { + case 'rsassa-pss-sha256': + return { + key: key, + padding: crypto_1.default.constants.RSA_PKCS1_PSS_PADDING, + }; + default: + throw new error_1.UnsupportedAlgorithmError(`Unsupported RSA scheme: ${keyInfo.scheme}`); + } +} +function getED25519PublicKey(keyInfo) { + let key; + // If key is already PEM-encoded we can just parse it + if (keyInfo.keyVal.startsWith(PEM_HEADER)) { + key = crypto_1.default.createPublicKey(keyInfo.keyVal); + } + else { + // If key is not PEM-encoded it had better be hex + if (!isHex(keyInfo.keyVal)) { + throw new error_1.CryptoError('Invalid key format'); + } + key = crypto_1.default.createPublicKey({ + key: ed25519.hexToDER(keyInfo.keyVal), + format: 'der', + type: 'spki', + }); + } + return { key }; +} +function getECDCSAPublicKey(keyInfo) { + let key; + // If key is already PEM-encoded we can just parse it + if (keyInfo.keyVal.startsWith(PEM_HEADER)) { + key = crypto_1.default.createPublicKey(keyInfo.keyVal); + } + else { + // If key is not PEM-encoded it had better be hex + if (!isHex(keyInfo.keyVal)) { + throw new error_1.CryptoError('Invalid key format'); + } + key = crypto_1.default.createPublicKey({ + key: ecdsa.hexToDER(keyInfo.keyVal), + format: 'der', + type: 'spki', + }); + } + return { key }; +} +const ed25519 = { + // Translates a hex key into a crypto KeyObject + // https://keygen.sh/blog/how-to-use-hexadecimal-ed25519-keys-in-node/ + hexToDER: (hex) => { + const key = Buffer.from(hex, 'hex'); + const oid = (0, oid_1.encodeOIDString)(OID_EDDSA); + // Create a byte sequence containing the OID and key + const elements = Buffer.concat([ + Buffer.concat([ + Buffer.from([ASN1_TAG_SEQUENCE]), + Buffer.from([oid.length]), + oid, + ]), + Buffer.concat([ + Buffer.from([ANS1_TAG_BIT_STRING]), + Buffer.from([key.length + 1]), + Buffer.from([NULL_BYTE]), + key, + ]), + ]); + // Wrap up by creating a sequence of elements + const der = Buffer.concat([ + Buffer.from([ASN1_TAG_SEQUENCE]), + Buffer.from([elements.length]), + elements, + ]); + return der; + }, +}; +const ecdsa = { + hexToDER: (hex) => { + const key = Buffer.from(hex, 'hex'); + const bitString = Buffer.concat([ + Buffer.from([ANS1_TAG_BIT_STRING]), + Buffer.from([key.length + 1]), + Buffer.from([NULL_BYTE]), + key, + ]); + const oids = Buffer.concat([ + (0, oid_1.encodeOIDString)(OID_EC_PUBLIC_KEY), + (0, oid_1.encodeOIDString)(OID_EC_CURVE_P256V1), + ]); + const oidSequence = Buffer.concat([ + Buffer.from([ASN1_TAG_SEQUENCE]), + Buffer.from([oids.length]), + oids, + ]); + // Wrap up by creating a sequence of elements + const der = Buffer.concat([ + Buffer.from([ASN1_TAG_SEQUENCE]), + Buffer.from([oidSequence.length + bitString.length]), + oidSequence, + bitString, + ]); + return der; + }, +}; +const isHex = (key) => /^[0-9a-fA-F]+$/.test(key); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/utils/oid.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/utils/oid.js new file mode 100644 index 0000000000000..00b29c3030d1e --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/utils/oid.js @@ -0,0 +1,26 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.encodeOIDString = encodeOIDString; +const ANS1_TAG_OID = 0x06; +function encodeOIDString(oid) { + const parts = oid.split('.'); + // The first two subidentifiers are encoded into the first byte + const first = parseInt(parts[0], 10) * 40 + parseInt(parts[1], 10); + const rest = []; + parts.slice(2).forEach((part) => { + const bytes = encodeVariableLengthInteger(parseInt(part, 10)); + rest.push(...bytes); + }); + const der = Buffer.from([first, ...rest]); + return Buffer.from([ANS1_TAG_OID, der.length, ...der]); +} +function encodeVariableLengthInteger(value) { + const bytes = []; + let mask = 0x00; + while (value > 0) { + bytes.unshift((value & 0x7f) | mask); + value >>= 7; + mask = 0x80; + } + return bytes; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/utils/types.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/utils/types.js new file mode 100644 index 0000000000000..c8ad2e549bdc6 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/utils/types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/utils/verify.js b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/utils/verify.js new file mode 100644 index 0000000000000..8232b6f6a97ab --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/dist/utils/verify.js @@ -0,0 +1,13 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifySignature = void 0; +const canonical_json_1 = require("@tufjs/canonical-json"); +const crypto_1 = __importDefault(require("crypto")); +const verifySignature = (metaDataSignedData, key, signature) => { + const canonicalData = Buffer.from((0, canonical_json_1.canonicalize)(metaDataSignedData)); + return crypto_1.default.verify(undefined, canonicalData, key, Buffer.from(signature, 'hex')); +}; +exports.verifySignature = verifySignature; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/package.json b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/package.json new file mode 100644 index 0000000000000..8e5132ddf1079 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models/package.json @@ -0,0 +1,37 @@ +{ + "name": "@tufjs/models", + "version": "3.0.1", + "description": "TUF metadata models", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "tsc --build", + "clean": "rm -rf dist && rm tsconfig.tsbuildinfo", + "test": "jest" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/theupdateframework/tuf-js.git" + }, + "keywords": [ + "tuf", + "security", + "update" + ], + "author": "bdehamer@github.com", + "license": "MIT", + "bugs": { + "url": "https://github.com/theupdateframework/tuf-js/issues" + }, + "homepage": "https://github.com/theupdateframework/tuf-js/tree/main/packages/models#readme", + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.5" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/LICENSE b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/LICENSE new file mode 100644 index 0000000000000..a03cd0ed0b338 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter, Kat Marchán, npm, Inc., and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/bin/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/bin/index.js new file mode 100755 index 0000000000000..f35b62ca71a53 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/bin/index.js @@ -0,0 +1,158 @@ +#!/usr/bin/env node + +const run = conf => { + const pacote = require('../') + switch (conf._[0]) { + case 'resolve': + case 'manifest': + case 'packument': + if (conf._[0] === 'resolve' && conf.long) { + return pacote.manifest(conf._[1], conf).then(mani => ({ + resolved: mani._resolved, + integrity: mani._integrity, + from: mani._from, + })) + } + return pacote[conf._[0]](conf._[1], conf) + + case 'tarball': + if (!conf._[2] || conf._[2] === '-') { + return pacote.tarball.stream(conf._[1], stream => { + stream.pipe( + conf.testStdout || + /* istanbul ignore next */ + process.stdout + ) + // make sure it resolves something falsey + return stream.promise().then(() => { + return false + }) + }, conf) + } else { + return pacote.tarball.file(conf._[1], conf._[2], conf) + } + + case 'extract': + return pacote.extract(conf._[1], conf._[2], conf) + + default: /* istanbul ignore next */ { + throw new Error(`bad command: ${conf._[0]}`) + } + } +} + +const version = require('../package.json').version +const usage = () => +`Pacote - The JavaScript Package Handler, v${version} + +Usage: + + pacote resolve + Resolve a specifier and output the fully resolved target + Returns integrity and from if '--long' flag is set. + + pacote manifest + Fetch a manifest and print to stdout + + pacote packument + Fetch a full packument and print to stdout + + pacote tarball [] + Fetch a package tarball and save to + If is missing or '-', the tarball will be streamed to stdout. + + pacote extract + Extract a package to the destination folder. + +Configuration values all match the names of configs passed to npm, or +options passed to Pacote. Additional flags for this executable: + + --long Print an object from 'resolve', including integrity and spec. + --json Print result objects as JSON rather than node's default. + (This is the default if stdout is not a TTY.) + --help -h Print this helpful text. + +For example '--cache=/path/to/folder' will use that folder as the cache. +` + +const shouldJSON = (conf, result) => + conf.json || + !process.stdout.isTTY && + conf.json === undefined && + result && + typeof result === 'object' + +const pretty = (conf, result) => + shouldJSON(conf, result) ? JSON.stringify(result, 0, 2) : result + +let addedLogListener = false +const main = args => { + const conf = parse(args) + if (conf.help || conf.h) { + return console.log(usage()) + } + + if (!addedLogListener) { + process.on('log', console.error) + addedLogListener = true + } + + try { + return run(conf) + .then(result => result && console.log(pretty(conf, result))) + .catch(er => { + console.error(er) + process.exit(1) + }) + } catch (er) { + console.error(er.message) + console.error(usage()) + } +} + +const parseArg = arg => { + const split = arg.slice(2).split('=') + const k = split.shift() + const v = split.join('=') + const no = /^no-/.test(k) && !v + const key = (no ? k.slice(3) : k) + .replace(/^tag$/, 'defaultTag') + .replace(/-([a-z])/g, (_, c) => c.toUpperCase()) + const value = v ? v.replace(/^~/, process.env.HOME) : !no + return { key, value } +} + +const parse = args => { + const conf = { + _: [], + cache: process.env.HOME + '/.npm/_cacache', + } + let dashdash = false + args.forEach(arg => { + if (dashdash) { + conf._.push(arg) + } else if (arg === '--') { + dashdash = true + } else if (arg === '-h') { + conf.help = true + } else if (/^--/.test(arg)) { + const { key, value } = parseArg(arg) + conf[key] = value + } else { + conf._.push(arg) + } + }) + return conf +} + +if (module === require.main) { + main(process.argv.slice(2)) +} else { + module.exports = { + main, + run, + usage, + parseArg, + parse, + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/dir.js b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/dir.js new file mode 100644 index 0000000000000..04846eb8a6e22 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/dir.js @@ -0,0 +1,105 @@ +const { resolve } = require('node:path') +const packlist = require('npm-packlist') +const runScript = require('@npmcli/run-script') +const tar = require('tar') +const { Minipass } = require('minipass') +const Fetcher = require('./fetcher.js') +const FileFetcher = require('./file.js') +const _ = require('./util/protected.js') +const tarCreateOptions = require('./util/tar-create-options.js') + +class DirFetcher extends Fetcher { + constructor (spec, opts) { + super(spec, opts) + // just the fully resolved filename + this.resolved = this.spec.fetchSpec + + this.tree = opts.tree || null + this.Arborist = opts.Arborist || null + } + + // exposes tarCreateOptions as public API + static tarCreateOptions (manifest) { + return tarCreateOptions(manifest) + } + + get types () { + return ['directory'] + } + + #prepareDir () { + return this.manifest().then(mani => { + if (!mani.scripts || !mani.scripts.prepare) { + return + } + if (this.opts.ignoreScripts) { + return + } + + // we *only* run prepare. + // pre/post-pack is run by the npm CLI for publish and pack, + // but this function is *also* run when installing git deps + const stdio = this.opts.foregroundScripts ? 'inherit' : 'pipe' + + return runScript({ + // this || undefined is because runScript will be unhappy with the default null value + scriptShell: this.opts.scriptShell || undefined, + pkg: mani, + event: 'prepare', + path: this.resolved, + stdio, + env: { + npm_package_resolved: this.resolved, + npm_package_integrity: this.integrity, + npm_package_json: resolve(this.resolved, 'package.json'), + }, + }) + }) + } + + [_.tarballFromResolved] () { + if (!this.tree && !this.Arborist) { + throw new Error('DirFetcher requires either a tree or an Arborist constructor to pack') + } + + const stream = new Minipass() + stream.resolved = this.resolved + stream.integrity = this.integrity + + const { prefix, workspaces } = this.opts + + // run the prepare script, get the list of files, and tar it up + // pipe to the stream, and proxy errors the chain. + this.#prepareDir() + .then(async () => { + if (!this.tree) { + const arb = new this.Arborist({ path: this.resolved }) + this.tree = await arb.loadActual() + } + return packlist(this.tree, { path: this.resolved, prefix, workspaces }) + }) + .then(files => tar.c(tarCreateOptions(this.package), files) + .on('error', er => stream.emit('error', er)).pipe(stream)) + .catch(er => stream.emit('error', er)) + return stream + } + + manifest () { + if (this.package) { + return Promise.resolve(this.package) + } + + return this[_.readPackageJson](this.resolved) + .then(mani => this.package = { + ...mani, + _integrity: this.integrity && String(this.integrity), + _resolved: this.resolved, + _from: this.from, + }) + } + + packument () { + return FileFetcher.prototype.packument.apply(this) + } +} +module.exports = DirFetcher diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/fetcher.js b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/fetcher.js new file mode 100644 index 0000000000000..f2ac97619d3af --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/fetcher.js @@ -0,0 +1,497 @@ +// This is the base class that the other fetcher types in lib +// all descend from. +// It handles the unpacking and retry logic that is shared among +// all of the other Fetcher types. + +const { basename, dirname } = require('node:path') +const { rm, mkdir } = require('node:fs/promises') +const PackageJson = require('@npmcli/package-json') +const cacache = require('cacache') +const fsm = require('fs-minipass') +const getContents = require('@npmcli/installed-package-contents') +const npa = require('npm-package-arg') +const retry = require('promise-retry') +const ssri = require('ssri') +const tar = require('tar') +const { Minipass } = require('minipass') +const { log } = require('proc-log') +const _ = require('./util/protected.js') +const cacheDir = require('./util/cache-dir.js') +const isPackageBin = require('./util/is-package-bin.js') +const removeTrailingSlashes = require('./util/trailing-slashes.js') + +// Pacote is only concerned with the package.json contents +const packageJsonPrepare = (p) => PackageJson.prepare(p).then(pkg => pkg.content) +const packageJsonNormalize = (p) => PackageJson.normalize(p).then(pkg => pkg.content) + +class FetcherBase { + constructor (spec, opts) { + if (!opts || typeof opts !== 'object') { + throw new TypeError('options object is required') + } + this.spec = npa(spec, opts.where) + + this.allowGitIgnore = !!opts.allowGitIgnore + + // a bit redundant because presumably the caller already knows this, + // but it makes it easier to not have to keep track of the requested + // spec when we're dispatching thousands of these at once, and normalizing + // is nice. saveSpec is preferred if set, because it turns stuff like + // x/y#committish into github:x/y#committish. use name@rawSpec for + // registry deps so that we turn xyz and xyz@ -> xyz@ + this.from = this.spec.registry + ? `${this.spec.name}@${this.spec.rawSpec}` : this.spec.saveSpec + + this.#assertType() + // clone the opts object so that others aren't upset when we mutate it + // by adding/modifying the integrity value. + this.opts = { ...opts } + + this.cache = opts.cache || cacheDir().cacache + this.tufCache = opts.tufCache || cacheDir().tufcache + this.resolved = opts.resolved || null + + // default to caching/verifying with sha512, that's what we usually have + // need to change this default, or start overriding it, when sha512 + // is no longer strong enough. + this.defaultIntegrityAlgorithm = opts.defaultIntegrityAlgorithm || 'sha512' + + if (typeof opts.integrity === 'string') { + this.opts.integrity = ssri.parse(opts.integrity) + } + + this.package = null + this.type = this.constructor.name + this.fmode = opts.fmode || 0o666 + this.dmode = opts.dmode || 0o777 + // we don't need a default umask, because we don't chmod files coming + // out of package tarballs. they're forced to have a mode that is + // valid, regardless of what's in the tarball entry, and then we let + // the process's umask setting do its job. but if configured, we do + // respect it. + this.umask = opts.umask || 0 + + this.preferOnline = !!opts.preferOnline + this.preferOffline = !!opts.preferOffline + this.offline = !!opts.offline + + this.before = opts.before + this.fullMetadata = this.before ? true : !!opts.fullMetadata + this.fullReadJson = !!opts.fullReadJson + this[_.readPackageJson] = this.fullReadJson + ? packageJsonPrepare + : packageJsonNormalize + + // rrh is a registry hostname or 'never' or 'always' + // defaults to registry.npmjs.org + this.replaceRegistryHost = (!opts.replaceRegistryHost || opts.replaceRegistryHost === 'npmjs') ? + 'registry.npmjs.org' : opts.replaceRegistryHost + + this.defaultTag = opts.defaultTag || 'latest' + this.registry = removeTrailingSlashes(opts.registry || 'https://registry.npmjs.org') + + // command to run 'prepare' scripts on directories and git dirs + // To use pacote with yarn, for example, set npmBin to 'yarn' + // and npmCliConfig with yarn's equivalents. + this.npmBin = opts.npmBin || 'npm' + + // command to install deps for preparing + this.npmInstallCmd = opts.npmInstallCmd || ['install', '--force'] + + // XXX fill more of this in based on what we know from this.opts + // we explicitly DO NOT fill in --tag, though, since we are often + // going to be packing in the context of a publish, which may set + // a dist-tag, but certainly wants to keep defaulting to latest. + this.npmCliConfig = opts.npmCliConfig || [ + `--cache=${dirname(this.cache)}`, + `--prefer-offline=${!!this.preferOffline}`, + `--prefer-online=${!!this.preferOnline}`, + `--offline=${!!this.offline}`, + ...(this.before ? [`--before=${this.before.toISOString()}`] : []), + '--no-progress', + '--no-save', + '--no-audit', + // override any omit settings from the environment + '--include=dev', + '--include=peer', + '--include=optional', + // we need the actual things, not just the lockfile + '--no-package-lock-only', + '--no-dry-run', + ] + } + + get integrity () { + return this.opts.integrity || null + } + + set integrity (i) { + if (!i) { + return + } + + i = ssri.parse(i) + const current = this.opts.integrity + + // do not ever update an existing hash value, but do + // merge in NEW algos and hashes that we don't already have. + if (current) { + current.merge(i) + } else { + this.opts.integrity = i + } + } + + get notImplementedError () { + return new Error('not implemented in this fetcher type: ' + this.type) + } + + // override in child classes + // Returns a Promise that resolves to this.resolved string value + resolve () { + return this.resolved ? Promise.resolve(this.resolved) + : Promise.reject(this.notImplementedError) + } + + packument () { + return Promise.reject(this.notImplementedError) + } + + // override in child class + // returns a manifest containing: + // - name + // - version + // - _resolved + // - _integrity + // - plus whatever else was in there (corgi, full metadata, or pj file) + manifest () { + return Promise.reject(this.notImplementedError) + } + + // private, should be overridden. + // Note that they should *not* calculate or check integrity or cache, + // but *just* return the raw tarball data stream. + [_.tarballFromResolved] () { + throw this.notImplementedError + } + + // public, should not be overridden + tarball () { + return this.tarballStream(stream => stream.concat().then(data => { + data.integrity = this.integrity && String(this.integrity) + data.resolved = this.resolved + data.from = this.from + return data + })) + } + + // private + // Note: cacache will raise a EINTEGRITY error if the integrity doesn't match + #tarballFromCache () { + const startTime = Date.now() + const stream = cacache.get.stream.byDigest(this.cache, this.integrity, this.opts) + const elapsedTime = Date.now() - startTime + // cache is good, so log it as a hit in particular since there was no fetch logged + log.http( + 'cache', + `${this.spec} ${elapsedTime}ms (cache hit)` + ) + return stream + } + + get [_.cacheFetches] () { + return true + } + + #istream (stream) { + // if not caching this, just return it + if (!this.opts.cache || !this[_.cacheFetches]) { + // instead of creating a new integrity stream, we only piggyback on the + // provided stream's events + if (stream.hasIntegrityEmitter) { + stream.on('integrity', i => this.integrity = i) + return stream + } + + const istream = ssri.integrityStream(this.opts) + istream.on('integrity', i => this.integrity = i) + stream.on('error', err => istream.emit('error', err)) + return stream.pipe(istream) + } + + // we have to return a stream that gets ALL the data, and proxies errors, + // but then pipe from the original tarball stream into the cache as well. + // To do this without losing any data, and since the cacache put stream + // is not a passthrough, we have to pipe from the original stream into + // the cache AFTER we pipe into the middleStream. Since the cache stream + // has an asynchronous flush to write its contents to disk, we need to + // defer the middleStream end until the cache stream ends. + const middleStream = new Minipass() + stream.on('error', err => middleStream.emit('error', err)) + stream.pipe(middleStream, { end: false }) + const cstream = cacache.put.stream( + this.opts.cache, + `pacote:tarball:${this.from}`, + this.opts + ) + cstream.on('integrity', i => this.integrity = i) + cstream.on('error', err => stream.emit('error', err)) + stream.pipe(cstream) + + // eslint-disable-next-line promise/catch-or-return + cstream.promise().catch(() => {}).then(() => middleStream.end()) + return middleStream + } + + pickIntegrityAlgorithm () { + return this.integrity ? this.integrity.pickAlgorithm(this.opts) + : this.defaultIntegrityAlgorithm + } + + // TODO: check error class, once those are rolled out to our deps + isDataCorruptionError (er) { + return er.code === 'EINTEGRITY' || er.code === 'Z_DATA_ERROR' + } + + // override the types getter + get types () { + return false + } + + #assertType () { + if (this.types && !this.types.includes(this.spec.type)) { + throw new TypeError(`Wrong spec type (${ + this.spec.type + }) for ${ + this.constructor.name + }. Supported types: ${this.types.join(', ')}`) + } + } + + // We allow ENOENTs from cacache, but not anywhere else. + // An ENOENT trying to read a tgz file, for example, is Right Out. + isRetriableError (er) { + // TODO: check error class, once those are rolled out to our deps + return this.isDataCorruptionError(er) || + er.code === 'ENOENT' || + er.code === 'EISDIR' + } + + // Mostly internal, but has some uses + // Pass in a function which returns a promise + // Function will be called 1 or more times with streams that may fail. + // Retries: + // Function MUST handle errors on the stream by rejecting the promise, + // so that retry logic can pick it up and either retry or fail whatever + // promise it was making (ie, failing extraction, etc.) + // + // The return value of this method is a Promise that resolves the same + // as whatever the streamHandler resolves to. + // + // This should never be overridden by child classes, but it is public. + tarballStream (streamHandler) { + // Only short-circuit via cache if we have everything else we'll need, + // and the user has not expressed a preference for checking online. + + const fromCache = ( + !this.preferOnline && + this.integrity && + this.resolved + ) ? streamHandler(this.#tarballFromCache()).catch(er => { + if (this.isDataCorruptionError(er)) { + log.warn('tarball', `cached data for ${ + this.spec + } (${this.integrity}) seems to be corrupted. Refreshing cache.`) + return this.cleanupCached().then(() => { + throw er + }) + } else { + throw er + } + }) : null + + const fromResolved = er => { + if (er) { + if (!this.isRetriableError(er)) { + throw er + } + log.silly('tarball', `no local data for ${ + this.spec + }. Extracting by manifest.`) + } + return this.resolve().then(() => retry(tryAgain => + streamHandler(this.#istream(this[_.tarballFromResolved]())) + .catch(streamErr => { + // Most likely data integrity. A cache ENOENT error is unlikely + // here, since we're definitely not reading from the cache, but it + // IS possible that the fetch subsystem accessed the cache, and the + // entry got blown away or something. Try one more time to be sure. + if (this.isRetriableError(streamErr)) { + log.warn('tarball', `tarball data for ${ + this.spec + } (${this.integrity}) seems to be corrupted. Trying again.`) + return this.cleanupCached().then(() => tryAgain(streamErr)) + } + throw streamErr + }), { retries: 1, minTimeout: 0, maxTimeout: 0 })) + } + + return fromCache ? fromCache.catch(fromResolved) : fromResolved() + } + + cleanupCached () { + return cacache.rm.content(this.cache, this.integrity, this.opts) + } + + #empty (path) { + return getContents({ path, depth: 1 }).then(contents => Promise.all( + contents.map(entry => rm(entry, { recursive: true, force: true })))) + } + + async #mkdir (dest) { + await this.#empty(dest) + return await mkdir(dest, { recursive: true }) + } + + // extraction is always the same. the only difference is where + // the tarball comes from. + async extract (dest) { + await this.#mkdir(dest) + return this.tarballStream((tarball) => this.#extract(dest, tarball)) + } + + #toFile (dest) { + return this.tarballStream(str => new Promise((res, rej) => { + const writer = new fsm.WriteStream(dest) + str.on('error', er => writer.emit('error', er)) + writer.on('error', er => rej(er)) + writer.on('close', () => res({ + integrity: this.integrity && String(this.integrity), + resolved: this.resolved, + from: this.from, + })) + str.pipe(writer) + })) + } + + // don't use this.#mkdir because we don't want to rimraf anything + async tarballFile (dest) { + const dir = dirname(dest) + await mkdir(dir, { recursive: true }) + return this.#toFile(dest) + } + + #extract (dest, tarball) { + const extractor = tar.x(this.#tarxOptions({ cwd: dest })) + const p = new Promise((resolve, reject) => { + extractor.on('end', () => { + resolve({ + resolved: this.resolved, + integrity: this.integrity && String(this.integrity), + from: this.from, + }) + }) + + extractor.on('error', er => { + log.warn('tar', er.message) + log.silly('tar', er) + reject(er) + }) + + tarball.on('error', er => reject(er)) + }) + + tarball.pipe(extractor) + return p + } + + // always ensure that entries are at least as permissive as our configured + // dmode/fmode, but never more permissive than the umask allows. + #entryMode (path, mode, type) { + const m = /Directory|GNUDumpDir/.test(type) ? this.dmode + : /File$/.test(type) ? this.fmode + : /* istanbul ignore next - should never happen in a pkg */ 0 + + // make sure package bins are executable + const exe = isPackageBin(this.package, path) ? 0o111 : 0 + // always ensure that files are read/writable by the owner + return ((mode | m) & ~this.umask) | exe | 0o600 + } + + #tarxOptions ({ cwd }) { + const sawIgnores = new Set() + return { + cwd, + noChmod: true, + noMtime: true, + filter: (name, entry) => { + if (/Link$/.test(entry.type)) { + return false + } + entry.mode = this.#entryMode(entry.path, entry.mode, entry.type) + // this replicates the npm pack behavior where .gitignore files + // are treated like .npmignore files, but only if a .npmignore + // file is not present. + if (/File$/.test(entry.type)) { + const base = basename(entry.path) + if (base === '.npmignore') { + sawIgnores.add(entry.path) + } else if (base === '.gitignore' && !this.allowGitIgnore) { + // rename, but only if there's not already a .npmignore + const ni = entry.path.replace(/\.gitignore$/, '.npmignore') + if (sawIgnores.has(ni)) { + return false + } + entry.path = ni + } + return true + } + }, + strip: 1, + onwarn: /* istanbul ignore next - we can trust that tar logs */ + (code, msg, data) => { + log.warn('tar', code, msg) + log.silly('tar', code, msg, data) + }, + umask: this.umask, + // always ignore ownership info from tarball metadata + preserveOwner: false, + } + } +} + +module.exports = FetcherBase + +// Child classes +const GitFetcher = require('./git.js') +const RegistryFetcher = require('./registry.js') +const FileFetcher = require('./file.js') +const DirFetcher = require('./dir.js') +const RemoteFetcher = require('./remote.js') + +// Get an appropriate fetcher object from a spec and options +FetcherBase.get = (rawSpec, opts = {}) => { + const spec = npa(rawSpec, opts.where) + switch (spec.type) { + case 'git': + return new GitFetcher(spec, opts) + + case 'remote': + return new RemoteFetcher(spec, opts) + + case 'version': + case 'range': + case 'tag': + case 'alias': + return new RegistryFetcher(spec.subSpec || spec, opts) + + case 'file': + return new FileFetcher(spec, opts) + + case 'directory': + return new DirFetcher(spec, opts) + + default: + throw new TypeError('Unknown spec type: ' + spec.type) + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/file.js b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/file.js new file mode 100644 index 0000000000000..2021325085e4f --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/file.js @@ -0,0 +1,94 @@ +const { resolve } = require('node:path') +const { stat, chmod } = require('node:fs/promises') +const cacache = require('cacache') +const fsm = require('fs-minipass') +const Fetcher = require('./fetcher.js') +const _ = require('./util/protected.js') + +class FileFetcher extends Fetcher { + constructor (spec, opts) { + super(spec, opts) + // just the fully resolved filename + this.resolved = this.spec.fetchSpec + } + + get types () { + return ['file'] + } + + manifest () { + if (this.package) { + return Promise.resolve(this.package) + } + + // have to unpack the tarball for this. + return cacache.tmp.withTmp(this.cache, this.opts, dir => + this.extract(dir) + .then(() => this[_.readPackageJson](dir)) + .then(mani => this.package = { + ...mani, + _integrity: this.integrity && String(this.integrity), + _resolved: this.resolved, + _from: this.from, + })) + } + + #exeBins (pkg, dest) { + if (!pkg.bin) { + return Promise.resolve() + } + + return Promise.all(Object.keys(pkg.bin).map(async k => { + const script = resolve(dest, pkg.bin[k]) + // Best effort. Ignore errors here, the only result is that + // a bin script is not executable. But if it's missing or + // something, we just leave it for a later stage to trip over + // when we can provide a more useful contextual error. + try { + const st = await stat(script) + const mode = st.mode | 0o111 + if (mode === st.mode) { + return + } + await chmod(script, mode) + } catch { + // Ignore errors here + } + })) + } + + extract (dest) { + // if we've already loaded the manifest, then the super got it. + // but if not, read the unpacked manifest and chmod properly. + return super.extract(dest) + .then(result => this.package ? result + : this[_.readPackageJson](dest).then(pkg => + this.#exeBins(pkg, dest)).then(() => result)) + } + + [_.tarballFromResolved] () { + // create a read stream and return it + return new fsm.ReadStream(this.resolved) + } + + packument () { + // simulate based on manifest + return this.manifest().then(mani => ({ + name: mani.name, + 'dist-tags': { + [this.defaultTag]: mani.version, + }, + versions: { + [mani.version]: { + ...mani, + dist: { + tarball: `file:${this.resolved}`, + integrity: this.integrity && String(this.integrity), + }, + }, + }, + })) + } +} + +module.exports = FileFetcher diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/git.js b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/git.js new file mode 100644 index 0000000000000..077193a86f026 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/git.js @@ -0,0 +1,317 @@ +const cacache = require('cacache') +const git = require('@npmcli/git') +const npa = require('npm-package-arg') +const pickManifest = require('npm-pick-manifest') +const { Minipass } = require('minipass') +const { log } = require('proc-log') +const DirFetcher = require('./dir.js') +const Fetcher = require('./fetcher.js') +const FileFetcher = require('./file.js') +const RemoteFetcher = require('./remote.js') +const _ = require('./util/protected.js') +const addGitSha = require('./util/add-git-sha.js') +const npm = require('./util/npm.js') + +const hashre = /^[a-f0-9]{40}$/ + +// get the repository url. +// prefer https if there's auth, since ssh will drop that. +// otherwise, prefer ssh if available (more secure). +// We have to add the git+ back because npa suppresses it. +const repoUrl = (h, opts) => + h.sshurl && !(h.https && h.auth) && addGitPlus(h.sshurl(opts)) || + h.https && addGitPlus(h.https(opts)) + +// add git+ to the url, but only one time. +const addGitPlus = url => url && `git+${url}`.replace(/^(git\+)+/, 'git+') + +class GitFetcher extends Fetcher { + constructor (spec, opts) { + super(spec, opts) + + // we never want to compare integrity for git dependencies: npm/rfcs#525 + if (this.opts.integrity) { + delete this.opts.integrity + log.warn(`skipping integrity check for git dependency ${this.spec.fetchSpec}`) + } + + this.resolvedRef = null + if (this.spec.hosted) { + this.from = this.spec.hosted.shortcut({ noCommittish: false }) + } + + // shortcut: avoid full clone when we can go straight to the tgz + // if we have the full sha and it's a hosted git platform + if (this.spec.gitCommittish && hashre.test(this.spec.gitCommittish)) { + this.resolvedSha = this.spec.gitCommittish + // use hosted.tarball() when we shell to RemoteFetcher later + this.resolved = this.spec.hosted + ? repoUrl(this.spec.hosted, { noCommittish: false }) + : this.spec.rawSpec + } else { + this.resolvedSha = '' + } + + this.Arborist = opts.Arborist || null + } + + // just exposed to make it easier to test all the combinations + static repoUrl (hosted, opts) { + return repoUrl(hosted, opts) + } + + get types () { + return ['git'] + } + + resolve () { + // likely a hosted git repo with a sha, so get the tarball url + // but in general, no reason to resolve() more than necessary! + if (this.resolved) { + return super.resolve() + } + + // fetch the git repo and then look at the current hash + const h = this.spec.hosted + // try to use ssh, fall back to git. + return h + ? this.#resolvedFromHosted(h) + : this.#resolvedFromRepo(this.spec.fetchSpec) + } + + // first try https, since that's faster and passphrase-less for + // public repos, and supports private repos when auth is provided. + // Fall back to SSH to support private repos + // NB: we always store the https url in resolved field if auth + // is present, otherwise ssh if the hosted type provides it + #resolvedFromHosted (hosted) { + return this.#resolvedFromRepo(hosted.https && hosted.https()).catch(er => { + // Throw early since we know pathspec errors will fail again if retried + if (er instanceof git.errors.GitPathspecError) { + throw er + } + const ssh = hosted.sshurl && hosted.sshurl() + // no fallthrough if we can't fall through or have https auth + if (!ssh || hosted.auth) { + throw er + } + return this.#resolvedFromRepo(ssh) + }) + } + + #resolvedFromRepo (gitRemote) { + // XXX make this a custom error class + if (!gitRemote) { + return Promise.reject(new Error(`No git url for ${this.spec}`)) + } + const gitRange = this.spec.gitRange + const name = this.spec.name + return git.revs(gitRemote, this.opts).then(remoteRefs => { + return gitRange ? pickManifest({ + versions: remoteRefs.versions, + 'dist-tags': remoteRefs['dist-tags'], + name, + }, gitRange, this.opts) + : this.spec.gitCommittish ? + remoteRefs.refs[this.spec.gitCommittish] || + remoteRefs.refs[remoteRefs.shas[this.spec.gitCommittish]] + : remoteRefs.refs.HEAD // no git committish, get default head + }).then(revDoc => { + // the committish provided isn't in the rev list + // things like HEAD~3 or @yesterday can land here. + if (!revDoc || !revDoc.sha) { + return this.#resolvedFromClone() + } + + this.resolvedRef = revDoc + this.resolvedSha = revDoc.sha + this.#addGitSha(revDoc.sha) + return this.resolved + }) + } + + #setResolvedWithSha (withSha) { + // we haven't cloned, so a tgz download is still faster + // of course, if it's not a known host, we can't do that. + this.resolved = !this.spec.hosted ? withSha + : repoUrl(npa(withSha).hosted, { noCommittish: false }) + } + + // when we get the git sha, we affix it to our spec to build up + // either a git url with a hash, or a tarball download URL + #addGitSha (sha) { + this.#setResolvedWithSha(addGitSha(this.spec, sha)) + } + + #resolvedFromClone () { + // do a full or shallow clone, then look at the HEAD + // kind of wasteful, but no other option, really + return this.#clone(() => this.resolved) + } + + #prepareDir (dir) { + return this[_.readPackageJson](dir).then(mani => { + // no need if we aren't going to do any preparation. + const scripts = mani.scripts + if (!mani.workspaces && (!scripts || !( + scripts.postinstall || + scripts.build || + scripts.preinstall || + scripts.install || + scripts.prepack || + scripts.prepare))) { + return + } + + // to avoid cases where we have an cycle of git deps that depend + // on one another, we only ever do preparation for one instance + // of a given git dep along the chain of installations. + // Note that this does mean that a dependency MAY in theory end up + // trying to run its prepare script using a dependency that has not + // been properly prepared itself, but that edge case is smaller + // and less hazardous than a fork bomb of npm and git commands. + const noPrepare = !process.env._PACOTE_NO_PREPARE_ ? [] + : process.env._PACOTE_NO_PREPARE_.split('\n') + if (noPrepare.includes(this.resolved)) { + log.info('prepare', 'skip prepare, already seen', this.resolved) + return + } + noPrepare.push(this.resolved) + + // the DirFetcher will do its own preparation to run the prepare scripts + // All we have to do is put the deps in place so that it can succeed. + return npm( + this.npmBin, + [].concat(this.npmInstallCmd).concat(this.npmCliConfig), + dir, + { ...process.env, _PACOTE_NO_PREPARE_: noPrepare.join('\n') }, + { message: 'git dep preparation failed' } + ) + }) + } + + [_.tarballFromResolved] () { + const stream = new Minipass() + stream.resolved = this.resolved + stream.from = this.from + + // check it out and then shell out to the DirFetcher tarball packer + this.#clone(dir => this.#prepareDir(dir) + .then(() => new Promise((res, rej) => { + if (!this.Arborist) { + throw new Error('GitFetcher requires an Arborist constructor to pack a tarball') + } + const df = new DirFetcher(`file:${dir}`, { + ...this.opts, + Arborist: this.Arborist, + resolved: null, + integrity: null, + }) + const dirStream = df[_.tarballFromResolved]() + dirStream.on('error', rej) + dirStream.on('end', res) + dirStream.pipe(stream) + }))).catch( + /* istanbul ignore next: very unlikely and hard to test */ + er => stream.emit('error', er) + ) + return stream + } + + // clone a git repo into a temp folder (or fetch and unpack if possible) + // handler accepts a directory, and returns a promise that resolves + // when we're done with it, at which point, cacache deletes it + // + // TODO: after cloning, create a tarball of the folder, and add to the cache + // with cacache.put.stream(), using a key that's deterministic based on the + // spec and repo, so that we don't ever clone the same thing multiple times. + #clone (handler, tarballOk = true) { + const o = { tmpPrefix: 'git-clone' } + const ref = this.resolvedSha || this.spec.gitCommittish + const h = this.spec.hosted + const resolved = this.resolved + + // can be set manually to false to fall back to actual git clone + tarballOk = tarballOk && + h && resolved === repoUrl(h, { noCommittish: false }) && h.tarball + + return cacache.tmp.withTmp(this.cache, o, async tmp => { + // if we're resolved, and have a tarball url, shell out to RemoteFetcher + if (tarballOk) { + const nameat = this.spec.name ? `${this.spec.name}@` : '' + return new RemoteFetcher(h.tarball({ noCommittish: false }), { + ...this.opts, + allowGitIgnore: true, + pkgid: `git:${nameat}${this.resolved}`, + resolved: this.resolved, + integrity: null, // it'll always be different, if we have one + }).extract(tmp).then(() => handler(tmp), er => { + // fall back to ssh download if tarball fails + if (er.constructor.name.match(/^Http/)) { + return this.#clone(handler, false) + } else { + throw er + } + }) + } + + const sha = await ( + h ? this.#cloneHosted(ref, tmp) + : this.#cloneRepo(this.spec.fetchSpec, ref, tmp) + ) + this.resolvedSha = sha + if (!this.resolved) { + await this.#addGitSha(sha) + } + return handler(tmp) + }) + } + + // first try https, since that's faster and passphrase-less for + // public repos, and supports private repos when auth is provided. + // Fall back to SSH to support private repos + // NB: we always store the https url in resolved field if auth + // is present, otherwise ssh if the hosted type provides it + #cloneHosted (ref, tmp) { + const hosted = this.spec.hosted + return this.#cloneRepo(hosted.https({ noCommittish: true }), ref, tmp) + .catch(er => { + // Throw early since we know pathspec errors will fail again if retried + if (er instanceof git.errors.GitPathspecError) { + throw er + } + const ssh = hosted.sshurl && hosted.sshurl({ noCommittish: true }) + // no fallthrough if we can't fall through or have https auth + if (!ssh || hosted.auth) { + throw er + } + return this.#cloneRepo(ssh, ref, tmp) + }) + } + + #cloneRepo (repo, ref, tmp) { + const { opts, spec } = this + return git.clone(repo, ref, tmp, { ...opts, spec }) + } + + manifest () { + if (this.package) { + return Promise.resolve(this.package) + } + + return this.spec.hosted && this.resolved + ? FileFetcher.prototype.manifest.apply(this) + : this.#clone(dir => + this[_.readPackageJson](dir) + .then(mani => this.package = { + ...mani, + _resolved: this.resolved, + _from: this.from, + })) + } + + packument () { + return FileFetcher.prototype.packument.apply(this) + } +} +module.exports = GitFetcher diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/index.js new file mode 100644 index 0000000000000..f35314d275d5f --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/index.js @@ -0,0 +1,23 @@ +const { get } = require('./fetcher.js') +const GitFetcher = require('./git.js') +const RegistryFetcher = require('./registry.js') +const FileFetcher = require('./file.js') +const DirFetcher = require('./dir.js') +const RemoteFetcher = require('./remote.js') + +const tarball = (spec, opts) => get(spec, opts).tarball() +tarball.stream = (spec, handler, opts) => get(spec, opts).tarballStream(handler) +tarball.file = (spec, dest, opts) => get(spec, opts).tarballFile(dest) + +module.exports = { + GitFetcher, + RegistryFetcher, + FileFetcher, + DirFetcher, + RemoteFetcher, + resolve: (spec, opts) => get(spec, opts).resolve(), + extract: (spec, dest, opts) => get(spec, opts).extract(dest), + manifest: (spec, opts) => get(spec, opts).manifest(), + packument: (spec, opts) => get(spec, opts).packument(), + tarball, +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/registry.js b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/registry.js new file mode 100644 index 0000000000000..1ecf4ee177349 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/registry.js @@ -0,0 +1,369 @@ +const crypto = require('node:crypto') +const PackageJson = require('@npmcli/package-json') +const pickManifest = require('npm-pick-manifest') +const ssri = require('ssri') +const npa = require('npm-package-arg') +const sigstore = require('sigstore') +const fetch = require('npm-registry-fetch') +const Fetcher = require('./fetcher.js') +const RemoteFetcher = require('./remote.js') +const pacoteVersion = require('../package.json').version +const removeTrailingSlashes = require('./util/trailing-slashes.js') +const _ = require('./util/protected.js') + +// Corgis are cute. 🐕🐶 +const corgiDoc = 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*' +const fullDoc = 'application/json' + +// Some really old packages have no time field in their packument so we need a +// cutoff date. +const MISSING_TIME_CUTOFF = '2015-01-01T00:00:00.000Z' + +class RegistryFetcher extends Fetcher { + #cacheKey + constructor (spec, opts) { + super(spec, opts) + + // you usually don't want to fetch the same packument multiple times in + // the span of a given script or command, no matter how many pacote calls + // are made, so this lets us avoid doing that. It's only relevant for + // registry fetchers, because other types simulate their packument from + // the manifest, which they memoize on this.package, so it's very cheap + // already. + this.packumentCache = this.opts.packumentCache || null + + this.registry = fetch.pickRegistry(spec, opts) + this.packumentUrl = `${removeTrailingSlashes(this.registry)}/${this.spec.escapedName}` + this.#cacheKey = `${this.fullMetadata ? 'full' : 'corgi'}:${this.packumentUrl}` + + const parsed = new URL(this.registry) + const regKey = `//${parsed.host}${parsed.pathname}` + // unlike the nerf-darted auth keys, this one does *not* allow a mismatch + // of trailing slashes. It must match exactly. + if (this.opts[`${regKey}:_keys`]) { + this.registryKeys = this.opts[`${regKey}:_keys`] + } + + // XXX pacote <=9 has some logic to ignore opts.resolved if + // the resolved URL doesn't go to the same registry. + // Consider reproducing that here, to throw away this.resolved + // in that case. + } + + async resolve () { + // fetching the manifest sets resolved and (if present) integrity + await this.manifest() + if (!this.resolved) { + throw Object.assign( + new Error('Invalid package manifest: no `dist.tarball` field'), + { package: this.spec.toString() } + ) + } + return this.resolved + } + + #headers () { + return { + // npm will override UA, but ensure that we always send *something* + 'user-agent': this.opts.userAgent || + `pacote/${pacoteVersion} node/${process.version}`, + ...(this.opts.headers || {}), + 'pacote-version': pacoteVersion, + 'pacote-req-type': 'packument', + 'pacote-pkg-id': `registry:${this.spec.name}`, + accept: this.fullMetadata ? fullDoc : corgiDoc, + } + } + + async packument () { + // note this might be either an in-flight promise for a request, + // or the actual packument, but we never want to make more than + // one request at a time for the same thing regardless. + if (this.packumentCache?.has(this.#cacheKey)) { + return this.packumentCache.get(this.#cacheKey) + } + + // npm-registry-fetch the packument + // set the appropriate header for corgis if fullMetadata isn't set + // return the res.json() promise + try { + const res = await fetch(this.packumentUrl, { + ...this.opts, + headers: this.#headers(), + spec: this.spec, + + // never check integrity for packuments themselves + integrity: null, + }) + const packument = await res.json() + const contentLength = res.headers.get('content-length') + if (contentLength) { + packument._contentLength = Number(contentLength) + } + this.packumentCache?.set(this.#cacheKey, packument) + return packument + } catch (err) { + this.packumentCache?.delete(this.#cacheKey) + if (err.code !== 'E404' || this.fullMetadata) { + throw err + } + // possible that corgis are not supported by this registry + this.fullMetadata = true + return this.packument() + } + } + + async manifest () { + if (this.package) { + return this.package + } + + // When verifying signatures, we need to fetch the full/uncompressed + // packument to get publish time as this is not included in the + // corgi/compressed packument. + if (this.opts.verifySignatures) { + this.fullMetadata = true + } + + const packument = await this.packument() + const steps = PackageJson.normalizeSteps.filter(s => s !== '_attributes') + const mani = await new PackageJson().fromContent(pickManifest(packument, this.spec.fetchSpec, { + ...this.opts, + defaultTag: this.defaultTag, + before: this.before, + })).normalize({ steps }).then(p => p.content) + + /* XXX add ETARGET and E403 revalidation of cached packuments here */ + + // add _time from packument if fetched with fullMetadata + const time = packument.time?.[mani.version] + if (time) { + mani._time = time + } + + // add _resolved and _integrity from dist object + const { dist } = mani + if (dist) { + this.resolved = mani._resolved = dist.tarball + mani._from = this.from + const distIntegrity = dist.integrity ? ssri.parse(dist.integrity) + : dist.shasum ? ssri.fromHex(dist.shasum, 'sha1', { ...this.opts }) + : null + if (distIntegrity) { + if (this.integrity && !this.integrity.match(distIntegrity)) { + // only bork if they have algos in common. + // otherwise we end up breaking if we have saved a sha512 + // previously for the tarball, but the manifest only + // provides a sha1, which is possible for older publishes. + // Otherwise, this is almost certainly a case of holding it + // wrong, and will result in weird or insecure behavior + // later on when building package tree. + for (const algo of Object.keys(this.integrity)) { + if (distIntegrity[algo]) { + throw Object.assign(new Error( + `Integrity checksum failed when using ${algo}: ` + + `wanted ${this.integrity} but got ${distIntegrity}.` + ), { code: 'EINTEGRITY' }) + } + } + } + // made it this far, the integrity is worthwhile. accept it. + // the setter here will take care of merging it into what we already + // had. + this.integrity = distIntegrity + } + } + if (this.integrity) { + mani._integrity = String(this.integrity) + if (dist.signatures) { + if (this.opts.verifySignatures) { + // validate and throw on error, then set _signatures + const message = `${mani._id}:${mani._integrity}` + for (const signature of dist.signatures) { + const publicKey = this.registryKeys && + this.registryKeys.filter(key => (key.keyid === signature.keyid))[0] + if (!publicKey) { + throw Object.assign(new Error( + `${mani._id} has a registry signature with keyid: ${signature.keyid} ` + + 'but no corresponding public key can be found' + ), { code: 'EMISSINGSIGNATUREKEY' }) + } + + const publishedTime = Date.parse(mani._time || MISSING_TIME_CUTOFF) + const validPublicKey = !publicKey.expires || + publishedTime < Date.parse(publicKey.expires) + if (!validPublicKey) { + throw Object.assign(new Error( + `${mani._id} has a registry signature with keyid: ${signature.keyid} ` + + `but the corresponding public key has expired ${publicKey.expires}` + ), { code: 'EEXPIREDSIGNATUREKEY' }) + } + const verifier = crypto.createVerify('SHA256') + verifier.write(message) + verifier.end() + const valid = verifier.verify( + publicKey.pemkey, + signature.sig, + 'base64' + ) + if (!valid) { + throw Object.assign(new Error( + `${mani._id} has an invalid registry signature with ` + + `keyid: ${publicKey.keyid} and signature: ${signature.sig}` + ), { + code: 'EINTEGRITYSIGNATURE', + keyid: publicKey.keyid, + signature: signature.sig, + resolved: mani._resolved, + integrity: mani._integrity, + }) + } + } + mani._signatures = dist.signatures + } else { + mani._signatures = dist.signatures + } + } + + if (dist.attestations) { + if (this.opts.verifyAttestations) { + // Always fetch attestations from the current registry host + const attestationsPath = new URL(dist.attestations.url).pathname + const attestationsUrl = removeTrailingSlashes(this.registry) + attestationsPath + const res = await fetch(attestationsUrl, { + ...this.opts, + // disable integrity check for attestations json payload, we check the + // integrity in the verification steps below + integrity: null, + }) + const { attestations } = await res.json() + const bundles = attestations.map(({ predicateType, bundle }) => { + const statement = JSON.parse( + Buffer.from(bundle.dsseEnvelope.payload, 'base64').toString('utf8') + ) + const keyid = bundle.dsseEnvelope.signatures[0].keyid + const signature = bundle.dsseEnvelope.signatures[0].sig + + return { + predicateType, + bundle, + statement, + keyid, + signature, + } + }) + + const attestationKeyIds = bundles.map((b) => b.keyid).filter((k) => !!k) + const attestationRegistryKeys = (this.registryKeys || []) + .filter(key => attestationKeyIds.includes(key.keyid)) + if (!attestationRegistryKeys.length) { + throw Object.assign(new Error( + `${mani._id} has attestations but no corresponding public key(s) can be found` + ), { code: 'EMISSINGSIGNATUREKEY' }) + } + + for (const { predicateType, bundle, keyid, signature, statement } of bundles) { + const publicKey = attestationRegistryKeys.find(key => key.keyid === keyid) + // Publish attestations have a keyid set and a valid public key must be found + if (keyid) { + if (!publicKey) { + throw Object.assign(new Error( + `${mani._id} has attestations with keyid: ${keyid} ` + + 'but no corresponding public key can be found' + ), { code: 'EMISSINGSIGNATUREKEY' }) + } + + const integratedTime = new Date( + Number( + bundle.verificationMaterial.tlogEntries[0].integratedTime + ) * 1000 + ) + const validPublicKey = !publicKey.expires || + (integratedTime < Date.parse(publicKey.expires)) + if (!validPublicKey) { + throw Object.assign(new Error( + `${mani._id} has attestations with keyid: ${keyid} ` + + `but the corresponding public key has expired ${publicKey.expires}` + ), { code: 'EEXPIREDSIGNATUREKEY' }) + } + } + + const subject = { + name: statement.subject[0].name, + sha512: statement.subject[0].digest.sha512, + } + + // Only type 'version' can be turned into a PURL + const purl = this.spec.type === 'version' ? npa.toPurl(this.spec) : this.spec + // Verify the statement subject matches the package, version + if (subject.name !== purl) { + throw Object.assign(new Error( + `${mani._id} package name and version (PURL): ${purl} ` + + `doesn't match what was signed: ${subject.name}` + ), { code: 'EATTESTATIONSUBJECT' }) + } + + // Verify the statement subject matches the tarball integrity + const integrityHexDigest = ssri.parse(this.integrity).hexDigest() + if (subject.sha512 !== integrityHexDigest) { + throw Object.assign(new Error( + `${mani._id} package integrity (hex digest): ` + + `${integrityHexDigest} ` + + `doesn't match what was signed: ${subject.sha512}` + ), { code: 'EATTESTATIONSUBJECT' }) + } + + try { + // Provenance attestations are signed with a signing certificate + // (including the key) so we don't need to return a public key. + // + // Publish attestations are signed with a keyid so we need to + // specify a public key from the keys endpoint: `registry-host.tld/-/npm/v1/keys` + const options = { + tufCachePath: this.tufCache, + tufForceCache: true, + keySelector: publicKey ? () => publicKey.pemkey : undefined, + } + await sigstore.verify(bundle, options) + } catch (e) { + throw Object.assign(new Error( + `${mani._id} failed to verify attestation: ${e.message}` + ), { + code: 'EATTESTATIONVERIFY', + predicateType, + keyid, + signature, + resolved: mani._resolved, + integrity: mani._integrity, + }) + } + } + mani._attestations = dist.attestations + } else { + mani._attestations = dist.attestations + } + } + } + + this.package = mani + return this.package + } + + [_.tarballFromResolved] () { + // we use a RemoteFetcher to get the actual tarball stream + return new RemoteFetcher(this.resolved, { + ...this.opts, + resolved: this.resolved, + pkgid: `registry:${this.spec.name}@${this.resolved}`, + })[_.tarballFromResolved]() + } + + get types () { + return [ + 'tag', + 'version', + 'range', + ] + } +} +module.exports = RegistryFetcher diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/remote.js b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/remote.js new file mode 100644 index 0000000000000..bd321e65a1f18 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/remote.js @@ -0,0 +1,89 @@ +const fetch = require('npm-registry-fetch') +const { Minipass } = require('minipass') +const Fetcher = require('./fetcher.js') +const FileFetcher = require('./file.js') +const _ = require('./util/protected.js') +const pacoteVersion = require('../package.json').version + +class RemoteFetcher extends Fetcher { + constructor (spec, opts) { + super(spec, opts) + this.resolved = this.spec.fetchSpec + const resolvedURL = new URL(this.resolved) + if (this.replaceRegistryHost !== 'never' + && (this.replaceRegistryHost === 'always' + || this.replaceRegistryHost === resolvedURL.host)) { + this.resolved = new URL(resolvedURL.pathname, this.registry).href + } + + // nam is a fermented pork sausage that is good to eat + const nameat = this.spec.name ? `${this.spec.name}@` : '' + this.pkgid = opts.pkgid ? opts.pkgid : `remote:${nameat}${this.resolved}` + } + + // Don't need to cache tarball fetches in pacote, because make-fetch-happen + // will write into cacache anyway. + get [_.cacheFetches] () { + return false + } + + [_.tarballFromResolved] () { + const stream = new Minipass() + stream.hasIntegrityEmitter = true + + const fetchOpts = { + ...this.opts, + headers: this.#headers(), + spec: this.spec, + integrity: this.integrity, + algorithms: [this.pickIntegrityAlgorithm()], + } + + // eslint-disable-next-line promise/always-return + fetch(this.resolved, fetchOpts).then(res => { + res.body.on('error', + /* istanbul ignore next - exceedingly rare and hard to simulate */ + er => stream.emit('error', er) + ) + + res.body.on('integrity', i => { + this.integrity = i + stream.emit('integrity', i) + }) + + res.body.pipe(stream) + }).catch(er => stream.emit('error', er)) + + return stream + } + + #headers () { + return { + // npm will override this, but ensure that we always send *something* + 'user-agent': this.opts.userAgent || + `pacote/${pacoteVersion} node/${process.version}`, + ...(this.opts.headers || {}), + 'pacote-version': pacoteVersion, + 'pacote-req-type': 'tarball', + 'pacote-pkg-id': this.pkgid, + ...(this.integrity ? { 'pacote-integrity': String(this.integrity) } + : {}), + ...(this.opts.headers || {}), + } + } + + get types () { + return ['remote'] + } + + // getting a packument and/or manifest is the same as with a file: spec. + // unpack the tarball stream, and then read from the package.json file. + packument () { + return FileFetcher.prototype.packument.apply(this) + } + + manifest () { + return FileFetcher.prototype.manifest.apply(this) + } +} +module.exports = RemoteFetcher diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/add-git-sha.js b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/add-git-sha.js new file mode 100644 index 0000000000000..843fe5b600caf --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/add-git-sha.js @@ -0,0 +1,15 @@ +// add a sha to a git remote url spec +const addGitSha = (spec, sha) => { + if (spec.hosted) { + const h = spec.hosted + const opt = { noCommittish: true } + const base = h.https && h.auth ? h.https(opt) : h.shortcut(opt) + + return `${base}#${sha}` + } else { + // don't use new URL for this, because it doesn't handle scp urls + return spec.rawSpec.replace(/#.*$/, '') + `#${sha}` + } +} + +module.exports = addGitSha diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/cache-dir.js b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/cache-dir.js new file mode 100644 index 0000000000000..ba5683a7bb5bf --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/cache-dir.js @@ -0,0 +1,15 @@ +const { resolve } = require('node:path') +const { tmpdir, homedir } = require('node:os') + +module.exports = (fakePlatform = false) => { + const temp = tmpdir() + const uidOrPid = process.getuid ? process.getuid() : process.pid + const home = homedir() || resolve(temp, 'npm-' + uidOrPid) + const platform = fakePlatform || process.platform + const cacheExtra = platform === 'win32' ? 'npm-cache' : '.npm' + const cacheRoot = (platform === 'win32' && process.env.LOCALAPPDATA) || home + return { + cacache: resolve(cacheRoot, cacheExtra, '_cacache'), + tufcache: resolve(cacheRoot, cacheExtra, '_tuf'), + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/is-package-bin.js b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/is-package-bin.js new file mode 100644 index 0000000000000..49a3f73f537ce --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/is-package-bin.js @@ -0,0 +1,25 @@ +// Function to determine whether a path is in the package.bin set. +// Used to prevent issues when people publish a package from a +// windows machine, and then install with --no-bin-links. +// +// Note: this is not possible in remote or file fetchers, since +// we don't have the manifest until AFTER we've unpacked. But the +// main use case is registry fetching with git a distant second, +// so that's an acceptable edge case to not handle. + +const binObj = (name, bin) => + typeof bin === 'string' ? { [name]: bin } : bin + +const hasBin = (pkg, path) => { + const bin = binObj(pkg.name, pkg.bin) + const p = path.replace(/^[^\\/]*\//, '') + for (const kv of Object.entries(bin)) { + if (kv[1] === p) { + return true + } + } + return false +} + +module.exports = (pkg, path) => + pkg && pkg.bin ? hasBin(pkg, path) : false diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/npm.js b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/npm.js new file mode 100644 index 0000000000000..a3005c255565f --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/npm.js @@ -0,0 +1,14 @@ +// run an npm command +const spawn = require('@npmcli/promise-spawn') + +module.exports = (npmBin, npmCommand, cwd, env, extra) => { + const isJS = npmBin.endsWith('.js') + const cmd = isJS ? process.execPath : npmBin + const args = (isJS ? [npmBin] : []).concat(npmCommand) + // when installing to run the `prepare` script for a git dep, we need + // to ensure that we don't run into a cycle of checking out packages + // in temp directories. this lets us link previously-seen repos that + // are also being prepared. + + return spawn(cmd, args, { cwd, env }, extra) +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/protected.js b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/protected.js new file mode 100644 index 0000000000000..e05203b481e6a --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/protected.js @@ -0,0 +1,5 @@ +module.exports = { + cacheFetches: Symbol.for('pacote.Fetcher._cacheFetches'), + readPackageJson: Symbol.for('package.Fetcher._readPackageJson'), + tarballFromResolved: Symbol.for('pacote.Fetcher._tarballFromResolved'), +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/tar-create-options.js b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/tar-create-options.js new file mode 100644 index 0000000000000..d070f0f7ba2d4 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/tar-create-options.js @@ -0,0 +1,31 @@ +const isPackageBin = require('./is-package-bin.js') + +const tarCreateOptions = manifest => ({ + cwd: manifest._resolved, + prefix: 'package/', + portable: true, + gzip: { + // forcing the level to 9 seems to avoid some + // platform specific optimizations that cause + // integrity mismatch errors due to differing + // end results after compression + level: 9, + }, + + // ensure that package bins are always executable + // Note that npm-packlist is already filtering out + // anything that is not a regular file, ignored by + // .npmignore or package.json "files", etc. + filter: (path, stat) => { + if (isPackageBin(manifest, path)) { + stat.mode |= 0o111 + } + return true + }, + + // Provide a specific date in the 1980s for the benefit of zip, + // which is confounded by files dated at the Unix epoch 0. + mtime: new Date('1985-10-26T08:15:00.000Z'), +}) + +module.exports = tarCreateOptions diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/trailing-slashes.js b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/trailing-slashes.js new file mode 100644 index 0000000000000..c50cb6173b92e --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/lib/util/trailing-slashes.js @@ -0,0 +1,10 @@ +const removeTrailingSlashes = (input) => { + // in order to avoid regexp redos detection + let output = input + while (output.endsWith('/')) { + output = output.slice(0, -1) + } + return output +} + +module.exports = removeTrailingSlashes diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/package.json b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/package.json new file mode 100644 index 0000000000000..335c7a6c87bd3 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/pacote/package.json @@ -0,0 +1,79 @@ +{ + "name": "pacote", + "version": "20.0.0", + "description": "JavaScript package downloader", + "author": "GitHub Inc.", + "bin": { + "pacote": "bin/index.js" + }, + "license": "ISC", + "main": "lib/index.js", + "scripts": { + "test": "tap", + "snap": "tap", + "lint": "npm run eslint", + "postlint": "template-oss-check", + "lintfix": "npm run eslint -- --fix", + "posttest": "npm run lint", + "template-oss-apply": "template-oss-apply --force", + "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"" + }, + "tap": { + "timeout": 300, + "nyc-arg": [ + "--exclude", + "tap-snapshots/**" + ] + }, + "devDependencies": { + "@npmcli/arborist": "^7.1.0", + "@npmcli/eslint-config": "^5.0.0", + "@npmcli/template-oss": "4.23.3", + "hosted-git-info": "^8.0.0", + "mutate-fs": "^2.1.1", + "nock": "^13.2.4", + "npm-registry-mock": "^1.3.2", + "tap": "^16.0.1" + }, + "files": [ + "bin/", + "lib/" + ], + "keywords": [ + "packages", + "npm", + "git" + ], + "dependencies": { + "@npmcli/git": "^6.0.0", + "@npmcli/installed-package-contents": "^3.0.0", + "@npmcli/package-json": "^6.0.0", + "@npmcli/promise-spawn": "^8.0.0", + "@npmcli/run-script": "^9.0.0", + "cacache": "^19.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^12.0.0", + "npm-packlist": "^9.0.0", + "npm-pick-manifest": "^10.0.0", + "npm-registry-fetch": "^18.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "sigstore": "^3.0.0", + "ssri": "^12.0.0", + "tar": "^6.1.11" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/npm/pacote.git" + }, + "templateOSS": { + "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", + "version": "4.23.3", + "windowsCI": false, + "publish": "true" + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/sigstore/LICENSE b/node_modules/@npmcli/metavuln-calculator/node_modules/sigstore/LICENSE new file mode 100644 index 0000000000000..e9e7c1679a09d --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/sigstore/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 The Sigstore Authors + + 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. diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/sigstore/dist/config.js b/node_modules/@npmcli/metavuln-calculator/node_modules/sigstore/dist/config.js new file mode 100644 index 0000000000000..e8b2392f97f23 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/sigstore/dist/config.js @@ -0,0 +1,120 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DEFAULT_TIMEOUT = exports.DEFAULT_RETRY = void 0; +exports.createBundleBuilder = createBundleBuilder; +exports.createKeyFinder = createKeyFinder; +exports.createVerificationPolicy = createVerificationPolicy; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const core_1 = require("@sigstore/core"); +const sign_1 = require("@sigstore/sign"); +const verify_1 = require("@sigstore/verify"); +exports.DEFAULT_RETRY = { retries: 2 }; +exports.DEFAULT_TIMEOUT = 5000; +function createBundleBuilder(bundleType, options) { + const bundlerOptions = { + signer: initSigner(options), + witnesses: initWitnesses(options), + }; + switch (bundleType) { + case 'messageSignature': + return new sign_1.MessageSignatureBundleBuilder(bundlerOptions); + case 'dsseEnvelope': + return new sign_1.DSSEBundleBuilder({ + ...bundlerOptions, + certificateChain: options.legacyCompatibility, + }); + } +} +// Translates the public KeySelector type into the KeyFinderFunc type needed by +// the verifier. +function createKeyFinder(keySelector) { + return (hint) => { + const key = keySelector(hint); + if (!key) { + throw new verify_1.VerificationError({ + code: 'PUBLIC_KEY_ERROR', + message: `key not found: ${hint}`, + }); + } + return { + publicKey: core_1.crypto.createPublicKey(key), + validFor: () => true, + }; + }; +} +function createVerificationPolicy(options) { + const policy = {}; + const san = options.certificateIdentityEmail || options.certificateIdentityURI; + if (san) { + policy.subjectAlternativeName = san; + } + if (options.certificateIssuer) { + policy.extensions = { issuer: options.certificateIssuer }; + } + return policy; +} +// Instantiate the FulcioSigner based on the supplied options. +function initSigner(options) { + return new sign_1.FulcioSigner({ + fulcioBaseURL: options.fulcioURL, + identityProvider: options.identityProvider || initIdentityProvider(options), + retry: options.retry ?? exports.DEFAULT_RETRY, + timeout: options.timeout ?? exports.DEFAULT_TIMEOUT, + }); +} +// Instantiate an identity provider based on the supplied options. If an +// explicit identity token is provided, use that. Otherwise, use the CI +// context provider. +function initIdentityProvider(options) { + const token = options.identityToken; + if (token) { + /* istanbul ignore next */ + return { getToken: () => Promise.resolve(token) }; + } + else { + return new sign_1.CIContextProvider('sigstore'); + } +} +// Instantiate a collection of witnesses based on the supplied options. +function initWitnesses(options) { + const witnesses = []; + if (isRekorEnabled(options)) { + witnesses.push(new sign_1.RekorWitness({ + rekorBaseURL: options.rekorURL, + entryType: options.legacyCompatibility ? 'intoto' : 'dsse', + fetchOnConflict: false, + retry: options.retry ?? exports.DEFAULT_RETRY, + timeout: options.timeout ?? exports.DEFAULT_TIMEOUT, + })); + } + if (isTSAEnabled(options)) { + witnesses.push(new sign_1.TSAWitness({ + tsaBaseURL: options.tsaServerURL, + retry: options.retry ?? exports.DEFAULT_RETRY, + timeout: options.timeout ?? exports.DEFAULT_TIMEOUT, + })); + } + return witnesses; +} +// Type assertion to ensure that Rekor is enabled +function isRekorEnabled(options) { + return options.tlogUpload !== false; +} +// Type assertion to ensure that TSA is enabled +function isTSAEnabled(options) { + return options.tsaServerURL !== undefined; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/sigstore/dist/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/sigstore/dist/index.js new file mode 100644 index 0000000000000..7f6a5cf86bbfc --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/sigstore/dist/index.js @@ -0,0 +1,34 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verify = exports.sign = exports.createVerifier = exports.attest = exports.VerificationError = exports.PolicyError = exports.TUFError = exports.InternalError = exports.DEFAULT_REKOR_URL = exports.DEFAULT_FULCIO_URL = exports.ValidationError = void 0; +/* +Copyright 2022 The Sigstore Authors. + +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. +*/ +var bundle_1 = require("@sigstore/bundle"); +Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return bundle_1.ValidationError; } }); +var sign_1 = require("@sigstore/sign"); +Object.defineProperty(exports, "DEFAULT_FULCIO_URL", { enumerable: true, get: function () { return sign_1.DEFAULT_FULCIO_URL; } }); +Object.defineProperty(exports, "DEFAULT_REKOR_URL", { enumerable: true, get: function () { return sign_1.DEFAULT_REKOR_URL; } }); +Object.defineProperty(exports, "InternalError", { enumerable: true, get: function () { return sign_1.InternalError; } }); +var tuf_1 = require("@sigstore/tuf"); +Object.defineProperty(exports, "TUFError", { enumerable: true, get: function () { return tuf_1.TUFError; } }); +var verify_1 = require("@sigstore/verify"); +Object.defineProperty(exports, "PolicyError", { enumerable: true, get: function () { return verify_1.PolicyError; } }); +Object.defineProperty(exports, "VerificationError", { enumerable: true, get: function () { return verify_1.VerificationError; } }); +var sigstore_1 = require("./sigstore"); +Object.defineProperty(exports, "attest", { enumerable: true, get: function () { return sigstore_1.attest; } }); +Object.defineProperty(exports, "createVerifier", { enumerable: true, get: function () { return sigstore_1.createVerifier; } }); +Object.defineProperty(exports, "sign", { enumerable: true, get: function () { return sigstore_1.sign; } }); +Object.defineProperty(exports, "verify", { enumerable: true, get: function () { return sigstore_1.verify; } }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/sigstore/dist/sigstore.js b/node_modules/@npmcli/metavuln-calculator/node_modules/sigstore/dist/sigstore.js new file mode 100644 index 0000000000000..2b37ef46b7438 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/sigstore/dist/sigstore.js @@ -0,0 +1,102 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.sign = sign; +exports.attest = attest; +exports.verify = verify; +exports.createVerifier = createVerifier; +/* +Copyright 2023 The Sigstore Authors. + +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. +*/ +const bundle_1 = require("@sigstore/bundle"); +const tuf = __importStar(require("@sigstore/tuf")); +const verify_1 = require("@sigstore/verify"); +const config = __importStar(require("./config")); +async function sign(payload, +/* istanbul ignore next */ +options = {}) { + const bundler = config.createBundleBuilder('messageSignature', options); + const bundle = await bundler.create({ data: payload }); + return (0, bundle_1.bundleToJSON)(bundle); +} +async function attest(payload, payloadType, +/* istanbul ignore next */ +options = {}) { + const bundler = config.createBundleBuilder('dsseEnvelope', options); + const bundle = await bundler.create({ data: payload, type: payloadType }); + return (0, bundle_1.bundleToJSON)(bundle); +} +async function verify(bundle, dataOrOptions, options) { + let data; + if (Buffer.isBuffer(dataOrOptions)) { + data = dataOrOptions; + } + else { + options = dataOrOptions; + } + return createVerifier(options).then((verifier) => verifier.verify(bundle, data)); +} +async function createVerifier( +/* istanbul ignore next */ +options = {}) { + const trustedRoot = await tuf.getTrustedRoot({ + mirrorURL: options.tufMirrorURL, + rootPath: options.tufRootPath, + cachePath: options.tufCachePath, + forceCache: options.tufForceCache, + retry: options.retry ?? config.DEFAULT_RETRY, + timeout: options.timeout ?? config.DEFAULT_TIMEOUT, + }); + const keyFinder = options.keySelector + ? config.createKeyFinder(options.keySelector) + : undefined; + const trustMaterial = (0, verify_1.toTrustMaterial)(trustedRoot, keyFinder); + const verifierOptions = { + ctlogThreshold: options.ctLogThreshold, + tlogThreshold: options.tlogThreshold, + }; + const verifier = new verify_1.Verifier(trustMaterial, verifierOptions); + const policy = config.createVerificationPolicy(options); + return { + verify: (bundle, payload) => { + const deserializedBundle = (0, bundle_1.bundleFromJSON)(bundle); + const signedEntity = (0, verify_1.toSignedEntity)(deserializedBundle, payload); + verifier.verify(signedEntity, policy); + return; + }, + }; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/sigstore/package.json b/node_modules/@npmcli/metavuln-calculator/node_modules/sigstore/package.json new file mode 100644 index 0000000000000..0f798a263657b --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/sigstore/package.json @@ -0,0 +1,47 @@ +{ + "name": "sigstore", + "version": "3.0.0", + "description": "code-signing for npm packages", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "clean": "shx rm -rf dist *.tsbuildinfo", + "build": "tsc --build", + "test": "jest" + }, + "files": [ + "dist", + "store" + ], + "author": "bdehamer@github.com", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "git+https://github.com/sigstore/sigstore-js.git" + }, + "bugs": { + "url": "https://github.com/sigstore/sigstore-js/issues" + }, + "homepage": "https://github.com/sigstore/sigstore-js/tree/main/packages/client#readme", + "publishConfig": { + "provenance": true + }, + "devDependencies": { + "@sigstore/rekor-types": "^3.0.0", + "@sigstore/jest": "^0.0.0", + "@sigstore/mock": "^0.8.0", + "@tufjs/repo-mock": "^3.0.1", + "@types/make-fetch-happen": "^10.0.4" + }, + "dependencies": { + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0", + "@sigstore/protobuf-specs": "^0.3.2", + "@sigstore/sign": "^3.0.0", + "@sigstore/tuf": "^3.0.0", + "@sigstore/verify": "^2.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/LICENSE b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/LICENSE new file mode 100644 index 0000000000000..420700f5d3765 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 GitHub and the TUF Contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/config.js b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/config.js new file mode 100644 index 0000000000000..c66d76af86b98 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/config.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.defaultConfig = void 0; +exports.defaultConfig = { + maxRootRotations: 256, + maxDelegations: 32, + rootMaxLength: 512000, //bytes + timestampMaxLength: 16384, // bytes + snapshotMaxLength: 2000000, // bytes + targetsMaxLength: 5000000, // bytes + prefixTargetsWithHash: true, + fetchTimeout: 100000, // milliseconds + fetchRetries: undefined, + fetchRetry: 2, +}; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/error.js b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/error.js new file mode 100644 index 0000000000000..f4b10fa202895 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/error.js @@ -0,0 +1,48 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DownloadHTTPError = exports.DownloadLengthMismatchError = exports.DownloadError = exports.ExpiredMetadataError = exports.EqualVersionError = exports.BadVersionError = exports.RepositoryError = exports.PersistError = exports.RuntimeError = exports.ValueError = void 0; +// An error about insufficient values +class ValueError extends Error { +} +exports.ValueError = ValueError; +class RuntimeError extends Error { +} +exports.RuntimeError = RuntimeError; +class PersistError extends Error { +} +exports.PersistError = PersistError; +// An error with a repository's state, such as a missing file. +// It covers all exceptions that come from the repository side when +// looking from the perspective of users of metadata API or ngclient. +class RepositoryError extends Error { +} +exports.RepositoryError = RepositoryError; +// An error for metadata that contains an invalid version number. +class BadVersionError extends RepositoryError { +} +exports.BadVersionError = BadVersionError; +// An error for metadata containing a previously verified version number. +class EqualVersionError extends BadVersionError { +} +exports.EqualVersionError = EqualVersionError; +// Indicate that a TUF Metadata file has expired. +class ExpiredMetadataError extends RepositoryError { +} +exports.ExpiredMetadataError = ExpiredMetadataError; +//----- Download Errors ------------------------------------------------------- +// An error occurred while attempting to download a file. +class DownloadError extends Error { +} +exports.DownloadError = DownloadError; +// Indicate that a mismatch of lengths was seen while downloading a file +class DownloadLengthMismatchError extends DownloadError { +} +exports.DownloadLengthMismatchError = DownloadLengthMismatchError; +// Returned by FetcherInterface implementations for HTTP errors. +class DownloadHTTPError extends DownloadError { + constructor(message, statusCode) { + super(message); + this.statusCode = statusCode; + } +} +exports.DownloadHTTPError = DownloadHTTPError; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/fetcher.js b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/fetcher.js new file mode 100644 index 0000000000000..f966ce1bb0cdc --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/fetcher.js @@ -0,0 +1,84 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DefaultFetcher = exports.BaseFetcher = void 0; +const debug_1 = __importDefault(require("debug")); +const fs_1 = __importDefault(require("fs")); +const make_fetch_happen_1 = __importDefault(require("make-fetch-happen")); +const util_1 = __importDefault(require("util")); +const error_1 = require("./error"); +const tmpfile_1 = require("./utils/tmpfile"); +const log = (0, debug_1.default)('tuf:fetch'); +class BaseFetcher { + // Download file from given URL. The file is downloaded to a temporary + // location and then passed to the given handler. The handler is responsible + // for moving the file to its final location. The temporary file is deleted + // after the handler returns. + async downloadFile(url, maxLength, handler) { + return (0, tmpfile_1.withTempFile)(async (tmpFile) => { + const reader = await this.fetch(url); + let numberOfBytesReceived = 0; + const fileStream = fs_1.default.createWriteStream(tmpFile); + // Read the stream a chunk at a time so that we can check + // the length of the file as we go + try { + for await (const chunk of reader) { + const bufferChunk = Buffer.from(chunk); + numberOfBytesReceived += bufferChunk.length; + if (numberOfBytesReceived > maxLength) { + throw new error_1.DownloadLengthMismatchError('Max length reached'); + } + await writeBufferToStream(fileStream, bufferChunk); + } + } + finally { + // Make sure we always close the stream + await util_1.default.promisify(fileStream.close).bind(fileStream)(); + } + return handler(tmpFile); + }); + } + // Download bytes from given URL. + async downloadBytes(url, maxLength) { + return this.downloadFile(url, maxLength, async (file) => { + const stream = fs_1.default.createReadStream(file); + const chunks = []; + for await (const chunk of stream) { + chunks.push(chunk); + } + return Buffer.concat(chunks); + }); + } +} +exports.BaseFetcher = BaseFetcher; +class DefaultFetcher extends BaseFetcher { + constructor(options = {}) { + super(); + this.timeout = options.timeout; + this.retry = options.retry; + } + async fetch(url) { + log('GET %s', url); + const response = await (0, make_fetch_happen_1.default)(url, { + timeout: this.timeout, + retry: this.retry, + }); + if (!response.ok || !response?.body) { + throw new error_1.DownloadHTTPError('Failed to download', response.status); + } + return response.body; + } +} +exports.DefaultFetcher = DefaultFetcher; +const writeBufferToStream = async (stream, buffer) => { + return new Promise((resolve, reject) => { + stream.write(buffer, (err) => { + if (err) { + reject(err); + } + resolve(true); + }); + }); +}; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/index.js b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/index.js new file mode 100644 index 0000000000000..5a83b91f355d8 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/index.js @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Updater = exports.BaseFetcher = exports.TargetFile = void 0; +var models_1 = require("@tufjs/models"); +Object.defineProperty(exports, "TargetFile", { enumerable: true, get: function () { return models_1.TargetFile; } }); +var fetcher_1 = require("./fetcher"); +Object.defineProperty(exports, "BaseFetcher", { enumerable: true, get: function () { return fetcher_1.BaseFetcher; } }); +var updater_1 = require("./updater"); +Object.defineProperty(exports, "Updater", { enumerable: true, get: function () { return updater_1.Updater; } }); diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/store.js b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/store.js new file mode 100644 index 0000000000000..8567336108709 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/store.js @@ -0,0 +1,208 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TrustedMetadataStore = void 0; +const models_1 = require("@tufjs/models"); +const error_1 = require("./error"); +class TrustedMetadataStore { + constructor(rootData) { + this.trustedSet = {}; + // Client workflow 5.1: record fixed update start time + this.referenceTime = new Date(); + // Client workflow 5.2: load trusted root metadata + this.loadTrustedRoot(rootData); + } + get root() { + if (!this.trustedSet.root) { + throw new ReferenceError('No trusted root metadata'); + } + return this.trustedSet.root; + } + get timestamp() { + return this.trustedSet.timestamp; + } + get snapshot() { + return this.trustedSet.snapshot; + } + get targets() { + return this.trustedSet.targets; + } + getRole(name) { + return this.trustedSet[name]; + } + updateRoot(bytesBuffer) { + const data = JSON.parse(bytesBuffer.toString('utf8')); + const newRoot = models_1.Metadata.fromJSON(models_1.MetadataKind.Root, data); + if (newRoot.signed.type != models_1.MetadataKind.Root) { + throw new error_1.RepositoryError(`Expected 'root', got ${newRoot.signed.type}`); + } + // Client workflow 5.4: check for arbitrary software attack + this.root.verifyDelegate(models_1.MetadataKind.Root, newRoot); + // Client workflow 5.5: check for rollback attack + if (newRoot.signed.version != this.root.signed.version + 1) { + throw new error_1.BadVersionError(`Expected version ${this.root.signed.version + 1}, got ${newRoot.signed.version}`); + } + // Check that new root is signed by self + newRoot.verifyDelegate(models_1.MetadataKind.Root, newRoot); + // Client workflow 5.7: set new root as trusted root + this.trustedSet.root = newRoot; + return newRoot; + } + updateTimestamp(bytesBuffer) { + if (this.snapshot) { + throw new error_1.RuntimeError('Cannot update timestamp after snapshot'); + } + if (this.root.signed.isExpired(this.referenceTime)) { + throw new error_1.ExpiredMetadataError('Final root.json is expired'); + } + const data = JSON.parse(bytesBuffer.toString('utf8')); + const newTimestamp = models_1.Metadata.fromJSON(models_1.MetadataKind.Timestamp, data); + if (newTimestamp.signed.type != models_1.MetadataKind.Timestamp) { + throw new error_1.RepositoryError(`Expected 'timestamp', got ${newTimestamp.signed.type}`); + } + // Client workflow 5.4.2: check for arbitrary software attack + this.root.verifyDelegate(models_1.MetadataKind.Timestamp, newTimestamp); + if (this.timestamp) { + // Prevent rolling back timestamp version + // Client workflow 5.4.3.1: check for rollback attack + if (newTimestamp.signed.version < this.timestamp.signed.version) { + throw new error_1.BadVersionError(`New timestamp version ${newTimestamp.signed.version} is less than current version ${this.timestamp.signed.version}`); + } + // Keep using old timestamp if versions are equal. + if (newTimestamp.signed.version === this.timestamp.signed.version) { + throw new error_1.EqualVersionError(`New timestamp version ${newTimestamp.signed.version} is equal to current version ${this.timestamp.signed.version}`); + } + // Prevent rolling back snapshot version + // Client workflow 5.4.3.2: check for rollback attack + const snapshotMeta = this.timestamp.signed.snapshotMeta; + const newSnapshotMeta = newTimestamp.signed.snapshotMeta; + if (newSnapshotMeta.version < snapshotMeta.version) { + throw new error_1.BadVersionError(`New snapshot version ${newSnapshotMeta.version} is less than current version ${snapshotMeta.version}`); + } + } + // expiry not checked to allow old timestamp to be used for rollback + // protection of new timestamp: expiry is checked in update_snapshot + this.trustedSet.timestamp = newTimestamp; + // Client workflow 5.4.4: check for freeze attack + this.checkFinalTimestamp(); + return newTimestamp; + } + updateSnapshot(bytesBuffer, trusted = false) { + if (!this.timestamp) { + throw new error_1.RuntimeError('Cannot update snapshot before timestamp'); + } + if (this.targets) { + throw new error_1.RuntimeError('Cannot update snapshot after targets'); + } + // Snapshot cannot be loaded if final timestamp is expired + this.checkFinalTimestamp(); + const snapshotMeta = this.timestamp.signed.snapshotMeta; + // Verify non-trusted data against the hashes in timestamp, if any. + // Trusted snapshot data has already been verified once. + // Client workflow 5.5.2: check against timestamp role's snaphsot hash + if (!trusted) { + snapshotMeta.verify(bytesBuffer); + } + const data = JSON.parse(bytesBuffer.toString('utf8')); + const newSnapshot = models_1.Metadata.fromJSON(models_1.MetadataKind.Snapshot, data); + if (newSnapshot.signed.type != models_1.MetadataKind.Snapshot) { + throw new error_1.RepositoryError(`Expected 'snapshot', got ${newSnapshot.signed.type}`); + } + // Client workflow 5.5.3: check for arbitrary software attack + this.root.verifyDelegate(models_1.MetadataKind.Snapshot, newSnapshot); + // version check against meta version (5.5.4) is deferred to allow old + // snapshot to be used in rollback protection + // Client workflow 5.5.5: check for rollback attack + if (this.snapshot) { + Object.entries(this.snapshot.signed.meta).forEach(([fileName, fileInfo]) => { + const newFileInfo = newSnapshot.signed.meta[fileName]; + if (!newFileInfo) { + throw new error_1.RepositoryError(`Missing file ${fileName} in new snapshot`); + } + if (newFileInfo.version < fileInfo.version) { + throw new error_1.BadVersionError(`New version ${newFileInfo.version} of ${fileName} is less than current version ${fileInfo.version}`); + } + }); + } + this.trustedSet.snapshot = newSnapshot; + // snapshot is loaded, but we raise if it's not valid _final_ snapshot + // Client workflow 5.5.4 & 5.5.6 + this.checkFinalSnapsnot(); + return newSnapshot; + } + updateDelegatedTargets(bytesBuffer, roleName, delegatorName) { + if (!this.snapshot) { + throw new error_1.RuntimeError('Cannot update delegated targets before snapshot'); + } + // Targets cannot be loaded if final snapshot is expired or its version + // does not match meta version in timestamp. + this.checkFinalSnapsnot(); + const delegator = this.trustedSet[delegatorName]; + if (!delegator) { + throw new error_1.RuntimeError(`No trusted ${delegatorName} metadata`); + } + // Extract metadata for the delegated role from snapshot + const meta = this.snapshot.signed.meta?.[`${roleName}.json`]; + if (!meta) { + throw new error_1.RepositoryError(`Missing ${roleName}.json in snapshot`); + } + // Client workflow 5.6.2: check against snapshot role's targets hash + meta.verify(bytesBuffer); + const data = JSON.parse(bytesBuffer.toString('utf8')); + const newDelegate = models_1.Metadata.fromJSON(models_1.MetadataKind.Targets, data); + if (newDelegate.signed.type != models_1.MetadataKind.Targets) { + throw new error_1.RepositoryError(`Expected 'targets', got ${newDelegate.signed.type}`); + } + // Client workflow 5.6.3: check for arbitrary software attack + delegator.verifyDelegate(roleName, newDelegate); + // Client workflow 5.6.4: Check against snapshot role’s targets version + const version = newDelegate.signed.version; + if (version != meta.version) { + throw new error_1.BadVersionError(`Version ${version} of ${roleName} does not match snapshot version ${meta.version}`); + } + // Client workflow 5.6.5: check for a freeze attack + if (newDelegate.signed.isExpired(this.referenceTime)) { + throw new error_1.ExpiredMetadataError(`${roleName}.json is expired`); + } + this.trustedSet[roleName] = newDelegate; + } + // Verifies and loads data as trusted root metadata. + // Note that an expired initial root is still considered valid. + loadTrustedRoot(bytesBuffer) { + const data = JSON.parse(bytesBuffer.toString('utf8')); + const root = models_1.Metadata.fromJSON(models_1.MetadataKind.Root, data); + if (root.signed.type != models_1.MetadataKind.Root) { + throw new error_1.RepositoryError(`Expected 'root', got ${root.signed.type}`); + } + root.verifyDelegate(models_1.MetadataKind.Root, root); + this.trustedSet['root'] = root; + } + checkFinalTimestamp() { + // Timestamp MUST be loaded + if (!this.timestamp) { + throw new ReferenceError('No trusted timestamp metadata'); + } + // Client workflow 5.4.4: check for freeze attack + if (this.timestamp.signed.isExpired(this.referenceTime)) { + throw new error_1.ExpiredMetadataError('Final timestamp.json is expired'); + } + } + checkFinalSnapsnot() { + // Snapshot and timestamp MUST be loaded + if (!this.snapshot) { + throw new ReferenceError('No trusted snapshot metadata'); + } + if (!this.timestamp) { + throw new ReferenceError('No trusted timestamp metadata'); + } + // Client workflow 5.5.6: check for freeze attack + if (this.snapshot.signed.isExpired(this.referenceTime)) { + throw new error_1.ExpiredMetadataError('snapshot.json is expired'); + } + // Client workflow 5.5.4: check against timestamp role’s snapshot version + const snapshotMeta = this.timestamp.signed.snapshotMeta; + if (this.snapshot.signed.version !== snapshotMeta.version) { + throw new error_1.BadVersionError("Snapshot version doesn't match timestamp"); + } + } +} +exports.TrustedMetadataStore = TrustedMetadataStore; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/updater.js b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/updater.js new file mode 100644 index 0000000000000..8d5eb4428f044 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/updater.js @@ -0,0 +1,350 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Updater = void 0; +const models_1 = require("@tufjs/models"); +const debug_1 = __importDefault(require("debug")); +const fs = __importStar(require("fs")); +const path = __importStar(require("path")); +const config_1 = require("./config"); +const error_1 = require("./error"); +const fetcher_1 = require("./fetcher"); +const store_1 = require("./store"); +const url = __importStar(require("./utils/url")); +const log = (0, debug_1.default)('tuf:cache'); +class Updater { + constructor(options) { + const { metadataDir, metadataBaseUrl, targetDir, targetBaseUrl, fetcher, config, } = options; + this.dir = metadataDir; + this.metadataBaseUrl = metadataBaseUrl; + this.targetDir = targetDir; + this.targetBaseUrl = targetBaseUrl; + this.forceCache = options.forceCache ?? false; + const data = this.loadLocalMetadata(models_1.MetadataKind.Root); + this.trustedSet = new store_1.TrustedMetadataStore(data); + this.config = { ...config_1.defaultConfig, ...config }; + this.fetcher = + fetcher || + new fetcher_1.DefaultFetcher({ + timeout: this.config.fetchTimeout, + retry: this.config.fetchRetries ?? this.config.fetchRetry, + }); + } + // refresh and load the metadata before downloading the target + // refresh should be called once after the client is initialized + async refresh() { + // If forceCache is true, try to load the timestamp from local storage + // without fetching it from the remote. Otherwise, load the root and + // timestamp from the remote per the TUF spec. + if (this.forceCache) { + // If anything fails, load the root and timestamp from the remote. This + // should cover any situation where the local metadata is corrupted or + // expired. + try { + await this.loadTimestamp({ checkRemote: false }); + } + catch (error) { + await this.loadRoot(); + await this.loadTimestamp(); + } + } + else { + await this.loadRoot(); + await this.loadTimestamp(); + } + await this.loadSnapshot(); + await this.loadTargets(models_1.MetadataKind.Targets, models_1.MetadataKind.Root); + } + // Returns the TargetFile instance with information for the given target path. + // + // Implicitly calls refresh if it hasn't already been called. + async getTargetInfo(targetPath) { + if (!this.trustedSet.targets) { + await this.refresh(); + } + return this.preorderDepthFirstWalk(targetPath); + } + async downloadTarget(targetInfo, filePath, targetBaseUrl) { + const targetPath = filePath || this.generateTargetPath(targetInfo); + if (!targetBaseUrl) { + if (!this.targetBaseUrl) { + throw new error_1.ValueError('Target base URL not set'); + } + targetBaseUrl = this.targetBaseUrl; + } + let targetFilePath = targetInfo.path; + const consistentSnapshot = this.trustedSet.root.signed.consistentSnapshot; + if (consistentSnapshot && this.config.prefixTargetsWithHash) { + const hashes = Object.values(targetInfo.hashes); + const { dir, base } = path.parse(targetFilePath); + const filename = `${hashes[0]}.${base}`; + targetFilePath = dir ? `${dir}/${filename}` : filename; + } + const targetUrl = url.join(targetBaseUrl, targetFilePath); + // Client workflow 5.7.3: download target file + await this.fetcher.downloadFile(targetUrl, targetInfo.length, async (fileName) => { + // Verify hashes and length of downloaded file + await targetInfo.verify(fs.createReadStream(fileName)); + // Copy file to target path + log('WRITE %s', targetPath); + fs.copyFileSync(fileName, targetPath); + }); + return targetPath; + } + async findCachedTarget(targetInfo, filePath) { + if (!filePath) { + filePath = this.generateTargetPath(targetInfo); + } + try { + if (fs.existsSync(filePath)) { + await targetInfo.verify(fs.createReadStream(filePath)); + return filePath; + } + } + catch (error) { + return; // File not found + } + return; // File not found + } + loadLocalMetadata(fileName) { + const filePath = path.join(this.dir, `${fileName}.json`); + log('READ %s', filePath); + return fs.readFileSync(filePath); + } + // Sequentially load and persist on local disk every newer root metadata + // version available on the remote. + // Client workflow 5.3: update root role + async loadRoot() { + // Client workflow 5.3.2: version of trusted root metadata file + const rootVersion = this.trustedSet.root.signed.version; + const lowerBound = rootVersion + 1; + const upperBound = lowerBound + this.config.maxRootRotations; + for (let version = lowerBound; version < upperBound; version++) { + const rootUrl = url.join(this.metadataBaseUrl, `${version}.root.json`); + try { + // Client workflow 5.3.3: download new root metadata file + const bytesData = await this.fetcher.downloadBytes(rootUrl, this.config.rootMaxLength); + // Client workflow 5.3.4 - 5.4.7 + this.trustedSet.updateRoot(bytesData); + // Client workflow 5.3.8: persist root metadata file + this.persistMetadata(models_1.MetadataKind.Root, bytesData); + } + catch (error) { + if (error instanceof error_1.DownloadHTTPError) { + // 404/403 means current root is newest available + if ([403, 404].includes(error.statusCode)) { + break; + } + } + throw error; + } + } + } + // Load local and remote timestamp metadata. + // Client workflow 5.4: update timestamp role + async loadTimestamp({ checkRemote } = { checkRemote: true }) { + // Load local and remote timestamp metadata + try { + const data = this.loadLocalMetadata(models_1.MetadataKind.Timestamp); + this.trustedSet.updateTimestamp(data); + // If checkRemote is disabled, return here to avoid fetching the remote + // timestamp metadata. + if (!checkRemote) { + return; + } + } + catch (error) { + // continue + } + //Load from remote (whether local load succeeded or not) + const timestampUrl = url.join(this.metadataBaseUrl, 'timestamp.json'); + // Client workflow 5.4.1: download timestamp metadata file + const bytesData = await this.fetcher.downloadBytes(timestampUrl, this.config.timestampMaxLength); + try { + // Client workflow 5.4.2 - 5.4.4 + this.trustedSet.updateTimestamp(bytesData); + } + catch (error) { + // If new timestamp version is same as current, discardd the new one. + // This is normal and should NOT raise an error. + if (error instanceof error_1.EqualVersionError) { + return; + } + // Re-raise any other error + throw error; + } + // Client workflow 5.4.5: persist timestamp metadata + this.persistMetadata(models_1.MetadataKind.Timestamp, bytesData); + } + // Load local and remote snapshot metadata. + // Client workflow 5.5: update snapshot role + async loadSnapshot() { + //Load local (and if needed remote) snapshot metadata + try { + const data = this.loadLocalMetadata(models_1.MetadataKind.Snapshot); + this.trustedSet.updateSnapshot(data, true); + } + catch (error) { + if (!this.trustedSet.timestamp) { + throw new ReferenceError('No timestamp metadata'); + } + const snapshotMeta = this.trustedSet.timestamp.signed.snapshotMeta; + const maxLength = snapshotMeta.length || this.config.snapshotMaxLength; + const version = this.trustedSet.root.signed.consistentSnapshot + ? snapshotMeta.version + : undefined; + const snapshotUrl = url.join(this.metadataBaseUrl, version ? `${version}.snapshot.json` : 'snapshot.json'); + try { + // Client workflow 5.5.1: download snapshot metadata file + const bytesData = await this.fetcher.downloadBytes(snapshotUrl, maxLength); + // Client workflow 5.5.2 - 5.5.6 + this.trustedSet.updateSnapshot(bytesData); + // Client workflow 5.5.7: persist snapshot metadata file + this.persistMetadata(models_1.MetadataKind.Snapshot, bytesData); + } + catch (error) { + throw new error_1.RuntimeError(`Unable to load snapshot metadata error ${error}`); + } + } + } + // Load local and remote targets metadata. + // Client workflow 5.6: update targets role + async loadTargets(role, parentRole) { + if (this.trustedSet.getRole(role)) { + return this.trustedSet.getRole(role); + } + try { + const buffer = this.loadLocalMetadata(role); + this.trustedSet.updateDelegatedTargets(buffer, role, parentRole); + } + catch (error) { + // Local 'role' does not exist or is invalid: update from remote + if (!this.trustedSet.snapshot) { + throw new ReferenceError('No snapshot metadata'); + } + const metaInfo = this.trustedSet.snapshot.signed.meta[`${role}.json`]; + // TODO: use length for fetching + const maxLength = metaInfo.length || this.config.targetsMaxLength; + const version = this.trustedSet.root.signed.consistentSnapshot + ? metaInfo.version + : undefined; + const encodedRole = encodeURIComponent(role); + const metadataUrl = url.join(this.metadataBaseUrl, version ? `${version}.${encodedRole}.json` : `${encodedRole}.json`); + try { + // Client workflow 5.6.1: download targets metadata file + const bytesData = await this.fetcher.downloadBytes(metadataUrl, maxLength); + // Client workflow 5.6.2 - 5.6.6 + this.trustedSet.updateDelegatedTargets(bytesData, role, parentRole); + // Client workflow 5.6.7: persist targets metadata file + this.persistMetadata(role, bytesData); + } + catch (error) { + throw new error_1.RuntimeError(`Unable to load targets error ${error}`); + } + } + return this.trustedSet.getRole(role); + } + async preorderDepthFirstWalk(targetPath) { + // Interrogates the tree of target delegations in order of appearance + // (which implicitly order trustworthiness), and returns the matching + // target found in the most trusted role. + // List of delegations to be interrogated. A (role, parent role) pair + // is needed to load and verify the delegated targets metadata. + const delegationsToVisit = [ + { + roleName: models_1.MetadataKind.Targets, + parentRoleName: models_1.MetadataKind.Root, + }, + ]; + const visitedRoleNames = new Set(); + // Client workflow 5.6.7: preorder depth-first traversal of the graph of + // target delegations + while (visitedRoleNames.size <= this.config.maxDelegations && + delegationsToVisit.length > 0) { + // Pop the role name from the top of the stack. + const { roleName, parentRoleName } = delegationsToVisit.pop(); + // Skip any visited current role to prevent cycles. + // Client workflow 5.6.7.1: skip already-visited roles + if (visitedRoleNames.has(roleName)) { + continue; + } + // The metadata for 'role_name' must be downloaded/updated before + // its targets, delegations, and child roles can be inspected. + const targets = (await this.loadTargets(roleName, parentRoleName)) + ?.signed; + if (!targets) { + continue; + } + const target = targets.targets?.[targetPath]; + if (target) { + return target; + } + // After preorder check, add current role to set of visited roles. + visitedRoleNames.add(roleName); + if (targets.delegations) { + const childRolesToVisit = []; + // NOTE: This may be a slow operation if there are many delegated roles. + const rolesForTarget = targets.delegations.rolesForTarget(targetPath); + for (const { role: childName, terminating } of rolesForTarget) { + childRolesToVisit.push({ + roleName: childName, + parentRoleName: roleName, + }); + // Client workflow 5.6.7.2.1 + if (terminating) { + delegationsToVisit.splice(0); // empty the array + break; + } + } + childRolesToVisit.reverse(); + delegationsToVisit.push(...childRolesToVisit); + } + } + return; // no matching target found + } + generateTargetPath(targetInfo) { + if (!this.targetDir) { + throw new error_1.ValueError('Target directory not set'); + } + // URL encode target path + const filePath = encodeURIComponent(targetInfo.path); + return path.join(this.targetDir, filePath); + } + persistMetadata(metaDataName, bytesData) { + const encodedName = encodeURIComponent(metaDataName); + try { + const filePath = path.join(this.dir, `${encodedName}.json`); + log('WRITE %s', filePath); + fs.writeFileSync(filePath, bytesData.toString('utf8')); + } + catch (error) { + throw new error_1.PersistError(`Failed to persist metadata ${encodedName} error: ${error}`); + } + } +} +exports.Updater = Updater; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/utils/tmpfile.js b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/utils/tmpfile.js new file mode 100644 index 0000000000000..923eef6044bcc --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/utils/tmpfile.js @@ -0,0 +1,25 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.withTempFile = void 0; +const promises_1 = __importDefault(require("fs/promises")); +const os_1 = __importDefault(require("os")); +const path_1 = __importDefault(require("path")); +// Invokes the given handler with the path to a temporary file. The file +// is deleted after the handler returns. +const withTempFile = async (handler) => withTempDir(async (dir) => handler(path_1.default.join(dir, 'tempfile'))); +exports.withTempFile = withTempFile; +// Invokes the given handler with a temporary directory. The directory is +// deleted after the handler returns. +const withTempDir = async (handler) => { + const tmpDir = await promises_1.default.realpath(os_1.default.tmpdir()); + const dir = await promises_1.default.mkdtemp(tmpDir + path_1.default.sep); + try { + return await handler(dir); + } + finally { + await promises_1.default.rm(dir, { force: true, recursive: true, maxRetries: 3 }); + } +}; diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/utils/url.js b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/utils/url.js new file mode 100644 index 0000000000000..359d1f3ef385b --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/dist/utils/url.js @@ -0,0 +1,13 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.join = join; +const url_1 = require("url"); +function join(base, path) { + return new url_1.URL(ensureTrailingSlash(base) + removeLeadingSlash(path)).toString(); +} +function ensureTrailingSlash(path) { + return path.endsWith('/') ? path : path + '/'; +} +function removeLeadingSlash(path) { + return path.startsWith('/') ? path.slice(1) : path; +} diff --git a/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/package.json b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/package.json new file mode 100644 index 0000000000000..e79a3d45f3f06 --- /dev/null +++ b/node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/package.json @@ -0,0 +1,43 @@ +{ + "name": "tuf-js", + "version": "3.0.1", + "description": "JavaScript implementation of The Update Framework (TUF)", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "build": "tsc --build", + "clean": "rm -rf dist && rm tsconfig.tsbuildinfo", + "test": "jest" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/theupdateframework/tuf-js.git" + }, + "files": [ + "dist" + ], + "keywords": [ + "tuf", + "security", + "update" + ], + "author": "bdehamer@github.com", + "license": "MIT", + "bugs": { + "url": "https://github.com/theupdateframework/tuf-js/issues" + }, + "homepage": "https://github.com/theupdateframework/tuf-js/tree/main/packages/client#readme", + "devDependencies": { + "@tufjs/repo-mock": "3.0.1", + "@types/debug": "^4.1.12", + "@types/make-fetch-happen": "^10.0.4" + }, + "dependencies": { + "@tufjs/models": "3.0.1", + "debug": "^4.3.6", + "make-fetch-happen": "^14.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } +} diff --git a/node_modules/@npmcli/metavuln-calculator/package.json b/node_modules/@npmcli/metavuln-calculator/package.json index d4c3cf54d83ea..df0b8f2f4faf1 100644 --- a/node_modules/@npmcli/metavuln-calculator/package.json +++ b/node_modules/@npmcli/metavuln-calculator/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/metavuln-calculator", - "version": "8.0.0", + "version": "8.0.1", "main": "lib/index.js", "files": [ "bin/", @@ -41,7 +41,7 @@ "dependencies": { "cacache": "^19.0.0", "json-parse-even-better-errors": "^4.0.0", - "pacote": "^19.0.0", + "pacote": "^20.0.0", "proc-log": "^5.0.0", "semver": "^7.3.5" }, diff --git a/package-lock.json b/package-lock.json index a72ece9382ccd..0bc0435f3afb8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2407,14 +2407,14 @@ } }, "node_modules/@npmcli/metavuln-calculator": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-8.0.0.tgz", - "integrity": "sha512-zR2TGfhR8fH1u4VRz9fuC7r1nI9dweViRDsFnMH8J89OA90lJNwF6idTttEzYSWaOTW4NVoAIB6+ujV+/wI+kg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-8.0.1.tgz", + "integrity": "sha512-WXlJx9cz3CfHSt9W9Opi1PTFc4WZLFomm5O8wekxQZmkyljrBRwATwDxfC9iOXJwYVmfiW1C1dUe0W2aN0UrSg==", "license": "ISC", "dependencies": { "cacache": "^19.0.0", "json-parse-even-better-errors": "^4.0.0", - "pacote": "^19.0.0", + "pacote": "^20.0.0", "proc-log": "^5.0.0", "semver": "^7.3.5" }, @@ -2422,6 +2422,146 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-3.0.0.tgz", + "integrity": "sha512-XDUYX56iMPAn/cdgh/DTJxz5RWmqKV4pwvUAEKEWJl+HzKdCd/24wUa9JYNMlDSCb7SUHAdtksxYX779Nne/Zg==", + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.2" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-2.0.0.tgz", + "integrity": "sha512-nYxaSb/MtlSI+JWcwTHQxyNmWeWrUXJJ/G4liLrGG7+tS4vAz6LF3xRXqLH6wPIVUoZQel2Fs4ddLx4NCpiIYg==", + "license": "Apache-2.0", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-3.0.0.tgz", + "integrity": "sha512-UjhDMQOkyDoktpXoc5YPJpJK6IooF2gayAr5LvXI4EL7O0vd58okgfRcxuaH+YTdhvb5aa1Q9f+WJ0c2sVuYIw==", + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0", + "@sigstore/protobuf-specs": "^0.3.2", + "make-fetch-happen": "^14.0.1", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-3.0.0.tgz", + "integrity": "sha512-9Xxy/8U5OFJu7s+OsHzI96IX/OzjF/zj0BSSaWhgJgTqtlBhQIV2xdrQI5qxLD7+CWWDepadnXAxzaZ3u9cvRw==", + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.2", + "tuf-js": "^3.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/verify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-2.0.0.tgz", + "integrity": "sha512-Ggtq2GsJuxFNUvQzLoXqRwS4ceRfLAJnrIHUDrzAD0GgnOhwujJkKkxM/s5Bako07c3WtAs/sZo5PJq7VHjeDg==", + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0", + "@sigstore/protobuf-specs": "^0.3.2" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-3.0.1.tgz", + "integrity": "sha512-UUYHISyhCU3ZgN8yaear3cGATHb3SMuKHsQ/nVbHXcmnBf+LzQ/cQfhNG+rfaSHgqGKNEm2cOCLVLELStUQ1JA==", + "license": "MIT", + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.5" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/pacote": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-20.0.0.tgz", + "integrity": "sha512-pRjC5UFwZCgx9kUFDVM9YEahv4guZ1nSLqwmWiLUnDbGsjs+U5w7z6Uc8HNR1a6x8qnu5y9xtGE6D1uAuYz+0A==", + "license": "ISC", + "dependencies": { + "@npmcli/git": "^6.0.0", + "@npmcli/installed-package-contents": "^3.0.0", + "@npmcli/package-json": "^6.0.0", + "@npmcli/promise-spawn": "^8.0.0", + "@npmcli/run-script": "^9.0.0", + "cacache": "^19.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^12.0.0", + "npm-packlist": "^9.0.0", + "npm-pick-manifest": "^10.0.0", + "npm-registry-fetch": "^18.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "sigstore": "^3.0.0", + "ssri": "^12.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "bin/index.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/sigstore": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-3.0.0.tgz", + "integrity": "sha512-PHMifhh3EN4loMcHCz6l3v/luzgT3za+9f8subGgeMNjbJjzH4Ij/YoX3Gvu+kaouJRIlVdTHHCREADYf+ZteA==", + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0", + "@sigstore/protobuf-specs": "^0.3.2", + "@sigstore/sign": "^3.0.0", + "@sigstore/tuf": "^3.0.0", + "@sigstore/verify": "^2.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-3.0.1.tgz", + "integrity": "sha512-+68OP1ZzSF84rTckf3FA95vJ1Zlx/uaXyiiKyPd1pA4rZNkpEvDAKmsu1xUSmbF/chCRYgZ6UZkDwC7PmzmAyA==", + "license": "MIT", + "dependencies": { + "@tufjs/models": "3.0.1", + "debug": "^4.3.6", + "make-fetch-happen": "^14.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/@npmcli/mock-globals": { "resolved": "mock-globals", "link": true