@ttt-productions/monitoring-core 0.12.0 → 0.13.1
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/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/safe-event.d.ts +64 -0
- package/dist/safe-event.d.ts.map +1 -0
- package/dist/safe-event.js +59 -0
- package/dist/safe-event.js.map +1 -0
- package/dist/scrubber.d.ts +100 -0
- package/dist/scrubber.d.ts.map +1 -0
- package/dist/scrubber.js +158 -0
- package/dist/scrubber.js.map +1 -0
- package/dist/types.d.ts +2 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -2,4 +2,8 @@ export type { MonitoringInitOptions, MonitoringUser, MonitoringProvider, ScopeLi
|
|
|
2
2
|
export type { MonitoringAdapter } from "./adapter.js";
|
|
3
3
|
export { initMonitoring, getMonitoringAdapter, setMonitoringAdapter, resetMonitoringAdapter } from "./init.js";
|
|
4
4
|
export { captureException, captureMessage, setUser, setTag, withScope, addBreadcrumb } from "./api.js";
|
|
5
|
+
export type { ForbiddenPattern, RedactStringOptions, ScrubbableEvent, TelemetryScrubberOptions, BeforeSendHook, } from "./scrubber.js";
|
|
6
|
+
export { REDACTION_PLACEHOLDER, DEFAULT_FORBIDDEN_PATTERNS, redactString, redactEvent, createTelemetryScrubber, } from "./scrubber.js";
|
|
7
|
+
export type { DefaultSafeEventKey, SafeEvent, BuildSafeEventOptions, } from "./safe-event.js";
|
|
8
|
+
export { DEFAULT_SAFE_EVENT_KEYS, buildSafeEvent } from "./safe-event.js";
|
|
5
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,qBAAqB,EAAE,cAAc,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvG,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAC/G,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,qBAAqB,EAAE,cAAc,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvG,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAC/G,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEvG,YAAY,EACV,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,wBAAwB,EACxB,cAAc,GACf,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,YAAY,EACZ,WAAW,EACX,uBAAuB,GACxB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,mBAAmB,EACnB,SAAS,EACT,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { initMonitoring, getMonitoringAdapter, setMonitoringAdapter, resetMonitoringAdapter } from "./init.js";
|
|
2
2
|
export { captureException, captureMessage, setUser, setTag, withScope, addBreadcrumb } from "./api.js";
|
|
3
|
+
export { REDACTION_PLACEHOLDER, DEFAULT_FORBIDDEN_PATTERNS, redactString, redactEvent, createTelemetryScrubber, } from "./scrubber.js";
|
|
4
|
+
export { DEFAULT_SAFE_EVENT_KEYS, buildSafeEvent } from "./safe-event.js";
|
|
3
5
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAC/G,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAC/G,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AASvG,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,YAAY,EACZ,WAAW,EACX,uBAAuB,GACxB,MAAM,eAAe,CAAC;AAOvB,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safe-event allowlist helper — the safety-scoped telemetry layer.
|
|
3
|
+
*
|
|
4
|
+
* Safety-domain code (the app's `functions/src/safety/` + `functions/src/ncii/`)
|
|
5
|
+
* must emit telemetry that carries ONLY a fixed allowlist of structurally-safe
|
|
6
|
+
* fields — never content, evidence URLs, IPs, detector hashes, or credentials.
|
|
7
|
+
* This helper takes an arbitrary object and returns a NEW object containing only
|
|
8
|
+
* the allowlisted keys; every other key is dropped. `undefined`-valued
|
|
9
|
+
* allowlisted keys are also dropped so the emitted payload stays minimal.
|
|
10
|
+
*
|
|
11
|
+
* This is the complement to the global {@link ./scrubber} redactor: the scrubber
|
|
12
|
+
* is defense-in-depth against leaks from anywhere; the safe-event allowlist is
|
|
13
|
+
* the positive contract for code that deliberately touches safety data — nothing
|
|
14
|
+
* escapes unless it is on the list.
|
|
15
|
+
*
|
|
16
|
+
* GENERIC: the default allowlist (`caseId`, `phase`, `safeCode`, `traceId`) is
|
|
17
|
+
* the safe field set named in the CSAM design doc, but the key set is
|
|
18
|
+
* configurable so the app can extend/replace it without a package change.
|
|
19
|
+
*/
|
|
20
|
+
/** The safe field set every safety telemetry event may carry. */
|
|
21
|
+
export declare const DEFAULT_SAFE_EVENT_KEYS: readonly ["caseId", "phase", "safeCode", "traceId"];
|
|
22
|
+
export type DefaultSafeEventKey = (typeof DEFAULT_SAFE_EVENT_KEYS)[number];
|
|
23
|
+
/** The allowlisted-only shape produced from an arbitrary input. */
|
|
24
|
+
export type SafeEvent = {
|
|
25
|
+
caseId?: string;
|
|
26
|
+
phase?: string;
|
|
27
|
+
safeCode?: string;
|
|
28
|
+
traceId?: string;
|
|
29
|
+
[key: string]: unknown;
|
|
30
|
+
};
|
|
31
|
+
export type BuildSafeEventOptions = {
|
|
32
|
+
/**
|
|
33
|
+
* Allowed keys. Defaults to {@link DEFAULT_SAFE_EVENT_KEYS}. Supply a custom
|
|
34
|
+
* list (a superset or a different set) to extend the contract app-side without
|
|
35
|
+
* changing this package.
|
|
36
|
+
*/
|
|
37
|
+
allowedKeys?: readonly string[];
|
|
38
|
+
/**
|
|
39
|
+
* Keep allowlisted keys whose value is `undefined`. Defaults to false (drop
|
|
40
|
+
* them) so the payload never carries empty slots.
|
|
41
|
+
*/
|
|
42
|
+
keepUndefined?: boolean;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Project an arbitrary object down to its allowlisted keys. Any key not on the
|
|
46
|
+
* allowlist is dropped entirely — the returned object is a fresh copy, never the
|
|
47
|
+
* input. Non-object input yields an empty object.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* const evt = buildSafeEvent({
|
|
51
|
+
* caseId: 'case_123',
|
|
52
|
+
* phase: 'quarantine',
|
|
53
|
+
* safeCode: 'CS-DENY',
|
|
54
|
+
* traceId: 't-abc',
|
|
55
|
+
* // everything below is DROPPED:
|
|
56
|
+
* evidenceUrl: 'https://…/ncii-evidence/x',
|
|
57
|
+
* reporterIp: '203.0.113.7',
|
|
58
|
+
* detectorHash: 'ab12…',
|
|
59
|
+
* });
|
|
60
|
+
* // → { caseId, phase, safeCode, traceId }
|
|
61
|
+
* captureMessage(JSON.stringify(evt)); // or attach as safe context
|
|
62
|
+
*/
|
|
63
|
+
export declare function buildSafeEvent(input: unknown, options?: BuildSafeEventOptions): SafeEvent;
|
|
64
|
+
//# sourceMappingURL=safe-event.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safe-event.d.ts","sourceRoot":"","sources":["../src/safe-event.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,iEAAiE;AACjE,eAAO,MAAM,uBAAuB,qDAAsD,CAAC;AAE3F,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3E,mEAAmE;AACnE,MAAM,MAAM,SAAS,GAAG;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;OAIG;IACH,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,qBAA0B,GAClC,SAAS,CAkBX"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safe-event allowlist helper — the safety-scoped telemetry layer.
|
|
3
|
+
*
|
|
4
|
+
* Safety-domain code (the app's `functions/src/safety/` + `functions/src/ncii/`)
|
|
5
|
+
* must emit telemetry that carries ONLY a fixed allowlist of structurally-safe
|
|
6
|
+
* fields — never content, evidence URLs, IPs, detector hashes, or credentials.
|
|
7
|
+
* This helper takes an arbitrary object and returns a NEW object containing only
|
|
8
|
+
* the allowlisted keys; every other key is dropped. `undefined`-valued
|
|
9
|
+
* allowlisted keys are also dropped so the emitted payload stays minimal.
|
|
10
|
+
*
|
|
11
|
+
* This is the complement to the global {@link ./scrubber} redactor: the scrubber
|
|
12
|
+
* is defense-in-depth against leaks from anywhere; the safe-event allowlist is
|
|
13
|
+
* the positive contract for code that deliberately touches safety data — nothing
|
|
14
|
+
* escapes unless it is on the list.
|
|
15
|
+
*
|
|
16
|
+
* GENERIC: the default allowlist (`caseId`, `phase`, `safeCode`, `traceId`) is
|
|
17
|
+
* the safe field set named in the CSAM design doc, but the key set is
|
|
18
|
+
* configurable so the app can extend/replace it without a package change.
|
|
19
|
+
*/
|
|
20
|
+
/** The safe field set every safety telemetry event may carry. */
|
|
21
|
+
export const DEFAULT_SAFE_EVENT_KEYS = ["caseId", "phase", "safeCode", "traceId"];
|
|
22
|
+
/**
|
|
23
|
+
* Project an arbitrary object down to its allowlisted keys. Any key not on the
|
|
24
|
+
* allowlist is dropped entirely — the returned object is a fresh copy, never the
|
|
25
|
+
* input. Non-object input yields an empty object.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* const evt = buildSafeEvent({
|
|
29
|
+
* caseId: 'case_123',
|
|
30
|
+
* phase: 'quarantine',
|
|
31
|
+
* safeCode: 'CS-DENY',
|
|
32
|
+
* traceId: 't-abc',
|
|
33
|
+
* // everything below is DROPPED:
|
|
34
|
+
* evidenceUrl: 'https://…/ncii-evidence/x',
|
|
35
|
+
* reporterIp: '203.0.113.7',
|
|
36
|
+
* detectorHash: 'ab12…',
|
|
37
|
+
* });
|
|
38
|
+
* // → { caseId, phase, safeCode, traceId }
|
|
39
|
+
* captureMessage(JSON.stringify(evt)); // or attach as safe context
|
|
40
|
+
*/
|
|
41
|
+
export function buildSafeEvent(input, options = {}) {
|
|
42
|
+
const allowed = options.allowedKeys ?? DEFAULT_SAFE_EVENT_KEYS;
|
|
43
|
+
const keepUndefined = options.keepUndefined ?? false;
|
|
44
|
+
const out = {};
|
|
45
|
+
if (input === null || typeof input !== "object") {
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
const record = input;
|
|
49
|
+
for (const key of allowed) {
|
|
50
|
+
if (!Object.prototype.hasOwnProperty.call(record, key))
|
|
51
|
+
continue;
|
|
52
|
+
const value = record[key];
|
|
53
|
+
if (value === undefined && !keepUndefined)
|
|
54
|
+
continue;
|
|
55
|
+
out[key] = value;
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=safe-event.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safe-event.js","sourceRoot":"","sources":["../src/safe-event.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,iEAAiE;AACjE,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,CAAU,CAAC;AA2B3F;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAc,EACd,UAAiC,EAAE;IAEnC,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,IAAI,uBAAuB,CAAC;IAC/D,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,KAAK,CAAC;IACrD,MAAM,GAAG,GAAc,EAAE,CAAC;IAE1B,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,MAAM,MAAM,GAAG,KAAgC,CAAC;IAEhD,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC;YAAE,SAAS;QACjE,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,aAAa;YAAE,SAAS;QACpD,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACnB,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telemetry scrubber — generic Sentry-event redaction.
|
|
3
|
+
*
|
|
4
|
+
* A defense-in-depth `beforeSend`-style hook that walks an ENTIRE Sentry event
|
|
5
|
+
* (message, exception values + stacktrace frame vars, breadcrumbs, extra,
|
|
6
|
+
* contexts, tags, request data, user) and replaces any substring matching a
|
|
7
|
+
* forbidden pattern with a fixed placeholder.
|
|
8
|
+
*
|
|
9
|
+
* This package is GENERIC — it ships only obvious, domain-neutral defaults
|
|
10
|
+
* (full IPv4/IPv6 addresses, bearer/authorization tokens, generic credential
|
|
11
|
+
* assignments). Product-specific patterns (evidence-bucket URL prefixes,
|
|
12
|
+
* detector-hash shapes, NCMEC credential markers) are INJECTED by the consuming
|
|
13
|
+
* app via {@link createTelemetryScrubber}'s `patterns` option. No app-data-package
|
|
14
|
+
* import, no app-specific literals.
|
|
15
|
+
*/
|
|
16
|
+
/** The fixed replacement written over any matched forbidden substring. */
|
|
17
|
+
export declare const REDACTION_PLACEHOLDER = "[REDACTED]";
|
|
18
|
+
/**
|
|
19
|
+
* A forbidden pattern. Either a `RegExp` (matched globally against every string
|
|
20
|
+
* in the event) or a literal `string` (every occurrence replaced). Strings are
|
|
21
|
+
* treated as literals, not regex source, so callers do not have to escape them.
|
|
22
|
+
*/
|
|
23
|
+
export type ForbiddenPattern = RegExp | string;
|
|
24
|
+
export type RedactStringOptions = {
|
|
25
|
+
/** Patterns to strip. Defaults to {@link DEFAULT_FORBIDDEN_PATTERNS}. */
|
|
26
|
+
patterns?: ForbiddenPattern[];
|
|
27
|
+
/** Replacement text. Defaults to {@link REDACTION_PLACEHOLDER}. */
|
|
28
|
+
placeholder?: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Generic, domain-neutral built-in patterns. These are intentionally
|
|
32
|
+
* conservative (specific → low collateral on ordinary errors) but catch the
|
|
33
|
+
* obvious secrets that must never reach telemetry regardless of app.
|
|
34
|
+
*/
|
|
35
|
+
export declare const DEFAULT_FORBIDDEN_PATTERNS: RegExp[];
|
|
36
|
+
/**
|
|
37
|
+
* Redact every forbidden-pattern hit inside a single string. Pure and safe on
|
|
38
|
+
* any input. Empty when nothing matches → returns the original reference.
|
|
39
|
+
*/
|
|
40
|
+
export declare function redactString(value: string, options?: RedactStringOptions): string;
|
|
41
|
+
/**
|
|
42
|
+
* Minimal structural shape of a Sentry event we walk. Deliberately loose — we
|
|
43
|
+
* do not depend on `@sentry/*` types (this package's Sentry deps are optional
|
|
44
|
+
* peers, and the scrubber is provider-agnostic). Unknown fields are left alone
|
|
45
|
+
* except that we deep-redact the free-form containers below.
|
|
46
|
+
*/
|
|
47
|
+
export type ScrubbableEvent = {
|
|
48
|
+
message?: unknown;
|
|
49
|
+
exception?: {
|
|
50
|
+
values?: Array<Record<string, unknown>>;
|
|
51
|
+
} | unknown;
|
|
52
|
+
breadcrumbs?: unknown;
|
|
53
|
+
extra?: unknown;
|
|
54
|
+
contexts?: unknown;
|
|
55
|
+
tags?: unknown;
|
|
56
|
+
request?: unknown;
|
|
57
|
+
user?: unknown;
|
|
58
|
+
[key: string]: unknown;
|
|
59
|
+
};
|
|
60
|
+
export type TelemetryScrubberOptions = {
|
|
61
|
+
/**
|
|
62
|
+
* App-injected forbidden patterns (evidence-bucket URL prefixes, detector-hash
|
|
63
|
+
* shapes, NCMEC credential markers, …). Merged AFTER the generic defaults
|
|
64
|
+
* unless {@link includeDefaults} is false.
|
|
65
|
+
*/
|
|
66
|
+
patterns?: ForbiddenPattern[];
|
|
67
|
+
/** Include {@link DEFAULT_FORBIDDEN_PATTERNS}. Defaults to true. */
|
|
68
|
+
includeDefaults?: boolean;
|
|
69
|
+
/** Replacement text. Defaults to {@link REDACTION_PLACEHOLDER}. */
|
|
70
|
+
placeholder?: string;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Redact a whole Sentry event in place and return it. Exported so the backend
|
|
74
|
+
* `withScope` / manual-capture path can benefit even where a `beforeSend`
|
|
75
|
+
* pipeline is not wired.
|
|
76
|
+
*/
|
|
77
|
+
export declare function redactEvent<T extends ScrubbableEvent>(event: T, options?: TelemetryScrubberOptions): T;
|
|
78
|
+
/**
|
|
79
|
+
* A Sentry `beforeSend`-style hook: `(event, hint?) => event | null`. Drop-in
|
|
80
|
+
* for `Sentry.init({ beforeSend })` in both the browser and Node SDKs.
|
|
81
|
+
*/
|
|
82
|
+
export type BeforeSendHook = (event: ScrubbableEvent, hint?: unknown) => ScrubbableEvent | null;
|
|
83
|
+
/**
|
|
84
|
+
* Build a `beforeSend` hook that scrubs every outgoing event. The app supplies
|
|
85
|
+
* its product-specific `patterns`; generic defaults are included unless disabled.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* Sentry.init({
|
|
89
|
+
* dsn,
|
|
90
|
+
* beforeSend: createTelemetryScrubber({
|
|
91
|
+
* patterns: [
|
|
92
|
+
* 'https://storage.googleapis.com/example-ncii-evidence/',
|
|
93
|
+
* /\bncmec-[a-z0-9]{16,}\b/gi,
|
|
94
|
+
* /\b[a-f0-9]{64}\b/g, // detector hash shape
|
|
95
|
+
* ],
|
|
96
|
+
* }),
|
|
97
|
+
* });
|
|
98
|
+
*/
|
|
99
|
+
export declare function createTelemetryScrubber(options?: TelemetryScrubberOptions): BeforeSendHook;
|
|
100
|
+
//# sourceMappingURL=scrubber.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrubber.d.ts","sourceRoot":"","sources":["../src/scrubber.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,0EAA0E;AAC1E,eAAO,MAAM,qBAAqB,eAAe,CAAC;AAElD;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,CAAC;AAE/C,MAAM,MAAM,mBAAmB,GAAG;IAChC,yEAAyE;IACzE,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC9B,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,EAAE,MAAM,EAY9C,CAAC;AAwBF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,MAAM,CASrF;AAwCD;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC;IAClE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC9B,oEAAoE;IACpE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,eAAe,EACnD,KAAK,EAAE,CAAC,EACR,OAAO,GAAE,wBAA6B,GACrC,CAAC,CAmCH;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,eAAe,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,eAAe,GAAG,IAAI,CAAC;AAEhG;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,GAAE,wBAA6B,GAAG,cAAc,CAK9F"}
|
package/dist/scrubber.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telemetry scrubber — generic Sentry-event redaction.
|
|
3
|
+
*
|
|
4
|
+
* A defense-in-depth `beforeSend`-style hook that walks an ENTIRE Sentry event
|
|
5
|
+
* (message, exception values + stacktrace frame vars, breadcrumbs, extra,
|
|
6
|
+
* contexts, tags, request data, user) and replaces any substring matching a
|
|
7
|
+
* forbidden pattern with a fixed placeholder.
|
|
8
|
+
*
|
|
9
|
+
* This package is GENERIC — it ships only obvious, domain-neutral defaults
|
|
10
|
+
* (full IPv4/IPv6 addresses, bearer/authorization tokens, generic credential
|
|
11
|
+
* assignments). Product-specific patterns (evidence-bucket URL prefixes,
|
|
12
|
+
* detector-hash shapes, NCMEC credential markers) are INJECTED by the consuming
|
|
13
|
+
* app via {@link createTelemetryScrubber}'s `patterns` option. No app-data-package
|
|
14
|
+
* import, no app-specific literals.
|
|
15
|
+
*/
|
|
16
|
+
/** The fixed replacement written over any matched forbidden substring. */
|
|
17
|
+
export const REDACTION_PLACEHOLDER = "[REDACTED]";
|
|
18
|
+
/**
|
|
19
|
+
* Generic, domain-neutral built-in patterns. These are intentionally
|
|
20
|
+
* conservative (specific → low collateral on ordinary errors) but catch the
|
|
21
|
+
* obvious secrets that must never reach telemetry regardless of app.
|
|
22
|
+
*/
|
|
23
|
+
export const DEFAULT_FORBIDDEN_PATTERNS = [
|
|
24
|
+
// Full IPv4 address (four dotted octets, each 0–255).
|
|
25
|
+
/\b(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\b/g,
|
|
26
|
+
// Full (uncompressed) IPv6 address — eight hextet groups.
|
|
27
|
+
/\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b/g,
|
|
28
|
+
// Compressed IPv6 with a "::" run (e.g. 2001:db8::1, ::1, fe80::abcd).
|
|
29
|
+
/\b(?:[0-9a-fA-F]{1,4}:){1,7}:(?:[0-9a-fA-F]{1,4}:?){0,6}(?:[0-9a-fA-F]{1,4})?\b|::(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}\b/g,
|
|
30
|
+
// Authorization / bearer token: "Bearer xyz", "Authorization: Basic xyz".
|
|
31
|
+
/\b(?:Bearer|Basic)\s+[A-Za-z0-9._~+/-]{8,}={0,2}/gi,
|
|
32
|
+
// Generic credential assignment: password=..., api_key: "...", secret=...,
|
|
33
|
+
// token=..., apiKey=..., access_token=... (value up to whitespace/quote).
|
|
34
|
+
/\b(?:password|passwd|pwd|secret|api[_-]?key|apikey|access[_-]?token|refresh[_-]?token|token|client[_-]?secret|authorization)\b\s*[:=]\s*["']?[^\s"',}{]{4,}/gi,
|
|
35
|
+
];
|
|
36
|
+
function escapeRegExp(input) {
|
|
37
|
+
return input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
38
|
+
}
|
|
39
|
+
function compilePatterns(patterns) {
|
|
40
|
+
return patterns.map((p) => {
|
|
41
|
+
if (typeof p === "string") {
|
|
42
|
+
return {
|
|
43
|
+
regex: new RegExp(escapeRegExp(p), "g"),
|
|
44
|
+
isLiteral: true,
|
|
45
|
+
literal: p,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
// Ensure the flag set is global so `String.replace` strips every hit; clone
|
|
49
|
+
// so we never mutate a caller-owned RegExp's lastIndex across calls.
|
|
50
|
+
const flags = p.flags.includes("g") ? p.flags : p.flags + "g";
|
|
51
|
+
return { regex: new RegExp(p.source, flags), isLiteral: false };
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Redact every forbidden-pattern hit inside a single string. Pure and safe on
|
|
56
|
+
* any input. Empty when nothing matches → returns the original reference.
|
|
57
|
+
*/
|
|
58
|
+
export function redactString(value, options = {}) {
|
|
59
|
+
const placeholder = options.placeholder ?? REDACTION_PLACEHOLDER;
|
|
60
|
+
const compiled = compilePatterns(options.patterns ?? DEFAULT_FORBIDDEN_PATTERNS);
|
|
61
|
+
let out = value;
|
|
62
|
+
for (const { regex } of compiled) {
|
|
63
|
+
regex.lastIndex = 0;
|
|
64
|
+
out = out.replace(regex, placeholder);
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Recursively redact every string reachable inside an arbitrary value (objects,
|
|
70
|
+
* arrays, nested combinations). Non-string primitives pass through untouched.
|
|
71
|
+
* Object keys are NOT rewritten (a forbidden value hiding in a key is
|
|
72
|
+
* pathological and rewriting keys would corrupt the event shape); only values
|
|
73
|
+
* are scrubbed. Guards against cycles.
|
|
74
|
+
*/
|
|
75
|
+
function deepRedact(value, options, seen) {
|
|
76
|
+
if (typeof value === "string") {
|
|
77
|
+
return redactString(value, options);
|
|
78
|
+
}
|
|
79
|
+
if (value === null || typeof value !== "object") {
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
82
|
+
if (seen.has(value)) {
|
|
83
|
+
return value;
|
|
84
|
+
}
|
|
85
|
+
seen.add(value);
|
|
86
|
+
if (Array.isArray(value)) {
|
|
87
|
+
for (let i = 0; i < value.length; i++) {
|
|
88
|
+
value[i] = deepRedact(value[i], options, seen);
|
|
89
|
+
}
|
|
90
|
+
return value;
|
|
91
|
+
}
|
|
92
|
+
const record = value;
|
|
93
|
+
for (const key of Object.keys(record)) {
|
|
94
|
+
record[key] = deepRedact(record[key], options, seen);
|
|
95
|
+
}
|
|
96
|
+
return record;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Redact a whole Sentry event in place and return it. Exported so the backend
|
|
100
|
+
* `withScope` / manual-capture path can benefit even where a `beforeSend`
|
|
101
|
+
* pipeline is not wired.
|
|
102
|
+
*/
|
|
103
|
+
export function redactEvent(event, options = {}) {
|
|
104
|
+
if (event === null || typeof event !== "object")
|
|
105
|
+
return event;
|
|
106
|
+
const includeDefaults = options.includeDefaults ?? true;
|
|
107
|
+
const patterns = [
|
|
108
|
+
...(includeDefaults ? DEFAULT_FORBIDDEN_PATTERNS : []),
|
|
109
|
+
...(options.patterns ?? []),
|
|
110
|
+
];
|
|
111
|
+
const deepOptions = {
|
|
112
|
+
patterns,
|
|
113
|
+
placeholder: options.placeholder ?? REDACTION_PLACEHOLDER,
|
|
114
|
+
};
|
|
115
|
+
const seen = new WeakSet();
|
|
116
|
+
// Top-level message (string or {message,params} structured form).
|
|
117
|
+
if (event.message !== undefined) {
|
|
118
|
+
event.message = deepRedact(event.message, deepOptions, seen);
|
|
119
|
+
}
|
|
120
|
+
// Exception values: type/value strings plus stacktrace frame vars/filenames.
|
|
121
|
+
const exception = event.exception;
|
|
122
|
+
if (exception && Array.isArray(exception.values)) {
|
|
123
|
+
for (const val of exception.values) {
|
|
124
|
+
deepRedact(val, deepOptions, seen);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Free-form containers — walked wholesale.
|
|
128
|
+
for (const container of ["breadcrumbs", "extra", "contexts", "tags", "request", "user"]) {
|
|
129
|
+
if (event[container] !== undefined) {
|
|
130
|
+
event[container] = deepRedact(event[container], deepOptions, seen);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return event;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Build a `beforeSend` hook that scrubs every outgoing event. The app supplies
|
|
137
|
+
* its product-specific `patterns`; generic defaults are included unless disabled.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* Sentry.init({
|
|
141
|
+
* dsn,
|
|
142
|
+
* beforeSend: createTelemetryScrubber({
|
|
143
|
+
* patterns: [
|
|
144
|
+
* 'https://storage.googleapis.com/example-ncii-evidence/',
|
|
145
|
+
* /\bncmec-[a-z0-9]{16,}\b/gi,
|
|
146
|
+
* /\b[a-f0-9]{64}\b/g, // detector hash shape
|
|
147
|
+
* ],
|
|
148
|
+
* }),
|
|
149
|
+
* });
|
|
150
|
+
*/
|
|
151
|
+
export function createTelemetryScrubber(options = {}) {
|
|
152
|
+
return (event, _hint) => {
|
|
153
|
+
if (event === null || typeof event !== "object")
|
|
154
|
+
return event;
|
|
155
|
+
return redactEvent(event, options);
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=scrubber.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrubber.js","sourceRoot":"","sources":["../src/scrubber.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -9,8 +9,8 @@ export type MonitoringInitOptions = {
|
|
|
9
9
|
* Omit to use the provider default. */
|
|
10
10
|
tracesSampleRate?: number;
|
|
11
11
|
/** Provider integrations passed through to the SDK init — e.g. `[]` to disable the
|
|
12
|
-
* default auto-integrations and keep init lightweight (the
|
|
13
|
-
* bootstrap does this). Typed loosely: it is a provider-specific pass-through. */
|
|
12
|
+
* default auto-integrations and keep init lightweight (the consuming app's Cloud
|
|
13
|
+
* Functions bootstrap does this). Typed loosely: it is a provider-specific pass-through. */
|
|
14
14
|
integrations?: unknown[];
|
|
15
15
|
};
|
|
16
16
|
export type MonitoringUser = {
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,aAAa,GAAG,MAAM,CAAC;AAEnE,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;4CACwC;IACxC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,aAAa,GAAG,MAAM,CAAC;AAEnE,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;4CACwC;IACxC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;iGAE6F;IAC7F,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,OAAO,EAAE,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/C,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACrE,CAAC"}
|