mynth-logger 2.1.2 → 2.1.3
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/dist/src/redact.js +32 -42
- package/dist/tests/redact.test.js +12 -0
- package/package.json +1 -1
- package/src/redact.ts +5 -18
- package/tests/redact.test.ts +22 -0
package/dist/src/redact.js
CHANGED
|
@@ -2,10 +2,6 @@ import { DeepRedact } from "@hackylabs/deep-redact/index.ts";
|
|
|
2
2
|
import { validateMnemonic } from "@scure/bip39";
|
|
3
3
|
import { wordlist } from "@scure/bip39/wordlists/english.js";
|
|
4
4
|
const replacement = "[REDACTED]";
|
|
5
|
-
const cloneRegex = (re) => {
|
|
6
|
-
const flags = re.flags.includes("g") ? re.flags : `${re.flags}g`;
|
|
7
|
-
return new RegExp(re.source, flags);
|
|
8
|
-
};
|
|
9
5
|
const sliceAround = (value, offset, matchLen, rule) => {
|
|
10
6
|
const before = rule.before ?? 10;
|
|
11
7
|
const after = rule.after ?? 0;
|
|
@@ -35,60 +31,54 @@ const getReplaceMeta = (args) => {
|
|
|
35
31
|
return null;
|
|
36
32
|
return { offset, whole };
|
|
37
33
|
};
|
|
38
|
-
const replaceAllMatchesWithContext = (value, pattern, replacement, allow) => {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
const match = args[0];
|
|
42
|
-
if (typeof match !== "string")
|
|
43
|
-
return replacement;
|
|
44
|
-
const meta = getReplaceMeta(args);
|
|
45
|
-
if (!meta)
|
|
46
|
-
return replacement;
|
|
47
|
-
if (shouldAllowByRules(meta.whole, match, meta.offset, allow))
|
|
48
|
-
return match;
|
|
34
|
+
const replaceAllMatchesWithContext = (value, pattern, replacement, allow) => value.replace(pattern, (...args) => {
|
|
35
|
+
const match = args[0];
|
|
36
|
+
if (typeof match !== "string")
|
|
49
37
|
return replacement;
|
|
50
|
-
|
|
51
|
-
|
|
38
|
+
const meta = getReplaceMeta(args);
|
|
39
|
+
if (!meta)
|
|
40
|
+
return replacement;
|
|
41
|
+
if (shouldAllowByRules(meta.whole, match, meta.offset, allow))
|
|
42
|
+
return match;
|
|
43
|
+
return replacement;
|
|
44
|
+
});
|
|
52
45
|
/**
|
|
53
46
|
* BIP39 contextual replacer:
|
|
54
47
|
* - Only redacts if the captured phrase validates as a BIP39 mnemonic
|
|
55
48
|
* - Still supports allow-rules (to suppress redaction in “safe” contexts)
|
|
56
49
|
*/
|
|
57
|
-
const replaceBip39MnemonicMatchesWithContext = (value, pattern, replacement, allow) => {
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return match.replace(phrase, replacement);
|
|
75
|
-
});
|
|
76
|
-
};
|
|
50
|
+
const replaceBip39MnemonicMatchesWithContext = (value, pattern, replacement, allow) => value.replace(pattern, (...args) => {
|
|
51
|
+
const match = args[0];
|
|
52
|
+
const phrase = args[1];
|
|
53
|
+
if (typeof match !== "string")
|
|
54
|
+
return replacement;
|
|
55
|
+
if (typeof phrase !== "string")
|
|
56
|
+
return match;
|
|
57
|
+
const meta = getReplaceMeta(args);
|
|
58
|
+
if (!meta)
|
|
59
|
+
return match;
|
|
60
|
+
if (shouldAllowByRules(meta.whole, match, meta.offset, allow))
|
|
61
|
+
return match;
|
|
62
|
+
const normalized = phrase.trim().toLowerCase().replace(/\s+/g, " ");
|
|
63
|
+
if (!validateMnemonic(normalized, wordlist))
|
|
64
|
+
return match;
|
|
65
|
+
return match.replace(phrase, replacement);
|
|
66
|
+
});
|
|
77
67
|
const createRedactor = (config = {}) => {
|
|
78
68
|
const HEX_MIN_LEN = 16;
|
|
79
69
|
const BASE64_MIN_BLOCKS = 4;
|
|
80
70
|
const BASE58_MIN_LEN = 16;
|
|
81
|
-
const HEX = new RegExp(String.raw `(?<![a-fA-F0-9])(?:0x)?[a-fA-F0-9]{${HEX_MIN_LEN},}(?![a-fA-F0-9])
|
|
71
|
+
const HEX = new RegExp(String.raw `(?<![a-fA-F0-9])(?:0x)?[a-fA-F0-9]{${HEX_MIN_LEN},}(?![a-fA-F0-9])`);
|
|
82
72
|
const hexAllow = config.hex?.allow ?? [];
|
|
83
|
-
const BASE64 = new RegExp(String.raw `(?<![A-Za-z0-9+/=])(?:[A-Za-z0-9+/]{4}){${BASE64_MIN_BLOCKS},}(?:[A-Za-z0-9+/]{2,3})?(?:={0,2})(?![A-Za-z0-9+/=])
|
|
73
|
+
const BASE64 = new RegExp(String.raw `(?<![A-Za-z0-9+/=])(?:[A-Za-z0-9+/]{4}){${BASE64_MIN_BLOCKS},}(?:[A-Za-z0-9+/]{2,3})?(?:={0,2})(?![A-Za-z0-9+/=])`);
|
|
84
74
|
const base64Allow = config.base64?.allow ?? [];
|
|
85
|
-
const BASE64URL = new RegExp(String.raw `(?<![A-Za-z0-9\-_])[A-Za-z0-9\-_]{16,}(?:={0,2})?(?![A-Za-z0-9\-_])
|
|
75
|
+
const BASE64URL = new RegExp(String.raw `(?<![A-Za-z0-9\-_])[A-Za-z0-9\-_]{16,}(?:={0,2})?(?![A-Za-z0-9\-_])`);
|
|
86
76
|
const base64urlAllow = config.base64url?.allow ?? [];
|
|
87
|
-
const BASE58 = new RegExp(String.raw `(?<![1-9A-HJ-NP-Za-km-z])[1-9A-HJ-NP-Za-km-z]{${BASE58_MIN_LEN},}(?![1-9A-HJ-NP-Za-km-z])
|
|
77
|
+
const BASE58 = new RegExp(String.raw `(?<![1-9A-HJ-NP-Za-km-z])[1-9A-HJ-NP-Za-km-z]{${BASE58_MIN_LEN},}(?![1-9A-HJ-NP-Za-km-z])`);
|
|
88
78
|
const base58Allow = config.base58?.allow ?? [];
|
|
89
79
|
const WORD = "[a-zA-Z]{2,8}";
|
|
90
80
|
const PHRASE_12_TO_24 = `(?:${WORD}\\s+){11,23}${WORD}`;
|
|
91
|
-
const MNEMONIC = new RegExp(String.raw `(?<![A-Za-z])(${PHRASE_12_TO_24})(?![A-Za-z])`, "
|
|
81
|
+
const MNEMONIC = new RegExp(String.raw `(?<![A-Za-z])(${PHRASE_12_TO_24})(?![A-Za-z])`, "i");
|
|
92
82
|
const mnemonicAllow = config.mnemonic?.allow ?? [];
|
|
93
83
|
const stringTests = [
|
|
94
84
|
{
|
|
@@ -11,4 +11,16 @@ describe("redact", () => {
|
|
|
11
11
|
const result = redact("Should redact private key (b49bd63e67e2cd11aba17befead483934939df828cb833a846c58661726d3b00) and API key (djOqmjzVb0GAGdqS0p0NtiEwvb6u1lx509JEkpDJLgnvMhmOMtBc9vqolpktd1OK7Xas)");
|
|
12
12
|
expect(result).toBe("Should redact private key ([REDACTED]) and API key ([REDACTED])");
|
|
13
13
|
});
|
|
14
|
+
it("allows whitelist each time", () => {
|
|
15
|
+
const redact = createRedact({ hex: { allow: [{ re: /\b(event)\b/i }] } });
|
|
16
|
+
for (let i = 0; i < 10; i++) {
|
|
17
|
+
const result = redact("Pushed event fcc6533b59301096a973b8be3e6518f0cd13f73a9821de558cca77ac9b014d6e.1771865100000");
|
|
18
|
+
expect(result).toBe("Pushed event fcc6533b59301096a973b8be3e6518f0cd13f73a9821de558cca77ac9b014d6e.1771865100000");
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
it("redacts multiple hex in same string", () => {
|
|
22
|
+
const redact = createRedact({});
|
|
23
|
+
const result = redact("Pushed event fcc6533b59301096a973b8be3e6518f0cd13f73a9821de558cca77ac9b014d6e.1561338e25f9b57a9babc7ad57a0e0ee0b13a7094a895319883c7daf4a869642 with key d13821711360de832b80be20507912cebe123ebe52240ae91e6a699b72beb26a");
|
|
24
|
+
expect(result).toBe("Pushed event [REDACTED].[REDACTED] with key [REDACTED]");
|
|
25
|
+
});
|
|
14
26
|
});
|
package/package.json
CHANGED
package/src/redact.ts
CHANGED
|
@@ -44,11 +44,6 @@ type RedactConfig = {
|
|
|
44
44
|
|
|
45
45
|
const replacement = "[REDACTED]";
|
|
46
46
|
|
|
47
|
-
const cloneRegex = (re: RegExp): RegExp => {
|
|
48
|
-
const flags = re.flags.includes("g") ? re.flags : `${re.flags}g`;
|
|
49
|
-
return new RegExp(re.source, flags);
|
|
50
|
-
};
|
|
51
|
-
|
|
52
47
|
const sliceAround = (
|
|
53
48
|
value: string,
|
|
54
49
|
offset: number,
|
|
@@ -100,9 +95,8 @@ const replaceAllMatchesWithContext = (
|
|
|
100
95
|
pattern: RegExp,
|
|
101
96
|
replacement: string,
|
|
102
97
|
allow?: ContextRule[],
|
|
103
|
-
) =>
|
|
104
|
-
|
|
105
|
-
return value.replace(re, (...args: unknown[]) => {
|
|
98
|
+
) =>
|
|
99
|
+
value.replace(pattern, (...args: unknown[]) => {
|
|
106
100
|
const match = args[0];
|
|
107
101
|
if (typeof match !== "string") return replacement;
|
|
108
102
|
|
|
@@ -112,7 +106,6 @@ const replaceAllMatchesWithContext = (
|
|
|
112
106
|
if (shouldAllowByRules(meta.whole, match, meta.offset, allow)) return match;
|
|
113
107
|
return replacement;
|
|
114
108
|
});
|
|
115
|
-
};
|
|
116
109
|
|
|
117
110
|
/**
|
|
118
111
|
* BIP39 contextual replacer:
|
|
@@ -124,9 +117,8 @@ const replaceBip39MnemonicMatchesWithContext = (
|
|
|
124
117
|
pattern: RegExp,
|
|
125
118
|
replacement: string,
|
|
126
119
|
allow?: ContextRule[],
|
|
127
|
-
) =>
|
|
128
|
-
|
|
129
|
-
return value.replace(re, (...args: unknown[]) => {
|
|
120
|
+
) =>
|
|
121
|
+
value.replace(pattern, (...args: unknown[]) => {
|
|
130
122
|
const match = args[0];
|
|
131
123
|
const phrase = args[1];
|
|
132
124
|
|
|
@@ -143,7 +135,6 @@ const replaceBip39MnemonicMatchesWithContext = (
|
|
|
143
135
|
|
|
144
136
|
return match.replace(phrase, replacement);
|
|
145
137
|
});
|
|
146
|
-
};
|
|
147
138
|
|
|
148
139
|
const createRedactor = (config: RedactConfig = {}) => {
|
|
149
140
|
const HEX_MIN_LEN = 16;
|
|
@@ -152,25 +143,21 @@ const createRedactor = (config: RedactConfig = {}) => {
|
|
|
152
143
|
|
|
153
144
|
const HEX = new RegExp(
|
|
154
145
|
String.raw`(?<![a-fA-F0-9])(?:0x)?[a-fA-F0-9]{${HEX_MIN_LEN},}(?![a-fA-F0-9])`,
|
|
155
|
-
"g",
|
|
156
146
|
);
|
|
157
147
|
const hexAllow: ContextRule[] = config.hex?.allow ?? [];
|
|
158
148
|
|
|
159
149
|
const BASE64 = new RegExp(
|
|
160
150
|
String.raw`(?<![A-Za-z0-9+/=])(?:[A-Za-z0-9+/]{4}){${BASE64_MIN_BLOCKS},}(?:[A-Za-z0-9+/]{2,3})?(?:={0,2})(?![A-Za-z0-9+/=])`,
|
|
161
|
-
"g",
|
|
162
151
|
);
|
|
163
152
|
const base64Allow = config.base64?.allow ?? [];
|
|
164
153
|
|
|
165
154
|
const BASE64URL = new RegExp(
|
|
166
155
|
String.raw`(?<![A-Za-z0-9\-_])[A-Za-z0-9\-_]{16,}(?:={0,2})?(?![A-Za-z0-9\-_])`,
|
|
167
|
-
"g",
|
|
168
156
|
);
|
|
169
157
|
const base64urlAllow = config.base64url?.allow ?? [];
|
|
170
158
|
|
|
171
159
|
const BASE58 = new RegExp(
|
|
172
160
|
String.raw`(?<![1-9A-HJ-NP-Za-km-z])[1-9A-HJ-NP-Za-km-z]{${BASE58_MIN_LEN},}(?![1-9A-HJ-NP-Za-km-z])`,
|
|
173
|
-
"g",
|
|
174
161
|
);
|
|
175
162
|
const base58Allow = config.base58?.allow ?? [];
|
|
176
163
|
|
|
@@ -178,7 +165,7 @@ const createRedactor = (config: RedactConfig = {}) => {
|
|
|
178
165
|
const PHRASE_12_TO_24 = `(?:${WORD}\\s+){11,23}${WORD}`;
|
|
179
166
|
const MNEMONIC = new RegExp(
|
|
180
167
|
String.raw`(?<![A-Za-z])(${PHRASE_12_TO_24})(?![A-Za-z])`,
|
|
181
|
-
"
|
|
168
|
+
"i",
|
|
182
169
|
);
|
|
183
170
|
const mnemonicAllow = config.mnemonic?.allow ?? [];
|
|
184
171
|
|
package/tests/redact.test.ts
CHANGED
|
@@ -19,4 +19,26 @@ describe("redact", () => {
|
|
|
19
19
|
"Should redact private key ([REDACTED]) and API key ([REDACTED])",
|
|
20
20
|
);
|
|
21
21
|
});
|
|
22
|
+
|
|
23
|
+
it("allows whitelist each time", () => {
|
|
24
|
+
const redact = createRedact({ hex: { allow: [{ re: /\b(event)\b/i }] } });
|
|
25
|
+
for (let i = 0; i < 10; i++) {
|
|
26
|
+
const result = redact(
|
|
27
|
+
"Pushed event fcc6533b59301096a973b8be3e6518f0cd13f73a9821de558cca77ac9b014d6e.1771865100000",
|
|
28
|
+
);
|
|
29
|
+
expect(result).toBe(
|
|
30
|
+
"Pushed event fcc6533b59301096a973b8be3e6518f0cd13f73a9821de558cca77ac9b014d6e.1771865100000",
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("redacts multiple hex in same string", () => {
|
|
36
|
+
const redact = createRedact({});
|
|
37
|
+
const result = redact(
|
|
38
|
+
"Pushed event fcc6533b59301096a973b8be3e6518f0cd13f73a9821de558cca77ac9b014d6e.1561338e25f9b57a9babc7ad57a0e0ee0b13a7094a895319883c7daf4a869642 with key d13821711360de832b80be20507912cebe123ebe52240ae91e6a699b72beb26a",
|
|
39
|
+
);
|
|
40
|
+
expect(result).toBe(
|
|
41
|
+
"Pushed event [REDACTED].[REDACTED] with key [REDACTED]",
|
|
42
|
+
);
|
|
43
|
+
});
|
|
22
44
|
});
|