mynth-logger 2.1.2 → 2.1.4

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.
@@ -5,11 +5,11 @@ import DiscordReporter from "./reporters/discord.js";
5
5
  const setupLogging = (config = {}) => {
6
6
  updateConfig(config);
7
7
  const consola = createConsola({ fancy: true, level: 5 });
8
- if (process.env.NODE_ENV === "production")
9
- consola.setReporters([DatadogReporter]);
10
8
  // Set Discord reporter as first so it can remove
11
9
  // Discord-related config before other reporters process the
12
10
  // log
11
+ if (process.env.NODE_ENV === "production")
12
+ consola.setReporters([DiscordReporter, DatadogReporter]);
13
13
  else
14
14
  consola.setReporters([DiscordReporter, ...consola.options.reporters]);
15
15
  consola.wrapConsole();
@@ -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 re = cloneRegex(pattern);
40
- return value.replace(re, (...args) => {
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 re = cloneRegex(pattern);
59
- return value.replace(re, (...args) => {
60
- const match = args[0];
61
- const phrase = args[1];
62
- if (typeof match !== "string")
63
- return replacement;
64
- if (typeof phrase !== "string")
65
- return match;
66
- const meta = getReplaceMeta(args);
67
- if (!meta)
68
- return match;
69
- if (shouldAllowByRules(meta.whole, match, meta.offset, allow))
70
- return match;
71
- const normalized = phrase.trim().toLowerCase().replace(/\s+/g, " ");
72
- if (!validateMnemonic(normalized, wordlist))
73
- return match;
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])`, "g");
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+/=])`, "g");
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\-_])`, "g");
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])`, "g");
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])`, "gi");
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mynth-logger",
3
- "version": "2.1.2",
3
+ "version": "2.1.4",
4
4
  "description": "Package to format logs for mynth microservices.",
5
5
  "main": "dist/src/index.js",
6
6
  "typings": "dist/src/index.d.ts",
package/src/logging.ts CHANGED
@@ -8,11 +8,11 @@ const setupLogging = (config: RedactConfig = {}) => {
8
8
  updateConfig(config);
9
9
  const consola = createConsola({ fancy: true, level: 5 });
10
10
 
11
- if (process.env.NODE_ENV === "production")
12
- consola.setReporters([DatadogReporter]);
13
11
  // Set Discord reporter as first so it can remove
14
12
  // Discord-related config before other reporters process the
15
13
  // log
14
+ if (process.env.NODE_ENV === "production")
15
+ consola.setReporters([DiscordReporter, DatadogReporter]);
16
16
  else consola.setReporters([DiscordReporter, ...consola.options.reporters]);
17
17
 
18
18
  consola.wrapConsole();
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
- const re = cloneRegex(pattern);
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
- const re = cloneRegex(pattern);
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
- "gi",
168
+ "i",
182
169
  );
183
170
  const mnemonicAllow = config.mnemonic?.allow ?? [];
184
171
 
@@ -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
  });