



















1+const PAYMENT_CREDENTIAL_KEYS =
2+"card[-_]?number|card[-_]?cvc|card[-_]?cvv|cvc|cvv|security[-_]?code|securityCode|payment[-_]?credential|paymentCredential|shared[-_]?payment[-_]?token|sharedPaymentToken";
3+4+const SECRET_DETAIL_PATTERNS: RegExp[] = [
5+/\b[A-Z0-9_]*(?:KEY|TOKEN|SECRET|PASSWORD|PASSWD|CARD[_-]?NUMBER|CARD[_-]?CVC|CARD[_-]?CVV|CVC|CVV|SECURITY[_-]?CODE|PAYMENT[_-]?CREDENTIAL|SHARED[_-]?PAYMENT[_-]?TOKEN)\b\s*[=:]\s*(["']?)([^\s"'\\&<>]+)\1/gi,
6+/\b[A-Z0-9_]*(?:KEY|TOKEN|SECRET|PASSWORD|PASSWD|CARD[_-]?NUMBER|CARD[_-]?CVC|CARD[_-]?CVV|CVC|CVV|SECURITY[_-]?CODE|PAYMENT[_-]?CREDENTIAL|SHARED[_-]?PAYMENT[_-]?TOKEN)\b\s*[=:]\s*\\+(["'])([^\s"'\\&<>]+)\\+\1/gi,
7+new RegExp(
8+`[?&](?:access[-_]?token|auth[-_]?token|hook[-_]?token|refresh[-_]?token|api[-_]?key|client[-_]?secret|token|key|secret|password|pass|passwd|auth|signature|${PAYMENT_CREDENTIAL_KEYS})=([^&\\s"'<>]+)`,
9+"gi",
10+),
11+/"(?:apiKey|token|secret|password|passwd|accessToken|refreshToken|cardNumber|card_number|cardCvc|card_cvc|cardCvv|card_cvv|cvc|cvv|securityCode|security_code|paymentCredential|payment_credential|sharedPaymentToken|shared_payment_token)"\s*:\s*"([^"]+)"/gi,
12+/(^|[\s,{])["']?(?:api[-_]key|access[-_]token|refresh[-_]token|authToken|auth[-_]token|clientSecret|client[-_]secret|appSecret|app[-_]secret)["']?\s*[:=]\s*(["'])([^"'\r\n]+)\2/gi,
13+/(^|[\s,{])["']?(?:authorization|proxy-authorization|cookie|set-cookie|x-api-key|x-auth-token)["']?\s*[:=]\s*(["'])([^"'\r\n]+)\2/gi,
14+new RegExp(
15+`--(?:api[-_]?key|hook[-_]?token|token|secret|password|passwd|${PAYMENT_CREDENTIAL_KEYS})\\s+(["']?)([^\\s"']+)\\1`,
16+"gi",
17+),
18+/Authorization\s*[:=]\s*Bearer\s+([A-Za-z0-9._\-+=]+)/gi,
19+/Authorization\s*[:=]\s*Basic\s+([A-Za-z0-9+/=]+)/gi,
20+/(?:X-OpenClaw-Token|x-pomerium-jwt-assertion|X-Api-Key|X-Auth-Token)\s*[:=]\s*([^\s"',;]+)/gi,
21+/\bBearer\s+([A-Za-z0-9._\-+=]{18,})\b/gi,
22+new RegExp(
23+`(^|[\\s,;])(?:access_token|refresh_token|auth[-_]?token|api[-_]?key|client[-_]?secret|app[-_]?secret|token|secret|password|passwd|${PAYMENT_CREDENTIAL_KEYS})=([^\\s&#]+)`,
24+"gi",
25+),
26+/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]+?-----END [A-Z ]*PRIVATE KEY-----/g,
27+/\b(sk-[A-Za-z0-9_-]{8,})\b/g,
28+/\b(ghp_[A-Za-z0-9]{20,})\b/g,
29+/\b(github_pat_[A-Za-z0-9_]{20,})\b/g,
30+/\b(xox[baprs]-[A-Za-z0-9-]{10,})\b/g,
31+/\b(xapp-[A-Za-z0-9-]{10,})\b/g,
32+/\b(gsk_[A-Za-z0-9_-]{10,})\b/g,
33+/\b(AIza[0-9A-Za-z\-_]{20,})\b/g,
34+/\b(ya29\.[0-9A-Za-z_\-./+=]{10,})\b/g,
35+/\b(1\/\/0[0-9A-Za-z_\-./+=]{10,})\b/g,
36+/\b(eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,})\b/g,
37+/\b(pplx-[A-Za-z0-9_-]{10,})\b/g,
38+/\b(npm_[A-Za-z0-9]{10,})\b/g,
39+/\b(AKID[A-Za-z0-9]{10,})\b/g,
40+/\b(LTAI[A-Za-z0-9]{10,})\b/g,
41+/\b(hf_[A-Za-z0-9]{10,})\b/g,
42+/\b(r8_[A-Za-z0-9]{10,})\b/g,
43+/\bbot(\d{6,}:[A-Za-z0-9_-]{20,})\b/g,
44+/\b(\d{6,}:[A-Za-z0-9_-]{20,})\b/g,
45+];
46+47+function redactToken(value: string): string {
48+if (value.length <= 10) {
49+return "***";
50+}
51+return `${value.slice(0, 6)}...${value.slice(-4)}`;
52+}
53+54+function redactPemBlock(block: string): string {
55+const lines = block.split(/\r?\n/).filter(Boolean);
56+if (lines.length < 2) {
57+return "***";
58+}
59+return `${lines[0]}\n...redacted...\n${lines[lines.length - 1]}`;
60+}
61+62+export function redactToolDetail(detail: string): string {
63+let redacted = detail;
64+for (const pattern of SECRET_DETAIL_PATTERNS) {
65+redacted = redacted.replace(pattern, (...args: string[]) => {
66+const match = args[0] ?? "";
67+if (match.includes("PRIVATE KEY-----")) {
68+return redactPemBlock(match);
69+}
70+const groups = args.slice(1, -2);
71+const token = groups.findLast((group) => typeof group === "string" && group.length > 0);
72+return token ? match.replace(token, redactToken(token)) : "***";
73+});
74+}
75+return redacted;
76+}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。