@yuneta/gobj-js 7.26.19 → 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 +101 -12
- package/dist/gobj-js.cjs.js.map +1 -1
- package/dist/gobj-js.cjs.min.js +762 -711
- package/dist/gobj-js.cjs.min.js.map +1 -1
- package/dist/gobj-js.es.js +101 -12
- package/dist/gobj-js.es.js.map +1 -1
- package/dist/gobj-js.es.min.js +780 -729
- package/dist/gobj-js.es.min.js.map +1 -1
- package/dist/gobj-js.iife.js +101 -12
- package/dist/gobj-js.iife.js.map +1 -1
- package/dist/gobj-js.iife.min.js +762 -711
- package/dist/gobj-js.iife.min.js.map +1 -1
- package/dist/gobj-js.umd.js +101 -12
- package/dist/gobj-js.umd.js.map +1 -1
- package/dist/gobj-js.umd.min.js +762 -711
- package/dist/gobj-js.umd.min.js.map +1 -1
- package/package.json +1 -1
package/dist/gobj-js.es.js
CHANGED
|
@@ -3435,6 +3435,11 @@ var SECRET_NAME_JOINED = [
|
|
|
3435
3435
|
"sessionkey",
|
|
3436
3436
|
"authdata"
|
|
3437
3437
|
];
|
|
3438
|
+
var SECRET_NAME_SEGMENTS = /* @__PURE__ */ new Set([
|
|
3439
|
+
"pass",
|
|
3440
|
+
"pin",
|
|
3441
|
+
"otp"
|
|
3442
|
+
]);
|
|
3438
3443
|
var NOT_SECRET_SEGMENTS = /* @__PURE__ */ new Set([
|
|
3439
3444
|
"endpoint",
|
|
3440
3445
|
"url",
|
|
@@ -3467,10 +3472,16 @@ function is_secret_name(name) {
|
|
|
3467
3472
|
if (typeof name !== "string" || name.length < 3) return false;
|
|
3468
3473
|
let lower = name.toLowerCase();
|
|
3469
3474
|
let hit = false;
|
|
3470
|
-
for (const
|
|
3475
|
+
for (const segment of lower.split(/[^a-z0-9]+/)) if (SECRET_NAME_SEGMENTS.has(segment)) {
|
|
3471
3476
|
hit = true;
|
|
3472
3477
|
break;
|
|
3473
3478
|
}
|
|
3479
|
+
if (!hit) {
|
|
3480
|
+
for (const part of SECRET_NAME_PARTS) if (lower.indexOf(part) >= 0) {
|
|
3481
|
+
hit = true;
|
|
3482
|
+
break;
|
|
3483
|
+
}
|
|
3484
|
+
}
|
|
3474
3485
|
if (!hit) {
|
|
3475
3486
|
let joined = lower.replace(/[_\-. \t]/g, "");
|
|
3476
3487
|
for (const part of SECRET_NAME_JOINED) if (joined.indexOf(part) >= 0) {
|
|
@@ -3508,17 +3519,63 @@ function inline_secret_value_end(str, p, outer) {
|
|
|
3508
3519
|
}
|
|
3509
3520
|
}
|
|
3510
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
|
+
/************************************************************
|
|
3511
3565
|
* A text (a command line) with the value of every "name=value"
|
|
3512
3566
|
* whose name is a secret's written as "********", quoted or not
|
|
3513
3567
|
* (and the "value" of a write-attr whose attribute names a
|
|
3514
|
-
* secret)
|
|
3515
|
-
*
|
|
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().
|
|
3516
3572
|
************************************************************/
|
|
3517
3573
|
var MASK_MAX_NAME = 128;
|
|
3518
3574
|
var MASK_MAX_BYTES = 4194304;
|
|
3519
3575
|
var MASK_TOO_LARGE = "<not shown: too large to mask>";
|
|
3520
3576
|
function mask_secrets_inline(str) {
|
|
3521
|
-
if (typeof str !== "string"
|
|
3577
|
+
if (typeof str !== "string") return null;
|
|
3578
|
+
if (str.indexOf("=") < 0 && str.indexOf("eyJ") < 0 && !/bearer/i.test(str)) return null;
|
|
3522
3579
|
if (str.length > MASK_MAX_BYTES) return MASK_TOO_LARGE;
|
|
3523
3580
|
let value_is_secret = false;
|
|
3524
3581
|
let re_attr = /(^|[ \t])attribute=["']?([^ \t"']*)/g;
|
|
@@ -3542,6 +3599,18 @@ function mask_secrets_inline(str) {
|
|
|
3542
3599
|
if (!outer && (p === 0 || str[p - 1] === " " || str[p - 1] === " " || str[p - 1] === "=")) outer = c;
|
|
3543
3600
|
else if (c === outer && is_blank_or_end(p + 1)) outer = "";
|
|
3544
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
|
+
}
|
|
3545
3614
|
if (c !== "=") {
|
|
3546
3615
|
p++;
|
|
3547
3616
|
continue;
|
|
@@ -3578,7 +3647,8 @@ function mask_secrets_inline(str) {
|
|
|
3578
3647
|
* value of a key with a secret's name is "********", whatever
|
|
3579
3648
|
* its type (not an absent one, a null or an empty string); so is
|
|
3580
3649
|
* the "value" of a dict whose "attribute" names a secret; and a
|
|
3581
|
-
* string is masked as mask_secrets_inline()
|
|
3650
|
+
* string, under any key, is masked as mask_secrets_inline() (a
|
|
3651
|
+
* JWT, a "Bearer" token, a secret name=value). Return a masked
|
|
3582
3652
|
* copy, or `jn` itself when there was nothing to mask. As the C
|
|
3583
3653
|
* kernel's json_mask_secrets().
|
|
3584
3654
|
*
|
|
@@ -3607,7 +3677,7 @@ function _json_mask_secrets(jn, memo, depth, budget) {
|
|
|
3607
3677
|
return MASK_TOO_LARGE;
|
|
3608
3678
|
}
|
|
3609
3679
|
budget.left -= jn.length;
|
|
3610
|
-
let masked = mask_secrets_inline(jn);
|
|
3680
|
+
let masked = mask_secrets_inline(jn.indexOf("\0") >= 0 ? jn.replace(/\u0000/g, " ") : jn);
|
|
3611
3681
|
return masked !== null ? masked : jn;
|
|
3612
3682
|
}
|
|
3613
3683
|
let is_array = Array.isArray(jn);
|
|
@@ -7109,15 +7179,34 @@ function save_trace_scope(gobj, attr, scope, levels) {
|
|
|
7109
7179
|
return gobj_save_persistent_attrs(gobj, attr);
|
|
7110
7180
|
}
|
|
7111
7181
|
/***************************************************************
|
|
7112
|
-
* "set" as the C command reads it
|
|
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.
|
|
7113
7189
|
***************************************************************/
|
|
7190
|
+
var INT_MIN = -2147483648;
|
|
7191
|
+
var INT_MAX = 2147483647;
|
|
7114
7192
|
function parse_set(value) {
|
|
7115
7193
|
if (value === true || value === false) return value;
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
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;
|
|
7121
7210
|
}
|
|
7122
7211
|
function yuno_prefix() {
|
|
7123
7212
|
return `${gobj_yuno_role()}^${gobj_yuno_name()}`;
|