From d55453db007f587f6d178fa39c679e692d95b948 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Thu, 20 Nov 2025 10:21:56 -0800 Subject: [PATCH 1/3] m --- .github/workflows/prod-release.yml | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/.github/workflows/prod-release.yml b/.github/workflows/prod-release.yml index 1e568174..44927b9c 100644 --- a/.github/workflows/prod-release.yml +++ b/.github/workflows/prod-release.yml @@ -63,14 +63,27 @@ jobs: # Log the commit for posterity git log -n 1 - # Once semantic versioning has run and bumped versions, publish to npm - # TODO: Publish step that doesn't use OTP but instead follows - # https://docs.npmjs.com/trusted-publishers + publish: + runs-on: ubuntu-latest + needs: [pre-release-ci, version] + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: '20' + registry-url: 'https://registry.npmjs.org' + + # Ensure npm 11.5.1 or later is installed + - name: Update npm + run: npm install -g npm@latest + - run: npm ci + - run: npm run build --if-present + - run: npm publish # Once publishing is complete, validate that the published packages are useable validate: uses: ./.github/workflows/shared-ci.yml - # TODO: Uncomment when adding publish step - # needs: [publish] + needs: [publish] with: test-published-packages: true From abf55b9abb943d9e957a57b17c32d49155cf119b Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Thu, 20 Nov 2025 11:02:41 -0800 Subject: [PATCH 2/3] m --- .github/workflows/prod-release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/prod-release.yml b/.github/workflows/prod-release.yml index 44927b9c..a27b3799 100644 --- a/.github/workflows/prod-release.yml +++ b/.github/workflows/prod-release.yml @@ -77,9 +77,9 @@ jobs: # Ensure npm 11.5.1 or later is installed - name: Update npm run: npm install -g npm@latest - - run: npm ci + - run: npm ci --unsafe-perm - run: npm run build --if-present - - run: npm publish + - run: npx lerna publish from-package --yes --dist-tag ${{ github.event.inputs.dist_tag }} # Once publishing is complete, validate that the published packages are useable validate: From 08ca9675a87f257c1d36c4bfdfcd0847c505adee Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Tue, 10 Feb 2026 10:49:12 -0800 Subject: [PATCH 3/3] Remove @aws-crypto/ie11-detection dependency - Remove dependency from web-crypto-backend package.json - Remove IE11 code paths from backend-factory.ts and synchronous_random_values.ts - Delete promisify-ms-crypto.ts (IE11-specific) - Remove IE11-specific tests and fixtures This removes IE11 support. Modern browsers with standard WebCrypto API are now required. Breaking change: IE11 is no longer supported. --- modules/web-crypto-backend/package.json | 1 - .../web-crypto-backend/src/backend-factory.ts | 3 - .../src/promisify-ms-crypto.ts | 38 ----- .../src/synchronous_random_values.ts | 5 - modules/web-crypto-backend/test/fixtures.ts | 149 +----------------- .../test/promisify-ms-crypto.test.ts | 36 ----- .../test/synchronous_random_values.test.ts | 12 +- package-lock.json | 13 +- 8 files changed, 8 insertions(+), 249 deletions(-) delete mode 100644 modules/web-crypto-backend/src/promisify-ms-crypto.ts delete mode 100644 modules/web-crypto-backend/test/promisify-ms-crypto.test.ts diff --git a/modules/web-crypto-backend/package.json b/modules/web-crypto-backend/package.json index 9bb91371..38b70346 100644 --- a/modules/web-crypto-backend/package.json +++ b/modules/web-crypto-backend/package.json @@ -19,7 +19,6 @@ }, "license": "Apache-2.0", "dependencies": { - "@aws-crypto/ie11-detection": "4.0.0", "@aws-crypto/supports-web-crypto": "5.2.0", "@aws-sdk/util-locate-window": "3.310.0", "tslib": "^2.2.0" diff --git a/modules/web-crypto-backend/src/backend-factory.ts b/modules/web-crypto-backend/src/backend-factory.ts index 289dd8a5..df843a86 100644 --- a/modules/web-crypto-backend/src/backend-factory.ts +++ b/modules/web-crypto-backend/src/backend-factory.ts @@ -1,14 +1,12 @@ // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -import { isMsWindow } from '@aws-crypto/ie11-detection' import { supportsWebCrypto, supportsSubtleCrypto, supportsZeroByteGCM, } from '@aws-crypto/supports-web-crypto' import { generateSynchronousRandomValues } from './synchronous_random_values' -import promisifyMsSubtleCrypto from './promisify-ms-crypto' type MaybeSubtleCrypto = SubtleCrypto | false export type WebCryptoBackend = @@ -140,7 +138,6 @@ export function pluckSubtleCrypto(window: Window): MaybeSubtleCrypto { // if needed webkitSubtle check should be added here // see: https://webkit.org/blog/7790/update-on-web-cryptography/ if (supportsWebCrypto(window)) return window.crypto.subtle - if (isMsWindow(window)) return promisifyMsSubtleCrypto(window.msCrypto.subtle) return false } diff --git a/modules/web-crypto-backend/src/promisify-ms-crypto.ts b/modules/web-crypto-backend/src/promisify-ms-crypto.ts deleted file mode 100644 index 4c17e629..00000000 --- a/modules/web-crypto-backend/src/promisify-ms-crypto.ts +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -import { MsSubtleCrypto } from '@aws-crypto/ie11-detection' - -type MsSubtleFunctions = keyof MsSubtleCrypto - -export default function promisifyMsSubtleCrypto(backend: MsSubtleCrypto) { - const usages: MsSubtleFunctions[] = [ - 'decrypt', - 'digest', - 'encrypt', - 'exportKey', - 'generateKey', - 'importKey', - 'sign', - 'verify', - ] - const decorateUsage = (fakeBackend: any, usage: MsSubtleFunctions) => - decorate(backend, fakeBackend, usage) - return usages.reduce(decorateUsage, {}) as SubtleCrypto -} - -function decorate( - subtle: MsSubtleCrypto, - fakeBackend: any, - name: MsSubtleFunctions -) { - fakeBackend[name] = async (...args: any[]) => { - return new Promise((resolve, reject) => { - // @ts-ignore - const operation = subtle[name](...args) - operation.oncomplete = () => resolve(operation.result) - operation.onerror = reject - }) - } - return fakeBackend -} diff --git a/modules/web-crypto-backend/src/synchronous_random_values.ts b/modules/web-crypto-backend/src/synchronous_random_values.ts index 0a0147c0..86cfdba3 100644 --- a/modules/web-crypto-backend/src/synchronous_random_values.ts +++ b/modules/web-crypto-backend/src/synchronous_random_values.ts @@ -1,7 +1,6 @@ // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -import { isMsWindow } from '@aws-crypto/ie11-detection' import { supportsSecureRandom } from '@aws-crypto/supports-web-crypto' import { locateWindow } from '@aws-sdk/util-locate-window' @@ -19,10 +18,6 @@ export function generateSynchronousRandomValues( return function synchronousRandomValues(byteLength: number): Uint8Array { if (supportsSecureRandom(globalScope)) { return globalScope.crypto.getRandomValues(new Uint8Array(byteLength)) - } else if (isMsWindow(globalScope)) { - const values = new Uint8Array(byteLength) - globalScope.msCrypto.getRandomValues(values) - return values } throw new Error(`Unable to locate a secure random source.`) diff --git a/modules/web-crypto-backend/test/fixtures.ts b/modules/web-crypto-backend/test/fixtures.ts index edddc884..cc51f9fe 100644 --- a/modules/web-crypto-backend/test/fixtures.ts +++ b/modules/web-crypto-backend/test/fixtures.ts @@ -3,7 +3,12 @@ export const fakeWindowWebCryptoSupportsZeroByteGCM: Window = { crypto: { - getRandomValues: () => {}, + getRandomValues: (array: Uint8Array) => { + for (let i = 0; i < array.length; i++) { + array[i] = Math.floor(Math.random() * 256) + } + return array + }, subtle: { async decrypt() { return {} as any @@ -142,145 +147,3 @@ export const subtleFallbackZeroByteEncryptFail = { } as any export const subtleFallbackNoWebCrypto = {} as any - -export const fakeWindowIE11OnComplete = { - msCrypto: { - getRandomValues: (values: Uint8Array) => { - return values.fill(1) - }, - subtle: { - decrypt() { - const obj = {} as any - setTimeout(() => { - obj.result = true - obj.oncomplete() - }) - return obj - }, - digest() { - const obj = {} as any - setTimeout(() => { - obj.result = true - obj.oncomplete() - }) - return obj - }, - encrypt() { - const obj = {} as any - setTimeout(() => { - obj.result = true - obj.oncomplete() - }) - return obj - }, - exportKey() { - const obj = {} as any - setTimeout(() => { - obj.result = true - obj.oncomplete() - }) - return obj - }, - generateKey() { - const obj = {} as any - setTimeout(() => { - obj.result = true - obj.oncomplete() - }) - return obj - }, - importKey() { - const obj = {} as any - setTimeout(() => { - obj.result = true - obj.oncomplete() - }) - return obj - }, - sign() { - const obj = {} as any - setTimeout(() => { - obj.result = true - obj.oncomplete() - }) - return obj - }, - verify() { - const obj = {} as any - setTimeout(() => { - obj.result = true - obj.oncomplete() - }) - return obj - }, - }, - }, - MSInputMethodContext: {} as any, -} as any - -export const fakeWindowIE11OnError = { - msCrypto: { - getRandomValues: (values: Uint8Array) => { - return values.fill(1) - }, - subtle: { - decrypt() { - const obj = {} as any - setTimeout(() => { - obj.onerror(new Error('stub error')) - }) - return obj - }, - digest() { - const obj = {} as any - setTimeout(() => { - obj.onerror(new Error('stub error')) - }) - return obj - }, - encrypt() { - const obj = {} as any - setTimeout(() => { - obj.onerror(new Error('stub error')) - }) - return obj - }, - exportKey() { - const obj = {} as any - setTimeout(() => { - obj.onerror(new Error('stub error')) - }) - return obj - }, - generateKey() { - const obj = {} as any - setTimeout(() => { - obj.onerror(new Error('stub error')) - }) - return obj - }, - importKey() { - const obj = {} as any - setTimeout(() => { - obj.onerror(new Error('stub error')) - }) - return obj - }, - sign() { - const obj = {} as any - setTimeout(() => { - obj.onerror(new Error('stub error')) - }) - return obj - }, - verify() { - const obj = {} as any - setTimeout(() => { - obj.onerror(new Error('stub error')) - }) - return obj - }, - }, - }, - MSInputMethodContext: {} as any, -} as any diff --git a/modules/web-crypto-backend/test/promisify-ms-crypto.test.ts b/modules/web-crypto-backend/test/promisify-ms-crypto.test.ts deleted file mode 100644 index 7c420478..00000000 --- a/modules/web-crypto-backend/test/promisify-ms-crypto.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -/* eslint-env mocha */ - -import * as chai from 'chai' -import chaiAsPromised from 'chai-as-promised' -import promisifyMsSubtleCrypto from '../src/promisify-ms-crypto' -import * as fixtures from './fixtures' - -chai.use(chaiAsPromised) -const { expect } = chai - -/* These tests are very simple - * I am not testing every subtle function - * because the promisify code is all the same. - */ -describe('promisifyMsSubtleCrypto', () => { - const backendComplete = promisifyMsSubtleCrypto( - fixtures.fakeWindowIE11OnComplete.msCrypto.subtle - ) - const backendError = promisifyMsSubtleCrypto( - fixtures.fakeWindowIE11OnError.msCrypto.subtle - ) - - it('backendComplete:decrypt', async () => { - // @ts-ignore These methods are stubs, ignore ts errors - const test = await backendComplete.decrypt() - expect(test).to.equal(true) - }) - - it('backendError:decrypt', async () => { - // @ts-ignore These methods are stubs, ignore ts errors - await expect(backendError.decrypt()).to.rejectedWith(Error) - }) -}) diff --git a/modules/web-crypto-backend/test/synchronous_random_values.test.ts b/modules/web-crypto-backend/test/synchronous_random_values.test.ts index 1c8d5245..8e3a06bf 100644 --- a/modules/web-crypto-backend/test/synchronous_random_values.test.ts +++ b/modules/web-crypto-backend/test/synchronous_random_values.test.ts @@ -5,25 +5,15 @@ import { expect } from 'chai' import { generateSynchronousRandomValues } from '../src/synchronous_random_values' -import { synchronousRandomValues } from '../src/index' import * as fixtures from './fixtures' describe('synchronousRandomValues', () => { it('should return random values', () => { - const test = synchronousRandomValues(5) - expect(test).to.be.instanceOf(Uint8Array) - expect(test).lengthOf(5) - }) - - it('should return msCrypto random values', () => { const synchronousRandomValues = generateSynchronousRandomValues( - fixtures.fakeWindowIE11OnComplete + fixtures.fakeWindowWebCryptoSupportsZeroByteGCM ) - const test = synchronousRandomValues(5) expect(test).to.be.instanceOf(Uint8Array) expect(test).lengthOf(5) - // The random is a stub, so I know the value - expect(test).to.deep.equal(new Uint8Array(5).fill(1)) }) }) diff --git a/package-lock.json b/package-lock.json index 6a4bf439..e5bea0bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -415,6 +415,7 @@ "@types/stream-to-promise": "^2.2.0", "@types/yargs": "^17.0.1", "buffer": "^6.0.3", + "end-of-stream": "<=1.4.4", "got": "^11.8.0", "jasmine-core": "^3.5.0", "karma": "^6.3.4", @@ -710,23 +711,11 @@ "version": "4.0.1", "license": "Apache-2.0", "dependencies": { - "@aws-crypto/ie11-detection": "4.0.0", "@aws-crypto/supports-web-crypto": "5.2.0", "@aws-sdk/util-locate-window": "3.310.0", "tslib": "^2.2.0" } }, - "modules/web-crypto-backend/node_modules/@aws-crypto/ie11-detection": { - "version": "4.0.0", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^1.11.1" - } - }, - "modules/web-crypto-backend/node_modules/@aws-crypto/ie11-detection/node_modules/tslib": { - "version": "1.14.1", - "license": "0BSD" - }, "modules/web-crypto-backend/node_modules/@aws-sdk/util-locate-window": { "version": "3.310.0", "license": "Apache-2.0",