@yuneta/gobj-js 7.26.18 → 7.26.20

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.
@@ -3335,18 +3335,23 @@ function format_log(format) {
3335
3335
  } else output = args.map((arg) => typeof arg === "object" ? log_stringify(arg) : log_string(arg)).join(" ");
3336
3336
  return output;
3337
3337
  }
3338
- var __in_log_function__ = false;
3339
3338
  function call_log_function(fn, ...args) {
3340
- if (__in_log_function__) return;
3341
- __in_log_function__ = true;
3342
3339
  try {
3343
3340
  fn(...args);
3344
3341
  } catch (e) {
3345
3342
  try {
3346
3343
  _console.error("a log function threw:", e);
3347
3344
  } catch (e2) {}
3345
+ }
3346
+ }
3347
+ var __in_remote_log__ = false;
3348
+ function call_remote_log_function(fn, ...args) {
3349
+ if (__in_remote_log__) return;
3350
+ __in_remote_log__ = true;
3351
+ try {
3352
+ call_log_function(fn, ...args);
3348
3353
  } finally {
3349
- __in_log_function__ = false;
3354
+ __in_remote_log__ = false;
3350
3355
  }
3351
3356
  }
3352
3357
  function log_error(format, ...args) {
@@ -3357,7 +3362,7 @@ function log_error(format, ...args) {
3357
3362
  if (console_wants("error", msg)) call_log_function(f_error, "%c" + hora + " ERROR: " + String(msg), "color:red");
3358
3363
  } else {
3359
3364
  if (console_wants("error", msg)) _console.error("%c" + hora + " ERROR: " + String(msg), "color:red");
3360
- call_log_function(f_error, `${hora} ERROR: ${String(msg)}`);
3365
+ call_remote_log_function(f_error, `${hora} ERROR: ${String(msg)}`);
3361
3366
  }
3362
3367
  }
3363
3368
  emit_log_callback("error", msg, hora);
@@ -3370,7 +3375,7 @@ function log_warning(format, ...args) {
3370
3375
  if (console_wants("warning", msg)) call_log_function(f_warning, "%c" + hora + " WARNING: " + String(msg), "color:yellow");
3371
3376
  } else {
3372
3377
  if (console_wants("warning", msg)) _console.warn("%c" + hora + " WARNING: " + String(msg), "color:yellow");
3373
- call_log_function(f_warning, `${hora} WARNING: ${String(msg)}`);
3378
+ call_remote_log_function(f_warning, `${hora} WARNING: ${String(msg)}`);
3374
3379
  }
3375
3380
  }
3376
3381
  emit_log_callback("warning", msg, hora);
@@ -3430,6 +3435,11 @@ var SECRET_NAME_JOINED = [
3430
3435
  "sessionkey",
3431
3436
  "authdata"
3432
3437
  ];
3438
+ var SECRET_NAME_SEGMENTS = /* @__PURE__ */ new Set([
3439
+ "pass",
3440
+ "pin",
3441
+ "otp"
3442
+ ]);
3433
3443
  var NOT_SECRET_SEGMENTS = /* @__PURE__ */ new Set([
3434
3444
  "endpoint",
3435
3445
  "url",
@@ -3462,10 +3472,16 @@ function is_secret_name(name) {
3462
3472
  if (typeof name !== "string" || name.length < 3) return false;
3463
3473
  let lower = name.toLowerCase();
3464
3474
  let hit = false;
3465
- for (const part of SECRET_NAME_PARTS) if (lower.indexOf(part) >= 0) {
3475
+ for (const segment of lower.split(/[^a-z0-9]+/)) if (SECRET_NAME_SEGMENTS.has(segment)) {
3466
3476
  hit = true;
3467
3477
  break;
3468
3478
  }
3479
+ if (!hit) {
3480
+ for (const part of SECRET_NAME_PARTS) if (lower.indexOf(part) >= 0) {
3481
+ hit = true;
3482
+ break;
3483
+ }
3484
+ }
3469
3485
  if (!hit) {
3470
3486
  let joined = lower.replace(/[_\-. \t]/g, "");
3471
3487
  for (const part of SECRET_NAME_JOINED) if (joined.indexOf(part) >= 0) {
@@ -3503,17 +3519,63 @@ function inline_secret_value_end(str, p, outer) {
3503
3519
  }
3504
3520
  }
3505
3521
  /************************************************************
3522
+ * A credential by its SHAPE, whatever names it -- the C kernel's
3523
+ * jwt_len() / bearer_token_len(), the shapes the agent's audit
3524
+ * record redacts:
3525
+ * - a JWT: "eyJ" (the base64url of '{"') at the start of a
3526
+ * word, and three parts of base64url joined by '.'; the dots
3527
+ * at the end of the run are not its own (a JWT ends a
3528
+ * sentence: "... eyJ.eyJ.sig.");
3529
+ * - the token after "Bearer " (any case, a word of its own).
3530
+ ************************************************************/
3531
+ function is_ascii_alnum_code(code) {
3532
+ return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122;
3533
+ }
3534
+ function is_base64url_code(code) {
3535
+ return is_ascii_alnum_code(code) || code === 45 || code === 95;
3536
+ }
3537
+ function jwt_len(str, p) {
3538
+ if (str.length - p < 3 || str[p] !== "e" || str[p + 1] !== "y" || str[p + 2] !== "J") return 0;
3539
+ if (p > 0 && (is_base64url_code(str.charCodeAt(p - 1)) || str[p - 1] === ".")) return 0;
3540
+ let e = p;
3541
+ let dots = 0;
3542
+ while (e < str.length && (is_base64url_code(str.charCodeAt(e)) || str[e] === ".")) {
3543
+ if (str[e] === ".") dots++;
3544
+ e++;
3545
+ }
3546
+ while (str[e - 1] === ".") {
3547
+ e--;
3548
+ dots--;
3549
+ }
3550
+ return dots === 2 ? e - p : 0;
3551
+ }
3552
+ var BEARER_STOPS = " \r\n'\",;}]\0";
3553
+ function bearer_token(str, p) {
3554
+ const word_len = 6;
3555
+ if (str.length - p <= word_len || str.slice(p, p + word_len).toLowerCase() !== "bearer") return [0, 0];
3556
+ if (p > 0 && is_ascii_alnum_code(str.charCodeAt(p - 1))) return [0, 0];
3557
+ let t = p + word_len;
3558
+ if (str[t] !== " " && str[t] !== " ") return [0, 0];
3559
+ while (t < str.length && (str[t] === " " || str[t] === " ")) t++;
3560
+ let e = t;
3561
+ while (e < str.length && BEARER_STOPS.indexOf(str[e]) < 0) e++;
3562
+ return [t - p, e - t];
3563
+ }
3564
+ /************************************************************
3506
3565
  * A text (a command line) with the value of every "name=value"
3507
3566
  * whose name is a secret's written as "********", quoted or not
3508
3567
  * (and the "value" of a write-attr whose attribute names a
3509
- * secret). The rest as it is. Return null when there was nothing
3510
- * to mask. As the C kernel's mask_secrets_inline().
3568
+ * secret); and a JWT or the token after "Bearer ", wherever they
3569
+ * are, whatever names them. The rest as it is. Return null when
3570
+ * there was nothing to mask. As the C kernel's
3571
+ * mask_secrets_inline().
3511
3572
  ************************************************************/
3512
3573
  var MASK_MAX_NAME = 128;
3513
3574
  var MASK_MAX_BYTES = 4194304;
3514
3575
  var MASK_TOO_LARGE = "<not shown: too large to mask>";
3515
3576
  function mask_secrets_inline(str) {
3516
- if (typeof str !== "string" || str.indexOf("=") < 0) return null;
3577
+ if (typeof str !== "string") return null;
3578
+ if (str.indexOf("=") < 0 && str.indexOf("eyJ") < 0 && !/bearer/i.test(str)) return null;
3517
3579
  if (str.length > MASK_MAX_BYTES) return MASK_TOO_LARGE;
3518
3580
  let value_is_secret = false;
3519
3581
  let re_attr = /(^|[ \t])attribute=["']?([^ \t"']*)/g;
@@ -3537,6 +3599,18 @@ function mask_secrets_inline(str) {
3537
3599
  if (!outer && (p === 0 || str[p - 1] === " " || str[p - 1] === " " || str[p - 1] === "=")) outer = c;
3538
3600
  else if (c === outer && is_blank_or_end(p + 1)) outer = "";
3539
3601
  }
3602
+ let shape = c === "e" ? jwt_len(str, p) : 0;
3603
+ let token_offset = 0;
3604
+ if (c === "b" || c === "B") [token_offset, shape] = bearer_token(str, p);
3605
+ if (shape) {
3606
+ parts.push(str.substring(copied, p + token_offset));
3607
+ parts.push("********");
3608
+ p += token_offset + shape;
3609
+ copied = p;
3610
+ changed = true;
3611
+ word = p;
3612
+ continue;
3613
+ }
3540
3614
  if (c !== "=") {
3541
3615
  p++;
3542
3616
  continue;
@@ -3573,7 +3647,8 @@ function mask_secrets_inline(str) {
3573
3647
  * value of a key with a secret's name is "********", whatever
3574
3648
  * its type (not an absent one, a null or an empty string); so is
3575
3649
  * the "value" of a dict whose "attribute" names a secret; and a
3576
- * string is masked as mask_secrets_inline(). Return a masked
3650
+ * string, under any key, is masked as mask_secrets_inline() (a
3651
+ * JWT, a "Bearer" token, a secret name=value). Return a masked
3577
3652
  * copy, or `jn` itself when there was nothing to mask. As the C
3578
3653
  * kernel's json_mask_secrets().
3579
3654
  *
@@ -3602,7 +3677,7 @@ function _json_mask_secrets(jn, memo, depth, budget) {
3602
3677
  return MASK_TOO_LARGE;
3603
3678
  }
3604
3679
  budget.left -= jn.length;
3605
- let masked = mask_secrets_inline(jn);
3680
+ let masked = mask_secrets_inline(jn.indexOf("\0") >= 0 ? jn.replace(/\u0000/g, " ") : jn);
3606
3681
  return masked !== null ? masked : jn;
3607
3682
  }
3608
3683
  let is_array = Array.isArray(jn);
@@ -7104,15 +7179,34 @@ function save_trace_scope(gobj, attr, scope, levels) {
7104
7179
  return gobj_save_persistent_attrs(gobj, attr);
7105
7180
  }
7106
7181
  /***************************************************************
7107
- * "set" as the C command reads it: TRUE / set / 1, FALSE / reset / 0
7182
+ * "set" as the C command reads it (trace_set_value() of c_yuno.c):
7183
+ * a boolean; an integer in the range of an int (true unless 0); or
7184
+ * text -- set / reset, a JSON integer -?(0|[1-9][0-9]*), or true /
7185
+ * false, yes / no, on / off, any case. null for anything else: a
7186
+ * real (2.5), " 1", "0x1", "1e3", "+5", "007" and "2.5" are refused,
7187
+ * as in C. Up to gobj-js 7.26.19 the text went through Number(),
7188
+ * which took all of them, and "yes" / "on" were refused.
7108
7189
  ***************************************************************/
7190
+ var INT_MIN = -2147483648;
7191
+ var INT_MAX = 2147483647;
7109
7192
  function parse_set(value) {
7110
7193
  if (value === true || value === false) return value;
7111
- let v = String(value === void 0 || value === null ? "" : value).toLowerCase();
7112
- if (v === "true" || v === "set") return true;
7113
- if (v === "false" || v === "reset") return false;
7114
- if (v === "" || isNaN(Number(v))) return null;
7115
- return Number(v) ? true : false;
7194
+ if (typeof value === "number") {
7195
+ if (!Number.isInteger(value) || value < INT_MIN || value > INT_MAX) return null;
7196
+ return value !== 0;
7197
+ }
7198
+ if (typeof value !== "string" || value === "") return null;
7199
+ let v = value.toLowerCase();
7200
+ if (v === "set") return true;
7201
+ if (v === "reset") return false;
7202
+ if (/^-?(0|[1-9][0-9]*)$/.test(value)) {
7203
+ let n = Number(value);
7204
+ if (n < INT_MIN || n > INT_MAX) return null;
7205
+ return n !== 0;
7206
+ }
7207
+ if (v === "true" || v === "yes" || v === "on") return true;
7208
+ if (v === "false" || v === "no" || v === "off") return false;
7209
+ return null;
7116
7210
  }
7117
7211
  function yuno_prefix() {
7118
7212
  return `${gobj_yuno_role()}^${gobj_yuno_name()}`;