@cat-factory/kernel 0.235.0 → 0.235.1
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redact-secrets.logic.d.ts","sourceRoot":"","sources":["../../src/shared/redact-secrets.logic.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"redact-secrets.logic.d.ts","sourceRoot":"","sources":["../../src/shared/redact-secrets.logic.ts"],"names":[],"mappings":"AAuGA;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAcjE;AA6CD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAe/E;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAShD"}
|
|
@@ -8,22 +8,52 @@
|
|
|
8
8
|
// scheme) so the redacted string stays diagnostic. Best-effort and never throws; it is a
|
|
9
9
|
// safety net over the structural allow-lists, not a substitute for them.
|
|
10
10
|
const REPLACEMENT = '[REDACTED]';
|
|
11
|
+
// The armor markers of a PEM-encoded private key, covering the RSA/EC/OPENSSH/ENCRYPTED/PGP
|
|
12
|
+
// variants. Kept as two SEPARATE patterns rather than one `BEGIN…[\s\S]*?…END` regex: see
|
|
13
|
+
// `redactPrivateKeyBlocks`.
|
|
14
|
+
const PEM_PRIVATE_KEY_BEGIN = /-----BEGIN[ A-Z0-9]*PRIVATE KEY[ A-Z0-9]*-----/g;
|
|
15
|
+
const PEM_PRIVATE_KEY_END = /-----END[ A-Z0-9]*PRIVATE KEY[ A-Z0-9]*-----/g;
|
|
16
|
+
/**
|
|
17
|
+
* Drop PEM-armored private keys pasted verbatim, block and all. Such a block has no
|
|
18
|
+
* field-name/URL/token-scheme scaffolding for the {@link RULES} shape rules to catch, so it is
|
|
19
|
+
* found by its armor header and dropped wholesale, regardless of the enclosing filename (a key
|
|
20
|
+
* pasted into a prompt or an ordinarily-named doc is caught too). Public certs
|
|
21
|
+
* (`BEGIN CERTIFICATE`) are intentionally left untouched.
|
|
22
|
+
*
|
|
23
|
+
* Two markers scanned in lockstep rather than one regex with a lazy `[\s\S]*?` body, because
|
|
24
|
+
* that body is unbounded: a header with no END after it makes the engine scan to end-of-string,
|
|
25
|
+
* then advance to the next header and scan the same tail again, which is quadratic in the number
|
|
26
|
+
* of unterminated headers (2MB of them cost ~19s). Here each marker scan only ever moves
|
|
27
|
+
* FORWARD, and a header with no END terminates the whole loop rather than one iteration, since
|
|
28
|
+
* no LATER header can have one either. That makes the pass strictly O(n) whatever the input
|
|
29
|
+
* shape, matching the regex byte-for-byte (pinned by the equivalence cases in the test).
|
|
30
|
+
*
|
|
31
|
+
* An unterminated header is left in place, exactly as the regex left it: there is no second
|
|
32
|
+
* delimiter to bound the drop, and guessing one would either spare a key body or swallow
|
|
33
|
+
* unrelated text to end-of-string.
|
|
34
|
+
*/
|
|
35
|
+
function redactPrivateKeyBlocks(value) {
|
|
36
|
+
PEM_PRIVATE_KEY_BEGIN.lastIndex = 0;
|
|
37
|
+
let begin = PEM_PRIVATE_KEY_BEGIN.exec(value);
|
|
38
|
+
if (begin === null)
|
|
39
|
+
return value;
|
|
40
|
+
let out = '';
|
|
41
|
+
let copiedTo = 0;
|
|
42
|
+
while (begin !== null) {
|
|
43
|
+
PEM_PRIVATE_KEY_END.lastIndex = begin.index + begin[0].length;
|
|
44
|
+
const end = PEM_PRIVATE_KEY_END.exec(value);
|
|
45
|
+
if (end === null)
|
|
46
|
+
break;
|
|
47
|
+
out += value.slice(copiedTo, begin.index) + REPLACEMENT;
|
|
48
|
+
copiedTo = end.index + end[0].length;
|
|
49
|
+
PEM_PRIVATE_KEY_BEGIN.lastIndex = copiedTo;
|
|
50
|
+
begin = PEM_PRIVATE_KEY_BEGIN.exec(value);
|
|
51
|
+
}
|
|
52
|
+
return copiedTo === 0 ? value : out + value.slice(copiedTo);
|
|
53
|
+
}
|
|
11
54
|
// Each rule matches a secret-bearing fragment; the capture group(s) bracket the literal
|
|
12
55
|
// prefix to keep (so the reader still sees WHAT was redacted) and the secret to drop.
|
|
13
56
|
const RULES = [
|
|
14
|
-
// PEM-armored private keys pasted verbatim (`-----BEGIN … PRIVATE KEY-----` …
|
|
15
|
-
// `-----END … PRIVATE KEY-----`), covering RSA/EC/OPENSSH/ENCRYPTED/PGP variants. Such a
|
|
16
|
-
// block has no field-name/URL/token-scheme scaffolding for the shape rules below to catch,
|
|
17
|
-
// so it is matched on its armor header and dropped wholesale — regardless of the enclosing
|
|
18
|
-
// filename, so a key pasted into a prompt or an ordinarily-named doc is caught too. The
|
|
19
|
-
// body is `[\s\S]*?` (non-greedy, bounded by the literal END marker), so no catastrophic
|
|
20
|
-
// backtracking. Runs FIRST so a later field-name rule (e.g. a `key:` echo preceding the
|
|
21
|
-
// block) can't consume the `-----BEGIN` marker and leave the body behind. Public certs
|
|
22
|
-
// (`BEGIN CERTIFICATE`) are intentionally left untouched.
|
|
23
|
-
{
|
|
24
|
-
pattern: /-----BEGIN[ A-Z0-9]*PRIVATE KEY[ A-Z0-9]*-----[\s\S]*?-----END[ A-Z0-9]*PRIVATE KEY[ A-Z0-9]*-----/g,
|
|
25
|
-
replace: () => REPLACEMENT,
|
|
26
|
-
},
|
|
27
57
|
// `Authorization: Bearer <token>` / `Bearer <token>` (case-insensitive scheme).
|
|
28
58
|
{
|
|
29
59
|
pattern: /\b(bearer|basic|token)\s+([A-Za-z0-9._+/=~-]{8,})/gi,
|
|
@@ -34,12 +64,19 @@ const RULES = [
|
|
|
34
64
|
pattern: /\b(authorization|x-api-key|x-auth-token|proxy-authorization)(["']?\s*[:=]\s*["']?)([^\s"',}]+)/gi,
|
|
35
65
|
replace: (m) => `${m[1]}${m[2]}${REPLACEMENT}`,
|
|
36
66
|
},
|
|
37
|
-
// Credentials embedded in a URL userinfo: `scheme://user:secret@host`. The scheme run
|
|
38
|
-
//
|
|
39
|
-
//
|
|
67
|
+
// Credentials embedded in a URL userinfo: `scheme://user:secret@host`. The scheme run is
|
|
68
|
+
// length-bounded (a real scheme is short) so a long non-URL string can't make the greedy
|
|
69
|
+
// scheme scan-then-backtrack at every offset, and it sits in a LOOKBEHIND rather than a
|
|
70
|
+
// leading capture so the pattern's first obligation at each offset is the literal `://`.
|
|
71
|
+
// A leading `[a-z]` made the engine walk that bounded run at every position of any
|
|
72
|
+
// alphanumeric text before failing: ~40 steps per character, which costs ~130ms per 512KB
|
|
73
|
+
// of base64 or minified source and made scrubbing one large context file the dominant cost
|
|
74
|
+
// of recording a snapshot. Behind the lookbehind the same offsets reject on a single
|
|
75
|
+
// character comparison (~2ms per 512KB), matching identically: the scheme is not consumed,
|
|
76
|
+
// so it survives in the output untouched instead of being re-emitted by the replacement.
|
|
40
77
|
{
|
|
41
|
-
pattern: /([a-z][a-z0-9+.-]{0,39}:\/\/)([^/\s:@]+):([^/\s@]+)@/gi,
|
|
42
|
-
replace: (m) => `${m[1]}
|
|
78
|
+
pattern: /(?<=[a-z][a-z0-9+.-]{0,39}:\/\/)([^/\s:@]+):([^/\s@]+)@/gi,
|
|
79
|
+
replace: (m) => `${m[1]}:${REPLACEMENT}@`,
|
|
43
80
|
},
|
|
44
81
|
// Secret-ish query/JSON params: token, key, secret, password, sig, signature,
|
|
45
82
|
// api_key/apikey, access_token, client_secret, etc. (`?token=…` or `"token":"…"`).
|
|
@@ -68,7 +105,9 @@ const RULES = [
|
|
|
68
105
|
export function redactSecrets(value) {
|
|
69
106
|
if (value == null)
|
|
70
107
|
return value;
|
|
71
|
-
|
|
108
|
+
// PEM blocks FIRST, so a later field-name rule (e.g. a `key:` echo preceding the block)
|
|
109
|
+
// can't consume the `-----BEGIN` marker and leave the body behind.
|
|
110
|
+
let out = redactPrivateKeyBlocks(value);
|
|
72
111
|
for (const rule of RULES) {
|
|
73
112
|
out = out.replace(rule.pattern, (...args) => {
|
|
74
113
|
// String.replace passes (match, ...groups, offset, string); reconstruct the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redact-secrets.logic.js","sourceRoot":"","sources":["../../src/shared/redact-secrets.logic.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,yFAAyF;AACzF,sFAAsF;AACtF,oFAAoF;AACpF,yFAAyF;AACzF,yFAAyF;AACzF,2FAA2F;AAC3F,yFAAyF;AACzF,yEAAyE;AAEzE,MAAM,WAAW,GAAG,YAAY,CAAA;AAEhC,
|
|
1
|
+
{"version":3,"file":"redact-secrets.logic.js","sourceRoot":"","sources":["../../src/shared/redact-secrets.logic.ts"],"names":[],"mappings":"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"}
|