fix(adapters,security): S-4 rss/browser redaction use the shared contracts key table

- contracts: isSensitiveQueryParam (whole-name match on SENSITIVE_QUERY_PARAMS
  or isSensitiveKey), the single source for query credential names
- rss/redact: drop local SENSITIVE_QUERY_KEYS; param checks go through
  isSensitiveQueryParam (+ caller extras); REDACTED re-exported from contracts
- browser/redact: CREDENTIAL_PARAM built from SENSITIVE_QUERY_PARAMS, JSON keys
  also checked with isSensitiveKey; keeps only its own rules (path passkey,
  cookie names, a11y password fields); remove stray regex statement
- redact-consistency.test: 24 credential spellings (pass_key, c_secure_pass,
  refresh_token, password, uid_key, auth, ...) masked by contracts, rss and
  browser alike; plain params untouched; rss extract/unredact round-trip

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-28 00:45:56 +08:00
1 parent b48d8592d5
commit 47bd04aec0
5 files changed
+95 -28

No files matched your search

+10
View File
@@ -55,6 +55,16 @@ export const SENSITIVE_QUERY_PARAMS: readonly string[] = [
"key",
];
const PARAM_NAME_RE = new RegExp(`^(?:${SENSITIVE_QUERY_PARAMS.join("|")})$`, "i");
/**
* 单个 URL 查询参数名是否为凭证(整名匹配 SENSITIVE_QUERY_PARAMS,或按 isSensitiveKey 的键名规则命中)。
* rss / browser 等适配器的参数判定都走这里,不再各自维护键表(验收 07 S-4)。
*/
export function isSensitiveQueryParam(name: string): boolean {
return PARAM_NAME_RE.test(name) || isSensitiveKey(name);
}
const PARAM_RE = new RegExp(`([?&;#]|\\b)(${SENSITIVE_QUERY_PARAMS.join("|")})=([^&;#\\s"'<>]+)`, "gi");
const URL_USERINFO_RE = /\b([a-z][a-z0-9+.-]*:\/\/)([^/\s:@]+):([^/\s@]+)@/gi;
const BEARER_RE = /\b(Bearer|Basic|Token)\s+[A-Za-z0-9._~+/=-]{6,}/g;