@foam-ai/node 0.1.0-alpha.5 → 0.1.0-alpha.6
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 +135 -72
- package/dist/before-send.d.ts +16 -0
- package/dist/before-send.js +41 -0
- package/dist/constants.d.ts +4 -3
- package/dist/constants.js +5 -35
- package/dist/exporters.d.ts +11 -3
- package/dist/exporters.js +123 -47
- package/dist/index.d.ts +5 -2
- package/dist/index.js +3 -1
- package/dist/ingest.d.ts +8 -2
- package/dist/ingest.js +15 -6
- package/dist/init.d.ts +4 -0
- package/dist/init.js +22 -3
- package/dist/logs.d.ts +2 -1
- package/dist/logs.js +2 -2
- package/dist/network-capture/collector.js +81 -26
- package/dist/network-capture/redact.d.ts +3 -0
- package/dist/network-capture/redact.js +339 -25
- package/dist/propagation.d.ts +1 -1
- package/dist/propagation.js +6 -4
- package/dist/redaction-keys.d.ts +3 -0
- package/dist/redaction-keys.js +421 -0
- package/dist/redaction.d.ts +24 -0
- package/dist/redaction.js +270 -0
- package/package.json +1 -1
|
@@ -1,32 +1,93 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.isSensitiveBodyKey = isSensitiveBodyKey;
|
|
4
|
+
exports.isNdjsonMediaType = isNdjsonMediaType;
|
|
5
|
+
exports.isJsonSequenceMediaType = isJsonSequenceMediaType;
|
|
6
|
+
exports.isTextualBodyMediaType = isTextualBodyMediaType;
|
|
4
7
|
exports.redactBodyText = redactBodyText;
|
|
5
8
|
const constants_js_1 = require("../constants.js");
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
const redaction_js_1 = require("../redaction.js");
|
|
10
|
+
const NDJSON_MEDIA_TYPES = new Set([
|
|
11
|
+
"application/json-stream",
|
|
12
|
+
"application/jsonl",
|
|
13
|
+
"application/jsonlines",
|
|
14
|
+
"application/ndjson",
|
|
15
|
+
"application/stream+json",
|
|
16
|
+
"application/x-json-stream",
|
|
17
|
+
"application/x-jsonlines",
|
|
18
|
+
"application/x-ldjson",
|
|
19
|
+
"application/x-ndjson",
|
|
20
|
+
]);
|
|
21
|
+
const JSON_SEQUENCE_MEDIA_TYPES = new Set([
|
|
22
|
+
"application/json-seq",
|
|
23
|
+
"application/x-json-seq",
|
|
24
|
+
]);
|
|
25
|
+
const XML_MEDIA_TYPES = new Set([
|
|
26
|
+
"application/xml",
|
|
27
|
+
"text/html",
|
|
28
|
+
"text/xml",
|
|
29
|
+
]);
|
|
30
|
+
const YAML_MEDIA_TYPES = new Set([
|
|
31
|
+
"application/x-yaml",
|
|
32
|
+
"application/yaml",
|
|
33
|
+
"text/x-yaml",
|
|
34
|
+
"text/yaml",
|
|
35
|
+
]);
|
|
36
|
+
function rawHeader(value) {
|
|
37
|
+
const first = Array.isArray(value) ? value[0] : value;
|
|
38
|
+
return typeof first === "string" ? first : "";
|
|
39
|
+
}
|
|
40
|
+
function parseContentType(value) {
|
|
41
|
+
const raw = rawHeader(value);
|
|
42
|
+
const media = (raw.split(";", 1)[0] ?? "").trim().toLowerCase();
|
|
43
|
+
const params = new Map();
|
|
44
|
+
const pattern = /;\s*([^=;\s]+)\s*=\s*(?:"([^"]*)"|([^;]*))/g;
|
|
45
|
+
let match;
|
|
46
|
+
while ((match = pattern.exec(raw)) !== null) {
|
|
47
|
+
params.set(match[1].toLowerCase(), (match[2] ?? match[3] ?? "").trim());
|
|
48
|
+
}
|
|
49
|
+
return { media, params };
|
|
9
50
|
}
|
|
10
51
|
function isSensitiveBodyKey(key) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
52
|
+
return (0, redaction_js_1.keyMatch)(key) !== undefined;
|
|
53
|
+
}
|
|
54
|
+
function isNdjsonMediaType(media) {
|
|
55
|
+
return (NDJSON_MEDIA_TYPES.has(media) ||
|
|
56
|
+
media.endsWith("+ndjson") ||
|
|
57
|
+
media.endsWith("/ndjson"));
|
|
58
|
+
}
|
|
59
|
+
function isJsonSequenceMediaType(media) {
|
|
60
|
+
return JSON_SEQUENCE_MEDIA_TYPES.has(media) || media.endsWith("+json-seq");
|
|
14
61
|
}
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
62
|
+
function isTextualBodyMediaType(media) {
|
|
63
|
+
return (media.startsWith("text/") ||
|
|
64
|
+
media.startsWith("multipart/") ||
|
|
65
|
+
media.endsWith("/json") ||
|
|
66
|
+
media.endsWith("+json") ||
|
|
67
|
+
media.endsWith("/xml") ||
|
|
68
|
+
media.endsWith("+xml") ||
|
|
69
|
+
media.endsWith("/yaml") ||
|
|
70
|
+
media.endsWith("+yaml") ||
|
|
71
|
+
isNdjsonMediaType(media) ||
|
|
72
|
+
isJsonSequenceMediaType(media) ||
|
|
73
|
+
media === "application/x-www-form-urlencoded");
|
|
20
74
|
}
|
|
21
75
|
function redactNode(node, state) {
|
|
76
|
+
if (typeof node === "string") {
|
|
77
|
+
const value = (0, redaction_js_1.redactString)(node);
|
|
78
|
+
if (value !== node)
|
|
79
|
+
state.changed = true;
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
22
82
|
if (Array.isArray(node)) {
|
|
23
83
|
return node.map((item) => redactNode(item, state));
|
|
24
84
|
}
|
|
25
85
|
if (node !== null && typeof node === "object") {
|
|
26
86
|
const result = {};
|
|
27
87
|
for (const [key, value] of Object.entries(node)) {
|
|
28
|
-
|
|
29
|
-
|
|
88
|
+
const match = (0, redaction_js_1.keyMatch)(key);
|
|
89
|
+
if (match && value !== null && value !== undefined) {
|
|
90
|
+
result[key] = (0, redaction_js_1.maskForMatch)(match, value);
|
|
30
91
|
state.changed = true;
|
|
31
92
|
}
|
|
32
93
|
else {
|
|
@@ -37,17 +98,18 @@ function redactNode(node, state) {
|
|
|
37
98
|
}
|
|
38
99
|
return node;
|
|
39
100
|
}
|
|
40
|
-
// pcga11: Captures a "key": value pair with a string (possibly unterminated
|
|
41
|
-
// at a truncation point), number, or literal value. Used only when the body
|
|
42
|
-
// does not parse as JSON, e.g. because the 1 MiB cap cut it mid-document.
|
|
43
101
|
const JSON_PAIR_PATTERN = /"((?:[^"\\]|\\.)*)"(\s*:\s*)("(?:[^"\\]|\\.)*"?|-?\d[\d.eE+-]*|true|false|null)/g;
|
|
102
|
+
function fallbackMask(kind) {
|
|
103
|
+
return kind === "secret" ? constants_js_1.FULL_MASK : constants_js_1.REDACTED_VALUE;
|
|
104
|
+
}
|
|
44
105
|
function redactJsonFallback(text) {
|
|
45
106
|
let changed = false;
|
|
46
107
|
const redacted = text.replace(JSON_PAIR_PATTERN, (match, key, separator) => {
|
|
47
|
-
|
|
108
|
+
const kind = (0, redaction_js_1.keyMatch)(key);
|
|
109
|
+
if (!kind)
|
|
48
110
|
return match;
|
|
49
111
|
changed = true;
|
|
50
|
-
return `"${key}"${separator}"${
|
|
112
|
+
return `"${key}"${separator}"${fallbackMask(kind)}"`;
|
|
51
113
|
});
|
|
52
114
|
return changed ? { text: redacted, changed } : { text, changed: false };
|
|
53
115
|
}
|
|
@@ -61,27 +123,279 @@ function redactJson(text) {
|
|
|
61
123
|
}
|
|
62
124
|
const state = { changed: false };
|
|
63
125
|
const redacted = redactNode(parsed, state);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
126
|
+
return state.changed
|
|
127
|
+
? { text: JSON.stringify(redacted), changed: true }
|
|
128
|
+
: { text, changed: false };
|
|
129
|
+
}
|
|
130
|
+
function redactByLine(text, redactLine) {
|
|
131
|
+
let changed = false;
|
|
132
|
+
const lines = text.split("\n").map((raw) => {
|
|
133
|
+
const hasCr = raw.endsWith("\r");
|
|
134
|
+
const line = hasCr ? raw.slice(0, -1) : raw;
|
|
135
|
+
if (!line)
|
|
136
|
+
return raw;
|
|
137
|
+
const result = redactLine(line);
|
|
138
|
+
if (!result.changed)
|
|
139
|
+
return raw;
|
|
140
|
+
changed = true;
|
|
141
|
+
return hasCr ? `${result.text}\r` : result.text;
|
|
142
|
+
});
|
|
143
|
+
return changed
|
|
144
|
+
? { text: lines.join("\n"), changed: true }
|
|
145
|
+
: { text, changed: false };
|
|
146
|
+
}
|
|
147
|
+
function redactNdjson(text) {
|
|
148
|
+
return redactByLine(text, redactJson);
|
|
149
|
+
}
|
|
150
|
+
function redactJsonSequence(text) {
|
|
151
|
+
if (!text.includes("\u001e"))
|
|
152
|
+
return redactJson(text);
|
|
153
|
+
let changed = false;
|
|
154
|
+
const segments = text.split("\u001e");
|
|
155
|
+
const redacted = segments.map((segment, index) => {
|
|
156
|
+
if (index === 0 || !segment)
|
|
157
|
+
return segment;
|
|
158
|
+
const ending = segment.match(/(?:\r\n|\n|\r)$/)?.[0] ?? "";
|
|
159
|
+
const document = ending ? segment.slice(0, -ending.length) : segment;
|
|
160
|
+
const result = redactJson(document);
|
|
161
|
+
if (!result.changed)
|
|
162
|
+
return segment;
|
|
163
|
+
changed = true;
|
|
164
|
+
return `${result.text}${ending}`;
|
|
165
|
+
});
|
|
166
|
+
return changed
|
|
167
|
+
? { text: redacted.join("\u001e"), changed: true }
|
|
168
|
+
: { text, changed: false };
|
|
169
|
+
}
|
|
170
|
+
function redactSseBlock(block) {
|
|
171
|
+
const lineEnding = block.match(/\r\n|\n|\r/)?.[0] ?? "\n";
|
|
172
|
+
const lines = block.split(/\r\n|\n|\r/);
|
|
173
|
+
const data = [];
|
|
174
|
+
lines.forEach((line, index) => {
|
|
175
|
+
const match = /^(data: ?)(.*)$/.exec(line);
|
|
176
|
+
if (match) {
|
|
177
|
+
data.push({ index, prefix: match[1], value: match[2] });
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
if (data.length === 0)
|
|
181
|
+
return { text: block, changed: false };
|
|
182
|
+
const payload = data.map((entry) => entry.value).join("\n");
|
|
183
|
+
const json = redactJson(payload);
|
|
184
|
+
const plain = json.changed ? json : redactPlainText(payload);
|
|
185
|
+
if (!plain.changed)
|
|
186
|
+
return { text: block, changed: false };
|
|
187
|
+
lines[data[0].index] = `${data[0].prefix}${plain.text}`;
|
|
188
|
+
for (let index = data.length - 1; index >= 1; index -= 1) {
|
|
189
|
+
lines.splice(data[index].index, 1);
|
|
190
|
+
}
|
|
191
|
+
return { text: lines.join(lineEnding), changed: true };
|
|
192
|
+
}
|
|
193
|
+
function redactSse(text) {
|
|
194
|
+
const separator = /(\r\n\r\n|\n\n|\r\r)/;
|
|
195
|
+
const parts = text.split(separator);
|
|
196
|
+
let changed = false;
|
|
197
|
+
for (let index = 0; index < parts.length; index += 2) {
|
|
198
|
+
const result = redactSseBlock(parts[index]);
|
|
199
|
+
if (result.changed) {
|
|
200
|
+
parts[index] = result.text;
|
|
201
|
+
changed = true;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return changed
|
|
205
|
+
? { text: parts.join(""), changed: true }
|
|
206
|
+
: { text, changed: false };
|
|
67
207
|
}
|
|
68
208
|
function redactForm(text) {
|
|
69
209
|
const params = new URLSearchParams(text);
|
|
70
210
|
let changed = false;
|
|
71
211
|
for (const key of new Set(params.keys())) {
|
|
72
|
-
if (!
|
|
212
|
+
if (!(0, redaction_js_1.keyMatch)(key) && !(0, redaction_js_1.isSensitiveQueryKey)(key))
|
|
73
213
|
continue;
|
|
74
214
|
params.set(key, constants_js_1.REDACTED_VALUE);
|
|
75
215
|
changed = true;
|
|
76
216
|
}
|
|
77
|
-
return changed
|
|
217
|
+
return changed
|
|
218
|
+
? { text: params.toString(), changed: true }
|
|
219
|
+
: { text, changed: false };
|
|
220
|
+
}
|
|
221
|
+
function localName(name) {
|
|
222
|
+
const separator = name.lastIndexOf(":");
|
|
223
|
+
return separator < 0 ? name : name.slice(separator + 1);
|
|
224
|
+
}
|
|
225
|
+
function escapePattern(value) {
|
|
226
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
227
|
+
}
|
|
228
|
+
function redactXmlElements(text) {
|
|
229
|
+
let changed = false;
|
|
230
|
+
let cursor = 0;
|
|
231
|
+
let output = "";
|
|
232
|
+
const opening = /<([A-Za-z_][\w:.-]*)(?:\s[^>]*)?>/g;
|
|
233
|
+
let match;
|
|
234
|
+
while ((match = opening.exec(text)) !== null) {
|
|
235
|
+
if (match[0].endsWith("/>"))
|
|
236
|
+
continue;
|
|
237
|
+
const kind = (0, redaction_js_1.keyMatch)(localName(match[1]));
|
|
238
|
+
if (!kind)
|
|
239
|
+
continue;
|
|
240
|
+
const closing = new RegExp(`</${escapePattern(match[1])}\\s*>`, "g");
|
|
241
|
+
closing.lastIndex = opening.lastIndex;
|
|
242
|
+
const close = closing.exec(text);
|
|
243
|
+
output += text.slice(cursor, opening.lastIndex);
|
|
244
|
+
if (!close) {
|
|
245
|
+
output += fallbackMask(kind);
|
|
246
|
+
cursor = text.length;
|
|
247
|
+
changed = true;
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
const value = text.slice(opening.lastIndex, close.index);
|
|
251
|
+
output += `${value.includes("<") ? fallbackMask(kind) : (0, redaction_js_1.maskForMatch)(kind, value)}${close[0]}`;
|
|
252
|
+
cursor = closing.lastIndex;
|
|
253
|
+
opening.lastIndex = cursor;
|
|
254
|
+
changed = true;
|
|
255
|
+
}
|
|
256
|
+
if (!changed)
|
|
257
|
+
return { text, changed: false };
|
|
258
|
+
return { text: output + text.slice(cursor), changed: true };
|
|
259
|
+
}
|
|
260
|
+
function redactXml(text) {
|
|
261
|
+
const elements = redactXmlElements(text);
|
|
262
|
+
let changed = elements.changed;
|
|
263
|
+
let output = elements.text;
|
|
264
|
+
output = output.replace(/(\s)([A-Za-z_:][\w:.-]*)(\s*=\s*)(["'])(.*?)\4/g, (match, spacing, name, separator, quote, value) => {
|
|
265
|
+
const kind = (0, redaction_js_1.keyMatch)(localName(name));
|
|
266
|
+
if (!kind)
|
|
267
|
+
return match;
|
|
268
|
+
changed = true;
|
|
269
|
+
return `${spacing}${name}${separator}${quote}${(0, redaction_js_1.maskForMatch)(kind, value)}${quote}`;
|
|
270
|
+
});
|
|
271
|
+
output = output.replace(/<input\b[^>]*>/gi, (tag) => {
|
|
272
|
+
const name = /\bname\s*=\s*(["'])(.*?)\1/i.exec(tag)?.[2];
|
|
273
|
+
if (!name || (!(0, redaction_js_1.keyMatch)(name) && !(0, redaction_js_1.isSensitiveQueryKey)(name)))
|
|
274
|
+
return tag;
|
|
275
|
+
const replaced = tag.replace(/(\bvalue\s*=\s*)(["'])(.*?)\2/i, `$1$2${constants_js_1.REDACTED_VALUE}$2`);
|
|
276
|
+
if (replaced === tag)
|
|
277
|
+
return tag;
|
|
278
|
+
changed = true;
|
|
279
|
+
return replaced;
|
|
280
|
+
});
|
|
281
|
+
return changed ? { text: output, changed: true } : { text, changed: false };
|
|
282
|
+
}
|
|
283
|
+
const YAML_PAIR = /^(\s*(?:-\s*)?)(["']?)([A-Za-z_][\w.-]*)\2(\s*:\s*)(.*)$/;
|
|
284
|
+
function redactYaml(text) {
|
|
285
|
+
let blockSecret = false;
|
|
286
|
+
const result = redactByLine(text, (line) => {
|
|
287
|
+
const match = YAML_PAIR.exec(line);
|
|
288
|
+
if (!match)
|
|
289
|
+
return { text: line, changed: false };
|
|
290
|
+
const kind = (0, redaction_js_1.keyMatch)(match[3]);
|
|
291
|
+
if (!kind)
|
|
292
|
+
return { text: line, changed: false };
|
|
293
|
+
if (/^[>|]/.test(match[5].trim()))
|
|
294
|
+
blockSecret = true;
|
|
295
|
+
return {
|
|
296
|
+
text: `${match[1]}${match[2]}${match[3]}${match[2]}${match[4]}${(0, redaction_js_1.maskForMatch)(kind, match[5].trim().replace(/^(["'])(.*)\1$/, "$2"))}`,
|
|
297
|
+
changed: true,
|
|
298
|
+
};
|
|
299
|
+
});
|
|
300
|
+
return blockSecret ? { text: constants_js_1.REDACTED_VALUE, changed: true } : result;
|
|
301
|
+
}
|
|
302
|
+
function redactPlainText(text) {
|
|
303
|
+
const trimmed = text.trimStart();
|
|
304
|
+
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
|
|
305
|
+
const json = redactJson(text);
|
|
306
|
+
if (json.changed)
|
|
307
|
+
return json;
|
|
308
|
+
}
|
|
309
|
+
const yaml = redactYaml(text);
|
|
310
|
+
if (yaml.changed)
|
|
311
|
+
return yaml;
|
|
312
|
+
const redacted = (0, redaction_js_1.redactString)(text);
|
|
313
|
+
return redacted === text
|
|
314
|
+
? { text, changed: false }
|
|
315
|
+
: { text: redacted, changed: true };
|
|
316
|
+
}
|
|
317
|
+
function contentDispositionName(headers) {
|
|
318
|
+
const line = headers
|
|
319
|
+
.split(/\r\n|\n|\r/)
|
|
320
|
+
.find((header) => /^content-disposition\s*:/i.test(header));
|
|
321
|
+
return line ? /\bname\s*=\s*(?:"([^"]*)"|([^;\s]*))/i.exec(line)?.slice(1).find(Boolean) : undefined;
|
|
322
|
+
}
|
|
323
|
+
function partContentType(headers) {
|
|
324
|
+
return headers
|
|
325
|
+
.split(/\r\n|\n|\r/)
|
|
326
|
+
.find((header) => /^content-type\s*:/i.test(header))
|
|
327
|
+
?.replace(/^[^:]+:\s*/, "");
|
|
328
|
+
}
|
|
329
|
+
function redactMultipart(text, boundary) {
|
|
330
|
+
if (!boundary || boundary.length > 70)
|
|
331
|
+
return { text, changed: false };
|
|
332
|
+
const marker = `--${boundary}`;
|
|
333
|
+
if (!text.includes(marker))
|
|
334
|
+
return { text, changed: false };
|
|
335
|
+
let changed = false;
|
|
336
|
+
const parts = text.split(marker);
|
|
337
|
+
for (let index = 1; index < parts.length; index += 1) {
|
|
338
|
+
const part = parts[index];
|
|
339
|
+
if (part.startsWith("--"))
|
|
340
|
+
continue;
|
|
341
|
+
const leading = part.match(/^(?:\r\n|\n|\r)/)?.[0] ?? "";
|
|
342
|
+
const content = leading ? part.slice(leading.length) : part;
|
|
343
|
+
const separator = /\r\n\r\n|\n\n|\r\r/.exec(content);
|
|
344
|
+
if (!separator?.index)
|
|
345
|
+
continue;
|
|
346
|
+
const headers = content.slice(0, separator.index);
|
|
347
|
+
const bodyWithEnding = content.slice(separator.index + separator[0].length);
|
|
348
|
+
const ending = bodyWithEnding.match(/(?:\r\n|\n|\r)$/)?.[0] ?? "";
|
|
349
|
+
const body = ending
|
|
350
|
+
? bodyWithEnding.slice(0, -ending.length)
|
|
351
|
+
: bodyWithEnding;
|
|
352
|
+
const name = contentDispositionName(headers);
|
|
353
|
+
let result;
|
|
354
|
+
if (name && ((0, redaction_js_1.keyMatch)(name) || (0, redaction_js_1.isSensitiveQueryKey)(name))) {
|
|
355
|
+
result = { text: constants_js_1.REDACTED_VALUE, changed: true };
|
|
356
|
+
}
|
|
357
|
+
else if (/\bfilename\s*=/i.test(headers)) {
|
|
358
|
+
result = { text: body, changed: false };
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
result = redactBodyText(body, partContentType(headers) ?? "text/plain");
|
|
362
|
+
}
|
|
363
|
+
if (!result.changed)
|
|
364
|
+
continue;
|
|
365
|
+
parts[index] = `${leading}${headers}${separator[0]}${result.text}${ending}`;
|
|
366
|
+
changed = true;
|
|
367
|
+
}
|
|
368
|
+
return changed
|
|
369
|
+
? { text: parts.join(marker), changed: true }
|
|
370
|
+
: { text, changed: false };
|
|
78
371
|
}
|
|
79
372
|
function redactBodyText(text, contentType) {
|
|
80
|
-
const media =
|
|
373
|
+
const { media, params } = parseContentType(contentType);
|
|
81
374
|
if (media === "application/x-www-form-urlencoded")
|
|
82
375
|
return redactForm(text);
|
|
83
|
-
if (media
|
|
376
|
+
if (media === "text/event-stream")
|
|
377
|
+
return redactSse(text);
|
|
378
|
+
if (isJsonSequenceMediaType(media))
|
|
379
|
+
return redactJsonSequence(text);
|
|
380
|
+
if (isNdjsonMediaType(media))
|
|
381
|
+
return redactNdjson(text);
|
|
382
|
+
if (media.endsWith("/json") || media.endsWith("+json"))
|
|
84
383
|
return redactJson(text);
|
|
384
|
+
if (media.startsWith("multipart/")) {
|
|
385
|
+
return redactMultipart(text, params.get("boundary") ?? "");
|
|
386
|
+
}
|
|
387
|
+
if (XML_MEDIA_TYPES.has(media) ||
|
|
388
|
+
media.endsWith("/xml") ||
|
|
389
|
+
media.endsWith("+xml")) {
|
|
390
|
+
return redactXml(text);
|
|
391
|
+
}
|
|
392
|
+
if (YAML_MEDIA_TYPES.has(media) ||
|
|
393
|
+
media.endsWith("/yaml") ||
|
|
394
|
+
media.endsWith("+yaml")) {
|
|
395
|
+
return redactYaml(text);
|
|
396
|
+
}
|
|
397
|
+
if (media.startsWith("text/") || params.has("charset")) {
|
|
398
|
+
return redactPlainText(text);
|
|
85
399
|
}
|
|
86
400
|
return { text, changed: false };
|
|
87
401
|
}
|
package/dist/propagation.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Context } from "@opentelemetry/api";
|
|
2
2
|
export declare function injectTraceContext(carrier: Record<string, string>): void;
|
|
3
3
|
export declare function extractTraceContext(carrier: Record<string, string>): Context;
|
|
4
|
-
export declare
|
|
4
|
+
export declare function setBaggage<T>(key: string, value: string, callback: () => T): T | undefined;
|
|
5
5
|
export declare function getBaggage(key: string): string | undefined;
|
package/dist/propagation.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.setBaggage = void 0;
|
|
4
3
|
exports.injectTraceContext = injectTraceContext;
|
|
5
4
|
exports.extractTraceContext = extractTraceContext;
|
|
5
|
+
exports.setBaggage = setBaggage;
|
|
6
6
|
exports.getBaggage = getBaggage;
|
|
7
7
|
const node_async_hooks_1 = require("node:async_hooks");
|
|
8
8
|
const api_1 = require("@opentelemetry/api");
|
|
@@ -34,11 +34,13 @@ function injectTraceContext(carrier) {
|
|
|
34
34
|
function extractTraceContext(carrier) {
|
|
35
35
|
return (0, utils_js_1.safely)(() => propagator.extract(api_1.context.active(), carrier, api_1.defaultTextMapGetter), api_1.context.active());
|
|
36
36
|
}
|
|
37
|
-
|
|
37
|
+
function setBaggage(key, value, callback) {
|
|
38
|
+
if ((0, state_js_1.getSignal)(state_js_1.Signals.baggage) === state_js_1.SignalSources.none)
|
|
39
|
+
return undefined;
|
|
38
40
|
const next = new Map(baggageStorage.getStore() ?? []);
|
|
39
41
|
next.set(key, value);
|
|
40
|
-
baggageStorage.
|
|
41
|
-
}
|
|
42
|
+
return baggageStorage.run(next, callback);
|
|
43
|
+
}
|
|
42
44
|
function getBaggage(key) {
|
|
43
45
|
return (0, utils_js_1.safely)(() => baggageStorage.getStore()?.get(key) ??
|
|
44
46
|
api_1.propagation.getBaggage(api_1.context.active())?.getEntry(key)?.value, undefined);
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const SENSITIVE_KEYS: readonly ["admin_password", "basic_auth_password", "confirm_password", "connection_password", "current_password", "database_password", "db_pass", "db_password", "ftp_password", "http_password", "keystore_password", "master_password", "mail_password", "mysql_pwd", "new_password", "old_password", "pass", "passcode", "passphrase", "passwd", "password", "password_confirmation", "postgres_password", "pwd", "redis_password", "root_password", "smtp_password", "user_password", "access_token_secret", "activation_token", "access_token", "api_token", "assertion", "auth", "auth_token", "authentication_token", "authorization", "authorization_code", "bearer", "bearer_token", "bot_token", "ci_job_token", "client_assertion", "client_secret", "credential", "credentials", "deploy_token", "email_verification_token", "id_token", "identity_token", "invite_token", "jwt", "jwt_token", "magic_link_token", "oauth_token", "oauth2_token", "oauth_token_secret", "password_reset_token", "personal_access_token", "registration_token", "request_token", "refresh_token", "reset_token", "saml_assertion", "saml_response", "secret_token", "security_token", "service_token", "sso_token", "token", "unsubscribe_token", "verification_token", "access_key", "access_key_id", "api_key", "api_secret", "amqp_url", "apikey", "app_key", "app_secret", "application_key", "application_secret", "aws_access_key_id", "aws_secret_access_key", "consumer_key", "consumer_secret", "broker_url", "connection_string", "connection_uri", "credential_blob", "decryption_key", "database_url", "database_connection_string", "db_url", "dsn", "encryption_key", "gcp_service_account_key", "google_application_credentials", "key", "key_password", "key_store_password", "keystore", "license_key", "mnemonic", "mongodb_uri", "kube_config", "kubeconfig", "pem", "private_key", "privatekey", "proxy_authorization", "redis_url", "redis_uri", "rabbitmq_url", "secret", "secret_access_key", "secret_key", "seed_phrase", "service_account_json", "service_account_key", "shared_secret", "signature", "signing_key", "signing_secret", "ssh_private_key", "smtp_url", "tls_private_key", "wallet_private_key", "wallet_seed", "webhook_secret", "www_authenticate", "_csrf", "_csrf_token", "_session", "_xsrf", "aiohttp_session", "anti_forgery_token", "backup_code", "backup_codes", "connect.sid", "cookie", "csrf", "csrf_token", "csrftoken", "django_session", "hotp", "laravel_session", "mfa", "mfa_code", "otp", "phpsessid", "pin", "recovery_code", "recovery_codes", "remember_token", "session", "session_id", "session_key", "session_token", "sessionid", "set_cookie", "setcookie", "sid", "symfony", "totp", "user_session", "x_csrf_token", "x_csrftoken", "x_xsrf_token", "xsrf", "xsrf_token", "account_number", "bank_account", "card", "card_number", "credit_card", "credit_card_number", "cvc", "cvv", "date_of_birth", "dob", "driver_license", "drivers_license", "iban", "ip_address", "national_id", "passport_number", "remote_addr", "routing_number", "sort_code", "ssn", "tax_id", "x_forwarded_for", "x_real_ip", "algolia_admin_api_key", "anthropic_api_key", "artifactory_api_key", "airtable_api_key", "azure_api_key", "buildkite_agent_token", "circle_token", "cohere_api_key", "cloudflare_api_token", "consul_http_token", "datadog_api_key", "datadog_app_key", "discord_bot_token", "docker_password", "docker_config_json", "digitalocean_token", "firebase_service_account", "gemini_api_key", "github_token", "gitlab_token", "google_api_key", "groq_api_key", "honeycomb_api_key", "huggingface_token", "heroku_api_key", "jfrog_access_token", "linear_api_key", "mapbox_access_token", "new_relic_license_key", "nomad_token", "notion_token", "npm_token", "openai_api_key", "pagerduty_routing_key", "pypi_token", "sentry_auth_token", "sentry_dsn", "sendgrid_api_key", "shopify_access_token", "shopify_api_secret", "slack_app_token", "slack_bot_token", "slack_signing_secret", "stripe_secret_key", "stripe_webhook_secret", "supabase_service_role_key", "telegram_bot_token", "terraform_cloud_token", "twilio_auth_token", "vault_token", "vercel_oidc_token", "x_api_key", "x_auth_token"];
|
|
2
|
+
export declare const SENSITIVE_HTTP_HEADERS: readonly ["authentication_info", "authorization", "cf_access_authenticated_user_email", "cf_access_jwt_assertion", "cookie", "grpcgateway_authorization", "impersonate_group", "impersonate_user", "jenkins_crumb", "job_token", "ocp_apim_subscription_key", "private_token", "proxy_authenticate", "proxy_authentication_info", "proxy_authorization", "set_cookie", "stripe_signature", "www_authenticate", "x_access_token", "x_algolia_api_key", "x_amz_credential", "x_amz_security_token", "x_amz_signature", "x_amzn_oidc_accesstoken", "x_amzn_oidc_data", "x_amzn_oidc_identity", "x_api_key", "x_asana_request_token", "x_aws_ec2_metadata_token", "x_auth_request_access_token", "x_auth_request_email", "x_auth_request_groups", "x_auth_request_preferred_username", "x_auth_request_user", "x_auth_token", "x_box_signature_primary", "x_box_signature_secondary", "x_cf_access_jwt_assertion", "x_csrf_token", "x_circle_token", "x_consul_token", "x_credential_identifier", "x_datadog_api_key", "x_discord_signature_ed25519", "x_docusign_signature_1", "x_dropbox_signature", "x_elastic_client_authentication", "x_firebase_appcheck", "x_forwarded_access_token", "x_forwarded_email", "x_forwarded_for", "x_forwarded_user", "x_functions_key", "x_github_token", "x_gitlab_token", "x_goog_api_key", "x_goog_firebase_installations_auth", "x_goog_iap_jwt_assertion", "x_hub_signature", "x_hub_signature_256", "x_honeycomb_api_key", "x_honeycomb_team", "x_intercom_hmac", "x_jwt_assertion", "x_linear_signature", "x_mailgun_signature", "x_master_key", "x_meili_api_key", "x_ms_client_principal", "x_ms_token_aad_access_token", "x_ms_token_aad_id_token", "x_ms_token_aad_refresh_token", "x_nf_client_connection_ip", "x_nomad_token", "x_npm_token", "x_original_authorization", "x_real_ip", "x_remote_email", "x_remote_groups", "x_remote_user", "x_pagerduty_signature", "x_parse_rest_api_key", "x_sendgrid_event_webhook_signature", "x_session_token", "x_shopify_hmac_sha256", "x_signature", "x_signature_ed25519", "x_slack_signature", "x_sonarqube_passcode", "x_squarespace_hmacsha256_signature", "x_twilio_signature", "x_typesense_api_key", "x_userinfo", "x_vault_token", "x_vercel_oidc_token", "x_webhook_signature", "x_webhook_secret", "x_wix_webhook_signature", "x_xsrf_token", "x_zendesk_webhook_signature"];
|
|
3
|
+
export declare const SENSITIVE_QUERY_KEYS: readonly ["access_token", "api_key", "api_secret", "api_token", "apikey", "assertion", "auth", "auth_token", "authorization", "authorization_code", "bearer_token", "client_assertion", "client_secret", "code", "code_verifier", "credential", "hmac", "id_token", "invite_token", "jwt", "key", "magic_link_token", "oauth_token_secret", "otp", "password_reset_token", "password", "policy", "pin", "refresh_token", "reset_token", "saml_response", "secret", "secret_key", "session", "session_id", "session_token", "sig", "signature", "token", "token_secret", "unsubscribe_token", "verification_token", "x_amz_credential", "x_amz_security_token", "x_amz_signature", "x_goog_credential", "x_goog_signature"];
|