From 6f5b8a56613daa153b8f9cba5047d20f01f0a8e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E7=88=AC=E7=9A=84=E8=80=81=E7=B2=89=E4=B8=9D?= <727842003@qq.com> Date: Sun, 11 Oct 2026 14:06:05 +0800 Subject: [PATCH 1/2] fix: restore complete security checks for dependency updates --- .eslintignore | 1 - .eslintrc | 98 +- .github/actions/corpus/action.yml | 10 +- .github/workflows/ci.yml | 5 +- .github/workflows/publish.yml | 3 +- .github/workflows/rebase.yml | 18 +- .github/workflows/require-allow-edits.yml | 4 + .github/workflows/security-regression.yml | 2 + bin/xlsx.njs | 1 - eslint.config.mjs | 28 + index.html | 1 - package-lock.json | 1213 +++++++++++---------- package.json | 8 +- tests/tooling-config.mjs | 51 + 14 files changed, 846 insertions(+), 597 deletions(-) delete mode 100644 .eslintignore create mode 100644 eslint.config.mjs create mode 100644 tests/tooling-config.mjs diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index ce7ed79a..00000000 --- a/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -xlsx.js diff --git a/.eslintrc b/.eslintrc index dfb762e5..0db3b961 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,26 +1,96 @@ { - "env": { "shared-node-browser":true }, + "env": { + "shared-node-browser": true + }, "globals": {}, "parserOptions": { "ecmaVersion": 3 }, - "plugins": [ "html", "json" ], - "extends": "eslint:recommended", + "plugins": [ + "html", + "json" + ], "rules": { - "comma-style": [ 2, "last" ], - "comma-dangle": [ 2, "never" ], - "curly": 0, - "no-bitwise": 0, + "constructor-super": "error", + "for-direction": "error", + "getter-return": "error", + "no-async-promise-executor": "error", + "no-case-declarations": "error", + "no-class-assign": "error", + "no-compare-neg-zero": "error", "no-cond-assign": 1, - "no-console": 0, + "no-const-assign": "error", + "no-constant-condition": "error", "no-control-regex": 0, - "no-unused-vars": 1, + "no-debugger": "error", + "no-delete-var": "error", + "no-dupe-args": "error", + "no-dupe-class-members": "error", + "no-dupe-else-if": "error", + "no-dupe-keys": "error", + "no-duplicate-case": "error", "no-empty": 0, - "no-trailing-spaces": 2, - "no-use-before-define": [ 1, { - "functions":false, "classes":true, "variables":false - }], + "no-empty-character-class": "error", + "no-empty-pattern": "error", + "no-ex-assign": "error", + "no-extra-boolean-cast": "error", + "no-extra-semi": "error", + "no-fallthrough": "error", + "no-func-assign": "error", + "no-global-assign": "error", + "no-import-assign": "error", + "no-inner-declarations": "error", + "no-invalid-regexp": "error", + "no-irregular-whitespace": "error", + "no-misleading-character-class": "error", + "no-mixed-spaces-and-tabs": "error", + "no-obj-calls": "error", + "no-octal": "error", + "no-prototype-builtins": "error", + "no-redeclare": "error", + "no-regex-spaces": "error", + "no-self-assign": "error", + "no-setter-return": "error", + "no-shadow-restricted-names": "error", + "no-sparse-arrays": "error", + "no-this-before-super": "error", + "no-undef": "error", + "no-unexpected-multiline": "error", + "no-unreachable": "error", + "no-unsafe-finally": "error", + "no-unsafe-negation": "error", + "no-unused-labels": "error", + "no-unused-vars": 1, + "no-useless-catch": "error", "no-useless-escape": 0, - "semi": [ 2, "always" ] + "no-with": "error", + "require-yield": "error", + "use-isnan": "error", + "valid-typeof": "error", + "no-new-native-nonconstructor": "error", + "comma-style": [ + 2, + "last" + ], + "comma-dangle": [ + 2, + "never" + ], + "curly": 0, + "no-bitwise": 0, + "no-console": 0, + "no-trailing-spaces": 2, + "no-use-before-define": [ + 1, + { + "functions": false, + "classes": true, + "variables": false + } + ], + "semi": [ + 2, + "always" + ] } } diff --git a/.github/actions/corpus/action.yml b/.github/actions/corpus/action.yml index 18415a55..ef021316 100644 --- a/.github/actions/corpus/action.yml +++ b/.github/actions/corpus/action.yml @@ -1,15 +1,9 @@ name: Verified SheetJS corpus -description: Restore the pinned official corpus without mutable SVN downloads +description: Download and verify the pinned official corpus without shared cache writes runs: using: composite steps: - - uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5 - id: archive - with: - path: ${{ runner.temp }}/sheetjs-test-files.zip - key: sheetjs-corpus-a786d4f1a80adf9447997b6f3b30b2593c776c27e0b075e3971627c17205f220 - - if: steps.archive.outputs.cache-hit != 'true' - shell: bash + - shell: bash run: curl --fail --location --retry 3 --max-time 300 https://test-files.sheetjs.com/test_files.zip -o "$RUNNER_TEMP/sheetjs-test-files.zip" - shell: bash run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4d00bad8..69105aea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,10 +34,11 @@ jobs: - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: ${{ matrix.node }} - cache: npm + package-manager-cache: false - run: npm ci --ignore-scripts - uses: ./.github/actions/corpus - run: make all + - run: npm run test:tooling - run: npm run test:security - run: npm run test:table-styles - run: npm run test:cfb-minifat @@ -62,7 +63,7 @@ jobs: - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: 24 - cache: npm + package-manager-cache: false - run: npm ci --ignore-scripts - uses: ./.github/actions/corpus - run: make all diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 3deb9d40..02865857 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -39,7 +39,7 @@ jobs: with: node-version: 24 registry-url: https://registry.npmjs.org - cache: npm + package-manager-cache: false - run: npm ci --ignore-scripts - run: node --test .github/scripts/publish-npm.test.mjs - run: npm run test:security @@ -63,6 +63,7 @@ jobs: node .github/scripts/publish-npm.mjs fi - name: Preserve the exact verified tarball + if: github.event_name == 'release' || inputs.dry_run == false env: GH_TOKEN: ${{ github.token }} GH_REPO: ${{ github.repository }} diff --git a/.github/workflows/rebase.yml b/.github/workflows/rebase.yml index 02e67002..26e578a5 100644 --- a/.github/workflows/rebase.yml +++ b/.github/workflows/rebase.yml @@ -2,14 +2,26 @@ name: Automatic Rebase on: [pull_request_target] +permissions: + contents: read + jobs: _: name: "Automatic Rebase" runs-on: ubuntu-latest + timeout-minutes: 5 steps: - - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 - - uses: ljharb/rebase@c6bd0a72b14dfaf76ad6a070029c8b4592d03eea + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - name: Read the branch relationship without rewriting a PR env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_HEAD: ${{ github.event.pull_request.head.sha }} + PR_BASE: ${{ github.event.pull_request.base.sha }} + run: | + node -e 'for (const name of ["PR_HEAD", "PR_BASE"]) { if (!/^[a-f0-9]{40}$/.test(process.env[name] || "")) throw new Error("Invalid PR commit identity"); }' + git fetch --no-tags origin "$PR_HEAD" "$PR_BASE" + git merge-base "$PR_BASE" "$PR_HEAD" + git rev-list --left-right --count "$PR_BASE...$PR_HEAD" diff --git a/.github/workflows/require-allow-edits.yml b/.github/workflows/require-allow-edits.yml index 9ae6992d..c457b218 100644 --- a/.github/workflows/require-allow-edits.yml +++ b/.github/workflows/require-allow-edits.yml @@ -2,11 +2,15 @@ name: Require “Allow Edits” on: [pull_request_target] +permissions: + contents: read + jobs: _: name: "Require “Allow Edits”" runs-on: ubuntu-latest + timeout-minutes: 5 steps: - uses: ljharb/require-allow-edits@13f90bc8cc5de000f2b44a0e2c3a11d108e8cd9f diff --git a/.github/workflows/security-regression.yml b/.github/workflows/security-regression.yml index e312a19b..efe32d1b 100644 --- a/.github/workflows/security-regression.yml +++ b/.github/workflows/security-regression.yml @@ -40,8 +40,10 @@ jobs: - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 with: node-version: 22 + package-manager-cache: false - run: npm ci --ignore-scripts - run: npm audit --audit-level=low + - run: npm run test:tooling - run: npm run test:security - run: npm run test:table-styles - run: make all diff --git a/bin/xlsx.njs b/bin/xlsx.njs index 13c8a183..f74227a8 100755 --- a/bin/xlsx.njs +++ b/bin/xlsx.njs @@ -1,6 +1,5 @@ #!/usr/bin/env node /* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */ -/* eslint-env node */ /* vim: set ts=2 ft=javascript: */ var n = "xlsx"; diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 00000000..3d403e0f --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,28 @@ +import { readFileSync } from 'node:fs' +import { FlatCompat } from '@eslint/eslintrc' +import json from 'eslint-plugin-json' + +const compat = new FlatCompat({ + baseDirectory: import.meta.dirname, +}) + +// The project keeps its original ES3 rule policy while using current ESLint. +// .eslintrc explicitly retains the previous recommended rules and overrides. +export default [ + { ignores: ['**/xlsx.js'] }, + ...compat.config( + JSON.parse(readFileSync(new URL('.eslintrc', import.meta.url), 'utf8')), + ), + { + files: ['**/*.{js,njs,json,html,htm}'], + languageOptions: { sourceType: 'script', globals: { JSON: 'readonly' } }, + }, + ...compat.config({ env: { node: true } }) + .map(config => ({ ...config, files: ['bin/**/*.njs'] })), + ...compat.config({ env: { browser: true } }) + .map(config => ({ ...config, files: ['**/*.{html,htm}'] })), + { + files: ['**/*.json'], + ...json.configs.recommended, + }, +] diff --git a/index.html b/index.html index ea19448a..b292de85 100644 --- a/index.html +++ b/index.html @@ -62,7 +62,6 @@ '), []) + assert.deepEqual(await messages(`probe.${extension}`, ''), []) + assert.ok((await messages(`probe.${extension}`, '')) + .some(message => message.ruleId === 'no-undef')) + } +}) + +test('the generated CJS bundle retains its existing exclusion', async () => { + assert.equal(await eslint.isPathIgnored('xlsx.js'), true) +}) From e329118afcad0a116177d0e8df1d05ad1c3414a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E7=88=AC=E7=9A=84=E8=80=81=E7=B2=89=E4=B8=9D?= <727842003@qq.com> Date: Sun, 11 Oct 2026 14:08:18 +0800 Subject: [PATCH 2/2] ci: keep maintenance configuration and regression sources reviewable --- .gitattributes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitattributes b/.gitattributes index fc04ca62..9a0ffd20 100644 --- a/.gitattributes +++ b/.gitattributes @@ -17,3 +17,5 @@ tests/fixtures.js linguist-generated=true binary test.mjs lingust-generated=false binary=false text eol=lf .github/scripts/*.mjs linguist-generated=false !binary text diff merge eol=lf +eslint.config.mjs linguist-generated=false !binary text diff merge eol=lf +tests/*.mjs linguist-generated=false !binary text diff merge eol=lf