From 2f2b2d937f2b41bff5bd6ae97ef90d456ca00e42 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 4 Oct 2026 23:55:13 +0000 Subject: [PATCH 1/2] Bump @peculiar/x509 from 1.14.3 to 2.1.0 Bumps [@peculiar/x509](https://github.com/PeculiarVentures/x509) from 1.14.3 to 2.1.0. - [Release notes](https://github.com/PeculiarVentures/x509/releases) - [Commits](https://github.com/PeculiarVentures/x509/compare/v1.14.3...v2.1.0) --- updated-dependencies: - dependency-name: "@peculiar/x509" dependency-version: 2.1.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package-lock.json | 62 +++++++++++++++++++++++++++++++++-------------- package.json | 2 +- 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/package-lock.json b/package-lock.json index 45fdb28..5f0884e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@peculiar/asn1-schema": "^2.10.0", "@peculiar/asn1-x509": "^2.10.0", - "@peculiar/x509": "^1.14.0" + "@peculiar/x509": "^2.1.0" }, "devDependencies": { "@axe-core/playwright": "^4.13.0", @@ -72,6 +72,22 @@ "url": "https://github.com/sponsors/oxc-project" } }, + "node_modules/@peculiar/asn1-asym-key": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-asym-key/-/asn1-asym-key-2.10.0.tgz", + "integrity": "sha512-1R8xUTeqcUTSMLFTTCzJyFuKiq3y25EQKs9DezUetJ8qMqbJyxo3XkzykiwwT/Xzlt5/vRzS/sW4M1r+pq1FTg==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-pkcs8": "^2.10.0", + "@peculiar/asn1-schema": "^2.10.0", + "@peculiar/asn1-x509": "^2.10.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/@peculiar/asn1-cms": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.10.0.tgz", @@ -228,6 +244,22 @@ "node": ">=14" } }, + "node_modules/@peculiar/asn1-x509-post-quantum": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-post-quantum/-/asn1-x509-post-quantum-2.10.0.tgz", + "integrity": "sha512-cXKcZ30wKbUkRK5RK4Z3W1imewXvHAB9apEAuIqJ0OOkOQCpJrwLOuN38QlsEXqOI+3gtUv8Kf3UZohUmCbf3w==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-asym-key": "^2.10.0", + "@peculiar/asn1-schema": "^2.10.0", + "@peculiar/asn1-x509": "^2.10.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/@peculiar/utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@peculiar/utils/-/utils-2.0.3.tgz", @@ -238,20 +270,20 @@ } }, "node_modules/@peculiar/x509": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.14.3.tgz", - "integrity": "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-2.1.0.tgz", + "integrity": "sha512-IYbg1R03CSQGWwl24kGyqrdVtixNSbRaDvBg1r5wyYjTP+VwPQkka1BzTgU5+vxiuwqg04OxdvdJ1xYYFIdUSA==", "license": "MIT", "dependencies": { - "@peculiar/asn1-cms": "^2.6.0", - "@peculiar/asn1-csr": "^2.6.0", - "@peculiar/asn1-ecc": "^2.6.0", - "@peculiar/asn1-pkcs9": "^2.6.0", - "@peculiar/asn1-rsa": "^2.6.0", - "@peculiar/asn1-schema": "^2.6.0", - "@peculiar/asn1-x509": "^2.6.0", + "@peculiar/asn1-cms": "^2.9.4", + "@peculiar/asn1-csr": "^2.9.4", + "@peculiar/asn1-ecc": "^2.9.4", + "@peculiar/asn1-pkcs9": "^2.9.4", + "@peculiar/asn1-rsa": "^2.9.4", + "@peculiar/asn1-schema": "^2.9.4", + "@peculiar/asn1-x509": "^2.9.4", + "@peculiar/asn1-x509-post-quantum": "^2.9.4", "pvtsutils": "^1.3.6", - "reflect-metadata": "^0.2.2", "tslib": "^2.8.1", "tsyringe": "^4.10.0" }, @@ -1154,12 +1186,6 @@ "node": ">=16.0.0" } }, - "node_modules/reflect-metadata": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", - "license": "Apache-2.0" - }, "node_modules/rolldown": { "version": "1.2.12", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.12.tgz", diff --git a/package.json b/package.json index 7a05874..49940d3 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,6 @@ "dependencies": { "@peculiar/asn1-schema": "^2.10.0", "@peculiar/asn1-x509": "^2.10.0", - "@peculiar/x509": "^1.14.0" + "@peculiar/x509": "^2.1.0" } } From ed40f30ebe3f4a25740da481d89e851a983264a8 Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Sun, 11 Oct 2026 18:41:05 -0400 Subject: [PATCH 2/2] Initialize Reflect metadata for X.509 2 entry points --- package-lock.json | 9 +++++- package.json | 3 +- scripts/mint-toy-pki.mjs | 2 ++ src/pki/bootstrap.test.ts | 63 +++++++++++++++++++++++++++++++++++++++ src/pki/parse.ts | 2 ++ 5 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 src/pki/bootstrap.test.ts diff --git a/package-lock.json b/package-lock.json index 3b00112..152eaa1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,8 @@ "dependencies": { "@peculiar/asn1-schema": "^2.10.0", "@peculiar/asn1-x509": "^2.10.0", - "@peculiar/x509": "^2.1.0" + "@peculiar/x509": "^2.1.0", + "reflect-metadata": "^0.2.2" }, "devDependencies": { "@axe-core/playwright": "^4.13.0", @@ -1526,6 +1527,12 @@ "node": ">=16.0.0" } }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "license": "Apache-2.0" + }, "node_modules/rolldown": { "version": "1.2.12", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.12.tgz", diff --git a/package.json b/package.json index 6c30f2f..2fdfc3b 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "dependencies": { "@peculiar/asn1-schema": "^2.10.0", "@peculiar/asn1-x509": "^2.10.0", - "@peculiar/x509": "^2.1.0" + "@peculiar/x509": "^2.1.0", + "reflect-metadata": "^0.2.2" } } diff --git a/scripts/mint-toy-pki.mjs b/scripts/mint-toy-pki.mjs index fb6bb9a..6c46061 100644 --- a/scripts/mint-toy-pki.mjs +++ b/scripts/mint-toy-pki.mjs @@ -34,6 +34,8 @@ * deliberately, and update that file when you do. */ +// The standalone entry point must initialize X.509 2 independently of the UI. +import 'reflect-metadata' import { webcrypto } from 'node:crypto' import { writeFileSync } from 'node:fs' import { fileURLToPath } from 'node:url' diff --git a/src/pki/bootstrap.test.ts b/src/pki/bootstrap.test.ts new file mode 100644 index 0000000..951646d --- /dev/null +++ b/src/pki/bootstrap.test.ts @@ -0,0 +1,63 @@ +import { spawnSync } from 'node:child_process' +import { X509Certificate } from 'node:crypto' +import { copyFileSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, symlinkSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { fileURLToPath } from 'node:url' +import { describe, expect, it } from 'vitest' + +const root = fileURLToPath(new URL('../../', import.meta.url)) +const childEnvironment = { ...process.env, NODE_OPTIONS: '' } + +describe('X.509 entry points in a fresh process', () => { + it('initializes the application parser before loading the SDK, without a test setup polyfill', () => { + const parser = new URL('./parse.ts', import.meta.url).href + const certificate = fileURLToPath(new URL('../../certs/real-github-leaf.pem', import.meta.url)) + const result = spawnSync(process.execPath, ['--experimental-strip-types', '--input-type=module', '--eval', ` + import assert from 'node:assert/strict' + import { readFileSync } from 'node:fs' + assert.equal(typeof Reflect.getMetadata, 'undefined') + const { parsePem, commonName, fingerprint } = await import(${JSON.stringify(parser)}) + const cert = parsePem(readFileSync(${JSON.stringify(certificate)}, 'utf8')) + assert.equal(commonName(cert), 'github.com') + assert.equal(await fingerprint(cert), '46b601ee08b418cf8a3a1ebfe670ba5ce43bb05a917fa8b2dd087a30471cfc63') + console.log('cold parser and certificate KAT passed') + `], { cwd: root, env: childEnvironment, encoding: 'utf8', timeout: 30_000 }) + expect(result.error).toBeUndefined() + expect(result.status, result.stderr).toBe(0) + expect(result.stdout).toContain('cold parser and certificate KAT passed') + }) + + it('initializes the standalone minter and verifies all signatures in isolated scratch', () => { + // The real script rotates the toy keys. Copy it into owned scratch so this + // regression never replaces the vendored certificates or their KATs. + const scratch = mkdtempSync(join(tmpdir(), 'padlock-minter-bootstrap-')) + try { + mkdirSync(join(scratch, 'scripts')) + mkdirSync(join(scratch, 'certs')) + copyFileSync(join(root, 'scripts/mint-toy-pki.mjs'), join(scratch, 'scripts/mint-toy-pki.mjs')) + symlinkSync(join(root, 'node_modules'), join(scratch, 'node_modules')) + const result = spawnSync(process.execPath, ['scripts/mint-toy-pki.mjs'], { + cwd: scratch, env: childEnvironment, encoding: 'utf8', timeout: 30_000, + }) + expect(result.error).toBeUndefined() + expect(result.status, result.stderr).toBe(0) + expect(result.stdout.match(/\bverified\b/g)).toHaveLength(4) + expect(readdirSync(join(scratch, 'certs')).sort()).toEqual([ + 'toy-attacker-leaf.pem', 'toy-dv-ca.pem', 'toy-root.pem', 'toy-selfsigned-leaf.pem', + ]) + const cert = (name: string) => new X509Certificate(readFileSync(join(scratch, 'certs', name))) + const rootCert = cert('toy-root.pem') + const dv = cert('toy-dv-ca.pem') + const attacker = cert('toy-attacker-leaf.pem') + const selfSigned = cert('toy-selfsigned-leaf.pem') + expect(dv.verify(rootCert.publicKey)).toBe(true) + expect(attacker.verify(dv.publicKey)).toBe(true) + expect(rootCert.verify(rootCert.publicKey)).toBe(true) + expect(selfSigned.verify(selfSigned.publicKey)).toBe(true) + expect(attacker.subjectAltName).toBe('DNS:login.yourbank-security.example') + } finally { + rmSync(scratch, { recursive: true, force: true }) + } + }) +}) diff --git a/src/pki/parse.ts b/src/pki/parse.ts index 57b7e5a..736d579 100644 --- a/src/pki/parse.ts +++ b/src/pki/parse.ts @@ -1,3 +1,5 @@ +// X.509 2 requires Reflect metadata before its dependency-injection setup runs. +import 'reflect-metadata' import * as x509 from '@peculiar/x509' import type { Validity } from './types'