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