@socprime/logtotal-sanitizer 0.0.1-beta.0
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/CHANGELOG.md +23 -0
- package/LICENSE +201 -0
- package/README.md +199 -0
- package/chunk-TAMK67JP.js +2205 -0
- package/chunk-TAMK67JP.js.map +1 -0
- package/chunk-U6SJR7S7.js +933 -0
- package/chunk-U6SJR7S7.js.map +1 -0
- package/chunk-VW3VVW6L.cjs +2218 -0
- package/chunk-VW3VVW6L.cjs.map +1 -0
- package/chunk-WISLDJT3.cjs +944 -0
- package/chunk-WISLDJT3.cjs.map +1 -0
- package/cli.js +3431 -0
- package/cli.js.map +1 -0
- package/index-CutSH_48.d.cts +409 -0
- package/index-CutSH_48.d.ts +409 -0
- package/index.cjs +93 -0
- package/index.cjs.map +1 -0
- package/index.d.cts +157 -0
- package/index.d.ts +157 -0
- package/index.js +4 -0
- package/index.js.map +1 -0
- package/node.cjs +147 -0
- package/node.cjs.map +1 -0
- package/node.d.cts +63 -0
- package/node.d.ts +63 -0
- package/node.js +58 -0
- package/node.js.map +1 -0
- package/package.json +75 -0
- package/rules.cjs +24 -0
- package/rules.cjs.map +1 -0
- package/rules.d.cts +1 -0
- package/rules.d.ts +1 -0
- package/rules.js +3 -0
- package/rules.js.map +1 -0
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identifiers of the rules shipped with this package.
|
|
3
|
+
*/
|
|
4
|
+
type BuiltinRuleId = 'secrets' | 'sessionCookies' | 'paymentInfo' | 'govIds' | 'healthInfo' | 'phoneNumbers' | 'ips' | 'hosts' | 'users' | 'geoLocation' | 'paths';
|
|
5
|
+
/**
|
|
6
|
+
* A rule identifier. Built-in identifiers are suggested by editors; any other string is accepted
|
|
7
|
+
* so custom rules can use their own namespace, for example `acme:ticketId`.
|
|
8
|
+
*
|
|
9
|
+
* A rule identifier must be a valid ASCII identifier because it is used as a named capture group
|
|
10
|
+
* in the combined pattern. Namespacing with `:` is not allowed — use `_` instead.
|
|
11
|
+
*/
|
|
12
|
+
type RuleId = BuiltinRuleId | (string & {});
|
|
13
|
+
/**
|
|
14
|
+
* How a matched value is replaced.
|
|
15
|
+
*
|
|
16
|
+
* - `pseudo` replaces the value with a token carrying the rule's own prefix, for example
|
|
17
|
+
* `<IP:4f2a1c9d5b3e7a08>`. The same input always maps to the same token for a given key, so
|
|
18
|
+
* occurrences stay correlatable across a run and across files sanitized with the same key.
|
|
19
|
+
* - `mask` produces the same stable token but always uses the neutral `R` prefix, so the kind of
|
|
20
|
+
* secret that was found is not disclosed by the output.
|
|
21
|
+
*/
|
|
22
|
+
type RedactionMode = 'pseudo' | 'mask';
|
|
23
|
+
/**
|
|
24
|
+
* How a key string is turned into bytes. Keys produced by {@link generateKey} are `hex`;
|
|
25
|
+
* user-supplied passphrases are usually `utf8`.
|
|
26
|
+
*/
|
|
27
|
+
type KeyEncoding = 'hex' | 'utf8';
|
|
28
|
+
/**
|
|
29
|
+
* A detection rule: a set of patterns plus the policy for replacing what they match.
|
|
30
|
+
*
|
|
31
|
+
* Create rules with {@link defineRule} rather than as plain objects — it validates the shape and
|
|
32
|
+
* fails early with an actionable message.
|
|
33
|
+
*/
|
|
34
|
+
interface SanitizeRule {
|
|
35
|
+
/**
|
|
36
|
+
* Unique identifier, also used as the named capture group in the combined pattern.
|
|
37
|
+
* Must match `/^[A-Za-z_$][A-Za-z0-9_$]*$/`.
|
|
38
|
+
*/
|
|
39
|
+
id: RuleId;
|
|
40
|
+
/** Short human-readable name, suitable for a checkbox label or a report heading. */
|
|
41
|
+
label: string;
|
|
42
|
+
/** One sentence describing what the rule detects. */
|
|
43
|
+
description: string;
|
|
44
|
+
/** Replacement policy for values this rule matches. */
|
|
45
|
+
mode: RedactionMode;
|
|
46
|
+
/**
|
|
47
|
+
* Token prefix used in `pseudo` mode, for example `IP` produces `<IP:…>`. Must match
|
|
48
|
+
* `/^[A-Z][A-Z0-9]*$/`. Ignored in `mask` mode. Defaults to the uppercased identifier.
|
|
49
|
+
*/
|
|
50
|
+
token?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Regular expression source fragments, combined into one alternation. Each fragment is compiled
|
|
53
|
+
* with the `u` flag and must not contain capture groups other than non-capturing `(?:…)` —
|
|
54
|
+
* numbered groups shift the combined pattern's group indices.
|
|
55
|
+
*/
|
|
56
|
+
patterns: string[];
|
|
57
|
+
/**
|
|
58
|
+
* Additional, deliberately broader fragments applied only when `aggressive` is enabled. They
|
|
59
|
+
* belong to the same rule, so counts and tokens still use this rule's identifier.
|
|
60
|
+
*/
|
|
61
|
+
aggressivePatterns?: string[];
|
|
62
|
+
/**
|
|
63
|
+
* Final decision for a candidate the patterns matched. Return `false` to leave the value
|
|
64
|
+
* untouched — used to filter out well-known non-sensitive values and to apply checksums such as
|
|
65
|
+
* Luhn or IBAN mod-97. Must be side-effect free and fast: it runs once per candidate match.
|
|
66
|
+
*/
|
|
67
|
+
validate?: (match: string) => boolean;
|
|
68
|
+
/**
|
|
69
|
+
* JSON field names whose value is redacted by name alone, regardless of its shape, when the
|
|
70
|
+
* input line is a JSON object. Matching ignores case, hyphens and underscores, so `x-api-key`,
|
|
71
|
+
* `x_api_key` and `xApiKey` are the same key.
|
|
72
|
+
*/
|
|
73
|
+
jsonKeys?: string[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Public description of a rule taking part in a run, without its patterns.
|
|
77
|
+
*/
|
|
78
|
+
interface RuleInfo {
|
|
79
|
+
id: RuleId;
|
|
80
|
+
label: string;
|
|
81
|
+
description: string;
|
|
82
|
+
mode: RedactionMode;
|
|
83
|
+
}
|
|
84
|
+
/** Match counts per rule identifier. */
|
|
85
|
+
type RuleCounts = Partial<Record<RuleId, number>>;
|
|
86
|
+
/**
|
|
87
|
+
* A slice of a before/after preview. `changed` marks the parts a rule replaced.
|
|
88
|
+
*/
|
|
89
|
+
interface SanitizeSegment {
|
|
90
|
+
text: string;
|
|
91
|
+
changed: boolean;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* One distinct value that was replaced, with the number of times it occurred.
|
|
95
|
+
*/
|
|
96
|
+
interface SanitizeReplacement {
|
|
97
|
+
ruleId: RuleId;
|
|
98
|
+
original: string;
|
|
99
|
+
replacement: string;
|
|
100
|
+
count: number;
|
|
101
|
+
/** Text immediately before the first occurrence. Present only when `report.contextChars > 0`. */
|
|
102
|
+
contextBefore?: string;
|
|
103
|
+
/** Text immediately after the first occurrence. Present only when `report.contextChars > 0`. */
|
|
104
|
+
contextAfter?: string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Summary of a sanitization run.
|
|
108
|
+
*/
|
|
109
|
+
interface SanitizeReport {
|
|
110
|
+
/** Number of replacements per rule, for the whole input. */
|
|
111
|
+
counts: RuleCounts;
|
|
112
|
+
/** Sum of every entry in {@link SanitizeReport.counts}. */
|
|
113
|
+
totalMatches: number;
|
|
114
|
+
/** Number of lines processed. */
|
|
115
|
+
lineCount: number;
|
|
116
|
+
/**
|
|
117
|
+
* Distinct replaced values for the whole input, deduplicated by rule and original value.
|
|
118
|
+
* Empty when `report.replacements` is disabled.
|
|
119
|
+
*
|
|
120
|
+
* These entries contain the original, unredacted values. Treat the report as sensitive: it is
|
|
121
|
+
* meant for local review, not for shipping alongside the sanitized output.
|
|
122
|
+
*/
|
|
123
|
+
replacements: SanitizeReplacement[];
|
|
124
|
+
/**
|
|
125
|
+
* Before/after segments for the first `report.previewBytes` of output, so a UI can render a
|
|
126
|
+
* diff without holding the whole input in memory. Empty when `report.previewBytes` is `0`.
|
|
127
|
+
*/
|
|
128
|
+
preview: {
|
|
129
|
+
before: SanitizeSegment[];
|
|
130
|
+
after: SanitizeSegment[];
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Values and patterns that must be redacted regardless of which rules are active.
|
|
135
|
+
*
|
|
136
|
+
* Entries here take priority over every rule, so a value that would otherwise be missed is still
|
|
137
|
+
* replaced. Values allowlisted through {@link NeverRedactOptions} still win.
|
|
138
|
+
*/
|
|
139
|
+
interface AlwaysRedactOptions {
|
|
140
|
+
/** Exact substrings to redact. Matched literally; longer values win on overlap. */
|
|
141
|
+
values?: readonly string[];
|
|
142
|
+
/**
|
|
143
|
+
* Patterns to redact. A string is treated as a regular expression source, not as a literal.
|
|
144
|
+
* Flags on a `RegExp` are ignored; the combined pattern is always compiled with `gu`.
|
|
145
|
+
*/
|
|
146
|
+
patterns?: readonly (string | RegExp)[];
|
|
147
|
+
/**
|
|
148
|
+
* Rule identifier reported for these matches.
|
|
149
|
+
* @default 'custom'
|
|
150
|
+
*/
|
|
151
|
+
ruleId?: RuleId;
|
|
152
|
+
/**
|
|
153
|
+
* Replacement policy for these matches.
|
|
154
|
+
* @default 'pseudo'
|
|
155
|
+
*/
|
|
156
|
+
mode?: RedactionMode;
|
|
157
|
+
/**
|
|
158
|
+
* Token prefix for these matches in `pseudo` mode.
|
|
159
|
+
* @default 'CUSTOM'
|
|
160
|
+
*/
|
|
161
|
+
token?: string;
|
|
162
|
+
}
|
|
163
|
+
/** A per-rule allowlist entry. */
|
|
164
|
+
interface NeverRedactRuleEntry {
|
|
165
|
+
ruleId: RuleId;
|
|
166
|
+
values: readonly string[];
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Values that must never be redacted, even when a rule matches them.
|
|
170
|
+
*
|
|
171
|
+
* Checked against the matched value itself, not the surrounding line, and applied before any
|
|
172
|
+
* replacement is built.
|
|
173
|
+
*/
|
|
174
|
+
interface NeverRedactOptions {
|
|
175
|
+
/** Exact values to keep, whichever rule matched them. */
|
|
176
|
+
values?: readonly string[];
|
|
177
|
+
/**
|
|
178
|
+
* Patterns that keep a matched value when they match it in full. A string is treated as a
|
|
179
|
+
* regular expression source. Flags are ignored; matching is always anchored and Unicode-aware.
|
|
180
|
+
*/
|
|
181
|
+
patterns?: readonly (string | RegExp)[];
|
|
182
|
+
/** Exact values to keep only for a specific rule. */
|
|
183
|
+
byRule?: readonly NeverRedactRuleEntry[];
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Report detail level. Tightening these bounds lowers memory use on large inputs.
|
|
187
|
+
*/
|
|
188
|
+
interface ReportOptions {
|
|
189
|
+
/**
|
|
190
|
+
* Size of the before/after preview window, in output characters. `0` disables the preview.
|
|
191
|
+
* @default 262144
|
|
192
|
+
*/
|
|
193
|
+
previewBytes?: number;
|
|
194
|
+
/**
|
|
195
|
+
* Whether to collect the list of distinct replaced values. Disable it when the report is only
|
|
196
|
+
* used for counts — the list grows with the number of distinct sensitive values in the input.
|
|
197
|
+
* @default true
|
|
198
|
+
*/
|
|
199
|
+
replacements?: boolean;
|
|
200
|
+
/**
|
|
201
|
+
* How many characters of surrounding text to record next to each distinct replacement, to help
|
|
202
|
+
* a reviewer judge a match. `0` omits {@link SanitizeReplacement.contextBefore} and
|
|
203
|
+
* {@link SanitizeReplacement.contextAfter} entirely.
|
|
204
|
+
* @default 0
|
|
205
|
+
*/
|
|
206
|
+
contextChars?: number;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Line splitting bounds, relevant for inputs that contain very long lines.
|
|
210
|
+
*/
|
|
211
|
+
interface LineOptions {
|
|
212
|
+
/**
|
|
213
|
+
* A run of characters longer than this without a line terminator is processed in bounded
|
|
214
|
+
* segments instead of being buffered whole.
|
|
215
|
+
* @default 1048576
|
|
216
|
+
*/
|
|
217
|
+
maxLineChars?: number;
|
|
218
|
+
/**
|
|
219
|
+
* Characters carried from one bounded segment into the next, so a value straddling the cut is
|
|
220
|
+
* still matched. Must be smaller than `maxLineChars`.
|
|
221
|
+
* @default 1024
|
|
222
|
+
*/
|
|
223
|
+
overlapChars?: number;
|
|
224
|
+
}
|
|
225
|
+
/** A rule to run: either a built-in identifier or a rule object. */
|
|
226
|
+
type RuleSelector = RuleId | SanitizeRule;
|
|
227
|
+
/**
|
|
228
|
+
* Configuration for {@link createSanitizer}.
|
|
229
|
+
*/
|
|
230
|
+
interface SanitizerOptions {
|
|
231
|
+
/**
|
|
232
|
+
* Rules to run, in priority order: when two rules can match at the same position, the one
|
|
233
|
+
* listed first wins. Identifiers are resolved against the built-in rules. Passing a rule object
|
|
234
|
+
* whose identifier is already present replaces that rule while keeping its position.
|
|
235
|
+
* @default every built-in rule, in the order documented in the README
|
|
236
|
+
*/
|
|
237
|
+
rules?: readonly RuleSelector[];
|
|
238
|
+
/** Rules appended after {@link SanitizerOptions.rules}, so they run at the lowest priority. */
|
|
239
|
+
extraRules?: readonly SanitizeRule[];
|
|
240
|
+
/**
|
|
241
|
+
* Whether to also apply each rule's broader `aggressivePatterns`. Catches more, at the cost of
|
|
242
|
+
* more false positives.
|
|
243
|
+
* @default false
|
|
244
|
+
*/
|
|
245
|
+
aggressive?: boolean;
|
|
246
|
+
/**
|
|
247
|
+
* Key used to derive replacement tokens. Reuse it to keep tokens comparable across files or
|
|
248
|
+
* runs; change it to make them uncorrelatable.
|
|
249
|
+
* @default a fresh random 32-byte key from {@link generateKey}
|
|
250
|
+
*/
|
|
251
|
+
key?: string;
|
|
252
|
+
/**
|
|
253
|
+
* How {@link SanitizerOptions.key} is decoded.
|
|
254
|
+
* @default 'hex'
|
|
255
|
+
*/
|
|
256
|
+
keyEncoding?: KeyEncoding;
|
|
257
|
+
/** Values and patterns to redact regardless of the active rules. */
|
|
258
|
+
alwaysRedact?: AlwaysRedactOptions;
|
|
259
|
+
/** Values and patterns to keep even when a rule matches them. */
|
|
260
|
+
neverRedact?: NeverRedactOptions;
|
|
261
|
+
/**
|
|
262
|
+
* How to treat lines that parse as a JSON object or array.
|
|
263
|
+
*
|
|
264
|
+
* - `'auto'` redacts values of fields named in a rule's `jsonKeys` and re-serializes the
|
|
265
|
+
* record, falling back to plain-text scanning when the line is not valid JSON.
|
|
266
|
+
* - `false` always scans as plain text.
|
|
267
|
+
* @default 'auto'
|
|
268
|
+
*/
|
|
269
|
+
json?: 'auto' | false;
|
|
270
|
+
/** Report detail level. */
|
|
271
|
+
report?: ReportOptions;
|
|
272
|
+
/** Line splitting bounds. */
|
|
273
|
+
lines?: LineOptions;
|
|
274
|
+
}
|
|
275
|
+
/** Result of sanitizing an in-memory string. */
|
|
276
|
+
interface SanitizeTextResult {
|
|
277
|
+
/** The sanitized text. */
|
|
278
|
+
output: string;
|
|
279
|
+
/** Summary of what was replaced. */
|
|
280
|
+
report: SanitizeReport;
|
|
281
|
+
}
|
|
282
|
+
/** Progress of a streaming run. */
|
|
283
|
+
interface SanitizeProgress {
|
|
284
|
+
/** Characters consumed from the source so far. */
|
|
285
|
+
charsRead: number;
|
|
286
|
+
/**
|
|
287
|
+
* Snapshot of the report so far. Counts grow throughout the run; the distinct-replacement list
|
|
288
|
+
* is omitted from snapshots and only present in the final report.
|
|
289
|
+
*/
|
|
290
|
+
report: SanitizeReport;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* The subset of `AbortSignal` this package relies on, so passing a signal does not require DOM or
|
|
294
|
+
* Node type definitions to be in scope.
|
|
295
|
+
*/
|
|
296
|
+
interface AbortSignalLike {
|
|
297
|
+
readonly aborted: boolean;
|
|
298
|
+
}
|
|
299
|
+
/** Per-run options for {@link Sanitizer.sanitizeStream}. */
|
|
300
|
+
interface SanitizeStreamOptions {
|
|
301
|
+
/** Called after each source chunk with a live snapshot of progress. */
|
|
302
|
+
onProgress?: (progress: SanitizeProgress) => void;
|
|
303
|
+
/**
|
|
304
|
+
* Aborts the run between lines. The sink is not closed and a
|
|
305
|
+
* {@link SanitizationAbortedError} is thrown.
|
|
306
|
+
*/
|
|
307
|
+
signal?: AbortSignalLike;
|
|
308
|
+
}
|
|
309
|
+
/** A source of text chunks. Chunk boundaries do not need to align with line boundaries. */
|
|
310
|
+
type TextSource = AsyncIterable<string> | Iterable<string>;
|
|
311
|
+
/** A destination for sanitized text. */
|
|
312
|
+
interface TextSink {
|
|
313
|
+
write(chunk: string): void | Promise<void>;
|
|
314
|
+
/** Called once after the last chunk of a successful run. */
|
|
315
|
+
close?(): void | Promise<void>;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* The minimal shape of a `Blob` or `File` this package reads, so browser and Node values are both
|
|
319
|
+
* accepted without depending on DOM type definitions.
|
|
320
|
+
*/
|
|
321
|
+
interface BlobLike {
|
|
322
|
+
readonly size: number;
|
|
323
|
+
slice(start?: number, end?: number): BlobLike;
|
|
324
|
+
arrayBuffer(): Promise<ArrayBuffer>;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* The minimal shape of a `ReadableStream` this package reads.
|
|
328
|
+
*/
|
|
329
|
+
interface ReadableStreamLike<T> {
|
|
330
|
+
getReader(): {
|
|
331
|
+
read(): Promise<{
|
|
332
|
+
done: boolean;
|
|
333
|
+
value?: T;
|
|
334
|
+
}>;
|
|
335
|
+
releaseLock(): void;
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* A configured, reusable sanitizer. Rules are compiled once when it is created, so sanitizing many
|
|
340
|
+
* inputs with the same configuration does not recompile patterns.
|
|
341
|
+
*/
|
|
342
|
+
interface Sanitizer {
|
|
343
|
+
/**
|
|
344
|
+
* The key in use, hex-encoded when it was generated. Persist it to keep tokens comparable in a
|
|
345
|
+
* later run; treat it as a secret, since it is what makes the tokens unguessable.
|
|
346
|
+
*/
|
|
347
|
+
readonly key: string;
|
|
348
|
+
/** The rules taking part in a run, in priority order. */
|
|
349
|
+
readonly rules: readonly RuleInfo[];
|
|
350
|
+
/**
|
|
351
|
+
* Sanitizes an in-memory string.
|
|
352
|
+
*
|
|
353
|
+
* Holds both the input and the output in memory. For anything large, prefer
|
|
354
|
+
* {@link Sanitizer.sanitizeStream}.
|
|
355
|
+
*/
|
|
356
|
+
sanitizeText(text: string): SanitizeTextResult;
|
|
357
|
+
/**
|
|
358
|
+
* Streams text from `source` through the rules and writes the result to `sink`, holding no more
|
|
359
|
+
* than one chunk plus one line in memory.
|
|
360
|
+
*
|
|
361
|
+
* @returns The report for the whole run.
|
|
362
|
+
* @throws {SanitizationAbortedError} When `options.signal` is aborted.
|
|
363
|
+
*/
|
|
364
|
+
sanitizeStream(source: TextSource, sink: TextSink, options?: SanitizeStreamOptions): Promise<SanitizeReport>;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Validates a rule and returns it unchanged.
|
|
369
|
+
*
|
|
370
|
+
* Use it instead of a plain object literal: the shape is checked once, at module load, so a typo in
|
|
371
|
+
* a pattern surfaces immediately rather than as a silent miss during a run.
|
|
372
|
+
*
|
|
373
|
+
* @throws {InvalidRuleError} When the rule is malformed.
|
|
374
|
+
*
|
|
375
|
+
* @example
|
|
376
|
+
* ```ts
|
|
377
|
+
* const ticketRule = defineRule({
|
|
378
|
+
* id: 'acme_ticket',
|
|
379
|
+
* label: 'Support ticket IDs',
|
|
380
|
+
* description: 'Internal ticket references such as ACME-123456.',
|
|
381
|
+
* mode: 'pseudo',
|
|
382
|
+
* token: 'TICKET',
|
|
383
|
+
* patterns: ['(?:\\bACME-\\d{6}\\b)'],
|
|
384
|
+
* jsonKeys: ['ticketId'],
|
|
385
|
+
* });
|
|
386
|
+
*
|
|
387
|
+
* const sanitizer = createSanitizer({ extraRules: [ticketRule] });
|
|
388
|
+
* ```
|
|
389
|
+
*/
|
|
390
|
+
declare function defineRule(rule: SanitizeRule): SanitizeRule;
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Every rule shipped with this package, in default priority order.
|
|
394
|
+
*
|
|
395
|
+
* Order matters: when two rules could match at the same position, the one listed first wins.
|
|
396
|
+
* Credential-shaped rules come first so a token is not partially consumed by a broader
|
|
397
|
+
* identifier rule.
|
|
398
|
+
*/
|
|
399
|
+
declare const builtinRules: readonly SanitizeRule[];
|
|
400
|
+
/** Identifiers of {@link builtinRules}, in the same order. */
|
|
401
|
+
declare const builtinRuleIds: readonly BuiltinRuleId[];
|
|
402
|
+
/**
|
|
403
|
+
* Looks up a built-in rule by identifier.
|
|
404
|
+
*
|
|
405
|
+
* @returns The rule, or `undefined` when the identifier is not built in.
|
|
406
|
+
*/
|
|
407
|
+
declare function getBuiltinRule(id: string): SanitizeRule | undefined;
|
|
408
|
+
|
|
409
|
+
export { type AbortSignalLike as A, type BlobLike as B, type KeyEncoding as K, type LineOptions as L, type NeverRedactOptions as N, type ReadableStreamLike as R, type SanitizerOptions as S, type TextSource as T, type SanitizeProgress as a, type SanitizeReport as b, type TextSink as c, type AlwaysRedactOptions as d, type BuiltinRuleId as e, type NeverRedactRuleEntry as f, type RedactionMode as g, type ReportOptions as h, type RuleCounts as i, type RuleId as j, type RuleInfo as k, type RuleSelector as l, type SanitizeReplacement as m, type SanitizeRule as n, type SanitizeSegment as o, type SanitizeStreamOptions as p, type SanitizeTextResult as q, type Sanitizer as r, builtinRuleIds as s, builtinRules as t, defineRule as u, getBuiltinRule as v };
|
package/index.cjs
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkWISLDJT3_cjs = require('./chunk-WISLDJT3.cjs');
|
|
4
|
+
var chunkVW3VVW6L_cjs = require('./chunk-VW3VVW6L.cjs');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
Object.defineProperty(exports, "createSanitizer", {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
get: function () { return chunkWISLDJT3_cjs.createSanitizer; }
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "fromBlob", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () { return chunkWISLDJT3_cjs.fromBlob; }
|
|
15
|
+
});
|
|
16
|
+
Object.defineProperty(exports, "fromString", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function () { return chunkWISLDJT3_cjs.fromString; }
|
|
19
|
+
});
|
|
20
|
+
Object.defineProperty(exports, "fromWebStream", {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
get: function () { return chunkWISLDJT3_cjs.fromWebStream; }
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, "generateKey", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () { return chunkWISLDJT3_cjs.generateKey; }
|
|
27
|
+
});
|
|
28
|
+
Object.defineProperty(exports, "sanitizeStream", {
|
|
29
|
+
enumerable: true,
|
|
30
|
+
get: function () { return chunkWISLDJT3_cjs.sanitizeStream; }
|
|
31
|
+
});
|
|
32
|
+
Object.defineProperty(exports, "sanitizeText", {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
get: function () { return chunkWISLDJT3_cjs.sanitizeText; }
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(exports, "toCallbackSink", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function () { return chunkWISLDJT3_cjs.toCallbackSink; }
|
|
39
|
+
});
|
|
40
|
+
Object.defineProperty(exports, "toNullSink", {
|
|
41
|
+
enumerable: true,
|
|
42
|
+
get: function () { return chunkWISLDJT3_cjs.toNullSink; }
|
|
43
|
+
});
|
|
44
|
+
Object.defineProperty(exports, "toStringSink", {
|
|
45
|
+
enumerable: true,
|
|
46
|
+
get: function () { return chunkWISLDJT3_cjs.toStringSink; }
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(exports, "InvalidKeyError", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () { return chunkVW3VVW6L_cjs.InvalidKeyError; }
|
|
51
|
+
});
|
|
52
|
+
Object.defineProperty(exports, "InvalidOptionError", {
|
|
53
|
+
enumerable: true,
|
|
54
|
+
get: function () { return chunkVW3VVW6L_cjs.InvalidOptionError; }
|
|
55
|
+
});
|
|
56
|
+
Object.defineProperty(exports, "InvalidRuleError", {
|
|
57
|
+
enumerable: true,
|
|
58
|
+
get: function () { return chunkVW3VVW6L_cjs.InvalidRuleError; }
|
|
59
|
+
});
|
|
60
|
+
Object.defineProperty(exports, "SanitizationAbortedError", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function () { return chunkVW3VVW6L_cjs.SanitizationAbortedError; }
|
|
63
|
+
});
|
|
64
|
+
Object.defineProperty(exports, "SanitizerError", {
|
|
65
|
+
enumerable: true,
|
|
66
|
+
get: function () { return chunkVW3VVW6L_cjs.SanitizerError; }
|
|
67
|
+
});
|
|
68
|
+
Object.defineProperty(exports, "UnknownRuleError", {
|
|
69
|
+
enumerable: true,
|
|
70
|
+
get: function () { return chunkVW3VVW6L_cjs.UnknownRuleError; }
|
|
71
|
+
});
|
|
72
|
+
Object.defineProperty(exports, "builtinRuleIds", {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
get: function () { return chunkVW3VVW6L_cjs.builtinRuleIds; }
|
|
75
|
+
});
|
|
76
|
+
Object.defineProperty(exports, "builtinRules", {
|
|
77
|
+
enumerable: true,
|
|
78
|
+
get: function () { return chunkVW3VVW6L_cjs.builtinRules; }
|
|
79
|
+
});
|
|
80
|
+
Object.defineProperty(exports, "defineRule", {
|
|
81
|
+
enumerable: true,
|
|
82
|
+
get: function () { return chunkVW3VVW6L_cjs.defineRule; }
|
|
83
|
+
});
|
|
84
|
+
Object.defineProperty(exports, "getBuiltinRule", {
|
|
85
|
+
enumerable: true,
|
|
86
|
+
get: function () { return chunkVW3VVW6L_cjs.getBuiltinRule; }
|
|
87
|
+
});
|
|
88
|
+
Object.defineProperty(exports, "isSanitizerError", {
|
|
89
|
+
enumerable: true,
|
|
90
|
+
get: function () { return chunkVW3VVW6L_cjs.isSanitizerError; }
|
|
91
|
+
});
|
|
92
|
+
//# sourceMappingURL=index.cjs.map
|
|
93
|
+
//# sourceMappingURL=index.cjs.map
|
package/index.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
|
package/index.d.cts
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { S as SanitizerOptions, r as Sanitizer, T as TextSource, c as TextSink, p as SanitizeStreamOptions, b as SanitizeReport, q as SanitizeTextResult, B as BlobLike, R as ReadableStreamLike } from './index-CutSH_48.cjs';
|
|
2
|
+
export { A as AbortSignalLike, d as AlwaysRedactOptions, e as BuiltinRuleId, K as KeyEncoding, L as LineOptions, N as NeverRedactOptions, f as NeverRedactRuleEntry, g as RedactionMode, h as ReportOptions, i as RuleCounts, j as RuleId, k as RuleInfo, l as RuleSelector, a as SanitizeProgress, m as SanitizeReplacement, n as SanitizeRule, o as SanitizeSegment, s as builtinRuleIds, t as builtinRules, u as defineRule, v as getBuiltinRule } from './index-CutSH_48.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Machine-readable cause of a {@link SanitizerError}.
|
|
6
|
+
*/
|
|
7
|
+
type SanitizerErrorCode = 'INVALID_RULE' | 'UNKNOWN_RULE' | 'INVALID_KEY' | 'INVALID_OPTION' | 'ABORTED';
|
|
8
|
+
/**
|
|
9
|
+
* Base class for every error this package throws.
|
|
10
|
+
*/
|
|
11
|
+
declare class SanitizerError extends Error {
|
|
12
|
+
/** Machine-readable cause, stable across releases. */
|
|
13
|
+
readonly code: SanitizerErrorCode;
|
|
14
|
+
constructor(code: SanitizerErrorCode, message: string);
|
|
15
|
+
}
|
|
16
|
+
/** A rule object is malformed. */
|
|
17
|
+
declare class InvalidRuleError extends SanitizerError {
|
|
18
|
+
constructor(message: string);
|
|
19
|
+
}
|
|
20
|
+
/** A rule identifier does not match any built-in rule. */
|
|
21
|
+
declare class UnknownRuleError extends SanitizerError {
|
|
22
|
+
constructor(message: string);
|
|
23
|
+
}
|
|
24
|
+
/** A key is malformed, or no secure random source is available to generate one. */
|
|
25
|
+
declare class InvalidKeyError extends SanitizerError {
|
|
26
|
+
constructor(message: string);
|
|
27
|
+
}
|
|
28
|
+
/** An option value is outside its allowed range. */
|
|
29
|
+
declare class InvalidOptionError extends SanitizerError {
|
|
30
|
+
constructor(message: string);
|
|
31
|
+
}
|
|
32
|
+
/** A streaming run was stopped through its `AbortSignal`. */
|
|
33
|
+
declare class SanitizationAbortedError extends SanitizerError {
|
|
34
|
+
constructor(message?: string);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Whether a caught value is an error thrown by this package.
|
|
38
|
+
*
|
|
39
|
+
* Prefer this over `instanceof` when the value may have crossed a bundle, worker or realm
|
|
40
|
+
* boundary, where class identity is not preserved.
|
|
41
|
+
*/
|
|
42
|
+
declare function isSanitizerError(value: unknown): value is SanitizerError;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Generates a random hex-encoded key for token derivation.
|
|
46
|
+
*
|
|
47
|
+
* Persist the returned value if tokens have to stay comparable across runs or files; discard it if
|
|
48
|
+
* they should not. There is no way to recover the original values from the tokens, with or without
|
|
49
|
+
* the key — the key only determines which token a given value maps to.
|
|
50
|
+
*
|
|
51
|
+
* @param byteLength Key length in bytes, at least 16.
|
|
52
|
+
* @throws {InvalidKeyError} When `byteLength` is too small or no secure random source is available.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* const key = generateKey();
|
|
57
|
+
* const sanitizer = createSanitizer({ key });
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
declare function generateKey(byteLength?: number): string;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Creates a reusable sanitizer.
|
|
64
|
+
*
|
|
65
|
+
* Rules are resolved, validated and compiled into a single pattern once, here — so sanitizing many
|
|
66
|
+
* inputs with one sanitizer is much cheaper than calling the one-shot helpers repeatedly.
|
|
67
|
+
*
|
|
68
|
+
* @throws {UnknownRuleError} When `rules` names a rule that is not built in.
|
|
69
|
+
* @throws {InvalidRuleError} When a custom rule is malformed.
|
|
70
|
+
* @throws {InvalidKeyError} When `key` is malformed, or none could be generated.
|
|
71
|
+
* @throws {InvalidOptionError} When an option value is out of range.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* const sanitizer = createSanitizer({
|
|
76
|
+
* rules: ['secrets', 'ips', 'users'],
|
|
77
|
+
* alwaysRedact: { values: ['acme-internal'] },
|
|
78
|
+
* neverRedact: { values: ['127.0.0.1'] },
|
|
79
|
+
* });
|
|
80
|
+
*
|
|
81
|
+
* const { output, report } = sanitizer.sanitizeText('login from 10.0.0.7 failed');
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
declare function createSanitizer(options?: SanitizerOptions): Sanitizer;
|
|
85
|
+
/**
|
|
86
|
+
* Sanitizes a string with a one-off configuration.
|
|
87
|
+
*
|
|
88
|
+
* Convenient for scripts and tests. Each call builds a new sanitizer, so unless `options.key` is
|
|
89
|
+
* supplied the tokens are not comparable between calls. For repeated use, create a sanitizer with
|
|
90
|
+
* {@link createSanitizer} instead.
|
|
91
|
+
*/
|
|
92
|
+
declare function sanitizeText(text: string, options?: SanitizerOptions): SanitizeTextResult;
|
|
93
|
+
/**
|
|
94
|
+
* Streams text through a one-off sanitizer.
|
|
95
|
+
*
|
|
96
|
+
* See {@link sanitizeText} for the trade-off of creating a sanitizer per call.
|
|
97
|
+
*/
|
|
98
|
+
declare function sanitizeStream(source: TextSource, sink: TextSink, options?: SanitizerOptions & SanitizeStreamOptions): Promise<SanitizeReport>;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Wraps a string as a source, split into fixed-size chunks.
|
|
102
|
+
*
|
|
103
|
+
* Useful for exercising the streaming path in tests and for feeding text that is already in memory
|
|
104
|
+
* without copying it in one piece.
|
|
105
|
+
*/
|
|
106
|
+
declare function fromString(text: string, chunkChars?: number): TextSource;
|
|
107
|
+
/**
|
|
108
|
+
* Reads a `Blob` or `File` as UTF-8 text, one chunk at a time.
|
|
109
|
+
*
|
|
110
|
+
* Multi-byte characters split across a chunk boundary are decoded correctly. Accepts any object
|
|
111
|
+
* with `size`, `slice` and `arrayBuffer`, so browser `File`, browser `Blob` and Node's `Blob` all
|
|
112
|
+
* work.
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```ts
|
|
116
|
+
* const report = await sanitizer.sanitizeStream(fromBlob(file), toStringSink());
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
declare function fromBlob(blob: BlobLike, chunkBytes?: number): TextSource;
|
|
120
|
+
/**
|
|
121
|
+
* Reads a `ReadableStream` of text or bytes.
|
|
122
|
+
*
|
|
123
|
+
* Byte chunks are decoded as UTF-8 across chunk boundaries. Accepts web streams from `fetch`,
|
|
124
|
+
* `Blob.stream()` and `node:stream/web`.
|
|
125
|
+
*/
|
|
126
|
+
declare function fromWebStream(stream: ReadableStreamLike<string | Uint8Array>): TextSource;
|
|
127
|
+
|
|
128
|
+
/** A sink that accumulates everything in memory. */
|
|
129
|
+
interface StringSink extends TextSink {
|
|
130
|
+
/** Everything written so far, joined. */
|
|
131
|
+
readonly text: string;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Collects sanitized output into a string.
|
|
135
|
+
*
|
|
136
|
+
* Only appropriate when the output is known to fit in memory — the point of the streaming API is
|
|
137
|
+
* usually to avoid that.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```ts
|
|
141
|
+
* const sink = toStringSink();
|
|
142
|
+
* const report = await sanitizer.sanitizeStream(fromString(input), sink);
|
|
143
|
+
* console.log(sink.text, report.totalMatches);
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
declare function toStringSink(): StringSink;
|
|
147
|
+
/**
|
|
148
|
+
* Sends sanitized output to a callback, one line at a time.
|
|
149
|
+
*
|
|
150
|
+
* The callback may return a promise; it is awaited before the next line is written, so
|
|
151
|
+
* backpressure propagates to the source.
|
|
152
|
+
*/
|
|
153
|
+
declare function toCallbackSink(onChunk: (chunk: string) => void | Promise<void>, onClose?: () => void | Promise<void>): TextSink;
|
|
154
|
+
/** A sink that discards everything, for report-only runs. */
|
|
155
|
+
declare function toNullSink(): TextSink;
|
|
156
|
+
|
|
157
|
+
export { BlobLike, InvalidKeyError, InvalidOptionError, InvalidRuleError, ReadableStreamLike, SanitizationAbortedError, SanitizeReport, SanitizeStreamOptions, SanitizeTextResult, Sanitizer, SanitizerError, type SanitizerErrorCode, SanitizerOptions, type StringSink, TextSink, TextSource, UnknownRuleError, createSanitizer, fromBlob, fromString, fromWebStream, generateKey, isSanitizerError, sanitizeStream, sanitizeText, toCallbackSink, toNullSink, toStringSink };
|