@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
|
@@ -36,6 +36,80 @@ function extractCorrelationMetadata(record) {
|
|
|
36
36
|
}
|
|
37
37
|
return found ? out : void 0;
|
|
38
38
|
}
|
|
39
|
+
|
|
40
|
+
// packages/core/src/safety/sensitive-key.ts
|
|
41
|
+
function keyHasExplicitSeparator(value) {
|
|
42
|
+
return /[_\-.]/.test(value);
|
|
43
|
+
}
|
|
44
|
+
function normalizeSensitiveKey(value) {
|
|
45
|
+
return value.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
46
|
+
}
|
|
47
|
+
var NON_CREDENTIAL_TOKEN_CONFIG_KEYS = new Set(
|
|
48
|
+
[
|
|
49
|
+
"tokens",
|
|
50
|
+
"max_tokens",
|
|
51
|
+
"min_tokens",
|
|
52
|
+
"ls_max_tokens",
|
|
53
|
+
"token_count",
|
|
54
|
+
"token_limit",
|
|
55
|
+
"token_budget",
|
|
56
|
+
"input_tokens",
|
|
57
|
+
"output_tokens",
|
|
58
|
+
"total_tokens",
|
|
59
|
+
"cached_tokens",
|
|
60
|
+
"prompt_tokens",
|
|
61
|
+
"completion_tokens"
|
|
62
|
+
].map(normalizeSensitiveKey)
|
|
63
|
+
);
|
|
64
|
+
var DEFAULT_CREDENTIAL_SENSITIVE_KEYS = [
|
|
65
|
+
"authorization",
|
|
66
|
+
"cookie",
|
|
67
|
+
"token",
|
|
68
|
+
"access_token",
|
|
69
|
+
"accesstoken",
|
|
70
|
+
"auth_token",
|
|
71
|
+
"authtoken",
|
|
72
|
+
"refresh_token",
|
|
73
|
+
"refreshtoken",
|
|
74
|
+
"id_token",
|
|
75
|
+
"idtoken",
|
|
76
|
+
"bearer_token",
|
|
77
|
+
"bearertoken",
|
|
78
|
+
"api_token",
|
|
79
|
+
"apitoken",
|
|
80
|
+
"apikey",
|
|
81
|
+
"api_key",
|
|
82
|
+
"password",
|
|
83
|
+
"secret",
|
|
84
|
+
"email"
|
|
85
|
+
];
|
|
86
|
+
function isTokenCredentialKey(normalized) {
|
|
87
|
+
if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;
|
|
88
|
+
if (normalized === "token") return true;
|
|
89
|
+
if (normalized.endsWith("tokens")) return false;
|
|
90
|
+
return normalized.endsWith("token");
|
|
91
|
+
}
|
|
92
|
+
function isCredentialSensitiveKey(key, sensitiveKeys = DEFAULT_CREDENTIAL_SENSITIVE_KEYS) {
|
|
93
|
+
if (!key) return false;
|
|
94
|
+
const normalized = normalizeSensitiveKey(key);
|
|
95
|
+
if (!normalized) return false;
|
|
96
|
+
if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;
|
|
97
|
+
const allowPrefixCompound = keyHasExplicitSeparator(key);
|
|
98
|
+
for (const sensitive of sensitiveKeys) {
|
|
99
|
+
const s = normalizeSensitiveKey(sensitive);
|
|
100
|
+
if (!s) continue;
|
|
101
|
+
if (s === "token") {
|
|
102
|
+
if (isTokenCredentialKey(normalized)) return true;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (normalized === s) return true;
|
|
106
|
+
if (normalized.endsWith(`_${s}`)) return true;
|
|
107
|
+
if (allowPrefixCompound && normalized.startsWith(`${s}_`)) return true;
|
|
108
|
+
}
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// packages/core/src/logs/redactor.ts
|
|
39
113
|
var DEFAULT_REDACT_KEYS = [
|
|
40
114
|
"authorization",
|
|
41
115
|
"cookie",
|
|
@@ -59,7 +133,7 @@ function compileRules(rules, extraKeys) {
|
|
|
59
133
|
const out = /* @__PURE__ */ new Map();
|
|
60
134
|
const set = (r) => {
|
|
61
135
|
const k = toKey(r.key);
|
|
62
|
-
out.set(k, { ...r, key: k });
|
|
136
|
+
out.set(k, { ...r, key: k, raw: r.raw ?? r.key });
|
|
63
137
|
};
|
|
64
138
|
for (const k of DEFAULT_REDACT_KEYS) {
|
|
65
139
|
set({ key: k, strategy: "full" });
|
|
@@ -88,9 +162,13 @@ var Redactor = class {
|
|
|
88
162
|
constructor(options) {
|
|
89
163
|
this.#rules = compileRules(options?.rules, options?.extraKeys);
|
|
90
164
|
}
|
|
165
|
+
/** Field names this redactor treats as sensitive, for value-level helpers. */
|
|
166
|
+
get sensitiveKeys() {
|
|
167
|
+
return this.#rules.map((rule) => rule.raw ?? rule.key);
|
|
168
|
+
}
|
|
91
169
|
redactValue(key, value) {
|
|
92
170
|
const k = toKey(key);
|
|
93
|
-
const rule = this.#rules.find((r) => r.key === k);
|
|
171
|
+
const rule = this.#rules.find((r) => r.key === k) ?? this.#rules.find((r) => isCredentialSensitiveKey(key, [r.raw ?? r.key]));
|
|
94
172
|
if (!rule) {
|
|
95
173
|
return this.#redactNested(value);
|
|
96
174
|
}
|
|
@@ -129,6 +207,30 @@ var Redactor = class {
|
|
|
129
207
|
}
|
|
130
208
|
};
|
|
131
209
|
|
|
210
|
+
// packages/core/src/safety/credential-value-patterns.ts
|
|
211
|
+
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;
|
|
212
|
+
var HIGH_CONFIDENCE_CREDENTIAL_PATTERNS = [
|
|
213
|
+
/^(?:basic|bearer|digest|apikey)\s+[a-z0-9._~+/=-]+$/i,
|
|
214
|
+
/\bbearer\s+[a-z0-9._~+/=-]{12,}\b/i,
|
|
215
|
+
/\b[a-z0-9_.-]+=[^;\s]+(?:;\s*[a-z0-9_.-]+=[^;\s]+)+/i,
|
|
216
|
+
/\beyJ[a-zA-Z0-9_-]{8,}\.[a-zA-Z0-9_-]{8,}\.[a-zA-Z0-9_-]{8,}\b/,
|
|
217
|
+
/\b(?:sk-(?:proj-)?[a-zA-Z0-9_-]{16,}|sk-ant-[a-zA-Z0-9_-]{16,}|AIza[0-9A-Za-z_-]{20,})\b/,
|
|
218
|
+
/\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{20,}\b/,
|
|
219
|
+
/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/,
|
|
220
|
+
/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*-----END [A-Z ]*PRIVATE KEY-----/,
|
|
221
|
+
KEY_VALUE_SECRET_PATTERN
|
|
222
|
+
];
|
|
223
|
+
function stringContainsHighConfidenceCredential(value) {
|
|
224
|
+
for (const pattern of HIGH_CONFIDENCE_CREDENTIAL_PATTERNS) {
|
|
225
|
+
pattern.lastIndex = 0;
|
|
226
|
+
if (pattern.test(value)) {
|
|
227
|
+
pattern.lastIndex = 0;
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
|
|
132
234
|
// packages/core/src/redaction-profiles.ts
|
|
133
235
|
var SHARE_PROFILE_EXTRA_KEYS = [
|
|
134
236
|
"userEmail",
|
|
@@ -2299,78 +2401,6 @@ function formatProgrammaticDiagnostic(code, detail) {
|
|
|
2299
2401
|
return `${code}: ${summary} Remediation: ${spec.remediation}`;
|
|
2300
2402
|
}
|
|
2301
2403
|
|
|
2302
|
-
// packages/core/src/safety/sensitive-key.ts
|
|
2303
|
-
function keyHasExplicitSeparator(value) {
|
|
2304
|
-
return /[_\-.]/.test(value);
|
|
2305
|
-
}
|
|
2306
|
-
function normalizeSensitiveKey(value) {
|
|
2307
|
-
return value.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
2308
|
-
}
|
|
2309
|
-
var NON_CREDENTIAL_TOKEN_CONFIG_KEYS = new Set(
|
|
2310
|
-
[
|
|
2311
|
-
"tokens",
|
|
2312
|
-
"max_tokens",
|
|
2313
|
-
"min_tokens",
|
|
2314
|
-
"ls_max_tokens",
|
|
2315
|
-
"token_count",
|
|
2316
|
-
"token_limit",
|
|
2317
|
-
"token_budget",
|
|
2318
|
-
"input_tokens",
|
|
2319
|
-
"output_tokens",
|
|
2320
|
-
"total_tokens",
|
|
2321
|
-
"cached_tokens",
|
|
2322
|
-
"prompt_tokens",
|
|
2323
|
-
"completion_tokens"
|
|
2324
|
-
].map(normalizeSensitiveKey)
|
|
2325
|
-
);
|
|
2326
|
-
var DEFAULT_CREDENTIAL_SENSITIVE_KEYS = [
|
|
2327
|
-
"authorization",
|
|
2328
|
-
"cookie",
|
|
2329
|
-
"token",
|
|
2330
|
-
"access_token",
|
|
2331
|
-
"accesstoken",
|
|
2332
|
-
"auth_token",
|
|
2333
|
-
"authtoken",
|
|
2334
|
-
"refresh_token",
|
|
2335
|
-
"refreshtoken",
|
|
2336
|
-
"id_token",
|
|
2337
|
-
"idtoken",
|
|
2338
|
-
"bearer_token",
|
|
2339
|
-
"bearertoken",
|
|
2340
|
-
"api_token",
|
|
2341
|
-
"apitoken",
|
|
2342
|
-
"apikey",
|
|
2343
|
-
"api_key",
|
|
2344
|
-
"password",
|
|
2345
|
-
"secret",
|
|
2346
|
-
"email"
|
|
2347
|
-
];
|
|
2348
|
-
function isTokenCredentialKey(normalized) {
|
|
2349
|
-
if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;
|
|
2350
|
-
if (normalized === "token") return true;
|
|
2351
|
-
if (normalized.endsWith("tokens")) return false;
|
|
2352
|
-
return normalized.endsWith("token");
|
|
2353
|
-
}
|
|
2354
|
-
function isCredentialSensitiveKey(key, sensitiveKeys = DEFAULT_CREDENTIAL_SENSITIVE_KEYS) {
|
|
2355
|
-
if (!key) return false;
|
|
2356
|
-
const normalized = normalizeSensitiveKey(key);
|
|
2357
|
-
if (!normalized) return false;
|
|
2358
|
-
if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;
|
|
2359
|
-
const allowPrefixCompound = keyHasExplicitSeparator(key);
|
|
2360
|
-
for (const sensitive of sensitiveKeys) {
|
|
2361
|
-
const s = normalizeSensitiveKey(sensitive);
|
|
2362
|
-
if (!s) continue;
|
|
2363
|
-
if (s === "token") {
|
|
2364
|
-
if (isTokenCredentialKey(normalized)) return true;
|
|
2365
|
-
continue;
|
|
2366
|
-
}
|
|
2367
|
-
if (normalized === s) return true;
|
|
2368
|
-
if (normalized.endsWith(`_${s}`)) return true;
|
|
2369
|
-
if (allowPrefixCompound && normalized.startsWith(`${s}_`)) return true;
|
|
2370
|
-
}
|
|
2371
|
-
return false;
|
|
2372
|
-
}
|
|
2373
|
-
|
|
2374
2404
|
// packages/core/src/checks/logical-events.ts
|
|
2375
2405
|
function isRecord6(value) {
|
|
2376
2406
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -3321,7 +3351,7 @@ var DEFAULT_SECRET_PATTERNS = [
|
|
|
3321
3351
|
// Keep in sync with packages/redact/src/key-value-secret.ts (KEY_VALUE_SECRET_PATTERN_SOURCE).
|
|
3322
3352
|
{
|
|
3323
3353
|
id: "key-value-secret",
|
|
3324
|
-
pattern: /\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=([^\s"'\\]{8,})/i
|
|
3354
|
+
pattern: /\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=(?!\[(?:REDACTED(?::[^\]]*)?|HASH:[0-9a-f]{8})\](?![^\s"'\\&#?;/]))([^\s"'\\]{8,})/i
|
|
3325
3355
|
}
|
|
3326
3356
|
];
|
|
3327
3357
|
function compareStrings(a, b) {
|
|
@@ -6662,6 +6692,99 @@ function openTrace(input, options = {}) {
|
|
|
6662
6692
|
// packages/core/src/exporters/types.ts
|
|
6663
6693
|
var EXPORT_PAYLOAD_VERSION = "0.1.2";
|
|
6664
6694
|
|
|
6695
|
+
// packages/core/src/safety/url-redaction.ts
|
|
6696
|
+
var HTTP_URL = /^https?:\/\/[^\s]+$/i;
|
|
6697
|
+
var UUID_SEGMENT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
6698
|
+
var HEX_SEGMENT = /^[0-9a-f]{12,}$/i;
|
|
6699
|
+
var NUMERIC_SEGMENT = /^\d{5,}$/;
|
|
6700
|
+
var OPAQUE_SEGMENT = /^[A-Za-z0-9_-]{20,}$/;
|
|
6701
|
+
function looksLikeHttpUrl(value) {
|
|
6702
|
+
return HTTP_URL.test(value.trim());
|
|
6703
|
+
}
|
|
6704
|
+
function parseHttpUrl(value) {
|
|
6705
|
+
try {
|
|
6706
|
+
const url = new URL(value.trim());
|
|
6707
|
+
return url.protocol === "http:" || url.protocol === "https:" ? url : void 0;
|
|
6708
|
+
} catch {
|
|
6709
|
+
return void 0;
|
|
6710
|
+
}
|
|
6711
|
+
}
|
|
6712
|
+
function isIdentifierSegment(segment) {
|
|
6713
|
+
if (UUID_SEGMENT.test(segment)) return true;
|
|
6714
|
+
if (HEX_SEGMENT.test(segment)) return true;
|
|
6715
|
+
if (NUMERIC_SEGMENT.test(segment)) return true;
|
|
6716
|
+
return OPAQUE_SEGMENT.test(segment) && /\d/.test(segment) && /[A-Za-z]/.test(segment);
|
|
6717
|
+
}
|
|
6718
|
+
function decodeParam(value) {
|
|
6719
|
+
try {
|
|
6720
|
+
return decodeURIComponent(value.replace(/\+/g, " "));
|
|
6721
|
+
} catch {
|
|
6722
|
+
return value;
|
|
6723
|
+
}
|
|
6724
|
+
}
|
|
6725
|
+
function redactParams(raw, options, replacement) {
|
|
6726
|
+
let redacted = false;
|
|
6727
|
+
const parts = raw.split("&").map((part) => {
|
|
6728
|
+
if (part.length === 0) return part;
|
|
6729
|
+
const separator = part.indexOf("=");
|
|
6730
|
+
if (separator < 0) return part;
|
|
6731
|
+
const rawKey = part.slice(0, separator);
|
|
6732
|
+
const rawValue = part.slice(separator + 1);
|
|
6733
|
+
const key = decodeParam(rawKey);
|
|
6734
|
+
const value = decodeParam(rawValue);
|
|
6735
|
+
if (isCredentialSensitiveKey(key, options.sensitiveKeys) || options.isSensitiveValue(value)) {
|
|
6736
|
+
redacted = true;
|
|
6737
|
+
return `${rawKey}=${replacement}`;
|
|
6738
|
+
}
|
|
6739
|
+
return part;
|
|
6740
|
+
});
|
|
6741
|
+
return { value: parts.join("&"), redacted };
|
|
6742
|
+
}
|
|
6743
|
+
function redactUrlString(value, options) {
|
|
6744
|
+
const unchanged = {
|
|
6745
|
+
value,
|
|
6746
|
+
credentialRedacted: false,
|
|
6747
|
+
identifiersMasked: false
|
|
6748
|
+
};
|
|
6749
|
+
if (!looksLikeHttpUrl(value)) return unchanged;
|
|
6750
|
+
const url = parseHttpUrl(value);
|
|
6751
|
+
if (!url) return unchanged;
|
|
6752
|
+
const replacement = options.replacement ?? "[REDACTED]";
|
|
6753
|
+
const idPlaceholder = options.idPlaceholder ?? "[id]";
|
|
6754
|
+
let credentialRedacted = url.username.length > 0 || url.password.length > 0;
|
|
6755
|
+
let identifiersMasked = false;
|
|
6756
|
+
let pathname = url.pathname;
|
|
6757
|
+
if (options.maskPathIds === true) {
|
|
6758
|
+
pathname = url.pathname.split("/").map((segment) => {
|
|
6759
|
+
if (segment.length === 0 || !isIdentifierSegment(decodeParam(segment))) {
|
|
6760
|
+
return segment;
|
|
6761
|
+
}
|
|
6762
|
+
identifiersMasked = true;
|
|
6763
|
+
return idPlaceholder;
|
|
6764
|
+
}).join("/");
|
|
6765
|
+
}
|
|
6766
|
+
let search = "";
|
|
6767
|
+
if (url.search.length > 1) {
|
|
6768
|
+
const params = redactParams(url.search.slice(1), options, replacement);
|
|
6769
|
+
if (params.redacted) credentialRedacted = true;
|
|
6770
|
+
search = `?${params.value}`;
|
|
6771
|
+
} else if (url.search.length === 1) {
|
|
6772
|
+
search = "?";
|
|
6773
|
+
}
|
|
6774
|
+
let hash = url.hash;
|
|
6775
|
+
if (url.hash.includes("=")) {
|
|
6776
|
+
const params = redactParams(url.hash.slice(1), options, replacement);
|
|
6777
|
+
if (params.redacted) credentialRedacted = true;
|
|
6778
|
+
hash = `#${params.value}`;
|
|
6779
|
+
}
|
|
6780
|
+
if (!credentialRedacted && !identifiersMasked) return unchanged;
|
|
6781
|
+
return {
|
|
6782
|
+
value: `${url.protocol}//${url.host}${pathname}${search}${hash}`,
|
|
6783
|
+
credentialRedacted,
|
|
6784
|
+
identifiersMasked
|
|
6785
|
+
};
|
|
6786
|
+
}
|
|
6787
|
+
|
|
6665
6788
|
// packages/core/src/exporters/redact-export.ts
|
|
6666
6789
|
function isRecord11(value) {
|
|
6667
6790
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -6679,21 +6802,34 @@ function deepClone(value) {
|
|
|
6679
6802
|
}
|
|
6680
6803
|
return out;
|
|
6681
6804
|
}
|
|
6682
|
-
function boundAttributeValues(record, maxMetadataValueLength, maxPreviewLength, seen, depth) {
|
|
6805
|
+
function boundAttributeValues(record, sensitiveKeys, maxMetadataValueLength, maxPreviewLength, seen, depth) {
|
|
6683
6806
|
if (depth > 32) {
|
|
6684
6807
|
return { truncated: true, reason: "maxDepth" };
|
|
6685
6808
|
}
|
|
6686
6809
|
const out = {};
|
|
6687
6810
|
for (const [key, value] of Object.entries(record)) {
|
|
6688
|
-
out[key] = boundValue(
|
|
6811
|
+
out[key] = boundValue(
|
|
6812
|
+
value,
|
|
6813
|
+
key,
|
|
6814
|
+
sensitiveKeys,
|
|
6815
|
+
maxMetadataValueLength,
|
|
6816
|
+
maxPreviewLength,
|
|
6817
|
+
seen,
|
|
6818
|
+
depth
|
|
6819
|
+
);
|
|
6689
6820
|
}
|
|
6690
6821
|
return out;
|
|
6691
6822
|
}
|
|
6692
|
-
function boundValue(value, key, maxMetadataValueLength, maxPreviewLength, seen, depth) {
|
|
6823
|
+
function boundValue(value, key, sensitiveKeys, maxMetadataValueLength, maxPreviewLength, seen, depth) {
|
|
6693
6824
|
if (value === null || typeof value !== "object") {
|
|
6694
6825
|
if (typeof value === "string") {
|
|
6826
|
+
const rewritten = redactUrlString(value, {
|
|
6827
|
+
sensitiveKeys,
|
|
6828
|
+
isSensitiveValue: stringContainsHighConfidenceCredential,
|
|
6829
|
+
maskPathIds: true
|
|
6830
|
+
}).value;
|
|
6695
6831
|
return truncateStringForProfile(
|
|
6696
|
-
|
|
6832
|
+
stringContainsHighConfidenceCredential(rewritten) ? "[REDACTED]" : rewritten,
|
|
6697
6833
|
key,
|
|
6698
6834
|
maxMetadataValueLength,
|
|
6699
6835
|
maxPreviewLength
|
|
@@ -6708,6 +6844,7 @@ function boundValue(value, key, maxMetadataValueLength, maxPreviewLength, seen,
|
|
|
6708
6844
|
(item, index) => boundValue(
|
|
6709
6845
|
item,
|
|
6710
6846
|
String(index),
|
|
6847
|
+
sensitiveKeys,
|
|
6711
6848
|
maxMetadataValueLength,
|
|
6712
6849
|
maxPreviewLength,
|
|
6713
6850
|
seen,
|
|
@@ -6717,6 +6854,7 @@ function boundValue(value, key, maxMetadataValueLength, maxPreviewLength, seen,
|
|
|
6717
6854
|
}
|
|
6718
6855
|
return boundAttributeValues(
|
|
6719
6856
|
value,
|
|
6857
|
+
sensitiveKeys,
|
|
6720
6858
|
maxMetadataValueLength,
|
|
6721
6859
|
maxPreviewLength,
|
|
6722
6860
|
seen,
|
|
@@ -6731,6 +6869,7 @@ function redactEventAttributes(attrs2, redactor, maxMetadataValueLength, maxPrev
|
|
|
6731
6869
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
6732
6870
|
const bounded = boundAttributeValues(
|
|
6733
6871
|
redacted,
|
|
6872
|
+
[...DEFAULT_REDACT_KEYS, ...redactor.sensitiveKeys],
|
|
6734
6873
|
maxMetadataValueLength,
|
|
6735
6874
|
maxPreviewLength,
|
|
6736
6875
|
seen,
|
|
@@ -7184,6 +7323,11 @@ function exportOpenInference(tree, options) {
|
|
|
7184
7323
|
function hexFrom2(seed, byteLen) {
|
|
7185
7324
|
return crypto.createHash("sha256").update(seed, "utf8").digest("hex").slice(0, byteLen * 2);
|
|
7186
7325
|
}
|
|
7326
|
+
function unixNano2(ms) {
|
|
7327
|
+
const whole = Math.trunc(ms);
|
|
7328
|
+
const fractionNs = Math.round((ms - whole) * 1e6);
|
|
7329
|
+
return BigInt(whole) * 1000000n + BigInt(fractionNs);
|
|
7330
|
+
}
|
|
7187
7331
|
function stringAttr2(key, value) {
|
|
7188
7332
|
return { key, value: { stringValue: value } };
|
|
7189
7333
|
}
|
|
@@ -7217,10 +7361,10 @@ function exportOtlpJson(tree, options) {
|
|
|
7217
7361
|
const ev = n.event;
|
|
7218
7362
|
const spanId = hexFrom2(`${tree.runId}:${ev.eventId}`, 8);
|
|
7219
7363
|
const parentSpanId = ev.parentId ? hexFrom2(`${tree.runId}:${ev.parentId}`, 8) : void 0;
|
|
7220
|
-
const startNs = String(
|
|
7364
|
+
const startNs = String(unixNano2(ev.timestamp));
|
|
7221
7365
|
let endNs;
|
|
7222
7366
|
if (ev.durationMs !== void 0 && Number.isFinite(ev.durationMs)) {
|
|
7223
|
-
endNs = String(
|
|
7367
|
+
endNs = String(unixNano2(ev.timestamp) + unixNano2(ev.durationMs));
|
|
7224
7368
|
}
|
|
7225
7369
|
const attrs2 = [
|
|
7226
7370
|
stringAttr2("agent_inspect.kind", ev.kind),
|
|
@@ -7396,14 +7540,107 @@ function isCredentialSensitiveKey2(key, sensitiveKeys) {
|
|
|
7396
7540
|
}
|
|
7397
7541
|
|
|
7398
7542
|
// packages/redact/src/key-value-secret.ts
|
|
7399
|
-
var KEY_VALUE_SECRET_PATTERN_SOURCE = String.raw`\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=([^\s"'\\]{8,})`;
|
|
7400
|
-
var
|
|
7543
|
+
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,})`;
|
|
7544
|
+
var KEY_VALUE_SECRET_PATTERN2 = new RegExp(
|
|
7401
7545
|
KEY_VALUE_SECRET_PATTERN_SOURCE,
|
|
7402
7546
|
"i"
|
|
7403
7547
|
);
|
|
7404
7548
|
function valueContainsKeyValueSecret(value) {
|
|
7405
|
-
|
|
7406
|
-
return
|
|
7549
|
+
KEY_VALUE_SECRET_PATTERN2.lastIndex = 0;
|
|
7550
|
+
return KEY_VALUE_SECRET_PATTERN2.test(value);
|
|
7551
|
+
}
|
|
7552
|
+
|
|
7553
|
+
// packages/redact/src/url-redaction.ts
|
|
7554
|
+
var HTTP_URL2 = /^https?:\/\/[^\s]+$/i;
|
|
7555
|
+
var UUID_SEGMENT2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
7556
|
+
var HEX_SEGMENT2 = /^[0-9a-f]{12,}$/i;
|
|
7557
|
+
var NUMERIC_SEGMENT2 = /^\d{5,}$/;
|
|
7558
|
+
var OPAQUE_SEGMENT2 = /^[A-Za-z0-9_-]{20,}$/;
|
|
7559
|
+
function looksLikeHttpUrl2(value) {
|
|
7560
|
+
return HTTP_URL2.test(value.trim());
|
|
7561
|
+
}
|
|
7562
|
+
function parseHttpUrl2(value) {
|
|
7563
|
+
try {
|
|
7564
|
+
const url = new URL(value.trim());
|
|
7565
|
+
return url.protocol === "http:" || url.protocol === "https:" ? url : void 0;
|
|
7566
|
+
} catch {
|
|
7567
|
+
return void 0;
|
|
7568
|
+
}
|
|
7569
|
+
}
|
|
7570
|
+
function isIdentifierSegment2(segment) {
|
|
7571
|
+
if (UUID_SEGMENT2.test(segment)) return true;
|
|
7572
|
+
if (HEX_SEGMENT2.test(segment)) return true;
|
|
7573
|
+
if (NUMERIC_SEGMENT2.test(segment)) return true;
|
|
7574
|
+
return OPAQUE_SEGMENT2.test(segment) && /\d/.test(segment) && /[A-Za-z]/.test(segment);
|
|
7575
|
+
}
|
|
7576
|
+
function decodeParam2(value) {
|
|
7577
|
+
try {
|
|
7578
|
+
return decodeURIComponent(value.replace(/\+/g, " "));
|
|
7579
|
+
} catch {
|
|
7580
|
+
return value;
|
|
7581
|
+
}
|
|
7582
|
+
}
|
|
7583
|
+
function redactParams2(raw, options, replacement) {
|
|
7584
|
+
let redacted = false;
|
|
7585
|
+
const parts = raw.split("&").map((part) => {
|
|
7586
|
+
if (part.length === 0) return part;
|
|
7587
|
+
const separator = part.indexOf("=");
|
|
7588
|
+
if (separator < 0) return part;
|
|
7589
|
+
const rawKey = part.slice(0, separator);
|
|
7590
|
+
const rawValue = part.slice(separator + 1);
|
|
7591
|
+
const key = decodeParam2(rawKey);
|
|
7592
|
+
const value = decodeParam2(rawValue);
|
|
7593
|
+
if (isCredentialSensitiveKey2(key, options.sensitiveKeys) || options.isSensitiveValue(value)) {
|
|
7594
|
+
redacted = true;
|
|
7595
|
+
return `${rawKey}=${replacement}`;
|
|
7596
|
+
}
|
|
7597
|
+
return part;
|
|
7598
|
+
});
|
|
7599
|
+
return { value: parts.join("&"), redacted };
|
|
7600
|
+
}
|
|
7601
|
+
function redactUrlString2(value, options) {
|
|
7602
|
+
const unchanged = {
|
|
7603
|
+
value,
|
|
7604
|
+
credentialRedacted: false,
|
|
7605
|
+
identifiersMasked: false
|
|
7606
|
+
};
|
|
7607
|
+
if (!looksLikeHttpUrl2(value)) return unchanged;
|
|
7608
|
+
const url = parseHttpUrl2(value);
|
|
7609
|
+
if (!url) return unchanged;
|
|
7610
|
+
const replacement = options.replacement ?? "[REDACTED]";
|
|
7611
|
+
const idPlaceholder = options.idPlaceholder ?? "[id]";
|
|
7612
|
+
let credentialRedacted = url.username.length > 0 || url.password.length > 0;
|
|
7613
|
+
let identifiersMasked = false;
|
|
7614
|
+
let pathname = url.pathname;
|
|
7615
|
+
if (options.maskPathIds === true) {
|
|
7616
|
+
pathname = url.pathname.split("/").map((segment) => {
|
|
7617
|
+
if (segment.length === 0 || !isIdentifierSegment2(decodeParam2(segment))) {
|
|
7618
|
+
return segment;
|
|
7619
|
+
}
|
|
7620
|
+
identifiersMasked = true;
|
|
7621
|
+
return idPlaceholder;
|
|
7622
|
+
}).join("/");
|
|
7623
|
+
}
|
|
7624
|
+
let search = "";
|
|
7625
|
+
if (url.search.length > 1) {
|
|
7626
|
+
const params = redactParams2(url.search.slice(1), options, replacement);
|
|
7627
|
+
if (params.redacted) credentialRedacted = true;
|
|
7628
|
+
search = `?${params.value}`;
|
|
7629
|
+
} else if (url.search.length === 1) {
|
|
7630
|
+
search = "?";
|
|
7631
|
+
}
|
|
7632
|
+
let hash = url.hash;
|
|
7633
|
+
if (url.hash.includes("=")) {
|
|
7634
|
+
const params = redactParams2(url.hash.slice(1), options, replacement);
|
|
7635
|
+
if (params.redacted) credentialRedacted = true;
|
|
7636
|
+
hash = `#${params.value}`;
|
|
7637
|
+
}
|
|
7638
|
+
if (!credentialRedacted && !identifiersMasked) return unchanged;
|
|
7639
|
+
return {
|
|
7640
|
+
value: `${url.protocol}//${url.host}${pathname}${search}${hash}`,
|
|
7641
|
+
credentialRedacted,
|
|
7642
|
+
identifiersMasked
|
|
7643
|
+
};
|
|
7407
7644
|
}
|
|
7408
7645
|
|
|
7409
7646
|
// packages/redact/src/index.ts
|
|
@@ -7472,7 +7709,9 @@ function findCompiledKeyRule(key, rules) {
|
|
|
7472
7709
|
const exact = toKey2(key);
|
|
7473
7710
|
const direct = rules.find((candidate) => candidate.key === exact);
|
|
7474
7711
|
if (direct) return direct;
|
|
7475
|
-
return rules.find(
|
|
7712
|
+
return rules.find(
|
|
7713
|
+
(candidate) => isCredentialSensitiveKey2(key, [candidate.raw ?? candidate.key])
|
|
7714
|
+
);
|
|
7476
7715
|
}
|
|
7477
7716
|
function stableHash2(value) {
|
|
7478
7717
|
const hash = crypto.createHash("sha256").update(value, "utf8").digest("hex");
|
|
@@ -7671,7 +7910,7 @@ function compileRules2(rules, extraKeys) {
|
|
|
7671
7910
|
const out = /* @__PURE__ */ new Map();
|
|
7672
7911
|
const set = (rule) => {
|
|
7673
7912
|
const key = toKey2(rule.key);
|
|
7674
|
-
out.set(key, { ...rule, key });
|
|
7913
|
+
out.set(key, { ...rule, key, raw: rule.raw ?? rule.key });
|
|
7675
7914
|
};
|
|
7676
7915
|
for (const key of DEFAULT_REDACT_KEYS2) {
|
|
7677
7916
|
set({ key, strategy: "full" });
|
|
@@ -7750,6 +7989,7 @@ function createRedactionProfile(profile = "local") {
|
|
|
7750
7989
|
}
|
|
7751
7990
|
var Redactor2 = class {
|
|
7752
7991
|
#rules;
|
|
7992
|
+
#sensitiveKeys;
|
|
7753
7993
|
#detectors;
|
|
7754
7994
|
#profile;
|
|
7755
7995
|
#replacement;
|
|
@@ -7762,6 +8002,7 @@ var Redactor2 = class {
|
|
|
7762
8002
|
...resolved.extraKeys,
|
|
7763
8003
|
...options?.extraKeys ?? []
|
|
7764
8004
|
]);
|
|
8005
|
+
this.#sensitiveKeys = this.#rules.map((rule) => rule.raw ?? rule.key);
|
|
7765
8006
|
this.#detectors = [
|
|
7766
8007
|
...builtInDetectorsForProfile(this.#profile),
|
|
7767
8008
|
...options?.detectors ?? []
|
|
@@ -7795,6 +8036,14 @@ var Redactor2 = class {
|
|
|
7795
8036
|
#recordFinding(state, finding) {
|
|
7796
8037
|
if (this.#collectFindings) state.findings.push(finding);
|
|
7797
8038
|
}
|
|
8039
|
+
#detect(value, key, path16) {
|
|
8040
|
+
for (const detector of this.#detectors) {
|
|
8041
|
+
for (const detection of detector.detect({ path: path16, key, value })) {
|
|
8042
|
+
if ((detection.action ?? "replace") !== "keep") return { detector, detection };
|
|
8043
|
+
}
|
|
8044
|
+
}
|
|
8045
|
+
return void 0;
|
|
8046
|
+
}
|
|
7798
8047
|
#redactValue(value, key, path16, depth, state) {
|
|
7799
8048
|
if (depth > this.#maxDepth) {
|
|
7800
8049
|
this.#recordFinding(
|
|
@@ -7813,6 +8062,43 @@ var Redactor2 = class {
|
|
|
7813
8062
|
return applyRule(rule, value, this.#replacement);
|
|
7814
8063
|
}
|
|
7815
8064
|
}
|
|
8065
|
+
if (typeof value === "string" && looksLikeHttpUrl2(value)) {
|
|
8066
|
+
const url = redactUrlString2(value, {
|
|
8067
|
+
sensitiveKeys: this.#sensitiveKeys,
|
|
8068
|
+
isSensitiveValue: (candidate) => this.#detect(candidate, key, path16) !== void 0,
|
|
8069
|
+
replacement: this.#replacement,
|
|
8070
|
+
maskPathIds: this.#profile !== "local"
|
|
8071
|
+
});
|
|
8072
|
+
if (url.value !== value) {
|
|
8073
|
+
this.#recordFinding(
|
|
8074
|
+
state,
|
|
8075
|
+
makeFinding(
|
|
8076
|
+
path16,
|
|
8077
|
+
url.credentialRedacted ? "value.urlCredential" : "value.urlIdentifier",
|
|
8078
|
+
"replace",
|
|
8079
|
+
"value",
|
|
8080
|
+
url.credentialRedacted ? "error" : "warning"
|
|
8081
|
+
)
|
|
8082
|
+
);
|
|
8083
|
+
const residual = this.#detect(
|
|
8084
|
+
url.value.split(this.#replacement).join(""),
|
|
8085
|
+
key,
|
|
8086
|
+
path16
|
|
8087
|
+
);
|
|
8088
|
+
if (residual === void 0) return url.value;
|
|
8089
|
+
this.#recordFinding(
|
|
8090
|
+
state,
|
|
8091
|
+
makeFinding(
|
|
8092
|
+
path16,
|
|
8093
|
+
residual.detector.id,
|
|
8094
|
+
"replace",
|
|
8095
|
+
residual.detection.matchKind ?? residual.detector.matchKind ?? "custom",
|
|
8096
|
+
residual.detection.severity ?? residual.detector.severity ?? "warning"
|
|
8097
|
+
)
|
|
8098
|
+
);
|
|
8099
|
+
return this.#replacement;
|
|
8100
|
+
}
|
|
8101
|
+
}
|
|
7816
8102
|
for (const detector of this.#detectors) {
|
|
7817
8103
|
const detections = detector.detect({ path: path16, key, value });
|
|
7818
8104
|
for (const detection of detections) {
|
|
@@ -8745,5 +9031,5 @@ async function runReadOnlyMcpServer(options = {}) {
|
|
|
8745
9031
|
}
|
|
8746
9032
|
|
|
8747
9033
|
export { MCP_MAX_REQUEST_BYTES, MCP_PROTOCOL_VERSION, MCP_SERVER_INSTRUCTIONS, READ_ONLY_TOOLS, TRACE_DATA_UNTRUSTED_WARNING, callReadOnlyTool, createMcpServerContext, handleMcpProtocolLine, runReadOnlyMcpServer };
|
|
8748
|
-
//# sourceMappingURL=chunk-
|
|
8749
|
-
//# sourceMappingURL=chunk-
|
|
9034
|
+
//# sourceMappingURL=chunk-OGX7RS23.mjs.map
|
|
9035
|
+
//# sourceMappingURL=chunk-OGX7RS23.mjs.map
|