@riocrypto/common-server 1.0.2711 → 1.0.2712

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.
@@ -21,9 +21,9 @@ function buildAxiosWithLogging() {
21
21
  "csrf",
22
22
  ];
23
23
  function maskHeaderValue(value) {
24
- return value.length > 4
25
- ? "*".repeat(value.length - 4) + value.slice(-4)
26
- : value;
24
+ return value.length > 2
25
+ ? "*".repeat(12) + value.slice(-2)
26
+ : "************";
27
27
  }
28
28
  // Masking function - masks any header containing a sensitive substring
29
29
  function maskHeaders(headers) {
@@ -2,10 +2,18 @@ import { Logger } from "winston";
2
2
  declare class LoggerService {
3
3
  private logger;
4
4
  constructor();
5
+ private sensitiveSubstrings;
6
+ private isSensitiveKey;
5
7
  private maskValue;
8
+ private deepMaskSensitiveKeys;
6
9
  private maskSensitiveData;
7
10
  private requestMethodFilter;
8
11
  private handleCustomErrorFormat;
12
+ private sanitizeArg;
13
+ private sensitiveStringPatterns;
14
+ private maskSensitiveString;
15
+ private setupConsoleMasking;
16
+ private setupStreamMasking;
9
17
  getLogger(): Logger;
10
18
  initLogger(): Promise<void>;
11
19
  }
@@ -8,33 +8,43 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __rest = (this && this.__rest) || function (s, e) {
12
+ var t = {};
13
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
14
+ t[p] = s[p];
15
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
16
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
17
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
18
+ t[p[i]] = s[p[i]];
19
+ }
20
+ return t;
21
+ };
11
22
  Object.defineProperty(exports, "__esModule", { value: true });
12
23
  const common_1 = require("@riocrypto/common");
13
24
  const winston_1 = require("winston");
14
25
  class LoggerService {
15
26
  constructor() {
27
+ this.sensitiveSubstrings = [
28
+ "key",
29
+ "token",
30
+ "secret",
31
+ "auth",
32
+ "sign",
33
+ "password",
34
+ "private",
35
+ "credential",
36
+ "passphrase",
37
+ "csrf",
38
+ ];
16
39
  this.maskSensitiveData = (0, winston_1.format)((info) => {
17
40
  var _a, _b, _c, _d, _e;
18
41
  // Mask sensitive headers
19
42
  if ((_b = (_a = info.meta) === null || _a === void 0 ? void 0 : _a.req) === null || _b === void 0 ? void 0 : _b.headers) {
20
43
  // Use optional chaining
21
44
  const headers = info.meta.req.headers;
22
- const sensitiveSubstrings = [
23
- "key",
24
- "token",
25
- "secret",
26
- "auth",
27
- "sign",
28
- "password",
29
- "private",
30
- "credential",
31
- "passphrase",
32
- "csrf",
33
- ];
34
45
  // Mask any header containing a sensitive substring
35
46
  Object.keys(headers).forEach((headerKey) => {
36
- const lower = headerKey.toLowerCase();
37
- if (sensitiveSubstrings.some((sub) => lower.includes(sub))) {
47
+ if (this.isSensitiveKey(headerKey)) {
38
48
  headers[headerKey] = this.maskValue(String(headers[headerKey]));
39
49
  }
40
50
  });
@@ -152,22 +162,131 @@ class LoggerService {
152
162
  if (typeof info.message === "object") {
153
163
  info.message = error.message;
154
164
  }
165
+ // Deep mask the error object to catch SDK errors with embedded configs/headers
155
166
  if ((_c = info.meta) === null || _c === void 0 ? void 0 : _c.err) {
156
- // Use optional chaining
157
- delete info.meta.err;
167
+ info.meta.err = this.deepMaskSensitiveKeys(info.meta.err);
158
168
  }
159
169
  }
170
+ // Deep mask the entire meta object to catch any remaining sensitive data
171
+ if (info.meta) {
172
+ const _d = info.meta, { req, res } = _d, rest = __rest(_d, ["req", "res"]);
173
+ // req/res are already handled above, deep mask everything else (error objects, SDK responses, etc.)
174
+ const masked = this.deepMaskSensitiveKeys(rest);
175
+ info.meta = Object.assign(Object.assign({}, info.meta), masked);
176
+ }
160
177
  return info;
161
178
  });
179
+ // Pre-compiled regex patterns for string masking
180
+ this.sensitiveStringPatterns = [
181
+ // Quoted keys: "Authorization":"value" or "api-key": "value"
182
+ new RegExp(`("(?:[^"]*(?:${this.sensitiveSubstrings.join("|")})[^"]*)"\\s*[:=]\\s*"?)([^",}\\s]+)`, "gi"),
183
+ // Unquoted keys: Authorization: value, apiKey=value, api_key: value
184
+ new RegExp(`((?:^|[\\s,;{])(?:[\\w-]*(?:${this.sensitiveSubstrings.join("|")})[\\w-]*)\\s*[:=]\\s*"?)([^",}\\s;]+)`, "gi"),
185
+ // Bearer tokens: Bearer <token>
186
+ /(\bBearer\s+)([^\s,;"]+)/gi,
187
+ ];
162
188
  this.logger = null;
189
+ this.setupConsoleMasking();
190
+ this.setupStreamMasking();
191
+ }
192
+ isSensitiveKey(key) {
193
+ const lower = key.toLowerCase();
194
+ return this.sensitiveSubstrings.some((sub) => lower.includes(sub));
163
195
  }
164
196
  maskValue(value, showLastFour = false) {
165
197
  if (showLastFour) {
166
- return value.length > 4 ? "*".repeat(12) + value.slice(-4) : value;
198
+ return value.length > 4 ? "*".repeat(12) + value.slice(-4) : "************";
199
+ }
200
+ return value.length > 2 ? "*".repeat(12) + value.slice(-2) : "************";
201
+ }
202
+ deepMaskSensitiveKeys(obj, seen = new WeakSet()) {
203
+ if (obj === null || obj === undefined)
204
+ return obj;
205
+ if (typeof obj !== "object")
206
+ return obj;
207
+ if (seen.has(obj))
208
+ return "[Circular]";
209
+ seen.add(obj);
210
+ if (Array.isArray(obj)) {
211
+ return obj.map((item) => this.deepMaskSensitiveKeys(item, seen));
167
212
  }
168
- else {
169
- return "************";
213
+ const result = {};
214
+ for (const key of Object.keys(obj)) {
215
+ const value = obj[key];
216
+ if (this.isSensitiveKey(key) && typeof value === "string") {
217
+ result[key] = this.maskValue(value);
218
+ }
219
+ else if (typeof value === "object" && value !== null) {
220
+ result[key] = this.deepMaskSensitiveKeys(value, seen);
221
+ }
222
+ else {
223
+ result[key] = value;
224
+ }
170
225
  }
226
+ return result;
227
+ }
228
+ sanitizeArg(arg) {
229
+ if (arg === null || arg === undefined)
230
+ return arg;
231
+ if (typeof arg === "string") {
232
+ return this.maskSensitiveString(arg);
233
+ }
234
+ if (arg instanceof Error) {
235
+ const masked = this.deepMaskSensitiveKeys(Object.assign(Object.assign({}, arg), { message: arg.message, stack: arg.stack }));
236
+ const sanitizedError = new Error(this.maskSensitiveString(masked.message));
237
+ sanitizedError.stack = this.maskSensitiveString(masked.stack || "");
238
+ Object.assign(sanitizedError, masked);
239
+ return sanitizedError;
240
+ }
241
+ if (typeof arg === "object") {
242
+ return this.deepMaskSensitiveKeys(arg);
243
+ }
244
+ return arg;
245
+ }
246
+ maskSensitiveString(str) {
247
+ let result = str;
248
+ for (const pattern of this.sensitiveStringPatterns) {
249
+ pattern.lastIndex = 0;
250
+ result = result.replace(pattern, (_match, prefix, value) => {
251
+ if (value.length > 2) {
252
+ return `${prefix}************${value.slice(-2)}`;
253
+ }
254
+ return `${prefix}************`;
255
+ });
256
+ }
257
+ return result;
258
+ }
259
+ setupConsoleMasking() {
260
+ const originalConsole = {
261
+ log: console.log.bind(console),
262
+ error: console.error.bind(console),
263
+ warn: console.warn.bind(console),
264
+ info: console.info.bind(console),
265
+ };
266
+ const sanitize = (...args) => args.map((arg) => this.sanitizeArg(arg));
267
+ console.log = (...args) => originalConsole.log(...sanitize(...args));
268
+ console.error = (...args) => originalConsole.error(...sanitize(...args));
269
+ console.warn = (...args) => originalConsole.warn(...sanitize(...args));
270
+ console.info = (...args) => originalConsole.info(...sanitize(...args));
271
+ }
272
+ setupStreamMasking() {
273
+ const originalStdoutWrite = process.stdout.write.bind(process.stdout);
274
+ const originalStderrWrite = process.stderr.write.bind(process.stderr);
275
+ const maskChunk = (chunk) => {
276
+ if (typeof chunk === "string") {
277
+ return this.maskSensitiveString(chunk);
278
+ }
279
+ if (Buffer.isBuffer(chunk)) {
280
+ return Buffer.from(this.maskSensitiveString(chunk.toString("utf8")));
281
+ }
282
+ return chunk;
283
+ };
284
+ process.stdout.write = (chunk, ...args) => {
285
+ return originalStdoutWrite(maskChunk(chunk), ...args);
286
+ };
287
+ process.stderr.write = (chunk, ...args) => {
288
+ return originalStderrWrite(maskChunk(chunk), ...args);
289
+ };
171
290
  }
172
291
  getLogger() {
173
292
  if (!this.logger) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riocrypto/common-server",
3
- "version": "1.0.2711",
3
+ "version": "1.0.2712",
4
4
  "description": "",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",