From 11cfc6d2f994b808e9ac45982e132b639a94111c Mon Sep 17 00:00:00 2001 From: Nicholas023 Date: Tue, 20 Oct 2026 02:12:32 +0800 Subject: [PATCH] =?UTF-8?q?fix(issue-11):=20=E6=95=8F=E6=84=9F=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E6=AD=A3=E5=88=99=E8=AF=AF=E6=8A=A5=20key.js/cert.js/?= =?UTF-8?q?pem.js=E2=80=94=E2=80=94=E9=99=90=E5=AE=9A=E7=8B=AC=E7=AB=8B?= =?UTF-8?q?=E6=89=A9=E5=B1=95=E5=90=8D=E5=8C=B9=E9=85=8D=20(closes=20#11)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/unit-smoke.mjs | 23 +++++++++++++++++++++++ src/sensitive-list.js | 9 ++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/scripts/unit-smoke.mjs b/scripts/unit-smoke.mjs index 6015adc..647e141 100644 --- a/scripts/unit-smoke.mjs +++ b/scripts/unit-smoke.mjs @@ -138,6 +138,29 @@ t('敏感不命中:.gitignore、README.md、src/main.go', () => { assert.equal(isSensitivePath('README.md'), false); assert.equal(isSensitivePath('src/main.go'), false); }); +// issue #11 回归:凭据词内嵌于源码文件名(src/key.js、cert.ts 等)不得误判为敏感文件 +// ——噪声稀释真正凭据命中信号(旧正则 (.*\.)? 可跳过,key 后跟 .js 的点即命中)。 +t('敏感不命中:凭据词内嵌于源码文件名(issue #11 回归)', () => { + assert.equal(isSensitivePath('src/key.js'), false); + assert.equal(isSensitivePath('src/key.ts'), false); + assert.equal(isSensitivePath('src/cert.js'), false); + assert.equal(isSensitivePath('src/cert.ts'), false); + assert.equal(isSensitivePath('src/pem.js'), false); + assert.equal(isSensitivePath('sessionkey.go'), false); + assert.equal(isSensitivePath('keycmd.go'), false); +}); +// issue #11 回归:凭据词作为独立扩展名仍须命中(修复不得造成真凭据漏报。 +// id_rsa/credentials.json/.env 由各自独立规则覆盖,一并钉住防回归)。 +t('敏感命中:凭据词为独立扩展名(issue #11 保留行为)', () => { + assert.equal(isSensitivePath('my.key'), true); + assert.equal(isSensitivePath('key.pem'), true); + assert.equal(isSensitivePath('cert.pfx'), true); + assert.equal(isSensitivePath('certs/app.pem'), true); + assert.equal(isSensitivePath('my.key.bak'), true); + assert.equal(isSensitivePath('id_rsa'), true); + assert.equal(isSensitivePath('credentials.json'), true); + assert.equal(isSensitivePath('.env'), true); +}); t('listSensitiveFiles 混合清单只点名命中项', () => { const hits = listSensitiveFiles(['README.md', '.env', 'src/main.go', '.ssh/id_ed25519']); assert.deepEqual(hits.map((h) => h.path).sort(), ['.env', '.ssh/id_ed25519'].sort()); diff --git a/src/sensitive-list.js b/src/sensitive-list.js index 1019ab1..9f96c47 100644 --- a/src/sensitive-list.js +++ b/src/sensitive-list.js @@ -30,7 +30,14 @@ export const SENSITIVE_PATH_PATTERNS = [ /(^|\/)\.[^/]*key[^/]*$/i, /(^|\/)\.[^/]*secret/i, /(^|\/)\.env(\.[^/]+)?$/i, // .env / .env.production 等 - /(^|\/)(.*\.)?(pem|p12|pfx|keystore|jks|cert|crt|key|kdbx|otpkey)(\.|$)/i, + // 凭据扩展名必须作为「独立扩展名」出现(my.key、cert.pfx、server.crt.bak 等): + // 敏感词前必须由点号分隔([^/]*\.),后跟行尾或再一个点(如 .key.bak 的 .bak)。 + // 旧正则的 (.*\.)? 可整体不参与匹配,导致 key.js / cert.ts / pem.js 中敏感词 + // 后跟源码扩展名的点即满足 (\.|$)——src/key.js、src/key.ts 等合法源码被误判为 + // 敏感文件,噪声稀释真正凭据命中的信号(issue #11)。修后路径段内嵌的 + // key/cert/pem(sessionkey.go、keycmd.go 等)也不再命中;id_rsa/credentials/.env + // 等由各自独立规则覆盖,不受此行影响。 + /(^|\/)[^/]*\.(pem|p12|pfx|keystore|jks|cert|crt|key|kdbx|otpkey)(\.|$)/i, /(^|\/)credentials[^/]*$/i, // token 模式收紧(形态:独立词段 token(s) + **凭据类扩展名或路径结尾**)—— // 原 `.*token[^/]*$` 命中路径任意位置含 "token" 的文件(src/tokenizer.js、