From ddb6a22396db0ce5dd1b033f96a837010f0b58af Mon Sep 17 00:00:00 2001 From: Juan Picado Date: Sun, 26 Feb 2023 13:19:22 +0100 Subject: [PATCH] feat: signature package (#3653) * feat: signature package * feat: signature package --- .changeset/kind-ladybugs-admire.md | 8 +++ packages/auth/jest.config.js | 2 +- packages/auth/package.json | 2 +- packages/auth/src/auth.ts | 5 +- packages/auth/src/index.ts | 5 +- packages/auth/src/utils.ts | 4 +- packages/auth/test/auth-utils.spec.ts | 9 ++-- packages/auth/tsconfig.json | 3 ++ packages/config/src/token.ts | 1 + packages/signature/.babelrc | 3 ++ packages/signature/jest.config.js | 3 ++ packages/signature/package.json | 53 +++++++++++++++++++ packages/signature/src/index.ts | 10 ++++ packages/{auth => signature}/src/jwt-token.ts | 0 .../signature/src/legacy-signature/index.ts | 51 ++++++++++++++++++ .../src/signature.ts} | 5 +- packages/{auth => signature}/src/token.ts | 7 ++- packages/signature/src/types.ts | 6 +++ packages/signature/src/utils.ts | 40 ++++++++++++++ packages/signature/test/jwt.spec.ts | 13 +++++ .../test/legacy-token-deprecated.spec.ts | 23 ++++++++ .../test/legacy-token.spec.ts | 2 +- packages/signature/test/utilts.spec.ts | 18 +++++++ packages/signature/tsconfig.build.json | 9 ++++ packages/signature/tsconfig.json | 17 ++++++ packages/ui-components/package.json | 4 -- pnpm-lock.yaml | 27 +++++++--- 27 files changed, 298 insertions(+), 32 deletions(-) create mode 100644 .changeset/kind-ladybugs-admire.md create mode 100644 packages/signature/.babelrc create mode 100644 packages/signature/jest.config.js create mode 100644 packages/signature/package.json create mode 100644 packages/signature/src/index.ts rename packages/{auth => signature}/src/jwt-token.ts (100%) create mode 100644 packages/signature/src/legacy-signature/index.ts rename packages/{auth/src/legacy-token.ts => signature/src/signature.ts} (96%) rename packages/{auth => signature}/src/token.ts (77%) create mode 100644 packages/signature/src/types.ts create mode 100644 packages/signature/src/utils.ts create mode 100644 packages/signature/test/jwt.spec.ts create mode 100644 packages/signature/test/legacy-token-deprecated.spec.ts rename packages/{auth => signature}/test/legacy-token.spec.ts (90%) create mode 100644 packages/signature/test/utilts.spec.ts create mode 100644 packages/signature/tsconfig.build.json create mode 100644 packages/signature/tsconfig.json diff --git a/.changeset/kind-ladybugs-admire.md b/.changeset/kind-ladybugs-admire.md new file mode 100644 index 000000000..b8896fc66 --- /dev/null +++ b/.changeset/kind-ladybugs-admire.md @@ -0,0 +1,8 @@ +--- +'@verdaccio/auth': minor +'@verdaccio/config': minor +'@verdaccio/signature': minor +'@verdaccio/ui-components': minor +--- + +feat: signature package diff --git a/packages/auth/jest.config.js b/packages/auth/jest.config.js index 8baa8063f..27023b982 100644 --- a/packages/auth/jest.config.js +++ b/packages/auth/jest.config.js @@ -4,7 +4,7 @@ module.exports = Object.assign({}, config, { coverageThreshold: { global: { // FIXME: increase to 90 - lines: 42, + lines: 30, }, }, }); diff --git a/packages/auth/package.json b/packages/auth/package.json index 8fed2065f..1ea2f81e5 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -43,10 +43,10 @@ "@verdaccio/config": "workspace:6.0.0-6-next.62", "@verdaccio/loaders": "workspace:6.0.0-6-next.31", "@verdaccio/logger": "workspace:6.0.0-6-next.30", + "@verdaccio/signature": "workspace:6.0.0-6-next.1", "@verdaccio/utils": "workspace:6.0.0-6-next.30", "debug": "4.3.4", "express": "4.18.2", - "jsonwebtoken": "9.0.0", "lodash": "4.17.21", "verdaccio-htpasswd": "workspace:11.0.0-6-next.32" }, diff --git a/packages/auth/src/auth.ts b/packages/auth/src/auth.ts index 525459099..8bc0078de 100644 --- a/packages/auth/src/auth.ts +++ b/packages/auth/src/auth.ts @@ -15,6 +15,7 @@ import { } from '@verdaccio/core'; import { asyncLoadPlugin } from '@verdaccio/loaders'; import { logger } from '@verdaccio/logger'; +import { aesEncrypt, parseBasicPayload, signPayload } from '@verdaccio/signature'; import { AllowAccess, Callback, @@ -27,9 +28,6 @@ import { } from '@verdaccio/types'; import { getMatchedPackagesSpec, isFunction, isNil } from '@verdaccio/utils'; -import { signPayload } from './jwt-token'; -import { aesEncrypt } from './legacy-token'; -import { parseBasicPayload } from './token'; import { convertPayloadToBase64, getDefaultPlugins, @@ -47,6 +45,7 @@ export interface TokenEncryption { aesEncrypt(buf: string): string | void; } +// remove export interface AESPayload { user: string; password: string; diff --git a/packages/auth/src/index.ts b/packages/auth/src/index.ts index 429ac35fa..308a3becf 100644 --- a/packages/auth/src/index.ts +++ b/packages/auth/src/index.ts @@ -1,5 +1,2 @@ -export { Auth, TokenEncryption } from './auth'; +export { Auth } from './auth'; export * from './utils'; -export * from './legacy-token'; -export * from './jwt-token'; -export * from './token'; diff --git a/packages/auth/src/utils.ts b/packages/auth/src/utils.ts index ef7893d44..fea42ad99 100644 --- a/packages/auth/src/utils.ts +++ b/packages/auth/src/utils.ts @@ -11,12 +11,10 @@ import { errorUtils, pluginUtils, } from '@verdaccio/core'; +import { aesDecrypt, parseBasicPayload, verifyPayload } from '@verdaccio/signature'; import { AuthPackageAllow, Config, Logger, RemoteUser, Security } from '@verdaccio/types'; import { AESPayload, TokenEncryption } from './auth'; -import { verifyPayload } from './jwt-token'; -import { aesDecrypt } from './legacy-token'; -import { parseBasicPayload } from './token'; const debug = buildDebug('verdaccio:auth:utils'); diff --git a/packages/auth/test/auth-utils.spec.ts b/packages/auth/test/auth-utils.spec.ts index ad3e8fe11..d094be1bb 100644 --- a/packages/auth/test/auth-utils.spec.ts +++ b/packages/auth/test/auth-utils.spec.ts @@ -17,24 +17,22 @@ import { errorUtils, } from '@verdaccio/core'; import { setup } from '@verdaccio/logger'; +import { aesDecrypt, signPayload, verifyPayload } from '@verdaccio/signature'; import { Config, RemoteUser, Security } from '@verdaccio/types'; import { buildToken, buildUserBuffer, getAuthenticatedMessage } from '@verdaccio/utils'; -import type { AllowActionCallbackResponse } from '@verdaccio/utils'; import { ActionsAllowed, + AllowActionCallbackResponse, Auth, - aesDecrypt, allow_action, getApiToken, getDefaultPlugins, getMiddlewareCredentials, - signPayload, verifyJWTPayload, - verifyPayload, } from '../src'; -setup([]); +setup({}); const parseConfigurationFile = (conf) => { const { name, ext } = path.parse(conf); @@ -452,6 +450,7 @@ describe('Auth utilities', () => { const config: Config = getConfig('security-legacy', secret); const auth: Auth = new Auth(config); await auth.init(); + // @ts-expect-error const token = auth.aesEncrypt(null); const security: Security = config.security; const credentials = getMiddlewareCredentials( diff --git a/packages/auth/tsconfig.json b/packages/auth/tsconfig.json index 5e31f7013..2cb7095c0 100644 --- a/packages/auth/tsconfig.json +++ b/packages/auth/tsconfig.json @@ -19,6 +19,9 @@ { "path": "../loaders" }, + { + "path": "../signature" + }, { "path": "../logger/logger" }, diff --git a/packages/config/src/token.ts b/packages/config/src/token.ts index c7e986610..6dbcc01fd 100644 --- a/packages/config/src/token.ts +++ b/packages/config/src/token.ts @@ -4,6 +4,7 @@ export const TOKEN_VALID_LENGTH = 32; /** * Secret key must have 32 characters. + * @deprecated */ export function generateRandomSecretKey(): string { return randomBytes(TOKEN_VALID_LENGTH).toString('base64').substring(0, TOKEN_VALID_LENGTH); diff --git a/packages/signature/.babelrc b/packages/signature/.babelrc new file mode 100644 index 000000000..633f93f42 --- /dev/null +++ b/packages/signature/.babelrc @@ -0,0 +1,3 @@ +{ + "extends": "../../.babelrc" +} diff --git a/packages/signature/jest.config.js b/packages/signature/jest.config.js new file mode 100644 index 000000000..7da7d2da8 --- /dev/null +++ b/packages/signature/jest.config.js @@ -0,0 +1,3 @@ +const config = require('../../jest/config'); + +module.exports = Object.assign({}, config, {}); diff --git a/packages/signature/package.json b/packages/signature/package.json new file mode 100644 index 000000000..52823052e --- /dev/null +++ b/packages/signature/package.json @@ -0,0 +1,53 @@ +{ + "name": "@verdaccio/signature", + "version": "6.0.0-6-next.1", + "description": "verdaccio signature utils", + "main": "./build/index.js", + "types": "build/index.d.ts", + "author": { + "name": "Juan Picado", + "email": "juanpicado19@gmail.com" + }, + "repository": { + "type": "https", + "url": "https://github.com/verdaccio/verdaccio" + }, + "license": "MIT", + "homepage": "https://verdaccio.org", + "keywords": [ + "private", + "package", + "repository", + "registry", + "enterprise", + "modules", + "proxy", + "server", + "verdaccio" + ], + "engines": { + "node": ">=12" + }, + "scripts": { + "clean": "rimraf ./build", + "test": "jest", + "type-check": "tsc --noEmit -p tsconfig.build.json", + "build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json", + "build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps", + "watch": "pnpm build:js -- --watch", + "build": "pnpm run build:js && pnpm run build:types" + }, + "dependencies": { + "jsonwebtoken": "9.0.0", + "debug": "4.3.4", + "lodash": "4.17.21" + }, + "devDependencies": { + "@verdaccio/config": "workspace:6.0.0-6-next.62", + "@verdaccio/types": "workspace:11.0.0-6-next.21" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } +} diff --git a/packages/signature/src/index.ts b/packages/signature/src/index.ts new file mode 100644 index 000000000..505f4d665 --- /dev/null +++ b/packages/signature/src/index.ts @@ -0,0 +1,10 @@ +export { + aesDecryptDeprecated, + aesEncryptDeprecated, + generateRandomSecretKeyDeprecated, +} from './legacy-signature'; +export { aesDecrypt, aesEncrypt } from './signature'; +export { signPayload, verifyPayload } from './jwt-token'; +export * as utils from './utils'; +export * as types from './types'; +export { parseBasicPayload } from './token'; diff --git a/packages/auth/src/jwt-token.ts b/packages/signature/src/jwt-token.ts similarity index 100% rename from packages/auth/src/jwt-token.ts rename to packages/signature/src/jwt-token.ts diff --git a/packages/signature/src/legacy-signature/index.ts b/packages/signature/src/legacy-signature/index.ts new file mode 100644 index 000000000..d65ce9c03 --- /dev/null +++ b/packages/signature/src/legacy-signature/index.ts @@ -0,0 +1,51 @@ +import { createCipher, createDecipher } from 'crypto'; + +import { generateRandomHexString } from '../utils'; + +export const defaultAlgorithm = 'aes192'; +export const defaultTarballHashAlgorithm = 'sha1'; + +/** + * + * @param buf + * @param secret + * @returns + */ +export function aesEncryptDeprecated(buf: Buffer, secret: string): Buffer { + // deprecated (it will be removed in Verdaccio 6), it is a breaking change + // https://nodejs.org/api/crypto.html#crypto_crypto_createcipher_algorithm_password_options + // https://www.grainger.xyz/changing-from-cipher-to-cipheriv/ + const c = createCipher(defaultAlgorithm, secret); + const b1 = c.update(buf); + const b2 = c.final(); + return Buffer.concat([b1, b2]); +} + +/** + * + * @param buf + * @param secret + * @returns + */ +export function aesDecryptDeprecated(buf: Buffer, secret: string): Buffer { + try { + // https://nodejs.org/api/crypto.html#crypto_crypto_createdecipher_algorithm_password_options + // https://www.grainger.xyz/changing-from-cipher-to-cipheriv/ + const c = createDecipher(defaultAlgorithm, secret); + const b1 = c.update(buf); + const b2 = c.final(); + return Buffer.concat([b1, b2]); + } catch (_) { + return Buffer.alloc(0); + } +} + +export const TOKEN_VALID_LENGTH_DEPRECATED = 64; + +/** + * Genrate a secret key of 64 characters. + * @deprecated keys should be length max of 64 + */ +export function generateRandomSecretKeyDeprecated(): string { + return generateRandomHexString(6); +} diff --git a/packages/auth/src/legacy-token.ts b/packages/signature/src/signature.ts similarity index 96% rename from packages/auth/src/legacy-token.ts rename to packages/signature/src/signature.ts index 91b12c421..0e762c8e7 100644 --- a/packages/auth/src/legacy-token.ts +++ b/packages/signature/src/signature.ts @@ -14,8 +14,6 @@ const debug = buildDebug('verdaccio:auth:token:legacy'); export const defaultAlgorithm = process.env.VERDACCIO_LEGACY_ALGORITHM || 'aes-256-ctr'; const inputEncoding: CharacterEncoding = 'utf8'; const outputEncoding: BinaryToTextEncoding = 'hex'; -// For AES, this is always 16 -const IV_LENGTH = 16; // Must be 256 bits (32 characters) // https://stackoverflow.com/questions/50963160/invalid-key-length-in-crypto-createcipheriv#50963356 const VERDACCIO_LEGACY_ENCRYPTION_KEY = process.env.VERDACCIO_LEGACY_ENCRYPTION_KEY; @@ -25,7 +23,8 @@ export function aesEncrypt(value: string, key: string): string | void { // https://www.grainger.xyz/changing-from-cipher-to-cipheriv/ debug('encrypt %o', value); debug('algorithm %o', defaultAlgorithm); - const iv = Buffer.from(randomBytes(IV_LENGTH)); + // IV must be a buffer of length 16 + const iv = Buffer.from(randomBytes(16)); const secretKey = VERDACCIO_LEGACY_ENCRYPTION_KEY || key; const isKeyValid = secretKey?.length === TOKEN_VALID_LENGTH; debug('length secret key %o', secretKey?.length); diff --git a/packages/auth/src/token.ts b/packages/signature/src/token.ts similarity index 77% rename from packages/auth/src/token.ts rename to packages/signature/src/token.ts index 05e518752..9ad54cbd4 100644 --- a/packages/auth/src/token.ts +++ b/packages/signature/src/token.ts @@ -1,5 +1,10 @@ -import { BasicPayload } from './utils'; +import { BasicPayload } from './types'; +/** + * + * @param credentials + * @returns + */ export function parseBasicPayload(credentials: string): BasicPayload { const index = credentials.indexOf(':'); if (index < 0) { diff --git a/packages/signature/src/types.ts b/packages/signature/src/types.ts new file mode 100644 index 000000000..518b7bba5 --- /dev/null +++ b/packages/signature/src/types.ts @@ -0,0 +1,6 @@ +export interface AESPayload { + user: string; + password: string; +} + +export type BasicPayload = AESPayload | void; diff --git a/packages/signature/src/utils.ts b/packages/signature/src/utils.ts new file mode 100644 index 000000000..b92644099 --- /dev/null +++ b/packages/signature/src/utils.ts @@ -0,0 +1,40 @@ +import { Hash, createHash, pseudoRandomBytes, randomBytes } from 'crypto'; + +export const defaultTarballHashAlgorithm = 'sha1'; + +/** + * + * @returns + */ +export function createTarballHash(algorithm = defaultTarballHashAlgorithm): Hash { + return createHash(algorithm); +} + +/** + * Express doesn't do ETAGS with requests <= 1024b + * we use md5 here, it works well on 1k+ bytes, but with fewer data + * could improve performance using crc32 after benchmarks. + * @param {Object} data + * @return {String} + */ +export function stringToMD5(data: Buffer | string): string { + return createHash('md5').update(data).digest('hex'); +} + +/** + * + * @param length + * @returns + */ +export function generateRandomHexString(length = 8): string { + return pseudoRandomBytes(length).toString('hex'); +} + +export const TOKEN_VALID_LENGTH = 32; + +/** + * Generate a secret of 32 characters. + */ +export function generateRandomSecretKey(): string { + return randomBytes(TOKEN_VALID_LENGTH).toString('base64').substring(0, TOKEN_VALID_LENGTH); +} diff --git a/packages/signature/test/jwt.spec.ts b/packages/signature/test/jwt.spec.ts new file mode 100644 index 000000000..23085de75 --- /dev/null +++ b/packages/signature/test/jwt.spec.ts @@ -0,0 +1,13 @@ +import { createRemoteUser } from '@verdaccio/config'; + +import { signPayload, verifyPayload } from '../src'; + +describe('verifyJWTPayload', () => { + test('should verify the token and return a remote user', async () => { + const remoteUser = createRemoteUser('foo', []); + const token = await signPayload(remoteUser, '12345'); + const verifiedToken = verifyPayload(token, '12345'); + expect(verifiedToken.groups).toEqual(remoteUser.groups); + expect(verifiedToken.name).toEqual(remoteUser.name); + }); +}); diff --git a/packages/signature/test/legacy-token-deprecated.spec.ts b/packages/signature/test/legacy-token-deprecated.spec.ts new file mode 100644 index 000000000..cfdc37ce0 --- /dev/null +++ b/packages/signature/test/legacy-token-deprecated.spec.ts @@ -0,0 +1,23 @@ +import { + aesDecryptDeprecated, + aesEncryptDeprecated, + generateRandomSecretKeyDeprecated, +} from '../src'; + +describe('test deprecated crypto utils', () => { + test('decrypt payload flow', () => { + const secret = generateRandomSecretKeyDeprecated(); + const payload = 'juan:password'; + const token = aesEncryptDeprecated(Buffer.from(payload), secret); + const data = aesDecryptDeprecated(token, secret); + + expect(data.toString()).toEqual(payload.toString()); + }); + + test('crypt fails if secret is incorrect', () => { + const payload = 'juan:password'; + expect(aesEncryptDeprecated(Buffer.from(payload), 'fake_token').toString()).not.toEqual( + Buffer.from(payload) + ); + }); +}); diff --git a/packages/auth/test/legacy-token.spec.ts b/packages/signature/test/legacy-token.spec.ts similarity index 90% rename from packages/auth/test/legacy-token.spec.ts rename to packages/signature/test/legacy-token.spec.ts index 1fe08b9be..62879297e 100644 --- a/packages/auth/test/legacy-token.spec.ts +++ b/packages/signature/test/legacy-token.spec.ts @@ -1,4 +1,4 @@ -import { aesDecrypt, aesEncrypt } from '../src/legacy-token'; +import { aesDecrypt, aesEncrypt } from '../src'; describe('test crypto utils', () => { test('decrypt payload flow', () => { diff --git a/packages/signature/test/utilts.spec.ts b/packages/signature/test/utilts.spec.ts new file mode 100644 index 000000000..57248c08c --- /dev/null +++ b/packages/signature/test/utilts.spec.ts @@ -0,0 +1,18 @@ +import { + TOKEN_VALID_LENGTH, + createTarballHash, + generateRandomSecretKey, + stringToMD5, +} from '../src/utils'; + +test('token generation length is valid', () => { + expect(generateRandomSecretKey()).toHaveLength(TOKEN_VALID_LENGTH); +}); + +test('string to md5 has valid length', () => { + expect(stringToMD5(Buffer.from('foo'))).toHaveLength(32); +}); + +test('create a hash of content', () => { + expect(typeof createTarballHash().update('1').digest('hex')).toEqual('string'); +}); diff --git a/packages/signature/tsconfig.build.json b/packages/signature/tsconfig.build.json new file mode 100644 index 000000000..fcc453bfe --- /dev/null +++ b/packages/signature/tsconfig.build.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./build" + }, + "include": ["src/**/*.ts"], + "exclude": ["src/**/*.test.ts"] +} diff --git a/packages/signature/tsconfig.json b/packages/signature/tsconfig.json new file mode 100644 index 000000000..b13cc4428 --- /dev/null +++ b/packages/signature/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tsconfig.reference.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./build", + "noImplicitAny": false + }, + "include": ["src/**/*.ts", "types/*.d.ts"], + "references": [ + { + "path": "../config" + }, + { + "path": "../utils" + } + ] +} diff --git a/packages/ui-components/package.json b/packages/ui-components/package.json index 8e8a50e7a..98a8e7a2d 100644 --- a/packages/ui-components/package.json +++ b/packages/ui-components/package.json @@ -7,10 +7,6 @@ "homepage": "https://verdaccio.org", "main": "./build/index.js", "types": "build/index.d.ts", - "files": [ - "./build", - "./src" - ], "scripts": { "test": "cross-env TZ=UTC jest --config jest/jest.config.js", "test:html": "cross-env TZ=UTC jest --config jest/jest.config.js --coverage-reporters=html", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 37345fd34..f46c0a406 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -391,11 +391,11 @@ importers: '@verdaccio/core': workspace:6.0.0-6-next.62 '@verdaccio/loaders': workspace:6.0.0-6-next.31 '@verdaccio/logger': workspace:6.0.0-6-next.30 + '@verdaccio/signature': workspace:6.0.0-6-next.1 '@verdaccio/types': workspace:11.0.0-6-next.21 '@verdaccio/utils': workspace:6.0.0-6-next.30 debug: 4.3.4 express: 4.18.2 - jsonwebtoken: 9.0.0 lodash: 4.17.21 verdaccio-htpasswd: workspace:11.0.0-6-next.32 dependencies: @@ -403,10 +403,10 @@ importers: '@verdaccio/core': link:../core/core '@verdaccio/loaders': link:../loaders '@verdaccio/logger': link:../logger/logger + '@verdaccio/signature': link:../signature '@verdaccio/utils': link:../utils debug: 4.3.4 express: 4.18.2 - jsonwebtoken: 9.0.0 lodash: 4.17.21 verdaccio-htpasswd: link:../plugins/htpasswd devDependencies: @@ -1108,6 +1108,21 @@ importers: '@verdaccio/types': link:../../core/types ts-node: 10.9.1_5cc4fd05cdbba7efed0227e61dc065e1 + packages/signature: + specifiers: + '@verdaccio/config': workspace:6.0.0-6-next.62 + '@verdaccio/types': workspace:11.0.0-6-next.21 + debug: 4.3.4 + jsonwebtoken: 9.0.0 + lodash: 4.17.21 + dependencies: + debug: 4.3.4 + jsonwebtoken: 9.0.0 + lodash: 4.17.21 + devDependencies: + '@verdaccio/config': link:../config + '@verdaccio/types': link:../core/types + packages/standalone: specifiers: '@verdaccio/cli': workspace:6.0.0-6-next.62 @@ -10911,7 +10926,7 @@ packages: dev: true /buffer-equal-constant-time/1.0.1: - resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + resolution: {integrity: sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=} /buffer-from/1.1.1: resolution: {integrity: sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==} @@ -15583,7 +15598,7 @@ packages: map-cache: 0.2.2 /fresh/0.5.2: - resolution: {integrity: sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=} + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} /friendly-errors-webpack-plugin/1.7.0_webpack@5.75.0: @@ -18164,7 +18179,7 @@ packages: dev: true /jsonparse/1.3.1: - resolution: {integrity: sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=} + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} engines: {'0': node >= 0.2.0} dev: false @@ -19074,7 +19089,7 @@ packages: dev: true /merge-descriptors/1.0.1: - resolution: {integrity: sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=} + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} /merge-stream/2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}