@socprime/logtotal-sanitizer 0.0.1-beta.3 → 0.2.0-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 +31 -0
- package/README.md +6 -2
- package/{chunk-U4HRIFW3.js → chunk-5R34WEOD.js} +180 -63
- package/chunk-5R34WEOD.js.map +1 -0
- package/{chunk-6CWTMBTN.cjs → chunk-DBC5DTD5.cjs} +367 -87
- package/chunk-DBC5DTD5.cjs.map +1 -0
- package/{chunk-32RNSQDF.js → chunk-FUDPRHOC.js} +350 -72
- package/chunk-FUDPRHOC.js.map +1 -0
- package/{chunk-MWY7W57Y.cjs → chunk-ISVRNSZF.cjs} +182 -62
- package/chunk-ISVRNSZF.cjs.map +1 -0
- package/cli.js +368 -127
- package/cli.js.map +1 -1
- package/{index-CutSH_48.d.cts → index-HPy5z0l3.d.cts} +22 -7
- package/{index-CutSH_48.d.ts → index-HPy5z0l3.d.ts} +22 -7
- package/index.cjs +31 -23
- package/index.d.cts +19 -30
- package/index.d.ts +19 -30
- package/index.js +2 -2
- package/node.cjs +33 -25
- package/node.d.cts +3 -3
- package/node.d.ts +3 -3
- package/node.js +3 -3
- package/package.json +1 -1
- package/rules.cjs +5 -5
- package/rules.d.cts +1 -1
- package/rules.d.ts +1 -1
- package/rules.js +1 -1
- package/chunk-32RNSQDF.js.map +0 -1
- package/chunk-6CWTMBTN.cjs.map +0 -1
- package/chunk-MWY7W57Y.cjs.map +0 -1
- package/chunk-U4HRIFW3.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.0-beta.0] - 2026-09-07
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `mergeReports` combines reports from disjoint, ordered ranges of the same input: counts and
|
|
15
|
+
line totals are summed, distinct replacements are merged by `(ruleId, original)`, and preview
|
|
16
|
+
segments are concatenated until `previewBytes`.
|
|
17
|
+
- `planLineAlignedRanges` splits a `Blob` / `File` into newline-aligned byte ranges so callers can
|
|
18
|
+
sanitize parts concurrently and concatenate the outputs.
|
|
19
|
+
- `report.maxReplacementsPerRule` caps distinct original values stored per rule. Counts stay
|
|
20
|
+
complete; `replacementsTruncated` is set when the cap drops at least one value. Unset by
|
|
21
|
+
default, so CLI `--report json` still dumps the full list.
|
|
22
|
+
- `sanitizeStream` accepts a per-run `previewBytes` override so one sanitizer can collect a
|
|
23
|
+
preview from only the first range.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Most positive lookbehind fragments now consume their prefix and capture only the value to redact.
|
|
28
|
+
JavaScriptCore (Safari) evaluates lookbehind-led alternatives about 15× slower than V8; this
|
|
29
|
+
rewrite is equivalent on value spans and is faster in both engines. Two fragments keep their
|
|
30
|
+
lookbehind because consumption would not be equivalent there.
|
|
31
|
+
- Patterns are compiled one regex per fragment, behind a cheap per-rule prefilter, instead of a
|
|
32
|
+
single combined pattern. Match selection is unchanged: the leftmost value wins, and ties go to
|
|
33
|
+
the earlier rule and then the earlier fragment.
|
|
34
|
+
- Sanitizing 1 MB of Windows PowerShell logs is about 4.9× faster under JavaScriptCore and about
|
|
35
|
+
1.6× faster under V8. Output is byte-identical: verified against the previous implementation on
|
|
36
|
+
318k real log lines and 1.8M generated adversarial lines across every rule, both modes, JSON
|
|
37
|
+
mode, allowlists and segment reporting.
|
|
38
|
+
- The CLI skips collecting the replacement list and preview unless `--report` is JSON, so a
|
|
39
|
+
normal run no longer pays for detail it never prints.
|
|
40
|
+
|
|
10
41
|
## [0.0.1-beta.3] - 2026-08-26
|
|
11
42
|
|
|
12
43
|
### Fixed
|
package/README.md
CHANGED
|
@@ -50,6 +50,7 @@ Reuse `key` across files when the same original value must map to the same token
|
|
|
50
50
|
| `alwaysRedact` | — | Extra literals and regexes, highest match priority. |
|
|
51
51
|
| `neverRedact` | — | Allowlist. Highest overall priority: matching values are left unchanged. |
|
|
52
52
|
| `report.contextChars` | `0` | Characters of surrounding text on each unique replacement. |
|
|
53
|
+
| `report.maxReplacementsPerRule` | — | Cap on distinct originals stored per rule. Counts stay complete. |
|
|
53
54
|
|
|
54
55
|
### Priority
|
|
55
56
|
|
|
@@ -116,7 +117,7 @@ const ticket = defineRule({
|
|
|
116
117
|
const sanitizer = createSanitizer({ rules: ['secrets', ticket] });
|
|
117
118
|
```
|
|
118
119
|
|
|
119
|
-
`id` must be a JavaScript identifier
|
|
120
|
+
`id` must be a JavaScript identifier. At most one capturing group per fragment; it marks the value to replace (the rest of the match is kept). Put expensive checks in `validate`, not in the regex.
|
|
120
121
|
|
|
121
122
|
## Streaming and I/O
|
|
122
123
|
|
|
@@ -129,6 +130,8 @@ const output = sink.result();
|
|
|
129
130
|
```
|
|
130
131
|
|
|
131
132
|
Browser helpers: `fromBlob`, `fromWebStream`, `toWebStream`.
|
|
133
|
+
`planLineAlignedRanges(blob, partCount)` returns newline-aligned byte ranges for concurrent
|
|
134
|
+
sanitization; `mergeReports(reports)` folds the resulting reports back together.
|
|
132
135
|
|
|
133
136
|
Node helpers (subpath `@socprime/logtotal-sanitizer/node`):
|
|
134
137
|
|
|
@@ -150,7 +153,8 @@ The root entry does not import `node:*`.
|
|
|
150
153
|
totalMatches: 3,
|
|
151
154
|
lineCount: 40,
|
|
152
155
|
replacements: [{ ruleId, original, replacement, count, contextBefore?, contextAfter? }],
|
|
153
|
-
preview: { before: [{ text, changed }], after: [{ text, changed }] }
|
|
156
|
+
preview: { before: [{ text, changed }], after: [{ text, changed }] },
|
|
157
|
+
replacementsTruncated?: true
|
|
154
158
|
}
|
|
155
159
|
```
|
|
156
160
|
|
|
@@ -86,13 +86,13 @@ var geoLocationRule = {
|
|
|
86
86
|
patterns: [
|
|
87
87
|
"(?:\\(\\s*-?\\d{1,3}\\.\\d{3,}\\s*[,;]\\s*-?\\d{1,3}\\.\\d{3,}\\s*\\))",
|
|
88
88
|
"(?:(?<![\\d.])-?\\d{1,3}\\.\\d{3,}\\s*[,;]\\s*-?\\d{1,3}\\.\\d{3,}(?!\\d))",
|
|
89
|
-
`(
|
|
90
|
-
`(
|
|
91
|
-
`(
|
|
89
|
+
`(?:\\b${LAT_KEY}\\s*[=:]\\s*)(-?\\d{1,3}\\.\\d+)`,
|
|
90
|
+
`(?:\\b${LON_KEY}\\s*[=:]\\s*)(-?\\d{1,3}\\.\\d+)`,
|
|
91
|
+
`(?:\\bgeohash\\s*[=:]\\s*)(${GEOHASH}{5,12}\\b)`,
|
|
92
92
|
`(?:(?<![\\w+])${OLC}{4,8}\\+${OLC}{2,3}(?![\\w+]))`,
|
|
93
93
|
`(?:\\b\\d{1,3}\xB0\\d{1,2}'\\d{1,2}(?:\\.\\d+)?"[NSEW]\\b)`,
|
|
94
94
|
"(?:\\b[A-Za-z]{1,2}\\d{1,2}[A-Za-z]?\\s\\d[A-Za-z]{2}\\b)",
|
|
95
|
-
`(
|
|
95
|
+
`(?:\\b${ZIP_KEY}\\s*[=:]\\s*)(\\d{5}(?:-\\d{4})?\\b)`
|
|
96
96
|
],
|
|
97
97
|
aggressivePatterns: [
|
|
98
98
|
"(?:\\(\\s*-?\\d{1,3}\\.\\d{2,}\\s*[,;]\\s*-?\\d{1,3}\\.\\d{2,}\\s*\\))",
|
|
@@ -206,14 +206,11 @@ var govIdentifiersRule = {
|
|
|
206
206
|
"(?:\\b(?:NHS|nhs)(?:[_-]?number)?\\s*[=:]\\s*\\d{10}\\b)",
|
|
207
207
|
"(?:\\b(?!BG|GB|NK|KN|TN|NT|ZZ)[A-CEGHJ-PR-TW-Z][A-CEGHJ-NPR-TW-Z]\\d{6}\\s?[A-D]\\b)",
|
|
208
208
|
"(?:(?<![A-Za-z0-9\u0410-\u042F\u0406\u0407\u0404\u0490\u0430-\u044F\u0456\u0457\u0454\u0491])[\u0410-\u042F\u0406\u0407\u0404\u0490]{2}\\d{6}\\b)",
|
|
209
|
-
`(
|
|
210
|
-
"(?:(
|
|
211
|
-
`(
|
|
212
|
-
],
|
|
213
|
-
aggressivePatterns: [
|
|
214
|
-
"(?:\\b[A-Z]{1,2}\\d{6,9}\\b)",
|
|
215
|
-
"(?:\\b\\d{9,11}\\b)"
|
|
209
|
+
`(?:\\b${SSN_CTX}\\s*[=:]?\\s*)(\\d{9})\\b`,
|
|
210
|
+
"(?:(?:\u0406\u041F\u041D|\u0420\u041D\u041E\u041A\u041F\u041F|tax[_-]?id)\\s*[=:]?\\s*)(\\d{10})\\b",
|
|
211
|
+
`(?:\\b${ID_CTX}\\s*[=:]\\s*)([A-Za-z0-9<]{5,32})`
|
|
216
212
|
],
|
|
213
|
+
aggressivePatterns: ["(?:\\b[A-Z]{1,2}\\d{6,9}\\b)", "(?:\\b\\d{9,11}\\b)"],
|
|
217
214
|
validate: validateGovId,
|
|
218
215
|
jsonKeys: [
|
|
219
216
|
"ssn",
|
|
@@ -262,11 +259,9 @@ var healthInfoRule = {
|
|
|
262
259
|
"(?:\\b(?:NDC|[Nn]dc)[:\\s]+\\d{4,5}-\\d{3,4}-\\d{1,2}\\b)",
|
|
263
260
|
"(?:\\b[ABFGMPRX][A-Z9]\\d{7}\\b)",
|
|
264
261
|
"(?:\\b(?:[Nn][Pp][Ii])\\s*[=:]\\s*\\d{10}\\b)",
|
|
265
|
-
`(
|
|
266
|
-
],
|
|
267
|
-
aggressivePatterns: [
|
|
268
|
-
"(?:(?<![A-Za-z0-9])[A-TV-Z]\\d{2}(?:\\.\\w{1,4})?(?![A-Za-z0-9:]))"
|
|
262
|
+
`(?:\\b${MRN_KEY}\\s*[=:]\\s*)([A-Za-z0-9-]{4,})\\b`
|
|
269
263
|
],
|
|
264
|
+
aggressivePatterns: ["(?:(?<![A-Za-z0-9])[A-TV-Z]\\d{2}(?:\\.\\w{1,4})?(?![A-Za-z0-9:]))"],
|
|
270
265
|
validate: validateHealth,
|
|
271
266
|
jsonKeys: [
|
|
272
267
|
"diagnosis",
|
|
@@ -301,18 +296,18 @@ var homePathsRule = {
|
|
|
301
296
|
mode: "mask",
|
|
302
297
|
token: "PATH",
|
|
303
298
|
patterns: [
|
|
304
|
-
`(
|
|
305
|
-
`(
|
|
306
|
-
`(
|
|
307
|
-
`(
|
|
308
|
-
`(
|
|
309
|
-
`(?:
|
|
310
|
-
`(?:
|
|
311
|
-
`(
|
|
312
|
-
`(?:
|
|
313
|
-
`(?:
|
|
314
|
-
`(
|
|
315
|
-
`(
|
|
299
|
+
`(?:/export/home/(${USER_SEG}))`,
|
|
300
|
+
`(?:/usr/home/(${USER_SEG}))`,
|
|
301
|
+
`(?:/var/home/(${USER_SEG}))`,
|
|
302
|
+
`(?:/home/(${USER_SEG}))`,
|
|
303
|
+
`(?:/Users/(${USER_SEG}))`,
|
|
304
|
+
`(?:[A-Za-z]:\\\\Users\\\\(${USER_SEG}))`,
|
|
305
|
+
`(?:[A-Za-z]:/Users/(${USER_SEG}))`,
|
|
306
|
+
`(?:\\\\\\\\\\?\\\\[A-Za-z]:\\\\Users\\\\(${USER_SEG}))`,
|
|
307
|
+
`(?:[A-Za-z]:\\\\Documents and Settings\\\\(${USER_SEG}))`,
|
|
308
|
+
`(?:[A-Za-z]:\\\\\\\\Users\\\\\\\\(${USER_SEG}))`,
|
|
309
|
+
`(?:/mnt/[A-Za-z]/Users/(${USER_SEG}))`,
|
|
310
|
+
`(?://wsl\\$/(?:[A-Za-z0-9_-]+)/home/(${USER_SEG}))`
|
|
316
311
|
],
|
|
317
312
|
validate: validateHomeUser
|
|
318
313
|
};
|
|
@@ -1281,18 +1276,18 @@ var TLD_EXACT = [...INTERNAL_COMPOUND_SUFFIXES, ...GTLD_UNRESTRICTED, ...INTERNA
|
|
|
1281
1276
|
var TLD_COLLISION = FILE_EXT_COLLISION_TLDS.join("|");
|
|
1282
1277
|
var LABEL = "[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?";
|
|
1283
1278
|
var HOST_EXACT = `(?:(?<![\\w.$-])(?<![^:/\\\\][/\\\\])(?:${LABEL}\\.)+(?:${TLD_EXACT})(?!\\.?\\w))`;
|
|
1284
|
-
var HOST_COLLISION = `(?:(
|
|
1285
|
-
var UNC_COMPUTER = "(
|
|
1286
|
-
var SPN_HOST = "(
|
|
1279
|
+
var HOST_COLLISION = `(?:(?:https?|sftp|ftps?|wss?)://(?:[^/@\\s]+@)?)((?:${LABEL}\\.)+(?:${TLD_COLLISION}))(?!\\.?\\w)`;
|
|
1280
|
+
var UNC_COMPUTER = "(?:\\\\\\\\)([A-Za-z][A-Za-z0-9-]{0,14})(?=\\\\[A-Za-z0-9$])";
|
|
1281
|
+
var SPN_HOST = "(?:\\b[A-Za-z][A-Za-z0-9]*/)([A-Za-z0-9][A-Za-z0-9.-]*)(?=@[A-Z0-9.-]+\\b)";
|
|
1287
1282
|
var HOST_CTX_KEY = "(?:host|hostname|computer)";
|
|
1288
|
-
var HOST_CTX = `(
|
|
1283
|
+
var HOST_CTX = `(?:\\b${HOST_CTX_KEY}\\s*[=:]\\s*)([A-Za-z0-9](?:[A-Za-z0-9.-]*[A-Za-z0-9])?)`;
|
|
1289
1284
|
var NETBIOS_AGGRESSIVE = "(?:\\b(?:WIN|DESKTOP)-[A-Z0-9]{7,10}\\b)";
|
|
1290
1285
|
var SYSLOG_MONTH = "(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)";
|
|
1291
1286
|
var SYSLOG_BSD_TS = `${SYSLOG_MONTH}\\s+\\d{1,2}\\s+\\d{2}:\\d{2}:\\d{2}`;
|
|
1292
1287
|
var SYSLOG_ISO_TS = "\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:?\\d{2})?";
|
|
1293
1288
|
var SYSLOG_HOST_NAME = `${LABEL}(?:\\.${LABEL})*`;
|
|
1294
1289
|
var SYSLOG_HOST_LOOKAHEAD = "(?=\\s+[A-Za-z][A-Za-z0-9_.@-]*(?:\\[\\d+\\])?:)";
|
|
1295
|
-
var SYSLOG_HOST = `(?:(
|
|
1290
|
+
var SYSLOG_HOST = `(?:(?:${SYSLOG_BSD_TS}|${SYSLOG_ISO_TS})\\s+)(${SYSLOG_HOST_NAME})${SYSLOG_HOST_LOOKAHEAD}`;
|
|
1296
1291
|
var INVENTORY_PREFIX = "(?:[Ss][Rr][Vv]|[Ww][Ee][Bb]|[Dd][Bb]|[Aa][Pp][Pp]|[Hh][Oo][Ss][Tt]|[Nn][Oo][Dd][Ee]|[Pp][Oo][Dd])";
|
|
1297
1292
|
var INVENTORY_HOST = `(?:\\b${INVENTORY_PREFIX}-[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*-\\d+\\b)`;
|
|
1298
1293
|
var hostnamesRule = {
|
|
@@ -1795,16 +1790,16 @@ var paymentInfoRule = {
|
|
|
1795
1790
|
"(?:(?<![.\\d])\\b\\d(?:[ -]?\\d){12,18}\\b)",
|
|
1796
1791
|
"(?:\\b[A-Z]{2}\\d{2}[A-Z0-9]{10,30}\\b)",
|
|
1797
1792
|
"(?:\\b[A-Z]{2}\\d{2}(?: [A-Z0-9]{4}){2,7}(?: [A-Z0-9]{1,4})?\\b)",
|
|
1798
|
-
`(
|
|
1799
|
-
`(
|
|
1793
|
+
`(?:\\b${CVV_KEY}\\s*[=:]\\s*)(\\d{3,4}\\b)`,
|
|
1794
|
+
`(?:\\b${EXP_KEY}\\s*[=:]\\s*)((?:0[1-9]|1[0-2])[/-](?:\\d{2}|\\d{4})\\b)`,
|
|
1800
1795
|
"(?:\\bbc1[a-z0-9]{25,39}\\b)",
|
|
1801
1796
|
"(?:(?<![A-Za-z0-9])[13][A-HJ-NP-Za-km-z1-9]{25,34}(?![A-Za-z0-9]))",
|
|
1802
1797
|
"(?:\\b0x[A-Fa-f0-9]{40}\\b)"
|
|
1803
1798
|
],
|
|
1804
1799
|
aggressivePatterns: [
|
|
1805
1800
|
"(?:(?<![\\\\/])\\b[A-Z]{6}[A-Z0-9]{2}(?:[A-Z0-9]{3})?\\b(?![\\\\/]))",
|
|
1806
|
-
`(
|
|
1807
|
-
`(
|
|
1801
|
+
`(?:\\b${ROUTING_KEY}\\s*[=:]\\s*)(\\d{9}\\b)`,
|
|
1802
|
+
`(?:\\b${ACCOUNT_KEY}\\s*[=:]\\s*)(\\d{8,12}\\b)`
|
|
1808
1803
|
],
|
|
1809
1804
|
validate: validatePayment,
|
|
1810
1805
|
jsonKeys: [
|
|
@@ -1844,9 +1839,9 @@ var phoneNumbersRule = {
|
|
|
1844
1839
|
"(?:\\b1-\\d{3}-\\d{3}-\\d{4}\\b)",
|
|
1845
1840
|
"(?:\\b0\\d{2}-\\d{3}-\\d{2}-\\d{2}\\b)",
|
|
1846
1841
|
"(?:\\b0\\d{2}\\s\\d{3}\\s\\d{2}\\s\\d{2}\\b)",
|
|
1847
|
-
"(?:(?<![.\\d])\\b00[1-9](?:[\\s().-]*\\d){7,13}(?!\\
|
|
1848
|
-
"(
|
|
1849
|
-
`(
|
|
1842
|
+
"(?:(?<![.\\d-])\\b00[1-9](?:[\\s().-]*\\d){7,13}(?!\\w)(?!-[\\dA-Fa-f]))",
|
|
1843
|
+
"(?:\\b(?:tel|sms):)(\\+?[1-9](?:[\\s().-]*\\d){6,14})(?!\\d)",
|
|
1844
|
+
`(?:\\b${PHONE_KEY}\\s*[=:]\\s*)(\\+?[0-9](?:[\\s().-]*\\d){6,14})(?!\\d)`
|
|
1850
1845
|
],
|
|
1851
1846
|
validate: validatePhone,
|
|
1852
1847
|
jsonKeys: [
|
|
@@ -1906,12 +1901,12 @@ var secretsRule = {
|
|
|
1906
1901
|
mode: "mask",
|
|
1907
1902
|
token: "SECRET",
|
|
1908
1903
|
patterns: [
|
|
1909
|
-
"(?:(
|
|
1910
|
-
"(?:(
|
|
1904
|
+
"(?:(?:Bearer|bearer|BEARER)\\s+)([A-Za-z0-9._\\-+/=]{8,})",
|
|
1905
|
+
"(?:(?:Basic|basic|BASIC)\\s+)([A-Za-z0-9+/]{8,}={0,2})",
|
|
1911
1906
|
"(?:(?<![A-Za-z0-9_-])eyJ[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}(?:\\.[A-Za-z0-9_-]{8,})?)",
|
|
1912
1907
|
"(?:-----BEGIN (?:(?:RSA |EC |DSA |OPENSSH |ENCRYPTED )?PRIVATE KEY|CERTIFICATE)-----[A-Za-z0-9+/=\\s\\\\]+?-----END (?:(?:RSA |EC |DSA |OPENSSH |ENCRYPTED )?PRIVATE KEY|CERTIFICATE)-----)",
|
|
1913
1908
|
"(?:\\b(?:AKIA|ASIA|ABIA|ACCA)[A-Z0-9]{16}\\b)",
|
|
1914
|
-
"(?:(
|
|
1909
|
+
"(?:(?:aws_secret_access_key|AWS_SECRET_ACCESS_KEY)\\s*[=:]\\s*)([A-Za-z0-9/+=]{30,})",
|
|
1915
1910
|
"(?:github_pat_[A-Za-z0-9_]{22,})",
|
|
1916
1911
|
"(?:gh[pousr]_[A-Za-z0-9]{36,})",
|
|
1917
1912
|
"(?:xox[abprs]-[A-Za-z0-9-]{10,})",
|
|
@@ -1920,13 +1915,15 @@ var secretsRule = {
|
|
|
1920
1915
|
"(?:(?:sk_live_|sk_test_|rk_live_|rk_test_)[A-Za-z0-9]{16,})",
|
|
1921
1916
|
"(?:sk-proj-[A-Za-z0-9_-]{16,})",
|
|
1922
1917
|
"(?:sk-[A-Za-z0-9]{20,})",
|
|
1918
|
+
// Kept as a lookbehind: `.{0,60}` asserts a nearby keyword rather than an adjacent prefix, so
|
|
1919
|
+
// one `Twilio` has to stay reusable by every identifier that follows it.
|
|
1923
1920
|
"(?:(?<=(?:[Tt]wilio.{0,60}|\\b(?:[Aa]ccount[Ss]id|[Aa]uth[Tt]oken|[Ss]id)\\s*[=:]\\s*))(?:AC|SK)[0-9A-Fa-f]{32})",
|
|
1924
1921
|
"(?:SG\\.[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,})",
|
|
1925
1922
|
"(?:npm_[A-Za-z0-9]{36,})",
|
|
1926
|
-
`(?:
|
|
1927
|
-
"(?:
|
|
1928
|
-
`(
|
|
1929
|
-
`(
|
|
1923
|
+
`(?:[?&][Ss]ig=)([^&\\s"']{16,})`,
|
|
1924
|
+
"(?:[a-zA-Z][a-zA-Z0-9+.-]*://)([^/@\\s:]+:[^/@\\s]+@)",
|
|
1925
|
+
`(?:--${CLI_FLAGS}(?:\\s+|=)"?)([^\\s"']{4,})`,
|
|
1926
|
+
`(?:\\b${CONTEXT_KEYS}"?\\s*[=:]\\s*"?)(${CONTEXT_VALUE})`
|
|
1930
1927
|
],
|
|
1931
1928
|
aggressivePatterns: [
|
|
1932
1929
|
"(?:(?<![A-Za-z0-9+/])[A-Za-z0-9+/]{40,}={0,2}(?![A-Za-z0-9+/=]))",
|
|
@@ -1978,7 +1975,7 @@ var sessionCookiesRule = {
|
|
|
1978
1975
|
`(?:(?:csrftoken|csrf_token|XSRF-TOKEN|xsrf-token)=${COOKIE_VALUE})`,
|
|
1979
1976
|
`(?:remember_token=${COOKIE_VALUE})`,
|
|
1980
1977
|
`(?:(?:SSESS|SESS)[A-Fa-f0-9]{32}=${COOKIE_VALUE})`,
|
|
1981
|
-
`(?:
|
|
1978
|
+
`(?:[Ss]et-[Cc]ookie:\\s*)([^;=\\s]+=${COOKIE_VALUE})`
|
|
1982
1979
|
],
|
|
1983
1980
|
aggressivePatterns: [
|
|
1984
1981
|
`(?:(?<![\\w-])[\\w-]*session[\\w-]*=${COOKIE_VALUE})`,
|
|
@@ -2000,21 +1997,21 @@ var NOT_GUID = "(?![0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-)";
|
|
|
2000
1997
|
var ACCOUNT_END = "(?![A-Za-z0-9_$\\\\/-])";
|
|
2001
1998
|
var PATH_ROOT = "(?:\\b(?:HKLM|HKCU|HKU|HKCR|HKEY_[A-Z_]+)|\\b[A-Za-z]:)\\\\";
|
|
2002
1999
|
var NOT_UNDER_PATH_ROOT = `(?<!${PATH_ROOT}(?:(?! [-/])[^<>'"\\n])*)`;
|
|
2003
|
-
var DOMAIN_USER = `(?:(
|
|
2000
|
+
var DOMAIN_USER = `(?:(?:(?:^|[^\\\\.-])\\b[A-Za-z0-9](?:[A-Za-z0-9.-]{0,13}[A-Za-z0-9])?\\\\)(?<!${WIN_DOMAIN_EXCLUDE})${NOT_FILENAME}${NOT_GUID}(${USER_SEG_SIMPLE})${ACCOUNT_END}${NOT_UNDER_PATH_ROOT})`;
|
|
2004
2001
|
var SID = "(?:\\bS-1-(?:\\d+-){1,14}\\d+\\b)";
|
|
2005
2002
|
var VALUE_WITH_LETTER = "[\\w.@+-]*[A-Za-z][\\w.@+-]*";
|
|
2006
|
-
var LDAP_DN_SINGLE = `(
|
|
2003
|
+
var LDAP_DN_SINGLE = `(?:\\b(?:uid|sAMAccountName)=)(${VALUE_WITH_LETTER})`;
|
|
2007
2004
|
var CN_VALUE = "(?:[A-Za-z0-9.'-]+(?: [A-Za-z0-9.'-]+){0,3})";
|
|
2008
|
-
var LDAP_DN_CN = `(
|
|
2009
|
-
var ARN_USER = "(
|
|
2010
|
-
var ARN_ASSUMED_ROLE_SESSION = "(
|
|
2011
|
-
var K8S_SERVICE_ACCOUNT = "(
|
|
2012
|
-
var SSHD_FOR_USER = "(?:(
|
|
2013
|
-
var SSHD_RUSER = "(
|
|
2014
|
-
var SSHD_LOGNAME = "(
|
|
2015
|
-
var SUDO_USER = "(
|
|
2005
|
+
var LDAP_DN_CN = `(?:\\bcn=)(${CN_VALUE})`;
|
|
2006
|
+
var ARN_USER = "(?::user/)([\\w.@+=,-]+)";
|
|
2007
|
+
var ARN_ASSUMED_ROLE_SESSION = "(?::assumed-role/[\\w+=,.@-]+/)([\\w.@+=,-]+)";
|
|
2008
|
+
var K8S_SERVICE_ACCOUNT = "(?:\\bsystem:serviceaccount:[A-Za-z0-9-]+:)([A-Za-z0-9-]+)";
|
|
2009
|
+
var SSHD_FOR_USER = "(?:(?:\\bfor (?:invalid )?user|\\b[Ii]nvalid user)\\s+)([A-Za-z0-9._-]+)";
|
|
2010
|
+
var SSHD_RUSER = "(?:\\bruser=)([A-Za-z0-9._-]+)";
|
|
2011
|
+
var SSHD_LOGNAME = "(?:\\blogname=)([A-Za-z0-9._-]+)";
|
|
2012
|
+
var SUDO_USER = "(?:\\bsudo:\\s+)([A-Za-z0-9._-]+)(?=\\s+:)";
|
|
2016
2013
|
var GENERIC_KEY = "(?:user|username|login|account|owner|actor|principal|requester|createdBy|modifiedBy|assignee|operator)";
|
|
2017
|
-
var GENERIC_CTX = `(
|
|
2014
|
+
var GENERIC_CTX = `(?:\\b${GENERIC_KEY}\\s*[=:]\\s*)(${VALUE_WITH_LETTER})`;
|
|
2018
2015
|
var SLACK_USER_ID_AGGRESSIVE = "(?:\\bU[A-Z0-9]{8,10}\\b)";
|
|
2019
2016
|
var SYSTEM_ACCOUNTS = /* @__PURE__ */ new Set([
|
|
2020
2017
|
"root",
|
|
@@ -2126,6 +2123,121 @@ function getBuiltinRule(id) {
|
|
|
2126
2123
|
return builtinsById.get(id);
|
|
2127
2124
|
}
|
|
2128
2125
|
|
|
2126
|
+
// src/core/regexSource.ts
|
|
2127
|
+
function matchParen(source, openIndex) {
|
|
2128
|
+
let depth = 0;
|
|
2129
|
+
let inClass = false;
|
|
2130
|
+
for (let index = openIndex; index < source.length; index += 1) {
|
|
2131
|
+
const char = source[index];
|
|
2132
|
+
if (char === "\\") {
|
|
2133
|
+
index += 1;
|
|
2134
|
+
continue;
|
|
2135
|
+
}
|
|
2136
|
+
if (inClass) {
|
|
2137
|
+
if (char === "]") {
|
|
2138
|
+
inClass = false;
|
|
2139
|
+
}
|
|
2140
|
+
continue;
|
|
2141
|
+
}
|
|
2142
|
+
if (char === "[") {
|
|
2143
|
+
inClass = true;
|
|
2144
|
+
continue;
|
|
2145
|
+
}
|
|
2146
|
+
if (char === "(") {
|
|
2147
|
+
depth += 1;
|
|
2148
|
+
} else if (char === ")") {
|
|
2149
|
+
depth -= 1;
|
|
2150
|
+
if (depth === 0) {
|
|
2151
|
+
return index;
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
return -1;
|
|
2156
|
+
}
|
|
2157
|
+
function countCapturingGroups(source) {
|
|
2158
|
+
let count = 0;
|
|
2159
|
+
let inClass = false;
|
|
2160
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
2161
|
+
const char = source[index];
|
|
2162
|
+
if (char === "\\") {
|
|
2163
|
+
index += 1;
|
|
2164
|
+
continue;
|
|
2165
|
+
}
|
|
2166
|
+
if (inClass) {
|
|
2167
|
+
if (char === "]") {
|
|
2168
|
+
inClass = false;
|
|
2169
|
+
}
|
|
2170
|
+
continue;
|
|
2171
|
+
}
|
|
2172
|
+
if (char === "[") {
|
|
2173
|
+
inClass = true;
|
|
2174
|
+
continue;
|
|
2175
|
+
}
|
|
2176
|
+
if (char !== "(") {
|
|
2177
|
+
continue;
|
|
2178
|
+
}
|
|
2179
|
+
const next = source.slice(index, index + 4);
|
|
2180
|
+
if (next.startsWith("(?:") || next.startsWith("(?=") || next.startsWith("(?!") || next.startsWith("(?<=") || next.startsWith("(?<!")) {
|
|
2181
|
+
continue;
|
|
2182
|
+
}
|
|
2183
|
+
count += 1;
|
|
2184
|
+
}
|
|
2185
|
+
return count;
|
|
2186
|
+
}
|
|
2187
|
+
function deriveGateSource(source) {
|
|
2188
|
+
let output = "";
|
|
2189
|
+
let inClass = false;
|
|
2190
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
2191
|
+
const char = source[index];
|
|
2192
|
+
if (char === "\\") {
|
|
2193
|
+
output += source.slice(index, index + 2);
|
|
2194
|
+
index += 1;
|
|
2195
|
+
continue;
|
|
2196
|
+
}
|
|
2197
|
+
if (inClass) {
|
|
2198
|
+
output += char;
|
|
2199
|
+
if (char === "]") {
|
|
2200
|
+
inClass = false;
|
|
2201
|
+
}
|
|
2202
|
+
continue;
|
|
2203
|
+
}
|
|
2204
|
+
if (char === "[") {
|
|
2205
|
+
inClass = true;
|
|
2206
|
+
output += char;
|
|
2207
|
+
continue;
|
|
2208
|
+
}
|
|
2209
|
+
if (char === "(" && source.startsWith("(?<=", index)) {
|
|
2210
|
+
const close = matchParen(source, index);
|
|
2211
|
+
if (close === -1) {
|
|
2212
|
+
output += char;
|
|
2213
|
+
continue;
|
|
2214
|
+
}
|
|
2215
|
+
output += `(?:${source.slice(index + 4, close)})`;
|
|
2216
|
+
index = close;
|
|
2217
|
+
continue;
|
|
2218
|
+
}
|
|
2219
|
+
if (char === "(" && (source.startsWith("(?<!", index) || source.startsWith("(?=", index) || source.startsWith("(?!", index))) {
|
|
2220
|
+
const close = matchParen(source, index);
|
|
2221
|
+
if (close === -1) {
|
|
2222
|
+
output += char;
|
|
2223
|
+
continue;
|
|
2224
|
+
}
|
|
2225
|
+
index = close;
|
|
2226
|
+
continue;
|
|
2227
|
+
}
|
|
2228
|
+
output += char;
|
|
2229
|
+
}
|
|
2230
|
+
return output;
|
|
2231
|
+
}
|
|
2232
|
+
function lineHasAnyChar(line, chars) {
|
|
2233
|
+
for (let index = 0; index < line.length; index += 1) {
|
|
2234
|
+
if (chars.includes(line[index])) {
|
|
2235
|
+
return true;
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
return false;
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2129
2241
|
// src/rules/validateRule.ts
|
|
2130
2242
|
var RULE_ID_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
2131
2243
|
var TOKEN_PATTERN = /^[A-Z][A-Z0-9]*$/;
|
|
@@ -2151,7 +2263,7 @@ function assertPatterns(patterns, ruleId, field) {
|
|
|
2151
2263
|
}
|
|
2152
2264
|
if (NAMED_GROUP_PATTERN.test(pattern)) {
|
|
2153
2265
|
throw new InvalidRuleError(
|
|
2154
|
-
`Rule "${ruleId}": \`${field}[${index}]\` must not declare a named capture group
|
|
2266
|
+
`Rule "${ruleId}": \`${field}[${index}]\` must not declare a named capture group.`
|
|
2155
2267
|
);
|
|
2156
2268
|
}
|
|
2157
2269
|
try {
|
|
@@ -2161,6 +2273,11 @@ function assertPatterns(patterns, ruleId, field) {
|
|
|
2161
2273
|
`Rule "${ruleId}": \`${field}[${index}]\` is not a valid Unicode regular expression: ${String(cause)}`
|
|
2162
2274
|
);
|
|
2163
2275
|
}
|
|
2276
|
+
if (countCapturingGroups(pattern) > 1) {
|
|
2277
|
+
throw new InvalidRuleError(
|
|
2278
|
+
`Rule "${ruleId}": \`${field}[${index}]\` must contain at most one capturing group, which marks the value to replace.`
|
|
2279
|
+
);
|
|
2280
|
+
}
|
|
2164
2281
|
return pattern;
|
|
2165
2282
|
});
|
|
2166
2283
|
}
|
|
@@ -2171,7 +2288,7 @@ function validateRule(rule) {
|
|
|
2171
2288
|
const id = requireText(rule.id, String(rule.id), "id");
|
|
2172
2289
|
if (!RULE_ID_PATTERN.test(id)) {
|
|
2173
2290
|
throw new InvalidRuleError(
|
|
2174
|
-
`Rule "${id}": \`id\` must be a valid ASCII identifier matching ${RULE_ID_PATTERN.source}
|
|
2291
|
+
`Rule "${id}": \`id\` must be a valid ASCII identifier matching ${RULE_ID_PATTERN.source}.`
|
|
2175
2292
|
);
|
|
2176
2293
|
}
|
|
2177
2294
|
requireText(rule.label, id, "label");
|
|
@@ -2208,6 +2325,6 @@ function defineRule(rule) {
|
|
|
2208
2325
|
return validateRule(rule);
|
|
2209
2326
|
}
|
|
2210
2327
|
|
|
2211
|
-
export { InvalidKeyError, InvalidOptionError, InvalidRuleError, SanitizationAbortedError, SanitizerError, UnknownRuleError, builtinRuleIds, builtinRules, defineRule, getBuiltinRule, isSanitizerError, validateRule };
|
|
2212
|
-
//# sourceMappingURL=chunk-
|
|
2213
|
-
//# sourceMappingURL=chunk-
|
|
2328
|
+
export { InvalidKeyError, InvalidOptionError, InvalidRuleError, SanitizationAbortedError, SanitizerError, UnknownRuleError, builtinRuleIds, builtinRules, countCapturingGroups, defineRule, deriveGateSource, getBuiltinRule, isSanitizerError, lineHasAnyChar, validateRule };
|
|
2329
|
+
//# sourceMappingURL=chunk-5R34WEOD.js.map
|
|
2330
|
+
//# sourceMappingURL=chunk-5R34WEOD.js.map
|