@agent-inspect/mcp-server 6.31.2 → 6.31.4
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/dist/{chunk-YWFDV7U3.mjs → chunk-OGX7RS23.mjs} +375 -89
- package/dist/chunk-OGX7RS23.mjs.map +1 -0
- package/dist/cli.cjs +373 -87
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/index.cjs +373 -87
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +3 -3
- package/dist/chunk-YWFDV7U3.mjs.map +0 -1
package/dist/cli.cjs
CHANGED
|
@@ -46,6 +46,80 @@ function extractCorrelationMetadata(record) {
|
|
|
46
46
|
}
|
|
47
47
|
return found ? out : void 0;
|
|
48
48
|
}
|
|
49
|
+
|
|
50
|
+
// packages/core/src/safety/sensitive-key.ts
|
|
51
|
+
function keyHasExplicitSeparator(value) {
|
|
52
|
+
return /[_\-.]/.test(value);
|
|
53
|
+
}
|
|
54
|
+
function normalizeSensitiveKey(value) {
|
|
55
|
+
return value.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
56
|
+
}
|
|
57
|
+
var NON_CREDENTIAL_TOKEN_CONFIG_KEYS = new Set(
|
|
58
|
+
[
|
|
59
|
+
"tokens",
|
|
60
|
+
"max_tokens",
|
|
61
|
+
"min_tokens",
|
|
62
|
+
"ls_max_tokens",
|
|
63
|
+
"token_count",
|
|
64
|
+
"token_limit",
|
|
65
|
+
"token_budget",
|
|
66
|
+
"input_tokens",
|
|
67
|
+
"output_tokens",
|
|
68
|
+
"total_tokens",
|
|
69
|
+
"cached_tokens",
|
|
70
|
+
"prompt_tokens",
|
|
71
|
+
"completion_tokens"
|
|
72
|
+
].map(normalizeSensitiveKey)
|
|
73
|
+
);
|
|
74
|
+
var DEFAULT_CREDENTIAL_SENSITIVE_KEYS = [
|
|
75
|
+
"authorization",
|
|
76
|
+
"cookie",
|
|
77
|
+
"token",
|
|
78
|
+
"access_token",
|
|
79
|
+
"accesstoken",
|
|
80
|
+
"auth_token",
|
|
81
|
+
"authtoken",
|
|
82
|
+
"refresh_token",
|
|
83
|
+
"refreshtoken",
|
|
84
|
+
"id_token",
|
|
85
|
+
"idtoken",
|
|
86
|
+
"bearer_token",
|
|
87
|
+
"bearertoken",
|
|
88
|
+
"api_token",
|
|
89
|
+
"apitoken",
|
|
90
|
+
"apikey",
|
|
91
|
+
"api_key",
|
|
92
|
+
"password",
|
|
93
|
+
"secret",
|
|
94
|
+
"email"
|
|
95
|
+
];
|
|
96
|
+
function isTokenCredentialKey(normalized) {
|
|
97
|
+
if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;
|
|
98
|
+
if (normalized === "token") return true;
|
|
99
|
+
if (normalized.endsWith("tokens")) return false;
|
|
100
|
+
return normalized.endsWith("token");
|
|
101
|
+
}
|
|
102
|
+
function isCredentialSensitiveKey(key, sensitiveKeys = DEFAULT_CREDENTIAL_SENSITIVE_KEYS) {
|
|
103
|
+
if (!key) return false;
|
|
104
|
+
const normalized = normalizeSensitiveKey(key);
|
|
105
|
+
if (!normalized) return false;
|
|
106
|
+
if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;
|
|
107
|
+
const allowPrefixCompound = keyHasExplicitSeparator(key);
|
|
108
|
+
for (const sensitive of sensitiveKeys) {
|
|
109
|
+
const s = normalizeSensitiveKey(sensitive);
|
|
110
|
+
if (!s) continue;
|
|
111
|
+
if (s === "token") {
|
|
112
|
+
if (isTokenCredentialKey(normalized)) return true;
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if (normalized === s) return true;
|
|
116
|
+
if (normalized.endsWith(`_${s}`)) return true;
|
|
117
|
+
if (allowPrefixCompound && normalized.startsWith(`${s}_`)) return true;
|
|
118
|
+
}
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// packages/core/src/logs/redactor.ts
|
|
49
123
|
var DEFAULT_REDACT_KEYS = [
|
|
50
124
|
"authorization",
|
|
51
125
|
"cookie",
|
|
@@ -69,7 +143,7 @@ function compileRules(rules, extraKeys) {
|
|
|
69
143
|
const out = /* @__PURE__ */ new Map();
|
|
70
144
|
const set = (r) => {
|
|
71
145
|
const k = toKey(r.key);
|
|
72
|
-
out.set(k, { ...r, key: k });
|
|
146
|
+
out.set(k, { ...r, key: k, raw: r.raw ?? r.key });
|
|
73
147
|
};
|
|
74
148
|
for (const k of DEFAULT_REDACT_KEYS) {
|
|
75
149
|
set({ key: k, strategy: "full" });
|
|
@@ -98,9 +172,13 @@ var Redactor = class {
|
|
|
98
172
|
constructor(options) {
|
|
99
173
|
this.#rules = compileRules(options?.rules, options?.extraKeys);
|
|
100
174
|
}
|
|
175
|
+
/** Field names this redactor treats as sensitive, for value-level helpers. */
|
|
176
|
+
get sensitiveKeys() {
|
|
177
|
+
return this.#rules.map((rule) => rule.raw ?? rule.key);
|
|
178
|
+
}
|
|
101
179
|
redactValue(key, value) {
|
|
102
180
|
const k = toKey(key);
|
|
103
|
-
const rule = this.#rules.find((r) => r.key === k);
|
|
181
|
+
const rule = this.#rules.find((r) => r.key === k) ?? this.#rules.find((r) => isCredentialSensitiveKey(key, [r.raw ?? r.key]));
|
|
104
182
|
if (!rule) {
|
|
105
183
|
return this.#redactNested(value);
|
|
106
184
|
}
|
|
@@ -139,6 +217,30 @@ var Redactor = class {
|
|
|
139
217
|
}
|
|
140
218
|
};
|
|
141
219
|
|
|
220
|
+
// packages/core/src/safety/credential-value-patterns.ts
|
|
221
|
+
var KEY_VALUE_SECRET_PATTERN = /\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=(?!\[(?:REDACTED(?::[^\]]*)?|HASH:[0-9a-f]{8})\](?![^\s"'\\&#?;/]))([^\s"'\\]{8,})/i;
|
|
222
|
+
var HIGH_CONFIDENCE_CREDENTIAL_PATTERNS = [
|
|
223
|
+
/^(?:basic|bearer|digest|apikey)\s+[a-z0-9._~+/=-]+$/i,
|
|
224
|
+
/\bbearer\s+[a-z0-9._~+/=-]{12,}\b/i,
|
|
225
|
+
/\b[a-z0-9_.-]+=[^;\s]+(?:;\s*[a-z0-9_.-]+=[^;\s]+)+/i,
|
|
226
|
+
/\beyJ[a-zA-Z0-9_-]{8,}\.[a-zA-Z0-9_-]{8,}\.[a-zA-Z0-9_-]{8,}\b/,
|
|
227
|
+
/\b(?:sk-(?:proj-)?[a-zA-Z0-9_-]{16,}|sk-ant-[a-zA-Z0-9_-]{16,}|AIza[0-9A-Za-z_-]{20,})\b/,
|
|
228
|
+
/\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{20,}\b/,
|
|
229
|
+
/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/,
|
|
230
|
+
/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*-----END [A-Z ]*PRIVATE KEY-----/,
|
|
231
|
+
KEY_VALUE_SECRET_PATTERN
|
|
232
|
+
];
|
|
233
|
+
function stringContainsHighConfidenceCredential(value) {
|
|
234
|
+
for (const pattern of HIGH_CONFIDENCE_CREDENTIAL_PATTERNS) {
|
|
235
|
+
pattern.lastIndex = 0;
|
|
236
|
+
if (pattern.test(value)) {
|
|
237
|
+
pattern.lastIndex = 0;
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
|
|
142
244
|
// packages/core/src/redaction-profiles.ts
|
|
143
245
|
var SHARE_PROFILE_EXTRA_KEYS = [
|
|
144
246
|
"userEmail",
|
|
@@ -2309,78 +2411,6 @@ function formatProgrammaticDiagnostic(code, detail) {
|
|
|
2309
2411
|
return `${code}: ${summary} Remediation: ${spec.remediation}`;
|
|
2310
2412
|
}
|
|
2311
2413
|
|
|
2312
|
-
// packages/core/src/safety/sensitive-key.ts
|
|
2313
|
-
function keyHasExplicitSeparator(value) {
|
|
2314
|
-
return /[_\-.]/.test(value);
|
|
2315
|
-
}
|
|
2316
|
-
function normalizeSensitiveKey(value) {
|
|
2317
|
-
return value.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
2318
|
-
}
|
|
2319
|
-
var NON_CREDENTIAL_TOKEN_CONFIG_KEYS = new Set(
|
|
2320
|
-
[
|
|
2321
|
-
"tokens",
|
|
2322
|
-
"max_tokens",
|
|
2323
|
-
"min_tokens",
|
|
2324
|
-
"ls_max_tokens",
|
|
2325
|
-
"token_count",
|
|
2326
|
-
"token_limit",
|
|
2327
|
-
"token_budget",
|
|
2328
|
-
"input_tokens",
|
|
2329
|
-
"output_tokens",
|
|
2330
|
-
"total_tokens",
|
|
2331
|
-
"cached_tokens",
|
|
2332
|
-
"prompt_tokens",
|
|
2333
|
-
"completion_tokens"
|
|
2334
|
-
].map(normalizeSensitiveKey)
|
|
2335
|
-
);
|
|
2336
|
-
var DEFAULT_CREDENTIAL_SENSITIVE_KEYS = [
|
|
2337
|
-
"authorization",
|
|
2338
|
-
"cookie",
|
|
2339
|
-
"token",
|
|
2340
|
-
"access_token",
|
|
2341
|
-
"accesstoken",
|
|
2342
|
-
"auth_token",
|
|
2343
|
-
"authtoken",
|
|
2344
|
-
"refresh_token",
|
|
2345
|
-
"refreshtoken",
|
|
2346
|
-
"id_token",
|
|
2347
|
-
"idtoken",
|
|
2348
|
-
"bearer_token",
|
|
2349
|
-
"bearertoken",
|
|
2350
|
-
"api_token",
|
|
2351
|
-
"apitoken",
|
|
2352
|
-
"apikey",
|
|
2353
|
-
"api_key",
|
|
2354
|
-
"password",
|
|
2355
|
-
"secret",
|
|
2356
|
-
"email"
|
|
2357
|
-
];
|
|
2358
|
-
function isTokenCredentialKey(normalized) {
|
|
2359
|
-
if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;
|
|
2360
|
-
if (normalized === "token") return true;
|
|
2361
|
-
if (normalized.endsWith("tokens")) return false;
|
|
2362
|
-
return normalized.endsWith("token");
|
|
2363
|
-
}
|
|
2364
|
-
function isCredentialSensitiveKey(key, sensitiveKeys = DEFAULT_CREDENTIAL_SENSITIVE_KEYS) {
|
|
2365
|
-
if (!key) return false;
|
|
2366
|
-
const normalized = normalizeSensitiveKey(key);
|
|
2367
|
-
if (!normalized) return false;
|
|
2368
|
-
if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;
|
|
2369
|
-
const allowPrefixCompound = keyHasExplicitSeparator(key);
|
|
2370
|
-
for (const sensitive of sensitiveKeys) {
|
|
2371
|
-
const s = normalizeSensitiveKey(sensitive);
|
|
2372
|
-
if (!s) continue;
|
|
2373
|
-
if (s === "token") {
|
|
2374
|
-
if (isTokenCredentialKey(normalized)) return true;
|
|
2375
|
-
continue;
|
|
2376
|
-
}
|
|
2377
|
-
if (normalized === s) return true;
|
|
2378
|
-
if (normalized.endsWith(`_${s}`)) return true;
|
|
2379
|
-
if (allowPrefixCompound && normalized.startsWith(`${s}_`)) return true;
|
|
2380
|
-
}
|
|
2381
|
-
return false;
|
|
2382
|
-
}
|
|
2383
|
-
|
|
2384
2414
|
// packages/core/src/checks/logical-events.ts
|
|
2385
2415
|
function isRecord6(value) {
|
|
2386
2416
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -3331,7 +3361,7 @@ var DEFAULT_SECRET_PATTERNS = [
|
|
|
3331
3361
|
// Keep in sync with packages/redact/src/key-value-secret.ts (KEY_VALUE_SECRET_PATTERN_SOURCE).
|
|
3332
3362
|
{
|
|
3333
3363
|
id: "key-value-secret",
|
|
3334
|
-
pattern: /\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=([^\s"'\\]{8,})/i
|
|
3364
|
+
pattern: /\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=(?!\[(?:REDACTED(?::[^\]]*)?|HASH:[0-9a-f]{8})\](?![^\s"'\\&#?;/]))([^\s"'\\]{8,})/i
|
|
3335
3365
|
}
|
|
3336
3366
|
];
|
|
3337
3367
|
function compareStrings(a, b) {
|
|
@@ -6672,6 +6702,99 @@ function openTrace(input, options = {}) {
|
|
|
6672
6702
|
// packages/core/src/exporters/types.ts
|
|
6673
6703
|
var EXPORT_PAYLOAD_VERSION = "0.1.2";
|
|
6674
6704
|
|
|
6705
|
+
// packages/core/src/safety/url-redaction.ts
|
|
6706
|
+
var HTTP_URL = /^https?:\/\/[^\s]+$/i;
|
|
6707
|
+
var UUID_SEGMENT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
6708
|
+
var HEX_SEGMENT = /^[0-9a-f]{12,}$/i;
|
|
6709
|
+
var NUMERIC_SEGMENT = /^\d{5,}$/;
|
|
6710
|
+
var OPAQUE_SEGMENT = /^[A-Za-z0-9_-]{20,}$/;
|
|
6711
|
+
function looksLikeHttpUrl(value) {
|
|
6712
|
+
return HTTP_URL.test(value.trim());
|
|
6713
|
+
}
|
|
6714
|
+
function parseHttpUrl(value) {
|
|
6715
|
+
try {
|
|
6716
|
+
const url = new URL(value.trim());
|
|
6717
|
+
return url.protocol === "http:" || url.protocol === "https:" ? url : void 0;
|
|
6718
|
+
} catch {
|
|
6719
|
+
return void 0;
|
|
6720
|
+
}
|
|
6721
|
+
}
|
|
6722
|
+
function isIdentifierSegment(segment) {
|
|
6723
|
+
if (UUID_SEGMENT.test(segment)) return true;
|
|
6724
|
+
if (HEX_SEGMENT.test(segment)) return true;
|
|
6725
|
+
if (NUMERIC_SEGMENT.test(segment)) return true;
|
|
6726
|
+
return OPAQUE_SEGMENT.test(segment) && /\d/.test(segment) && /[A-Za-z]/.test(segment);
|
|
6727
|
+
}
|
|
6728
|
+
function decodeParam(value) {
|
|
6729
|
+
try {
|
|
6730
|
+
return decodeURIComponent(value.replace(/\+/g, " "));
|
|
6731
|
+
} catch {
|
|
6732
|
+
return value;
|
|
6733
|
+
}
|
|
6734
|
+
}
|
|
6735
|
+
function redactParams(raw, options, replacement) {
|
|
6736
|
+
let redacted = false;
|
|
6737
|
+
const parts = raw.split("&").map((part) => {
|
|
6738
|
+
if (part.length === 0) return part;
|
|
6739
|
+
const separator = part.indexOf("=");
|
|
6740
|
+
if (separator < 0) return part;
|
|
6741
|
+
const rawKey = part.slice(0, separator);
|
|
6742
|
+
const rawValue = part.slice(separator + 1);
|
|
6743
|
+
const key = decodeParam(rawKey);
|
|
6744
|
+
const value = decodeParam(rawValue);
|
|
6745
|
+
if (isCredentialSensitiveKey(key, options.sensitiveKeys) || options.isSensitiveValue(value)) {
|
|
6746
|
+
redacted = true;
|
|
6747
|
+
return `${rawKey}=${replacement}`;
|
|
6748
|
+
}
|
|
6749
|
+
return part;
|
|
6750
|
+
});
|
|
6751
|
+
return { value: parts.join("&"), redacted };
|
|
6752
|
+
}
|
|
6753
|
+
function redactUrlString(value, options) {
|
|
6754
|
+
const unchanged = {
|
|
6755
|
+
value,
|
|
6756
|
+
credentialRedacted: false,
|
|
6757
|
+
identifiersMasked: false
|
|
6758
|
+
};
|
|
6759
|
+
if (!looksLikeHttpUrl(value)) return unchanged;
|
|
6760
|
+
const url = parseHttpUrl(value);
|
|
6761
|
+
if (!url) return unchanged;
|
|
6762
|
+
const replacement = options.replacement ?? "[REDACTED]";
|
|
6763
|
+
const idPlaceholder = options.idPlaceholder ?? "[id]";
|
|
6764
|
+
let credentialRedacted = url.username.length > 0 || url.password.length > 0;
|
|
6765
|
+
let identifiersMasked = false;
|
|
6766
|
+
let pathname = url.pathname;
|
|
6767
|
+
if (options.maskPathIds === true) {
|
|
6768
|
+
pathname = url.pathname.split("/").map((segment) => {
|
|
6769
|
+
if (segment.length === 0 || !isIdentifierSegment(decodeParam(segment))) {
|
|
6770
|
+
return segment;
|
|
6771
|
+
}
|
|
6772
|
+
identifiersMasked = true;
|
|
6773
|
+
return idPlaceholder;
|
|
6774
|
+
}).join("/");
|
|
6775
|
+
}
|
|
6776
|
+
let search = "";
|
|
6777
|
+
if (url.search.length > 1) {
|
|
6778
|
+
const params = redactParams(url.search.slice(1), options, replacement);
|
|
6779
|
+
if (params.redacted) credentialRedacted = true;
|
|
6780
|
+
search = `?${params.value}`;
|
|
6781
|
+
} else if (url.search.length === 1) {
|
|
6782
|
+
search = "?";
|
|
6783
|
+
}
|
|
6784
|
+
let hash = url.hash;
|
|
6785
|
+
if (url.hash.includes("=")) {
|
|
6786
|
+
const params = redactParams(url.hash.slice(1), options, replacement);
|
|
6787
|
+
if (params.redacted) credentialRedacted = true;
|
|
6788
|
+
hash = `#${params.value}`;
|
|
6789
|
+
}
|
|
6790
|
+
if (!credentialRedacted && !identifiersMasked) return unchanged;
|
|
6791
|
+
return {
|
|
6792
|
+
value: `${url.protocol}//${url.host}${pathname}${search}${hash}`,
|
|
6793
|
+
credentialRedacted,
|
|
6794
|
+
identifiersMasked
|
|
6795
|
+
};
|
|
6796
|
+
}
|
|
6797
|
+
|
|
6675
6798
|
// packages/core/src/exporters/redact-export.ts
|
|
6676
6799
|
function isRecord11(value) {
|
|
6677
6800
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -6689,21 +6812,34 @@ function deepClone(value) {
|
|
|
6689
6812
|
}
|
|
6690
6813
|
return out;
|
|
6691
6814
|
}
|
|
6692
|
-
function boundAttributeValues(record, maxMetadataValueLength, maxPreviewLength, seen, depth) {
|
|
6815
|
+
function boundAttributeValues(record, sensitiveKeys, maxMetadataValueLength, maxPreviewLength, seen, depth) {
|
|
6693
6816
|
if (depth > 32) {
|
|
6694
6817
|
return { truncated: true, reason: "maxDepth" };
|
|
6695
6818
|
}
|
|
6696
6819
|
const out = {};
|
|
6697
6820
|
for (const [key, value] of Object.entries(record)) {
|
|
6698
|
-
out[key] = boundValue(
|
|
6821
|
+
out[key] = boundValue(
|
|
6822
|
+
value,
|
|
6823
|
+
key,
|
|
6824
|
+
sensitiveKeys,
|
|
6825
|
+
maxMetadataValueLength,
|
|
6826
|
+
maxPreviewLength,
|
|
6827
|
+
seen,
|
|
6828
|
+
depth
|
|
6829
|
+
);
|
|
6699
6830
|
}
|
|
6700
6831
|
return out;
|
|
6701
6832
|
}
|
|
6702
|
-
function boundValue(value, key, maxMetadataValueLength, maxPreviewLength, seen, depth) {
|
|
6833
|
+
function boundValue(value, key, sensitiveKeys, maxMetadataValueLength, maxPreviewLength, seen, depth) {
|
|
6703
6834
|
if (value === null || typeof value !== "object") {
|
|
6704
6835
|
if (typeof value === "string") {
|
|
6836
|
+
const rewritten = redactUrlString(value, {
|
|
6837
|
+
sensitiveKeys,
|
|
6838
|
+
isSensitiveValue: stringContainsHighConfidenceCredential,
|
|
6839
|
+
maskPathIds: true
|
|
6840
|
+
}).value;
|
|
6705
6841
|
return truncateStringForProfile(
|
|
6706
|
-
|
|
6842
|
+
stringContainsHighConfidenceCredential(rewritten) ? "[REDACTED]" : rewritten,
|
|
6707
6843
|
key,
|
|
6708
6844
|
maxMetadataValueLength,
|
|
6709
6845
|
maxPreviewLength
|
|
@@ -6718,6 +6854,7 @@ function boundValue(value, key, maxMetadataValueLength, maxPreviewLength, seen,
|
|
|
6718
6854
|
(item, index) => boundValue(
|
|
6719
6855
|
item,
|
|
6720
6856
|
String(index),
|
|
6857
|
+
sensitiveKeys,
|
|
6721
6858
|
maxMetadataValueLength,
|
|
6722
6859
|
maxPreviewLength,
|
|
6723
6860
|
seen,
|
|
@@ -6727,6 +6864,7 @@ function boundValue(value, key, maxMetadataValueLength, maxPreviewLength, seen,
|
|
|
6727
6864
|
}
|
|
6728
6865
|
return boundAttributeValues(
|
|
6729
6866
|
value,
|
|
6867
|
+
sensitiveKeys,
|
|
6730
6868
|
maxMetadataValueLength,
|
|
6731
6869
|
maxPreviewLength,
|
|
6732
6870
|
seen,
|
|
@@ -6741,6 +6879,7 @@ function redactEventAttributes(attrs2, redactor, maxMetadataValueLength, maxPrev
|
|
|
6741
6879
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
6742
6880
|
const bounded = boundAttributeValues(
|
|
6743
6881
|
redacted,
|
|
6882
|
+
[...DEFAULT_REDACT_KEYS, ...redactor.sensitiveKeys],
|
|
6744
6883
|
maxMetadataValueLength,
|
|
6745
6884
|
maxPreviewLength,
|
|
6746
6885
|
seen,
|
|
@@ -7194,6 +7333,11 @@ function exportOpenInference(tree, options) {
|
|
|
7194
7333
|
function hexFrom2(seed, byteLen) {
|
|
7195
7334
|
return crypto__default.default.createHash("sha256").update(seed, "utf8").digest("hex").slice(0, byteLen * 2);
|
|
7196
7335
|
}
|
|
7336
|
+
function unixNano2(ms) {
|
|
7337
|
+
const whole = Math.trunc(ms);
|
|
7338
|
+
const fractionNs = Math.round((ms - whole) * 1e6);
|
|
7339
|
+
return BigInt(whole) * 1000000n + BigInt(fractionNs);
|
|
7340
|
+
}
|
|
7197
7341
|
function stringAttr2(key, value) {
|
|
7198
7342
|
return { key, value: { stringValue: value } };
|
|
7199
7343
|
}
|
|
@@ -7227,10 +7371,10 @@ function exportOtlpJson(tree, options) {
|
|
|
7227
7371
|
const ev = n.event;
|
|
7228
7372
|
const spanId = hexFrom2(`${tree.runId}:${ev.eventId}`, 8);
|
|
7229
7373
|
const parentSpanId = ev.parentId ? hexFrom2(`${tree.runId}:${ev.parentId}`, 8) : void 0;
|
|
7230
|
-
const startNs = String(
|
|
7374
|
+
const startNs = String(unixNano2(ev.timestamp));
|
|
7231
7375
|
let endNs;
|
|
7232
7376
|
if (ev.durationMs !== void 0 && Number.isFinite(ev.durationMs)) {
|
|
7233
|
-
endNs = String(
|
|
7377
|
+
endNs = String(unixNano2(ev.timestamp) + unixNano2(ev.durationMs));
|
|
7234
7378
|
}
|
|
7235
7379
|
const attrs2 = [
|
|
7236
7380
|
stringAttr2("agent_inspect.kind", ev.kind),
|
|
@@ -7406,14 +7550,107 @@ function isCredentialSensitiveKey2(key, sensitiveKeys) {
|
|
|
7406
7550
|
}
|
|
7407
7551
|
|
|
7408
7552
|
// packages/redact/src/key-value-secret.ts
|
|
7409
|
-
var KEY_VALUE_SECRET_PATTERN_SOURCE = String.raw`\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=([^\s"'\\]{8,})`;
|
|
7410
|
-
var
|
|
7553
|
+
var KEY_VALUE_SECRET_PATTERN_SOURCE = String.raw`\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=(?!\[(?:REDACTED(?::[^\]]*)?|HASH:[0-9a-f]{8})\](?![^\s"'\\&#?;/]))([^\s"'\\]{8,})`;
|
|
7554
|
+
var KEY_VALUE_SECRET_PATTERN2 = new RegExp(
|
|
7411
7555
|
KEY_VALUE_SECRET_PATTERN_SOURCE,
|
|
7412
7556
|
"i"
|
|
7413
7557
|
);
|
|
7414
7558
|
function valueContainsKeyValueSecret(value) {
|
|
7415
|
-
|
|
7416
|
-
return
|
|
7559
|
+
KEY_VALUE_SECRET_PATTERN2.lastIndex = 0;
|
|
7560
|
+
return KEY_VALUE_SECRET_PATTERN2.test(value);
|
|
7561
|
+
}
|
|
7562
|
+
|
|
7563
|
+
// packages/redact/src/url-redaction.ts
|
|
7564
|
+
var HTTP_URL2 = /^https?:\/\/[^\s]+$/i;
|
|
7565
|
+
var UUID_SEGMENT2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
7566
|
+
var HEX_SEGMENT2 = /^[0-9a-f]{12,}$/i;
|
|
7567
|
+
var NUMERIC_SEGMENT2 = /^\d{5,}$/;
|
|
7568
|
+
var OPAQUE_SEGMENT2 = /^[A-Za-z0-9_-]{20,}$/;
|
|
7569
|
+
function looksLikeHttpUrl2(value) {
|
|
7570
|
+
return HTTP_URL2.test(value.trim());
|
|
7571
|
+
}
|
|
7572
|
+
function parseHttpUrl2(value) {
|
|
7573
|
+
try {
|
|
7574
|
+
const url = new URL(value.trim());
|
|
7575
|
+
return url.protocol === "http:" || url.protocol === "https:" ? url : void 0;
|
|
7576
|
+
} catch {
|
|
7577
|
+
return void 0;
|
|
7578
|
+
}
|
|
7579
|
+
}
|
|
7580
|
+
function isIdentifierSegment2(segment) {
|
|
7581
|
+
if (UUID_SEGMENT2.test(segment)) return true;
|
|
7582
|
+
if (HEX_SEGMENT2.test(segment)) return true;
|
|
7583
|
+
if (NUMERIC_SEGMENT2.test(segment)) return true;
|
|
7584
|
+
return OPAQUE_SEGMENT2.test(segment) && /\d/.test(segment) && /[A-Za-z]/.test(segment);
|
|
7585
|
+
}
|
|
7586
|
+
function decodeParam2(value) {
|
|
7587
|
+
try {
|
|
7588
|
+
return decodeURIComponent(value.replace(/\+/g, " "));
|
|
7589
|
+
} catch {
|
|
7590
|
+
return value;
|
|
7591
|
+
}
|
|
7592
|
+
}
|
|
7593
|
+
function redactParams2(raw, options, replacement) {
|
|
7594
|
+
let redacted = false;
|
|
7595
|
+
const parts = raw.split("&").map((part) => {
|
|
7596
|
+
if (part.length === 0) return part;
|
|
7597
|
+
const separator = part.indexOf("=");
|
|
7598
|
+
if (separator < 0) return part;
|
|
7599
|
+
const rawKey = part.slice(0, separator);
|
|
7600
|
+
const rawValue = part.slice(separator + 1);
|
|
7601
|
+
const key = decodeParam2(rawKey);
|
|
7602
|
+
const value = decodeParam2(rawValue);
|
|
7603
|
+
if (isCredentialSensitiveKey2(key, options.sensitiveKeys) || options.isSensitiveValue(value)) {
|
|
7604
|
+
redacted = true;
|
|
7605
|
+
return `${rawKey}=${replacement}`;
|
|
7606
|
+
}
|
|
7607
|
+
return part;
|
|
7608
|
+
});
|
|
7609
|
+
return { value: parts.join("&"), redacted };
|
|
7610
|
+
}
|
|
7611
|
+
function redactUrlString2(value, options) {
|
|
7612
|
+
const unchanged = {
|
|
7613
|
+
value,
|
|
7614
|
+
credentialRedacted: false,
|
|
7615
|
+
identifiersMasked: false
|
|
7616
|
+
};
|
|
7617
|
+
if (!looksLikeHttpUrl2(value)) return unchanged;
|
|
7618
|
+
const url = parseHttpUrl2(value);
|
|
7619
|
+
if (!url) return unchanged;
|
|
7620
|
+
const replacement = options.replacement ?? "[REDACTED]";
|
|
7621
|
+
const idPlaceholder = options.idPlaceholder ?? "[id]";
|
|
7622
|
+
let credentialRedacted = url.username.length > 0 || url.password.length > 0;
|
|
7623
|
+
let identifiersMasked = false;
|
|
7624
|
+
let pathname = url.pathname;
|
|
7625
|
+
if (options.maskPathIds === true) {
|
|
7626
|
+
pathname = url.pathname.split("/").map((segment) => {
|
|
7627
|
+
if (segment.length === 0 || !isIdentifierSegment2(decodeParam2(segment))) {
|
|
7628
|
+
return segment;
|
|
7629
|
+
}
|
|
7630
|
+
identifiersMasked = true;
|
|
7631
|
+
return idPlaceholder;
|
|
7632
|
+
}).join("/");
|
|
7633
|
+
}
|
|
7634
|
+
let search = "";
|
|
7635
|
+
if (url.search.length > 1) {
|
|
7636
|
+
const params = redactParams2(url.search.slice(1), options, replacement);
|
|
7637
|
+
if (params.redacted) credentialRedacted = true;
|
|
7638
|
+
search = `?${params.value}`;
|
|
7639
|
+
} else if (url.search.length === 1) {
|
|
7640
|
+
search = "?";
|
|
7641
|
+
}
|
|
7642
|
+
let hash = url.hash;
|
|
7643
|
+
if (url.hash.includes("=")) {
|
|
7644
|
+
const params = redactParams2(url.hash.slice(1), options, replacement);
|
|
7645
|
+
if (params.redacted) credentialRedacted = true;
|
|
7646
|
+
hash = `#${params.value}`;
|
|
7647
|
+
}
|
|
7648
|
+
if (!credentialRedacted && !identifiersMasked) return unchanged;
|
|
7649
|
+
return {
|
|
7650
|
+
value: `${url.protocol}//${url.host}${pathname}${search}${hash}`,
|
|
7651
|
+
credentialRedacted,
|
|
7652
|
+
identifiersMasked
|
|
7653
|
+
};
|
|
7417
7654
|
}
|
|
7418
7655
|
|
|
7419
7656
|
// packages/redact/src/index.ts
|
|
@@ -7482,7 +7719,9 @@ function findCompiledKeyRule(key, rules) {
|
|
|
7482
7719
|
const exact = toKey2(key);
|
|
7483
7720
|
const direct = rules.find((candidate) => candidate.key === exact);
|
|
7484
7721
|
if (direct) return direct;
|
|
7485
|
-
return rules.find(
|
|
7722
|
+
return rules.find(
|
|
7723
|
+
(candidate) => isCredentialSensitiveKey2(key, [candidate.raw ?? candidate.key])
|
|
7724
|
+
);
|
|
7486
7725
|
}
|
|
7487
7726
|
function stableHash2(value) {
|
|
7488
7727
|
const hash = crypto__default.default.createHash("sha256").update(value, "utf8").digest("hex");
|
|
@@ -7681,7 +7920,7 @@ function compileRules2(rules, extraKeys) {
|
|
|
7681
7920
|
const out = /* @__PURE__ */ new Map();
|
|
7682
7921
|
const set = (rule) => {
|
|
7683
7922
|
const key = toKey2(rule.key);
|
|
7684
|
-
out.set(key, { ...rule, key });
|
|
7923
|
+
out.set(key, { ...rule, key, raw: rule.raw ?? rule.key });
|
|
7685
7924
|
};
|
|
7686
7925
|
for (const key of DEFAULT_REDACT_KEYS2) {
|
|
7687
7926
|
set({ key, strategy: "full" });
|
|
@@ -7760,6 +7999,7 @@ function createRedactionProfile(profile = "local") {
|
|
|
7760
7999
|
}
|
|
7761
8000
|
var Redactor2 = class {
|
|
7762
8001
|
#rules;
|
|
8002
|
+
#sensitiveKeys;
|
|
7763
8003
|
#detectors;
|
|
7764
8004
|
#profile;
|
|
7765
8005
|
#replacement;
|
|
@@ -7772,6 +8012,7 @@ var Redactor2 = class {
|
|
|
7772
8012
|
...resolved.extraKeys,
|
|
7773
8013
|
...options?.extraKeys ?? []
|
|
7774
8014
|
]);
|
|
8015
|
+
this.#sensitiveKeys = this.#rules.map((rule) => rule.raw ?? rule.key);
|
|
7775
8016
|
this.#detectors = [
|
|
7776
8017
|
...builtInDetectorsForProfile(this.#profile),
|
|
7777
8018
|
...options?.detectors ?? []
|
|
@@ -7805,6 +8046,14 @@ var Redactor2 = class {
|
|
|
7805
8046
|
#recordFinding(state, finding) {
|
|
7806
8047
|
if (this.#collectFindings) state.findings.push(finding);
|
|
7807
8048
|
}
|
|
8049
|
+
#detect(value, key, path17) {
|
|
8050
|
+
for (const detector of this.#detectors) {
|
|
8051
|
+
for (const detection of detector.detect({ path: path17, key, value })) {
|
|
8052
|
+
if ((detection.action ?? "replace") !== "keep") return { detector, detection };
|
|
8053
|
+
}
|
|
8054
|
+
}
|
|
8055
|
+
return void 0;
|
|
8056
|
+
}
|
|
7808
8057
|
#redactValue(value, key, path17, depth, state) {
|
|
7809
8058
|
if (depth > this.#maxDepth) {
|
|
7810
8059
|
this.#recordFinding(
|
|
@@ -7823,6 +8072,43 @@ var Redactor2 = class {
|
|
|
7823
8072
|
return applyRule(rule, value, this.#replacement);
|
|
7824
8073
|
}
|
|
7825
8074
|
}
|
|
8075
|
+
if (typeof value === "string" && looksLikeHttpUrl2(value)) {
|
|
8076
|
+
const url = redactUrlString2(value, {
|
|
8077
|
+
sensitiveKeys: this.#sensitiveKeys,
|
|
8078
|
+
isSensitiveValue: (candidate) => this.#detect(candidate, key, path17) !== void 0,
|
|
8079
|
+
replacement: this.#replacement,
|
|
8080
|
+
maskPathIds: this.#profile !== "local"
|
|
8081
|
+
});
|
|
8082
|
+
if (url.value !== value) {
|
|
8083
|
+
this.#recordFinding(
|
|
8084
|
+
state,
|
|
8085
|
+
makeFinding(
|
|
8086
|
+
path17,
|
|
8087
|
+
url.credentialRedacted ? "value.urlCredential" : "value.urlIdentifier",
|
|
8088
|
+
"replace",
|
|
8089
|
+
"value",
|
|
8090
|
+
url.credentialRedacted ? "error" : "warning"
|
|
8091
|
+
)
|
|
8092
|
+
);
|
|
8093
|
+
const residual = this.#detect(
|
|
8094
|
+
url.value.split(this.#replacement).join(""),
|
|
8095
|
+
key,
|
|
8096
|
+
path17
|
|
8097
|
+
);
|
|
8098
|
+
if (residual === void 0) return url.value;
|
|
8099
|
+
this.#recordFinding(
|
|
8100
|
+
state,
|
|
8101
|
+
makeFinding(
|
|
8102
|
+
path17,
|
|
8103
|
+
residual.detector.id,
|
|
8104
|
+
"replace",
|
|
8105
|
+
residual.detection.matchKind ?? residual.detector.matchKind ?? "custom",
|
|
8106
|
+
residual.detection.severity ?? residual.detector.severity ?? "warning"
|
|
8107
|
+
)
|
|
8108
|
+
);
|
|
8109
|
+
return this.#replacement;
|
|
8110
|
+
}
|
|
8111
|
+
}
|
|
7826
8112
|
for (const detector of this.#detectors) {
|
|
7827
8113
|
const detections = detector.detect({ path: path17, key, value });
|
|
7828
8114
|
for (const detection of detections) {
|