From a3d1fea0475a6d0fac162505f1be32f1d3ae45dc Mon Sep 17 00:00:00 2001 From: Michael D'Angelo Date: Wed, 29 Jul 2026 14:42:48 -0700 Subject: [PATCH 1/4] fix: harden npm package lifecycle and Node support --- .github/workflows/node-ci.yml | 12 +++++++++-- .github/workflows/node-release.yml | 3 +++ README.md | 2 +- sdk/typescript/README.md | 2 +- sdk/typescript/package.json | 4 +++- sdk/typescript/tests-ts/skeleton.test.ts | 26 ++++++++++++++++++++++++ 6 files changed, 44 insertions(+), 5 deletions(-) diff --git a/.github/workflows/node-ci.yml b/.github/workflows/node-ci.yml index fb527340..099196d7 100644 --- a/.github/workflows/node-ci.yml +++ b/.github/workflows/node-ci.yml @@ -10,12 +10,16 @@ permissions: jobs: test: - name: ${{ matrix.os }} / node-22 + name: ${{ matrix.os }} / node-${{ matrix.node }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] + node: ["22"] + include: + - os: ubuntu-latest + node: "24" steps: - name: Checkout repository @@ -26,7 +30,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6 with: - node-version: "22" + node-version: ${{ matrix.node }} - name: Set up Bun uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 @@ -40,6 +44,10 @@ jobs: - name: Install dependencies run: pnpm --dir sdk/typescript install --frozen-lockfile + - name: Audit production dependencies + if: matrix.os == 'ubuntu-latest' && matrix.node == '22' + run: pnpm --dir sdk/typescript run audit:prod + - name: Typecheck run: pnpm --dir sdk/typescript run types diff --git a/.github/workflows/node-release.yml b/.github/workflows/node-release.yml index 828b1994..c06cec7b 100644 --- a/.github/workflows/node-release.yml +++ b/.github/workflows/node-release.yml @@ -97,6 +97,9 @@ jobs: - name: Install dependencies run: sfw pnpm --dir sdk/typescript install --frozen-lockfile + - name: Audit production dependencies + run: sfw pnpm --dir sdk/typescript run audit:prod + - name: Verify run: | pnpm --dir sdk/typescript run types diff --git a/README.md b/README.md index 9f2cd146..715b012e 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ## Quick start -Requires Node.js 22 or later, Python 3.10 or later, and access to Codex Security. +Requires Node.js 22.13.0 or later, Python 3.10 or later, and access to Codex Security. ```bash npm install @openai/codex-security diff --git a/sdk/typescript/README.md b/sdk/typescript/README.md index 8d069014..cd7c8259 100644 --- a/sdk/typescript/README.md +++ b/sdk/typescript/README.md @@ -15,7 +15,7 @@ npm install @openai/codex-security npx @openai/codex-security --version ``` -The package supports macOS, Linux, and Windows and requires Node.js 22 or +The package supports macOS, Linux, and Windows and requires Node.js 22.13.0 or later. Scanning and exporting findings also require Python 3.10 or later. If you use Python 3.10, install the `tomli` package. Select another interpreter with `--python`, `pythonPath`, or `PYTHON` when needed. diff --git a/sdk/typescript/package.json b/sdk/typescript/package.json index a3760f70..e0abf780 100644 --- a/sdk/typescript/package.json +++ b/sdk/typescript/package.json @@ -13,7 +13,7 @@ "bugs": "https://github.com/openai/codex-security/issues", "type": "module", "engines": { - "node": ">=22" + "node": ">=22.13.0" }, "packageManager": "pnpm@11.9.0+sha512.bd682d5d03fe525ef7c9fd6780c6884d1e756ac4c9c9fe00c538782824310dcf90e3ddc4f53835f06dfaebd5085e41855e0bcbb3b60de2ac5bbab89e5036f03b", "main": "./dist/index.js", @@ -39,6 +39,7 @@ "access": "public" }, "scripts": { + "audit:prod": "pnpm audit --prod --audit-level high", "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"", "build": "pnpm run clean && tsc -p tsconfig.build.json", "check:package": "node scripts/check-package.mjs", @@ -46,6 +47,7 @@ "generate:models": "node scripts/generate-models.cjs", "generate:models:check": "node scripts/generate-models.cjs --check", "lint": "tsc --noEmit", + "prepack": "pnpm run build", "test": "bun test --timeout 30000 ./tests-ts", "test:package": "node scripts/smoke-package.mjs", "types": "pnpm run generate:models:check && tsc --noEmit" diff --git a/sdk/typescript/tests-ts/skeleton.test.ts b/sdk/typescript/tests-ts/skeleton.test.ts index cc5df587..dab3b627 100644 --- a/sdk/typescript/tests-ts/skeleton.test.ts +++ b/sdk/typescript/tests-ts/skeleton.test.ts @@ -28,6 +28,32 @@ function capture(): { } describe("TypeScript package skeleton", () => { + test("advertises only compatible Node.js releases", async () => { + const packageJson = JSON.parse( + await readFile(new URL("../package.json", import.meta.url), "utf8"), + ); + + expect(Bun.semver.satisfies("22.12.0", packageJson.engines.node)).toBe( + false, + ); + expect(Bun.semver.satisfies("22.13.0", packageJson.engines.node)).toBe( + true, + ); + expect(Bun.semver.satisfies("24.0.0", packageJson.engines.node)).toBe(true); + expect(Bun.semver.satisfies("26.0.0", packageJson.engines.node)).toBe(true); + }); + + test("builds packages before packing and provides a production audit", async () => { + const packageJson = JSON.parse( + await readFile(new URL("../package.json", import.meta.url), "utf8"), + ); + + expect(packageJson.scripts.prepack).toBe("pnpm run build"); + expect(packageJson.scripts["audit:prod"]).toBe( + "pnpm audit --prod --audit-level high", + ); + }); + test("exposes canonical finding and hardening fields with public types", () => { const finding = {} as Finding; const scan = {} as ScanRecord; From 2856cd8c89883325a9052ed9b0722a3f18ba9305 Mon Sep 17 00:00:00 2001 From: Michael D'Angelo Date: Wed, 29 Jul 2026 16:59:46 -0700 Subject: [PATCH 2/4] fix: make npm package lifecycle package-manager agnostic --- sdk/typescript/package.json | 4 ++-- sdk/typescript/tests-ts/skeleton.test.ts | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/sdk/typescript/package.json b/sdk/typescript/package.json index 5bb1d021..ac9479c7 100644 --- a/sdk/typescript/package.json +++ b/sdk/typescript/package.json @@ -41,13 +41,13 @@ "scripts": { "audit:prod": "pnpm audit --prod --audit-level high", "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"", - "build": "pnpm run clean && tsc -p tsconfig.build.json", + "build": "node --run clean && tsc -p tsconfig.build.json", "check:package": "node scripts/check-package.mjs", "format": "prettier --check --ignore-path .gitignore --ignore-path .prettierignore \"**/*.{cjs,mjs,js,ts,json,md}\"", "generate:models": "node scripts/generate-models.cjs", "generate:models:check": "node scripts/generate-models.cjs --check", "lint": "tsc --noEmit", - "prepack": "pnpm run build", + "prepack": "node --run build", "test": "bun test --timeout 30000 ./tests-ts", "test:package": "node scripts/smoke-package.mjs", "types": "pnpm run generate:models:check && tsc --noEmit" diff --git a/sdk/typescript/tests-ts/skeleton.test.ts b/sdk/typescript/tests-ts/skeleton.test.ts index 46d9377e..75186d76 100644 --- a/sdk/typescript/tests-ts/skeleton.test.ts +++ b/sdk/typescript/tests-ts/skeleton.test.ts @@ -55,12 +55,15 @@ describe("TypeScript package skeleton", () => { ).toEqual([]); }); - test("builds packages before packing and provides a production audit", async () => { + test("builds packages without a preinstalled package manager and provides a production audit", async () => { const packageJson = JSON.parse( await readFile(new URL("../package.json", import.meta.url), "utf8"), ); - expect(packageJson.scripts.prepack).toBe("pnpm run build"); + expect(packageJson.scripts.build).toBe( + "node --run clean && tsc -p tsconfig.build.json", + ); + expect(packageJson.scripts.prepack).toBe("node --run build"); expect(packageJson.scripts["audit:prod"]).toBe( "pnpm audit --prod --audit-level high", ); From 9a7520e19f388b28d8d88815bda3556022b9f2e5 Mon Sep 17 00:00:00 2001 From: Michael D'Angelo Date: Wed, 29 Jul 2026 17:06:50 -0700 Subject: [PATCH 3/4] fix: test every supported minimum Node.js version --- .github/workflows/node-ci.yml | 4 ++++ sdk/typescript/tests-ts/skeleton.test.ts | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/.github/workflows/node-ci.yml b/.github/workflows/node-ci.yml index cf79e27e..2be37c61 100644 --- a/.github/workflows/node-ci.yml +++ b/.github/workflows/node-ci.yml @@ -23,8 +23,12 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] node: ["22.13.0"] include: + - os: ubuntu-latest + node: "24.0.0" - os: ubuntu-latest node: "24" + - os: ubuntu-latest + node: "26.0.0" - os: ubuntu-latest node: "26" diff --git a/sdk/typescript/tests-ts/skeleton.test.ts b/sdk/typescript/tests-ts/skeleton.test.ts index 75186d76..23e6e266 100644 --- a/sdk/typescript/tests-ts/skeleton.test.ts +++ b/sdk/typescript/tests-ts/skeleton.test.ts @@ -55,6 +55,18 @@ describe("TypeScript package skeleton", () => { ).toEqual([]); }); + test("pins each supported Node.js minimum and retains latest LTS coverage", async () => { + const ciWorkflow = await readFile( + new URL("../../../.github/workflows/node-ci.yml", import.meta.url), + "utf8", + ); + + expect(ciWorkflow).toContain('node: ["22.13.0"]'); + for (const version of ["24.0.0", "24", "26.0.0", "26"]) { + expect(ciWorkflow).toContain(`node: "${version}"`); + } + }); + test("builds packages without a preinstalled package manager and provides a production audit", async () => { const packageJson = JSON.parse( await readFile(new URL("../package.json", import.meta.url), "utf8"), From a75ed5c3ba47e893ff9d4e17bcaa17fdad2c5ee6 Mon Sep 17 00:00:00 2001 From: Michael D'Angelo Date: Wed, 29 Jul 2026 17:14:01 -0700 Subject: [PATCH 4/4] fix: preserve required Node CI status checks --- .github/workflows/node-ci.yml | 2 +- sdk/typescript/tests-ts/skeleton.test.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/node-ci.yml b/.github/workflows/node-ci.yml index 2be37c61..c3b41308 100644 --- a/.github/workflows/node-ci.yml +++ b/.github/workflows/node-ci.yml @@ -14,7 +14,7 @@ concurrency: jobs: test: - name: ${{ matrix.os }} / node-${{ matrix.node }} + name: ${{ matrix.os }} / node-${{ matrix.node == '22.13.0' && '22' || matrix.node }} runs-on: ${{ matrix.os }} timeout-minutes: 20 strategy: diff --git a/sdk/typescript/tests-ts/skeleton.test.ts b/sdk/typescript/tests-ts/skeleton.test.ts index 23e6e266..c97fe65e 100644 --- a/sdk/typescript/tests-ts/skeleton.test.ts +++ b/sdk/typescript/tests-ts/skeleton.test.ts @@ -55,12 +55,15 @@ describe("TypeScript package skeleton", () => { ).toEqual([]); }); - test("pins each supported Node.js minimum and retains latest LTS coverage", async () => { + test("pins each Node.js minimum and preserves protected and latest LTS checks", async () => { const ciWorkflow = await readFile( new URL("../../../.github/workflows/node-ci.yml", import.meta.url), "utf8", ); + expect(ciWorkflow).toContain( + "${{ matrix.node == '22.13.0' && '22' || matrix.node }}", + ); expect(ciWorkflow).toContain('node: ["22.13.0"]'); for (const version of ["24.0.0", "24", "26.0.0", "26"]) { expect(ciWorkflow).toContain(`node: "${version}"`);