@agent-inspect/mcp-server 6.31.3 → 6.31.5
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-FUNPQPC3.mjs} +418 -87
- package/dist/chunk-FUNPQPC3.mjs.map +1 -0
- package/dist/cli.cjs +416 -85
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/index.cjs +416 -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,124 @@ 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 CONNECTION_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
6698
|
+
"postgres:",
|
|
6699
|
+
"postgresql:",
|
|
6700
|
+
"mysql:",
|
|
6701
|
+
"mariadb:",
|
|
6702
|
+
"mongodb:",
|
|
6703
|
+
"mongodb+srv:",
|
|
6704
|
+
"redis:",
|
|
6705
|
+
"rediss:",
|
|
6706
|
+
"amqp:",
|
|
6707
|
+
"amqps:"
|
|
6708
|
+
]);
|
|
6709
|
+
var CONNECTION_URI = /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/[^\s]+$/i;
|
|
6710
|
+
var UUID_SEGMENT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
6711
|
+
var HEX_SEGMENT = /^[0-9a-f]{12,}$/i;
|
|
6712
|
+
var NUMERIC_SEGMENT = /^\d{5,}$/;
|
|
6713
|
+
var OPAQUE_SEGMENT = /^[A-Za-z0-9_-]{20,}$/;
|
|
6714
|
+
function looksLikeHttpUrl(value) {
|
|
6715
|
+
return HTTP_URL.test(value.trim());
|
|
6716
|
+
}
|
|
6717
|
+
function looksLikeConnectionUri(value) {
|
|
6718
|
+
return CONNECTION_URI.test(value.trim());
|
|
6719
|
+
}
|
|
6720
|
+
function looksLikeUrlForRedaction(value) {
|
|
6721
|
+
return looksLikeHttpUrl(value) || looksLikeConnectionUri(value);
|
|
6722
|
+
}
|
|
6723
|
+
function parseRedactableUrl(value) {
|
|
6724
|
+
try {
|
|
6725
|
+
const url = new URL(value.trim());
|
|
6726
|
+
if (url.protocol === "http:" || url.protocol === "https:") return url;
|
|
6727
|
+
if (CONNECTION_PROTOCOLS.has(url.protocol)) return url;
|
|
6728
|
+
return void 0;
|
|
6729
|
+
} catch {
|
|
6730
|
+
return void 0;
|
|
6731
|
+
}
|
|
6732
|
+
}
|
|
6733
|
+
function isHttpProtocol(protocol) {
|
|
6734
|
+
return protocol === "http:" || protocol === "https:";
|
|
6735
|
+
}
|
|
6736
|
+
function isIdentifierSegment(segment) {
|
|
6737
|
+
if (UUID_SEGMENT.test(segment)) return true;
|
|
6738
|
+
if (HEX_SEGMENT.test(segment)) return true;
|
|
6739
|
+
if (NUMERIC_SEGMENT.test(segment)) return true;
|
|
6740
|
+
return OPAQUE_SEGMENT.test(segment) && /\d/.test(segment) && /[A-Za-z]/.test(segment);
|
|
6741
|
+
}
|
|
6742
|
+
function decodeParam(value) {
|
|
6743
|
+
try {
|
|
6744
|
+
return decodeURIComponent(value.replace(/\+/g, " "));
|
|
6745
|
+
} catch {
|
|
6746
|
+
return value;
|
|
6747
|
+
}
|
|
6748
|
+
}
|
|
6749
|
+
function redactParams(raw, options, replacement) {
|
|
6750
|
+
let redacted = false;
|
|
6751
|
+
const parts = raw.split("&").map((part) => {
|
|
6752
|
+
if (part.length === 0) return part;
|
|
6753
|
+
const separator = part.indexOf("=");
|
|
6754
|
+
if (separator < 0) return part;
|
|
6755
|
+
const rawKey = part.slice(0, separator);
|
|
6756
|
+
const rawValue = part.slice(separator + 1);
|
|
6757
|
+
const key = decodeParam(rawKey);
|
|
6758
|
+
const value = decodeParam(rawValue);
|
|
6759
|
+
if (isCredentialSensitiveKey(key, options.sensitiveKeys) || options.isSensitiveValue(value)) {
|
|
6760
|
+
redacted = true;
|
|
6761
|
+
return `${rawKey}=${replacement}`;
|
|
6762
|
+
}
|
|
6763
|
+
return part;
|
|
6764
|
+
});
|
|
6765
|
+
return { value: parts.join("&"), redacted };
|
|
6766
|
+
}
|
|
6767
|
+
function redactUrlString(value, options) {
|
|
6768
|
+
const unchanged = {
|
|
6769
|
+
value,
|
|
6770
|
+
credentialRedacted: false,
|
|
6771
|
+
identifiersMasked: false
|
|
6772
|
+
};
|
|
6773
|
+
if (!looksLikeUrlForRedaction(value)) return unchanged;
|
|
6774
|
+
const url = parseRedactableUrl(value);
|
|
6775
|
+
if (!url) return unchanged;
|
|
6776
|
+
const replacement = options.replacement ?? "[REDACTED]";
|
|
6777
|
+
const idPlaceholder = options.idPlaceholder ?? "[id]";
|
|
6778
|
+
const http = isHttpProtocol(url.protocol);
|
|
6779
|
+
let credentialRedacted = url.username.length > 0 || url.password.length > 0;
|
|
6780
|
+
let identifiersMasked = false;
|
|
6781
|
+
let pathname = url.pathname;
|
|
6782
|
+
if (http && options.maskPathIds === true) {
|
|
6783
|
+
pathname = url.pathname.split("/").map((segment) => {
|
|
6784
|
+
if (segment.length === 0 || !isIdentifierSegment(decodeParam(segment))) {
|
|
6785
|
+
return segment;
|
|
6786
|
+
}
|
|
6787
|
+
identifiersMasked = true;
|
|
6788
|
+
return idPlaceholder;
|
|
6789
|
+
}).join("/");
|
|
6790
|
+
}
|
|
6791
|
+
let search = "";
|
|
6792
|
+
if (url.search.length > 1) {
|
|
6793
|
+
const params = redactParams(url.search.slice(1), options, replacement);
|
|
6794
|
+
if (params.redacted) credentialRedacted = true;
|
|
6795
|
+
search = `?${params.value}`;
|
|
6796
|
+
} else if (url.search.length === 1) {
|
|
6797
|
+
search = "?";
|
|
6798
|
+
}
|
|
6799
|
+
let hash = url.hash;
|
|
6800
|
+
if (url.hash.includes("=")) {
|
|
6801
|
+
const params = redactParams(url.hash.slice(1), options, replacement);
|
|
6802
|
+
if (params.redacted) credentialRedacted = true;
|
|
6803
|
+
hash = `#${params.value}`;
|
|
6804
|
+
}
|
|
6805
|
+
if (!credentialRedacted && !identifiersMasked) return unchanged;
|
|
6806
|
+
return {
|
|
6807
|
+
value: `${url.protocol}//${url.host}${pathname}${search}${hash}`,
|
|
6808
|
+
credentialRedacted,
|
|
6809
|
+
identifiersMasked
|
|
6810
|
+
};
|
|
6811
|
+
}
|
|
6812
|
+
|
|
6665
6813
|
// packages/core/src/exporters/redact-export.ts
|
|
6666
6814
|
function isRecord11(value) {
|
|
6667
6815
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -6679,21 +6827,34 @@ function deepClone(value) {
|
|
|
6679
6827
|
}
|
|
6680
6828
|
return out;
|
|
6681
6829
|
}
|
|
6682
|
-
function boundAttributeValues(record, maxMetadataValueLength, maxPreviewLength, seen, depth) {
|
|
6830
|
+
function boundAttributeValues(record, sensitiveKeys, maxMetadataValueLength, maxPreviewLength, seen, depth) {
|
|
6683
6831
|
if (depth > 32) {
|
|
6684
6832
|
return { truncated: true, reason: "maxDepth" };
|
|
6685
6833
|
}
|
|
6686
6834
|
const out = {};
|
|
6687
6835
|
for (const [key, value] of Object.entries(record)) {
|
|
6688
|
-
out[key] = boundValue(
|
|
6836
|
+
out[key] = boundValue(
|
|
6837
|
+
value,
|
|
6838
|
+
key,
|
|
6839
|
+
sensitiveKeys,
|
|
6840
|
+
maxMetadataValueLength,
|
|
6841
|
+
maxPreviewLength,
|
|
6842
|
+
seen,
|
|
6843
|
+
depth
|
|
6844
|
+
);
|
|
6689
6845
|
}
|
|
6690
6846
|
return out;
|
|
6691
6847
|
}
|
|
6692
|
-
function boundValue(value, key, maxMetadataValueLength, maxPreviewLength, seen, depth) {
|
|
6848
|
+
function boundValue(value, key, sensitiveKeys, maxMetadataValueLength, maxPreviewLength, seen, depth) {
|
|
6693
6849
|
if (value === null || typeof value !== "object") {
|
|
6694
6850
|
if (typeof value === "string") {
|
|
6851
|
+
const rewritten = redactUrlString(value, {
|
|
6852
|
+
sensitiveKeys,
|
|
6853
|
+
isSensitiveValue: stringContainsHighConfidenceCredential,
|
|
6854
|
+
maskPathIds: true
|
|
6855
|
+
}).value;
|
|
6695
6856
|
return truncateStringForProfile(
|
|
6696
|
-
|
|
6857
|
+
stringContainsHighConfidenceCredential(rewritten) ? "[REDACTED]" : rewritten,
|
|
6697
6858
|
key,
|
|
6698
6859
|
maxMetadataValueLength,
|
|
6699
6860
|
maxPreviewLength
|
|
@@ -6708,6 +6869,7 @@ function boundValue(value, key, maxMetadataValueLength, maxPreviewLength, seen,
|
|
|
6708
6869
|
(item, index) => boundValue(
|
|
6709
6870
|
item,
|
|
6710
6871
|
String(index),
|
|
6872
|
+
sensitiveKeys,
|
|
6711
6873
|
maxMetadataValueLength,
|
|
6712
6874
|
maxPreviewLength,
|
|
6713
6875
|
seen,
|
|
@@ -6717,6 +6879,7 @@ function boundValue(value, key, maxMetadataValueLength, maxPreviewLength, seen,
|
|
|
6717
6879
|
}
|
|
6718
6880
|
return boundAttributeValues(
|
|
6719
6881
|
value,
|
|
6882
|
+
sensitiveKeys,
|
|
6720
6883
|
maxMetadataValueLength,
|
|
6721
6884
|
maxPreviewLength,
|
|
6722
6885
|
seen,
|
|
@@ -6731,6 +6894,7 @@ function redactEventAttributes(attrs2, redactor, maxMetadataValueLength, maxPrev
|
|
|
6731
6894
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
6732
6895
|
const bounded = boundAttributeValues(
|
|
6733
6896
|
redacted,
|
|
6897
|
+
[...DEFAULT_REDACT_KEYS, ...redactor.sensitiveKeys],
|
|
6734
6898
|
maxMetadataValueLength,
|
|
6735
6899
|
maxPreviewLength,
|
|
6736
6900
|
seen,
|
|
@@ -7401,14 +7565,132 @@ function isCredentialSensitiveKey2(key, sensitiveKeys) {
|
|
|
7401
7565
|
}
|
|
7402
7566
|
|
|
7403
7567
|
// 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
|
|
7568
|
+
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,})`;
|
|
7569
|
+
var KEY_VALUE_SECRET_PATTERN2 = new RegExp(
|
|
7406
7570
|
KEY_VALUE_SECRET_PATTERN_SOURCE,
|
|
7407
7571
|
"i"
|
|
7408
7572
|
);
|
|
7409
7573
|
function valueContainsKeyValueSecret(value) {
|
|
7410
|
-
|
|
7411
|
-
return
|
|
7574
|
+
KEY_VALUE_SECRET_PATTERN2.lastIndex = 0;
|
|
7575
|
+
return KEY_VALUE_SECRET_PATTERN2.test(value);
|
|
7576
|
+
}
|
|
7577
|
+
|
|
7578
|
+
// packages/redact/src/url-redaction.ts
|
|
7579
|
+
var HTTP_URL2 = /^https?:\/\/[^\s]+$/i;
|
|
7580
|
+
var CONNECTION_PROTOCOLS2 = /* @__PURE__ */ new Set([
|
|
7581
|
+
"postgres:",
|
|
7582
|
+
"postgresql:",
|
|
7583
|
+
"mysql:",
|
|
7584
|
+
"mariadb:",
|
|
7585
|
+
"mongodb:",
|
|
7586
|
+
"mongodb+srv:",
|
|
7587
|
+
"redis:",
|
|
7588
|
+
"rediss:",
|
|
7589
|
+
"amqp:",
|
|
7590
|
+
"amqps:"
|
|
7591
|
+
]);
|
|
7592
|
+
var CONNECTION_URI2 = /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/[^\s]+$/i;
|
|
7593
|
+
var UUID_SEGMENT2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
7594
|
+
var HEX_SEGMENT2 = /^[0-9a-f]{12,}$/i;
|
|
7595
|
+
var NUMERIC_SEGMENT2 = /^\d{5,}$/;
|
|
7596
|
+
var OPAQUE_SEGMENT2 = /^[A-Za-z0-9_-]{20,}$/;
|
|
7597
|
+
function looksLikeHttpUrl2(value) {
|
|
7598
|
+
return HTTP_URL2.test(value.trim());
|
|
7599
|
+
}
|
|
7600
|
+
function looksLikeConnectionUri2(value) {
|
|
7601
|
+
return CONNECTION_URI2.test(value.trim());
|
|
7602
|
+
}
|
|
7603
|
+
function looksLikeUrlForRedaction2(value) {
|
|
7604
|
+
return looksLikeHttpUrl2(value) || looksLikeConnectionUri2(value);
|
|
7605
|
+
}
|
|
7606
|
+
function parseRedactableUrl2(value) {
|
|
7607
|
+
try {
|
|
7608
|
+
const url = new URL(value.trim());
|
|
7609
|
+
if (url.protocol === "http:" || url.protocol === "https:") return url;
|
|
7610
|
+
if (CONNECTION_PROTOCOLS2.has(url.protocol)) return url;
|
|
7611
|
+
return void 0;
|
|
7612
|
+
} catch {
|
|
7613
|
+
return void 0;
|
|
7614
|
+
}
|
|
7615
|
+
}
|
|
7616
|
+
function isHttpProtocol2(protocol) {
|
|
7617
|
+
return protocol === "http:" || protocol === "https:";
|
|
7618
|
+
}
|
|
7619
|
+
function isIdentifierSegment2(segment) {
|
|
7620
|
+
if (UUID_SEGMENT2.test(segment)) return true;
|
|
7621
|
+
if (HEX_SEGMENT2.test(segment)) return true;
|
|
7622
|
+
if (NUMERIC_SEGMENT2.test(segment)) return true;
|
|
7623
|
+
return OPAQUE_SEGMENT2.test(segment) && /\d/.test(segment) && /[A-Za-z]/.test(segment);
|
|
7624
|
+
}
|
|
7625
|
+
function decodeParam2(value) {
|
|
7626
|
+
try {
|
|
7627
|
+
return decodeURIComponent(value.replace(/\+/g, " "));
|
|
7628
|
+
} catch {
|
|
7629
|
+
return value;
|
|
7630
|
+
}
|
|
7631
|
+
}
|
|
7632
|
+
function redactParams2(raw, options, replacement) {
|
|
7633
|
+
let redacted = false;
|
|
7634
|
+
const parts = raw.split("&").map((part) => {
|
|
7635
|
+
if (part.length === 0) return part;
|
|
7636
|
+
const separator = part.indexOf("=");
|
|
7637
|
+
if (separator < 0) return part;
|
|
7638
|
+
const rawKey = part.slice(0, separator);
|
|
7639
|
+
const rawValue = part.slice(separator + 1);
|
|
7640
|
+
const key = decodeParam2(rawKey);
|
|
7641
|
+
const value = decodeParam2(rawValue);
|
|
7642
|
+
if (isCredentialSensitiveKey2(key, options.sensitiveKeys) || options.isSensitiveValue(value)) {
|
|
7643
|
+
redacted = true;
|
|
7644
|
+
return `${rawKey}=${replacement}`;
|
|
7645
|
+
}
|
|
7646
|
+
return part;
|
|
7647
|
+
});
|
|
7648
|
+
return { value: parts.join("&"), redacted };
|
|
7649
|
+
}
|
|
7650
|
+
function redactUrlString2(value, options) {
|
|
7651
|
+
const unchanged = {
|
|
7652
|
+
value,
|
|
7653
|
+
credentialRedacted: false,
|
|
7654
|
+
identifiersMasked: false
|
|
7655
|
+
};
|
|
7656
|
+
if (!looksLikeUrlForRedaction2(value)) return unchanged;
|
|
7657
|
+
const url = parseRedactableUrl2(value);
|
|
7658
|
+
if (!url) return unchanged;
|
|
7659
|
+
const replacement = options.replacement ?? "[REDACTED]";
|
|
7660
|
+
const idPlaceholder = options.idPlaceholder ?? "[id]";
|
|
7661
|
+
const http = isHttpProtocol2(url.protocol);
|
|
7662
|
+
let credentialRedacted = url.username.length > 0 || url.password.length > 0;
|
|
7663
|
+
let identifiersMasked = false;
|
|
7664
|
+
let pathname = url.pathname;
|
|
7665
|
+
if (http && options.maskPathIds === true) {
|
|
7666
|
+
pathname = url.pathname.split("/").map((segment) => {
|
|
7667
|
+
if (segment.length === 0 || !isIdentifierSegment2(decodeParam2(segment))) {
|
|
7668
|
+
return segment;
|
|
7669
|
+
}
|
|
7670
|
+
identifiersMasked = true;
|
|
7671
|
+
return idPlaceholder;
|
|
7672
|
+
}).join("/");
|
|
7673
|
+
}
|
|
7674
|
+
let search = "";
|
|
7675
|
+
if (url.search.length > 1) {
|
|
7676
|
+
const params = redactParams2(url.search.slice(1), options, replacement);
|
|
7677
|
+
if (params.redacted) credentialRedacted = true;
|
|
7678
|
+
search = `?${params.value}`;
|
|
7679
|
+
} else if (url.search.length === 1) {
|
|
7680
|
+
search = "?";
|
|
7681
|
+
}
|
|
7682
|
+
let hash = url.hash;
|
|
7683
|
+
if (url.hash.includes("=")) {
|
|
7684
|
+
const params = redactParams2(url.hash.slice(1), options, replacement);
|
|
7685
|
+
if (params.redacted) credentialRedacted = true;
|
|
7686
|
+
hash = `#${params.value}`;
|
|
7687
|
+
}
|
|
7688
|
+
if (!credentialRedacted && !identifiersMasked) return unchanged;
|
|
7689
|
+
return {
|
|
7690
|
+
value: `${url.protocol}//${url.host}${pathname}${search}${hash}`,
|
|
7691
|
+
credentialRedacted,
|
|
7692
|
+
identifiersMasked
|
|
7693
|
+
};
|
|
7412
7694
|
}
|
|
7413
7695
|
|
|
7414
7696
|
// packages/redact/src/index.ts
|
|
@@ -7477,7 +7759,9 @@ function findCompiledKeyRule(key, rules) {
|
|
|
7477
7759
|
const exact = toKey2(key);
|
|
7478
7760
|
const direct = rules.find((candidate) => candidate.key === exact);
|
|
7479
7761
|
if (direct) return direct;
|
|
7480
|
-
return rules.find(
|
|
7762
|
+
return rules.find(
|
|
7763
|
+
(candidate) => isCredentialSensitiveKey2(key, [candidate.raw ?? candidate.key])
|
|
7764
|
+
);
|
|
7481
7765
|
}
|
|
7482
7766
|
function stableHash2(value) {
|
|
7483
7767
|
const hash = crypto.createHash("sha256").update(value, "utf8").digest("hex");
|
|
@@ -7676,7 +7960,7 @@ function compileRules2(rules, extraKeys) {
|
|
|
7676
7960
|
const out = /* @__PURE__ */ new Map();
|
|
7677
7961
|
const set = (rule) => {
|
|
7678
7962
|
const key = toKey2(rule.key);
|
|
7679
|
-
out.set(key, { ...rule, key });
|
|
7963
|
+
out.set(key, { ...rule, key, raw: rule.raw ?? rule.key });
|
|
7680
7964
|
};
|
|
7681
7965
|
for (const key of DEFAULT_REDACT_KEYS2) {
|
|
7682
7966
|
set({ key, strategy: "full" });
|
|
@@ -7755,6 +8039,7 @@ function createRedactionProfile(profile = "local") {
|
|
|
7755
8039
|
}
|
|
7756
8040
|
var Redactor2 = class {
|
|
7757
8041
|
#rules;
|
|
8042
|
+
#sensitiveKeys;
|
|
7758
8043
|
#detectors;
|
|
7759
8044
|
#profile;
|
|
7760
8045
|
#replacement;
|
|
@@ -7767,6 +8052,7 @@ var Redactor2 = class {
|
|
|
7767
8052
|
...resolved.extraKeys,
|
|
7768
8053
|
...options?.extraKeys ?? []
|
|
7769
8054
|
]);
|
|
8055
|
+
this.#sensitiveKeys = this.#rules.map((rule) => rule.raw ?? rule.key);
|
|
7770
8056
|
this.#detectors = [
|
|
7771
8057
|
...builtInDetectorsForProfile(this.#profile),
|
|
7772
8058
|
...options?.detectors ?? []
|
|
@@ -7800,6 +8086,14 @@ var Redactor2 = class {
|
|
|
7800
8086
|
#recordFinding(state, finding) {
|
|
7801
8087
|
if (this.#collectFindings) state.findings.push(finding);
|
|
7802
8088
|
}
|
|
8089
|
+
#detect(value, key, path16) {
|
|
8090
|
+
for (const detector of this.#detectors) {
|
|
8091
|
+
for (const detection of detector.detect({ path: path16, key, value })) {
|
|
8092
|
+
if ((detection.action ?? "replace") !== "keep") return { detector, detection };
|
|
8093
|
+
}
|
|
8094
|
+
}
|
|
8095
|
+
return void 0;
|
|
8096
|
+
}
|
|
7803
8097
|
#redactValue(value, key, path16, depth, state) {
|
|
7804
8098
|
if (depth > this.#maxDepth) {
|
|
7805
8099
|
this.#recordFinding(
|
|
@@ -7818,6 +8112,43 @@ var Redactor2 = class {
|
|
|
7818
8112
|
return applyRule(rule, value, this.#replacement);
|
|
7819
8113
|
}
|
|
7820
8114
|
}
|
|
8115
|
+
if (typeof value === "string" && looksLikeUrlForRedaction2(value)) {
|
|
8116
|
+
const url = redactUrlString2(value, {
|
|
8117
|
+
sensitiveKeys: this.#sensitiveKeys,
|
|
8118
|
+
isSensitiveValue: (candidate) => this.#detect(candidate, key, path16) !== void 0,
|
|
8119
|
+
replacement: this.#replacement,
|
|
8120
|
+
maskPathIds: this.#profile !== "local"
|
|
8121
|
+
});
|
|
8122
|
+
if (url.value !== value) {
|
|
8123
|
+
this.#recordFinding(
|
|
8124
|
+
state,
|
|
8125
|
+
makeFinding(
|
|
8126
|
+
path16,
|
|
8127
|
+
url.credentialRedacted ? "value.urlCredential" : "value.urlIdentifier",
|
|
8128
|
+
"replace",
|
|
8129
|
+
"value",
|
|
8130
|
+
url.credentialRedacted ? "error" : "warning"
|
|
8131
|
+
)
|
|
8132
|
+
);
|
|
8133
|
+
const residual = this.#detect(
|
|
8134
|
+
url.value.split(this.#replacement).join(""),
|
|
8135
|
+
key,
|
|
8136
|
+
path16
|
|
8137
|
+
);
|
|
8138
|
+
if (residual === void 0) return url.value;
|
|
8139
|
+
this.#recordFinding(
|
|
8140
|
+
state,
|
|
8141
|
+
makeFinding(
|
|
8142
|
+
path16,
|
|
8143
|
+
residual.detector.id,
|
|
8144
|
+
"replace",
|
|
8145
|
+
residual.detection.matchKind ?? residual.detector.matchKind ?? "custom",
|
|
8146
|
+
residual.detection.severity ?? residual.detector.severity ?? "warning"
|
|
8147
|
+
)
|
|
8148
|
+
);
|
|
8149
|
+
return this.#replacement;
|
|
8150
|
+
}
|
|
8151
|
+
}
|
|
7821
8152
|
for (const detector of this.#detectors) {
|
|
7822
8153
|
const detections = detector.detect({ path: path16, key, value });
|
|
7823
8154
|
for (const detection of detections) {
|
|
@@ -8750,5 +9081,5 @@ async function runReadOnlyMcpServer(options = {}) {
|
|
|
8750
9081
|
}
|
|
8751
9082
|
|
|
8752
9083
|
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-
|
|
9084
|
+
//# sourceMappingURL=chunk-FUNPQPC3.mjs.map
|
|
9085
|
+
//# sourceMappingURL=chunk-FUNPQPC3.mjs.map
|