@agent-inspect/mcp-server 6.31.3 → 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-P2HSJJKS.mjs → chunk-OGX7RS23.mjs} +368 -87
- package/dist/chunk-OGX7RS23.mjs.map +1 -0
- package/dist/cli.cjs +366 -85
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/index.cjs +366 -85
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +3 -3
- package/dist/chunk-P2HSJJKS.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,
|
|
@@ -7401,14 +7540,107 @@ function isCredentialSensitiveKey2(key, sensitiveKeys) {
|
|
|
7401
7540
|
}
|
|
7402
7541
|
|
|
7403
7542
|
// packages/redact/src/key-value-secret.ts
|
|
7404
|
-
var KEY_VALUE_SECRET_PATTERN_SOURCE = String.raw`\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=([^\s"'\\]{8,})`;
|
|
7405
|
-
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(
|
|
7406
7545
|
KEY_VALUE_SECRET_PATTERN_SOURCE,
|
|
7407
7546
|
"i"
|
|
7408
7547
|
);
|
|
7409
7548
|
function valueContainsKeyValueSecret(value) {
|
|
7410
|
-
|
|
7411
|
-
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
|
+
};
|
|
7412
7644
|
}
|
|
7413
7645
|
|
|
7414
7646
|
// packages/redact/src/index.ts
|
|
@@ -7477,7 +7709,9 @@ function findCompiledKeyRule(key, rules) {
|
|
|
7477
7709
|
const exact = toKey2(key);
|
|
7478
7710
|
const direct = rules.find((candidate) => candidate.key === exact);
|
|
7479
7711
|
if (direct) return direct;
|
|
7480
|
-
return rules.find(
|
|
7712
|
+
return rules.find(
|
|
7713
|
+
(candidate) => isCredentialSensitiveKey2(key, [candidate.raw ?? candidate.key])
|
|
7714
|
+
);
|
|
7481
7715
|
}
|
|
7482
7716
|
function stableHash2(value) {
|
|
7483
7717
|
const hash = crypto.createHash("sha256").update(value, "utf8").digest("hex");
|
|
@@ -7676,7 +7910,7 @@ function compileRules2(rules, extraKeys) {
|
|
|
7676
7910
|
const out = /* @__PURE__ */ new Map();
|
|
7677
7911
|
const set = (rule) => {
|
|
7678
7912
|
const key = toKey2(rule.key);
|
|
7679
|
-
out.set(key, { ...rule, key });
|
|
7913
|
+
out.set(key, { ...rule, key, raw: rule.raw ?? rule.key });
|
|
7680
7914
|
};
|
|
7681
7915
|
for (const key of DEFAULT_REDACT_KEYS2) {
|
|
7682
7916
|
set({ key, strategy: "full" });
|
|
@@ -7755,6 +7989,7 @@ function createRedactionProfile(profile = "local") {
|
|
|
7755
7989
|
}
|
|
7756
7990
|
var Redactor2 = class {
|
|
7757
7991
|
#rules;
|
|
7992
|
+
#sensitiveKeys;
|
|
7758
7993
|
#detectors;
|
|
7759
7994
|
#profile;
|
|
7760
7995
|
#replacement;
|
|
@@ -7767,6 +8002,7 @@ var Redactor2 = class {
|
|
|
7767
8002
|
...resolved.extraKeys,
|
|
7768
8003
|
...options?.extraKeys ?? []
|
|
7769
8004
|
]);
|
|
8005
|
+
this.#sensitiveKeys = this.#rules.map((rule) => rule.raw ?? rule.key);
|
|
7770
8006
|
this.#detectors = [
|
|
7771
8007
|
...builtInDetectorsForProfile(this.#profile),
|
|
7772
8008
|
...options?.detectors ?? []
|
|
@@ -7800,6 +8036,14 @@ var Redactor2 = class {
|
|
|
7800
8036
|
#recordFinding(state, finding) {
|
|
7801
8037
|
if (this.#collectFindings) state.findings.push(finding);
|
|
7802
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
|
+
}
|
|
7803
8047
|
#redactValue(value, key, path16, depth, state) {
|
|
7804
8048
|
if (depth > this.#maxDepth) {
|
|
7805
8049
|
this.#recordFinding(
|
|
@@ -7818,6 +8062,43 @@ var Redactor2 = class {
|
|
|
7818
8062
|
return applyRule(rule, value, this.#replacement);
|
|
7819
8063
|
}
|
|
7820
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
|
+
}
|
|
7821
8102
|
for (const detector of this.#detectors) {
|
|
7822
8103
|
const detections = detector.detect({ path: path16, key, value });
|
|
7823
8104
|
for (const detection of detections) {
|
|
@@ -8750,5 +9031,5 @@ async function runReadOnlyMcpServer(options = {}) {
|
|
|
8750
9031
|
}
|
|
8751
9032
|
|
|
8752
9033
|
export { MCP_MAX_REQUEST_BYTES, MCP_PROTOCOL_VERSION, MCP_SERVER_INSTRUCTIONS, READ_ONLY_TOOLS, TRACE_DATA_UNTRUSTED_WARNING, callReadOnlyTool, createMcpServerContext, handleMcpProtocolLine, runReadOnlyMcpServer };
|
|
8753
|
-
//# sourceMappingURL=chunk-
|
|
8754
|
-
//# sourceMappingURL=chunk-
|
|
9034
|
+
//# sourceMappingURL=chunk-OGX7RS23.mjs.map
|
|
9035
|
+
//# sourceMappingURL=chunk-OGX7RS23.mjs.map
|