@dcrays/mobook-security-plugin 2.0.12 → 2.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -137,34 +137,46 @@ const BANK_CARD_REGEX = /\b[3-6]\d{15,18}\b/g;
137
137
 
138
138
  // ---- 脱敏辅助:部分保留 + 星号遮盖 ----
139
139
  function maskKeep(str, keepHead, keepTail = 0, minStars = 4) {
140
- if (str.length <= keepHead + keepTail) return "*".repeat(str.length);
140
+ if (str.length <= keepHead + keepTail) return "\\*".repeat(str.length);
141
141
  const stars = Math.max(minStars, str.length - keepHead - keepTail);
142
- return str.slice(0, keepHead) + "*".repeat(stars) + (keepTail > 0 ? str.slice(-keepTail) : "");
142
+ return str.slice(0, keepHead) + "\\*".repeat(stars) + (keepTail > 0 ? str.slice(-keepTail) : "");
143
+ }
144
+
145
+ // ---- 智能识别:检测文本是否已脱敏 ----
146
+ function looksLikeMasked(text) {
147
+ // 只识别"明显的脱敏模式":数字/字母 + 连续4个以上星号 + 数字/字母/@
148
+ // 例如:138****5678、1**********@163.com
149
+ // 不误判 Markdown 格式(---、**粗体**)
150
+ return /[a-zA-Z0-9]\*{4,}[a-zA-Z0-9@]/.test(text);
143
151
  }
144
152
 
145
153
  const SENSITIVE_PATTERNS = [
154
+ // 优先级1:邮箱(避免被手机号规则破坏)
155
+ {
156
+ pattern: /\b([a-zA-Z0-9._%+-]+)@((?:qq|163|126|sina|sohu|gmail|outlook|hotmail|yahoo)\.[a-z]{2,})\b/gi,
157
+ replacer: (_m, local, domain) => maskKeep(local, 2, 0) + "@" + domain, // jq*****@gmail.com
158
+ name: "个人邮箱"
159
+ },
160
+ // 优先级2:身份证
146
161
  {
147
162
  pattern: ID_CARD_REGEX,
148
163
  validator: verifyIdCard,
149
164
  replacer: (m) => maskKeep(m, 3, 4), // 310***********1234
150
165
  name: "身份证号"
151
166
  },
167
+ // 优先级3:手机号(排除邮箱上下文)
152
168
  {
153
- pattern: /\b1[3-9]\d{9}\b/g,
169
+ pattern: /\b1[3-9]\d{9}\b(?!@)/g, // 负向前瞻:后面不能是 @
154
170
  replacer: (m) => maskKeep(m, 3, 4), // 138****5678
155
171
  name: "手机号"
156
172
  },
173
+ // 优先级4:银行卡
157
174
  {
158
175
  pattern: BANK_CARD_REGEX,
159
176
  validator: verifyLuhn,
160
177
  replacer: (m) => maskKeep(m, 4, 4), // 6222***********1234
161
178
  name: "银行卡号"
162
179
  },
163
- {
164
- pattern: /\b([a-zA-Z0-9._%+-]+)@((?:qq|163|126|sina|sohu|gmail|outlook|hotmail|yahoo)\.[a-z]{2,})\b/gi,
165
- replacer: (_m, local, domain) => maskKeep(local, 1, 0) + "@" + domain, // j*****@gmail.com
166
- name: "个人邮箱"
167
- },
168
180
  {
169
181
  pattern: /\b(sk-[a-zA-Z0-9-]{20,})\b/g,
170
182
  replacer: (m) => maskKeep(m, 5, 0), // sk-pr**************
@@ -198,6 +210,12 @@ const SENSITIVE_PATTERNS = [
198
210
  ];
199
211
 
200
212
  function sanitizeContent(content) {
213
+ // 智能识别:如果整体内容看起来已脱敏,跳过处理
214
+ if (looksLikeMasked(content)) {
215
+ log(`SKIP: 检测到已脱敏文本,跳过二次脱敏 | 长度=${content.length}`);
216
+ return { sanitized: content, matches: [] };
217
+ }
218
+
201
219
  let sanitized = content;
202
220
  const matches = [];
203
221
 
@@ -209,6 +227,9 @@ function sanitizeContent(content) {
209
227
  let hasMatch = false;
210
228
  sanitized = sanitized.replace(rule.pattern, (...args) => {
211
229
  const match = args[0];
230
+ // 跳过已脱敏的匹配
231
+ if (looksLikeMasked(match)) return match;
232
+
212
233
  if (rule.validator(match)) {
213
234
  hasMatch = true;
214
235
  return rule.replacer(...args);
@@ -219,7 +240,13 @@ function sanitizeContent(content) {
219
240
  } else if (rule.replacer) {
220
241
  // 使用 replacer 函数
221
242
  rule.pattern.lastIndex = 0;
222
- const replaced = sanitized.replace(rule.pattern, (...args) => rule.replacer(...args));
243
+ const replaced = sanitized.replace(rule.pattern, (...args) => {
244
+ const match = args[0];
245
+ // 跳过已脱敏的匹配
246
+ if (looksLikeMasked(match)) return match;
247
+
248
+ return rule.replacer(...args);
249
+ });
223
250
  if (replaced !== sanitized) {
224
251
  matches.push(rule.name);
225
252
  sanitized = replaced;
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "id": "mobook-security-plugin",
3
3
  "name": "MoBook 安全防护插件",
4
- "version": "2.0.12",
4
+ "version": "2.0.14",
5
5
  "description": "MoBook 企业级安全插件 - 危险命令分级拦截、敏感信息全渠道脱敏(身份证GB11643/银行卡Luhn校验)、LLM响应拦截、操作审计",
6
6
  "entry": "./index.js",
7
7
  "type": "plugin",
8
8
  "configSchema": {}
9
- }
9
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dcrays/mobook-security-plugin",
3
- "version": "2.0.12",
3
+ "version": "2.0.14",
4
4
  "type": "module",
5
5
  "description": "MoBook 企业级安全插件 - 危险命令分级拦截、敏感信息全渠道脱敏(身份证GB11643/银行卡Luhn校验)、LLM响应拦截、操作审计",
6
6
  "main": "index.js",
@@ -20,4 +20,4 @@
20
20
  "./index.js"
21
21
  ]
22
22
  }
23
- }
23
+ }