@link-foundation/sensitive-data-sanitizer 0.19.2 → 0.20.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +8 -1
  3. package/bin/sensitive-data-sanitizer.js +49 -28
  4. package/docs/API.md +193 -2
  5. package/docs/COVERAGE.md +22 -4
  6. package/docs/RULES.md +217 -0
  7. package/package.json +1 -1
  8. package/src/allow-list.js +93 -0
  9. package/src/confidence.js +24 -9
  10. package/src/context.js +121 -25
  11. package/src/credentials.js +44 -0
  12. package/src/crypto-addresses.js +74 -0
  13. package/src/detection.js +21 -6
  14. package/src/document-person-cues.js +1 -1
  15. package/src/encrypt.js +95 -0
  16. package/src/entities.js +4 -3
  17. package/src/fake.js +29 -1
  18. package/src/files.js +57 -12
  19. package/src/gitleaks.js +82 -27
  20. package/src/identifier-detector.js +36 -0
  21. package/src/identity.js +14 -0
  22. package/src/index.d.ts +117 -1
  23. package/src/index.js +7 -0
  24. package/src/national-checks.js +209 -0
  25. package/src/national.js +310 -92
  26. package/src/pattern-detector.js +219 -0
  27. package/src/personal-context.js +3 -2
  28. package/src/personal-evidence.js +233 -0
  29. package/src/personal.js +42 -10
  30. package/src/projection.js +85 -26
  31. package/src/rule-catalog.js +424 -0
  32. package/src/sanitizer.js +48 -3
  33. package/src/sarif.js +127 -0
  34. package/src/strict-attributes.js +71 -0
  35. package/src/strict.js +2 -12
  36. package/src/token-checksum.js +49 -0
  37. package/src/transforms.js +108 -25
  38. package/src/vendor/betterleaks/LICENSE +21 -0
  39. package/src/vendor/betterleaks/provenance.json +11 -0
  40. package/src/vendor/betterleaks/rules-0.json +463 -0
  41. package/src/vendor/betterleaks/rules-1.json +454 -0
  42. package/src/vendor/betterleaks/rules-2.json +461 -0
  43. package/src/vendor/betterleaks/rules-3.json +455 -0
  44. package/src/vendor/betterleaks/rules-4.json +483 -0
  45. package/src/vendor/betterleaks/rules-5.json +35 -0
  46. package/src/vendor/entities/aws.json +1 -1
  47. package/src/vendor/entities/azure.json +6 -2
  48. package/src/vendor/entities/google.json +2 -1
@@ -4,16 +4,221 @@ export const builtInRules = Object.freeze([
4
4
  'anthropic',
5
5
  'authorization',
6
6
  'aws',
7
+ 'betterleaks/abuseipdb-api-key.1',
8
+ 'betterleaks/aikido-ci-token',
9
+ 'betterleaks/aikido-client-secret',
10
+ 'betterleaks/airtable-oauth-token',
11
+ 'betterleaks/aiven-auth-token',
12
+ 'betterleaks/alibaba-sts-access-key-secret',
13
+ 'betterleaks/amplitude-secret-key',
14
+ 'betterleaks/apify-api-token',
15
+ 'betterleaks/apollo-api-key.1',
16
+ 'betterleaks/asaas-api-token',
17
+ 'betterleaks/assemblyai-api-key',
18
+ 'betterleaks/auth0-client-secret.1',
19
+ 'betterleaks/azure-app-configuration-connection-string',
20
+ 'betterleaks/azure-servicebus-connection-string',
21
+ 'betterleaks/azure-storage-account-key',
22
+ 'betterleaks/bitbucket-data-center-token',
23
+ 'betterleaks/bitly-access-token',
24
+ 'betterleaks/bitrise-access-token',
25
+ 'betterleaks/box-api-access-token',
26
+ 'betterleaks/brave-search-api-key',
27
+ 'betterleaks/browserstack-access-key.1',
28
+ 'betterleaks/buildkite-service-token',
29
+ 'betterleaks/buildkite-user-access-token',
30
+ 'betterleaks/canadian-digital-service-notify-api-key',
31
+ 'betterleaks/canva-client-secret',
32
+ 'betterleaks/cartesia-api-key.1',
33
+ 'betterleaks/cerebras-api-key',
34
+ 'betterleaks/checkout-secret-key',
35
+ 'betterleaks/circleci-personal-token',
36
+ 'betterleaks/circleci-project-token',
37
+ 'betterleaks/civo-api-key',
38
+ 'betterleaks/clerk-secret-key',
39
+ 'betterleaks/clickup-personal-api-token',
40
+ 'betterleaks/cloudflare-api-key.2',
41
+ 'betterleaks/cloudinary-api-secret',
42
+ 'betterleaks/cloudsmith-api-key',
43
+ 'betterleaks/cockroachlabs-cloud-api-key',
44
+ 'betterleaks/configcat-sdk-key',
45
+ 'betterleaks/configcat-sdk-key-extended',
46
+ 'betterleaks/couchbase-capella-api-key',
47
+ 'betterleaks/coveralls-personal-api-token',
48
+ 'betterleaks/crates-io-api-key',
49
+ 'betterleaks/cursor-api-key',
50
+ 'betterleaks/databento-api-key',
51
+ 'betterleaks/datadog-api-key',
52
+ 'betterleaks/datadog-application-key',
53
+ 'betterleaks/datagov-api-key',
54
+ 'betterleaks/datastax-astra-application-token',
55
+ 'betterleaks/deepgram-api-key',
56
+ 'betterleaks/deepseek-api-key',
57
+ 'betterleaks/deno-account-token',
58
+ 'betterleaks/devcycle-client-sdk-key',
59
+ 'betterleaks/devcycle-mobile-sdk-key',
60
+ 'betterleaks/devcycle-server-sdk-key',
61
+ 'betterleaks/devin-personal-api-key',
62
+ 'betterleaks/devin-service-api-key',
63
+ 'betterleaks/devin-service-user-token',
64
+ 'betterleaks/disqus-api-key',
65
+ 'betterleaks/docker-swarm-join-token',
66
+ 'betterleaks/docker-swarm-unlock-key',
67
+ 'betterleaks/dockerhub-organization-access-token',
68
+ 'betterleaks/dockerhub-personal-access-token',
69
+ 'betterleaks/ebay-client-secret',
70
+ 'betterleaks/elastic-cloud-api-key',
71
+ 'betterleaks/elevenlabs-api-key',
72
+ 'betterleaks/endorlabs-api-key',
73
+ 'betterleaks/endorlabs-api-secret',
74
+ 'betterleaks/etsy-open-api-key',
75
+ 'betterleaks/exoscale-api-key',
76
+ 'betterleaks/fal-api-key.1',
77
+ 'betterleaks/figma-personal-access-header-token',
78
+ 'betterleaks/figma-personal-access-token',
79
+ 'betterleaks/fullstory-api-key',
80
+ 'betterleaks/gcp-application-default-credentials',
81
+ 'betterleaks/gcp-gemini-api',
82
+ 'betterleaks/gcp-service-account',
83
+ 'betterleaks/gitea-access-token',
84
+ 'betterleaks/gitlab-incoming-mail-address-token',
85
+ 'betterleaks/gitlab-pat-routable-versioned',
86
+ 'betterleaks/greptile-api-key',
87
+ 'betterleaks/groq-api-key',
88
+ 'betterleaks/gumroad-access-token',
89
+ 'betterleaks/highnote-secret-live-key',
90
+ 'betterleaks/honeycomb-api-key',
91
+ 'betterleaks/hunter-api-key.1',
92
+ 'betterleaks/ibm-cloud-user-api-key',
93
+ 'betterleaks/influxdb-api-token',
94
+ 'betterleaks/infomaniak-api-token',
95
+ 'betterleaks/instantly-api-key.1',
96
+ 'betterleaks/ionic-personal-access-token',
97
+ 'betterleaks/jumpcloud-api-key',
98
+ 'betterleaks/kagi-api-key',
99
+ 'betterleaks/kimi-api-key',
100
+ 'betterleaks/klaviyo-api-key',
101
+ 'betterleaks/langchain-langsmith-personal-access-token',
102
+ 'betterleaks/langchain-langsmith-service-key',
103
+ 'betterleaks/langfuse-secret-key.1',
104
+ 'betterleaks/lark-app-secret',
105
+ 'betterleaks/lichess-personal-access-token',
106
+ 'betterleaks/lighton-paradigm-api-key',
107
+ 'betterleaks/llama-cloud-api-key.1',
108
+ 'betterleaks/mailersend-api-token',
109
+ 'betterleaks/mem0-api-key.1',
110
+ 'betterleaks/mercury-production-api-token',
111
+ 'betterleaks/mergify-application-key',
112
+ 'betterleaks/midtrans-production-server-client-key',
113
+ 'betterleaks/minimax-api-key',
114
+ 'betterleaks/miro-access-token',
115
+ 'betterleaks/miro-client-secret',
116
+ 'betterleaks/mistral-api-key',
117
+ 'betterleaks/monday-api-token.1',
118
+ 'betterleaks/mongodb-atlas-service-account-secret',
119
+ 'betterleaks/mongodb-connection-string',
120
+ 'betterleaks/mux-access-token-secret.1',
121
+ 'betterleaks/neon-api-key',
122
+ 'betterleaks/ngrok-api-key.1',
123
+ 'betterleaks/nuget-api-key',
124
+ 'betterleaks/nvidia-api-key',
125
+ 'betterleaks/nylas-api-key.1',
126
+ 'betterleaks/ollama-api-key',
127
+ 'betterleaks/onesignal-rich-authentication-token',
128
+ 'betterleaks/onfido-live-api-token-ca',
129
+ 'betterleaks/onfido-live-api-token-eu',
130
+ 'betterleaks/onfido-live-api-token-us',
131
+ 'betterleaks/openrouter-api-key',
132
+ 'betterleaks/openweather-api-key',
133
+ 'betterleaks/opsgenie-api-key.1',
134
+ 'betterleaks/ovh-application-secret',
135
+ 'betterleaks/paddle-live-api-key',
136
+ 'betterleaks/pagerduty-authorization-token.1',
137
+ 'betterleaks/paypal-client-secret.1',
138
+ 'betterleaks/persona-production-api-key',
139
+ 'betterleaks/pinecone-api-key.1',
140
+ 'betterleaks/pinecone-api-key.2',
141
+ 'betterleaks/pinterest-access-token',
142
+ 'betterleaks/plivo-auth-token',
143
+ 'betterleaks/polar-oauth-access-token',
144
+ 'betterleaks/polar-organization-access-token',
145
+ 'betterleaks/polar-personal-access-token',
146
+ 'betterleaks/polymarket-api-key',
147
+ 'betterleaks/polymarket-private-key',
148
+ 'betterleaks/posthog-personal-api-key',
149
+ 'betterleaks/posthog-project-api-key',
150
+ 'betterleaks/postmark-api-token.1',
151
+ 'betterleaks/proof-full-access-api-key',
152
+ 'betterleaks/rainforest-pay-production-api-key',
153
+ 'betterleaks/ramp-client-secret',
154
+ 'betterleaks/razorpay-key-secret.1',
155
+ 'betterleaks/redirect-pizza-api-token.1',
156
+ 'betterleaks/render-api-key',
157
+ 'betterleaks/replicate-api-token',
158
+ 'betterleaks/resend-api-key.1',
159
+ 'betterleaks/retell-api-key.1',
160
+ 'betterleaks/rootly-api-key.1',
161
+ 'betterleaks/runpod-api-key.1',
162
+ 'betterleaks/salesforce-access-token.1',
163
+ 'betterleaks/samsara-api-token.1',
164
+ 'betterleaks/scaleway-secret-key',
165
+ 'betterleaks/scalr-api-access-token.1',
166
+ 'betterleaks/segment-public-api-token.1',
167
+ 'betterleaks/slack-session-cookie',
168
+ 'betterleaks/slack-session-token',
169
+ 'betterleaks/snowflake-programmatic-access-token.1',
170
+ 'betterleaks/sslmate-api-key.1',
171
+ 'betterleaks/stability-ai-api-key',
172
+ 'betterleaks/supabase-management-token',
173
+ 'betterleaks/supabase-project-api-key',
174
+ 'betterleaks/tableau-personal-access-token.1',
175
+ 'betterleaks/tailscale-api-key.1',
176
+ 'betterleaks/telnyx-api-v2-key.1',
177
+ 'betterleaks/temporal-cloud-api-key.1',
178
+ 'betterleaks/thunderstore-api-token.1',
179
+ 'betterleaks/togetherai-api-key',
180
+ 'betterleaks/unkey-root-key.1',
181
+ 'betterleaks/upcloud-api-token',
182
+ 'betterleaks/upstage-api-key',
183
+ 'betterleaks/upstash-redis-rest-token.1',
184
+ 'betterleaks/val-town-api-token.1',
185
+ 'betterleaks/vercel-ai-gateway-key',
186
+ 'betterleaks/vercel-api-token',
187
+ 'betterleaks/vercel-app-access-token',
188
+ 'betterleaks/vercel-app-refresh-token',
189
+ 'betterleaks/vercel-integration-token',
190
+ 'betterleaks/vercel-personal-access-token',
191
+ 'betterleaks/virustotal-api-key.1',
192
+ 'betterleaks/voyageai-api-key',
193
+ 'betterleaks/vultr-api-key.1',
194
+ 'betterleaks/wakatime-api-key.1',
195
+ 'betterleaks/wakatime-api-key.2',
196
+ 'betterleaks/weatherstack-api-key.1',
197
+ 'betterleaks/weights-and-biases-api-key',
198
+ 'betterleaks/weights-and-biases-api-key-v1',
199
+ 'betterleaks/wiz-client-secret.1',
200
+ 'betterleaks/woocommerce-consumer-secret.1',
201
+ 'betterleaks/workato-developer-api-token.1',
202
+ 'betterleaks/workos-production-api-key.1',
203
+ 'betterleaks/xai-api-key',
204
+ 'betterleaks/xendit-production-api-key.1',
205
+ 'betterleaks/zai-api-key',
206
+ 'betterleaks/zoho-client-secret.1',
207
+ 'betterleaks/zoho-oauth-token.1',
208
+ 'betterleaks/zoho-zapi-key.1',
209
+ 'betterleaks/zuplo-consumer-api-key.1',
7
210
  'birth-context',
8
211
  'birth-year',
9
212
  'booking-context',
10
213
  'booking-filename',
214
+ 'card-context',
11
215
  'catalog/aws',
12
216
  'catalog/azure',
13
217
  'catalog/google',
14
218
  'cli-password',
15
219
  'context',
16
220
  'cookie',
221
+ 'credential-pair',
17
222
  'databricks',
18
223
  'detect-secrets',
19
224
  'digitalocean',
@@ -307,6 +512,7 @@ export const builtInRules = Object.freeze([
307
512
  'google',
308
513
  'grafana',
309
514
  'home-path',
515
+ 'honorific-name',
310
516
  'huggingface',
311
517
  'iban-checksum',
312
518
  'identity-number',
@@ -321,8 +527,10 @@ export const builtInRules = Object.freeze([
321
527
  'location-gazetteer',
322
528
  'location-label',
323
529
  'location-residence',
530
+ 'login-call',
324
531
  'luhn',
325
532
  'mac',
533
+ 'mail-display-name',
326
534
  'mailchimp',
327
535
  'messenger-handle',
328
536
  'messenger-label',
@@ -334,6 +542,7 @@ export const builtInRules = Object.freeze([
334
542
  'name-initials',
335
543
  'name-title',
336
544
  'name-variant',
545
+ 'named-value',
337
546
  'national-format',
338
547
  'national-phone',
339
548
  'ner/offline',
@@ -357,10 +566,13 @@ export const builtInRules = Object.freeze([
357
566
  'passport-format',
358
567
  'passport-issuer',
359
568
  'passport-series',
569
+ 'password-hash',
360
570
  'personal-profile-url',
361
571
  'phone-context',
572
+ 'po-box',
362
573
  'postal-address',
363
574
  'postal-code',
575
+ 'postal-label',
364
576
  'presidio',
365
577
  'private-key',
366
578
  'profile-attribute',
@@ -370,12 +582,17 @@ export const builtInRules = Object.freeze([
370
582
  'pypi',
371
583
  'quoted-entropy',
372
584
  'residence-prose',
585
+ 'salutation',
373
586
  'school-acronym-context',
374
587
  'secretlint',
588
+ 'self-introduction',
375
589
  'sendgrid',
376
590
  'shopify',
591
+ 'sign-off',
377
592
  'slack',
378
593
  'square',
594
+ 'ssn-label',
595
+ 'state-zip',
379
596
  'strict-age',
380
597
  'strict-attribute',
381
598
  'strict-date',
@@ -400,12 +617,216 @@ export const credentialRules = new Set([
400
617
  'anthropic',
401
618
  'authorization',
402
619
  'aws',
620
+ 'betterleaks/abuseipdb-api-key.1',
621
+ 'betterleaks/aikido-ci-token',
622
+ 'betterleaks/aikido-client-secret',
623
+ 'betterleaks/airtable-oauth-token',
624
+ 'betterleaks/aiven-auth-token',
625
+ 'betterleaks/alibaba-sts-access-key-secret',
626
+ 'betterleaks/amplitude-secret-key',
627
+ 'betterleaks/apify-api-token',
628
+ 'betterleaks/apollo-api-key.1',
629
+ 'betterleaks/asaas-api-token',
630
+ 'betterleaks/assemblyai-api-key',
631
+ 'betterleaks/auth0-client-secret.1',
632
+ 'betterleaks/azure-app-configuration-connection-string',
633
+ 'betterleaks/azure-servicebus-connection-string',
634
+ 'betterleaks/azure-storage-account-key',
635
+ 'betterleaks/bitbucket-data-center-token',
636
+ 'betterleaks/bitly-access-token',
637
+ 'betterleaks/bitrise-access-token',
638
+ 'betterleaks/box-api-access-token',
639
+ 'betterleaks/brave-search-api-key',
640
+ 'betterleaks/browserstack-access-key.1',
641
+ 'betterleaks/buildkite-service-token',
642
+ 'betterleaks/buildkite-user-access-token',
643
+ 'betterleaks/canadian-digital-service-notify-api-key',
644
+ 'betterleaks/canva-client-secret',
645
+ 'betterleaks/cartesia-api-key.1',
646
+ 'betterleaks/cerebras-api-key',
647
+ 'betterleaks/checkout-secret-key',
648
+ 'betterleaks/circleci-personal-token',
649
+ 'betterleaks/circleci-project-token',
650
+ 'betterleaks/civo-api-key',
651
+ 'betterleaks/clerk-secret-key',
652
+ 'betterleaks/clickup-personal-api-token',
653
+ 'betterleaks/cloudflare-api-key.2',
654
+ 'betterleaks/cloudinary-api-secret',
655
+ 'betterleaks/cloudsmith-api-key',
656
+ 'betterleaks/cockroachlabs-cloud-api-key',
657
+ 'betterleaks/configcat-sdk-key',
658
+ 'betterleaks/configcat-sdk-key-extended',
659
+ 'betterleaks/couchbase-capella-api-key',
660
+ 'betterleaks/coveralls-personal-api-token',
661
+ 'betterleaks/crates-io-api-key',
662
+ 'betterleaks/cursor-api-key',
663
+ 'betterleaks/databento-api-key',
664
+ 'betterleaks/datadog-api-key',
665
+ 'betterleaks/datadog-application-key',
666
+ 'betterleaks/datagov-api-key',
667
+ 'betterleaks/datastax-astra-application-token',
668
+ 'betterleaks/deepgram-api-key',
669
+ 'betterleaks/deepseek-api-key',
670
+ 'betterleaks/deno-account-token',
671
+ 'betterleaks/devcycle-client-sdk-key',
672
+ 'betterleaks/devcycle-mobile-sdk-key',
673
+ 'betterleaks/devcycle-server-sdk-key',
674
+ 'betterleaks/devin-personal-api-key',
675
+ 'betterleaks/devin-service-api-key',
676
+ 'betterleaks/devin-service-user-token',
677
+ 'betterleaks/disqus-api-key',
678
+ 'betterleaks/docker-swarm-join-token',
679
+ 'betterleaks/docker-swarm-unlock-key',
680
+ 'betterleaks/dockerhub-organization-access-token',
681
+ 'betterleaks/dockerhub-personal-access-token',
682
+ 'betterleaks/ebay-client-secret',
683
+ 'betterleaks/elastic-cloud-api-key',
684
+ 'betterleaks/elevenlabs-api-key',
685
+ 'betterleaks/endorlabs-api-key',
686
+ 'betterleaks/endorlabs-api-secret',
687
+ 'betterleaks/etsy-open-api-key',
688
+ 'betterleaks/exoscale-api-key',
689
+ 'betterleaks/fal-api-key.1',
690
+ 'betterleaks/figma-personal-access-header-token',
691
+ 'betterleaks/figma-personal-access-token',
692
+ 'betterleaks/fullstory-api-key',
693
+ 'betterleaks/gcp-application-default-credentials',
694
+ 'betterleaks/gcp-gemini-api',
695
+ 'betterleaks/gcp-service-account',
696
+ 'betterleaks/gitea-access-token',
697
+ 'betterleaks/gitlab-incoming-mail-address-token',
698
+ 'betterleaks/gitlab-pat-routable-versioned',
699
+ 'betterleaks/greptile-api-key',
700
+ 'betterleaks/groq-api-key',
701
+ 'betterleaks/gumroad-access-token',
702
+ 'betterleaks/highnote-secret-live-key',
703
+ 'betterleaks/honeycomb-api-key',
704
+ 'betterleaks/hunter-api-key.1',
705
+ 'betterleaks/ibm-cloud-user-api-key',
706
+ 'betterleaks/influxdb-api-token',
707
+ 'betterleaks/infomaniak-api-token',
708
+ 'betterleaks/instantly-api-key.1',
709
+ 'betterleaks/ionic-personal-access-token',
710
+ 'betterleaks/jumpcloud-api-key',
711
+ 'betterleaks/kagi-api-key',
712
+ 'betterleaks/kimi-api-key',
713
+ 'betterleaks/klaviyo-api-key',
714
+ 'betterleaks/langchain-langsmith-personal-access-token',
715
+ 'betterleaks/langchain-langsmith-service-key',
716
+ 'betterleaks/langfuse-secret-key.1',
717
+ 'betterleaks/lark-app-secret',
718
+ 'betterleaks/lichess-personal-access-token',
719
+ 'betterleaks/lighton-paradigm-api-key',
720
+ 'betterleaks/llama-cloud-api-key.1',
721
+ 'betterleaks/mailersend-api-token',
722
+ 'betterleaks/mem0-api-key.1',
723
+ 'betterleaks/mercury-production-api-token',
724
+ 'betterleaks/mergify-application-key',
725
+ 'betterleaks/midtrans-production-server-client-key',
726
+ 'betterleaks/minimax-api-key',
727
+ 'betterleaks/miro-access-token',
728
+ 'betterleaks/miro-client-secret',
729
+ 'betterleaks/mistral-api-key',
730
+ 'betterleaks/monday-api-token.1',
731
+ 'betterleaks/mongodb-atlas-service-account-secret',
732
+ 'betterleaks/mongodb-connection-string',
733
+ 'betterleaks/mux-access-token-secret.1',
734
+ 'betterleaks/neon-api-key',
735
+ 'betterleaks/ngrok-api-key.1',
736
+ 'betterleaks/nuget-api-key',
737
+ 'betterleaks/nvidia-api-key',
738
+ 'betterleaks/nylas-api-key.1',
739
+ 'betterleaks/ollama-api-key',
740
+ 'betterleaks/onesignal-rich-authentication-token',
741
+ 'betterleaks/onfido-live-api-token-ca',
742
+ 'betterleaks/onfido-live-api-token-eu',
743
+ 'betterleaks/onfido-live-api-token-us',
744
+ 'betterleaks/openrouter-api-key',
745
+ 'betterleaks/openweather-api-key',
746
+ 'betterleaks/opsgenie-api-key.1',
747
+ 'betterleaks/ovh-application-secret',
748
+ 'betterleaks/paddle-live-api-key',
749
+ 'betterleaks/pagerduty-authorization-token.1',
750
+ 'betterleaks/paypal-client-secret.1',
751
+ 'betterleaks/persona-production-api-key',
752
+ 'betterleaks/pinecone-api-key.1',
753
+ 'betterleaks/pinecone-api-key.2',
754
+ 'betterleaks/pinterest-access-token',
755
+ 'betterleaks/plivo-auth-token',
756
+ 'betterleaks/polar-oauth-access-token',
757
+ 'betterleaks/polar-organization-access-token',
758
+ 'betterleaks/polar-personal-access-token',
759
+ 'betterleaks/polymarket-api-key',
760
+ 'betterleaks/polymarket-private-key',
761
+ 'betterleaks/posthog-personal-api-key',
762
+ 'betterleaks/posthog-project-api-key',
763
+ 'betterleaks/postmark-api-token.1',
764
+ 'betterleaks/proof-full-access-api-key',
765
+ 'betterleaks/rainforest-pay-production-api-key',
766
+ 'betterleaks/ramp-client-secret',
767
+ 'betterleaks/razorpay-key-secret.1',
768
+ 'betterleaks/redirect-pizza-api-token.1',
769
+ 'betterleaks/render-api-key',
770
+ 'betterleaks/replicate-api-token',
771
+ 'betterleaks/resend-api-key.1',
772
+ 'betterleaks/retell-api-key.1',
773
+ 'betterleaks/rootly-api-key.1',
774
+ 'betterleaks/runpod-api-key.1',
775
+ 'betterleaks/salesforce-access-token.1',
776
+ 'betterleaks/samsara-api-token.1',
777
+ 'betterleaks/scaleway-secret-key',
778
+ 'betterleaks/scalr-api-access-token.1',
779
+ 'betterleaks/segment-public-api-token.1',
780
+ 'betterleaks/slack-session-cookie',
781
+ 'betterleaks/slack-session-token',
782
+ 'betterleaks/snowflake-programmatic-access-token.1',
783
+ 'betterleaks/sslmate-api-key.1',
784
+ 'betterleaks/stability-ai-api-key',
785
+ 'betterleaks/supabase-management-token',
786
+ 'betterleaks/supabase-project-api-key',
787
+ 'betterleaks/tableau-personal-access-token.1',
788
+ 'betterleaks/tailscale-api-key.1',
789
+ 'betterleaks/telnyx-api-v2-key.1',
790
+ 'betterleaks/temporal-cloud-api-key.1',
791
+ 'betterleaks/thunderstore-api-token.1',
792
+ 'betterleaks/togetherai-api-key',
793
+ 'betterleaks/unkey-root-key.1',
794
+ 'betterleaks/upcloud-api-token',
795
+ 'betterleaks/upstage-api-key',
796
+ 'betterleaks/upstash-redis-rest-token.1',
797
+ 'betterleaks/val-town-api-token.1',
798
+ 'betterleaks/vercel-ai-gateway-key',
799
+ 'betterleaks/vercel-api-token',
800
+ 'betterleaks/vercel-app-access-token',
801
+ 'betterleaks/vercel-app-refresh-token',
802
+ 'betterleaks/vercel-integration-token',
803
+ 'betterleaks/vercel-personal-access-token',
804
+ 'betterleaks/virustotal-api-key.1',
805
+ 'betterleaks/voyageai-api-key',
806
+ 'betterleaks/vultr-api-key.1',
807
+ 'betterleaks/wakatime-api-key.1',
808
+ 'betterleaks/wakatime-api-key.2',
809
+ 'betterleaks/weatherstack-api-key.1',
810
+ 'betterleaks/weights-and-biases-api-key',
811
+ 'betterleaks/weights-and-biases-api-key-v1',
812
+ 'betterleaks/wiz-client-secret.1',
813
+ 'betterleaks/woocommerce-consumer-secret.1',
814
+ 'betterleaks/workato-developer-api-token.1',
815
+ 'betterleaks/workos-production-api-key.1',
816
+ 'betterleaks/xai-api-key',
817
+ 'betterleaks/xendit-production-api-key.1',
818
+ 'betterleaks/zai-api-key',
819
+ 'betterleaks/zoho-client-secret.1',
820
+ 'betterleaks/zoho-oauth-token.1',
821
+ 'betterleaks/zoho-zapi-key.1',
822
+ 'betterleaks/zuplo-consumer-api-key.1',
403
823
  'catalog/aws',
404
824
  'catalog/azure',
405
825
  'catalog/google',
406
826
  'cli-password',
407
827
  'context',
408
828
  'cookie',
829
+ 'credential-pair',
409
830
  'databricks',
410
831
  'digitalocean',
411
832
  'discord',
@@ -645,12 +1066,15 @@ export const credentialRules = new Set([
645
1066
  'jwt',
646
1067
  'known-secret',
647
1068
  'linear',
1069
+ 'login-call',
648
1070
  'mailchimp',
1071
+ 'named-value',
649
1072
  'netrc',
650
1073
  'notion',
651
1074
  'npm',
652
1075
  'nuget',
653
1076
  'openai',
1077
+ 'password-hash',
654
1078
  'private-key',
655
1079
  'putty-private-key',
656
1080
  'pypi',
package/src/sanitizer.js CHANGED
@@ -28,6 +28,9 @@ import {
28
28
  } from './transforms.js';
29
29
  import { fakeIdentityValue, isIdentityType } from './identity.js';
30
30
  import { rejectRestoreMap } from './restore-map.js';
31
+ import { allowListed, validateAllowList } from './allow-list.js';
32
+ import { templatedCredential } from './credentials.js';
33
+ import { builtInRules } from './rule-catalog.js';
31
34
  import {
32
35
  initializePlaceholders,
33
36
  placeholderKnown,
@@ -99,6 +102,9 @@ const optionNames = new Set([
99
102
  'strict',
100
103
  'exactFields',
101
104
  'allowedFields',
105
+ 'minConfidenceByType',
106
+ 'allowList',
107
+ 'inlineAllow',
102
108
  ]);
103
109
 
104
110
  export function applyProfile(options = {}) {
@@ -225,6 +231,7 @@ export function validateOptions(options = {}) {
225
231
  throw failure('ERR_CONFIG');
226
232
  }
227
233
  validateCollections(options);
234
+ validateAllowList(options);
228
235
  validateDetectors(options.detectors);
229
236
  validatePolicyControls(options);
230
237
  compiledVocabulary(options.vocabulary);
@@ -255,6 +262,22 @@ function validateConfidence(options) {
255
262
  ) {
256
263
  throw failure('ERR_CONFIG');
257
264
  }
265
+ const byType = options.minConfidenceByType;
266
+ if (
267
+ byType !== undefined &&
268
+ (!byType ||
269
+ typeof byType !== 'object' ||
270
+ Array.isArray(byType) ||
271
+ !Object.entries(byType).every(
272
+ ([type, value]) =>
273
+ validType(type) &&
274
+ typeof value === 'number' &&
275
+ value >= 0 &&
276
+ value <= 1
277
+ ))
278
+ ) {
279
+ throw failure('ERR_CONFIG');
280
+ }
258
281
  }
259
282
 
260
283
  function validatePolicy(options) {
@@ -518,12 +541,34 @@ function inspectText(text, options = {}) {
518
541
  return reviewFindings(text, findings, options);
519
542
  }
520
543
 
544
+ // Allow-listed values and built-in credential matches whose value is only a
545
+ // template or mask (`${PASSWORD}`, `<token>`, `****`) are not findings.
546
+ function policyKept(text, finding, options) {
547
+ if (allowListed(text, finding, options)) {
548
+ return false;
549
+ }
550
+ if (builtInRule(finding) && templatedCredential(text, finding)) {
551
+ options.debug?.({ event: 'template-value', rule: finding.rule });
552
+ return false;
553
+ }
554
+ return true;
555
+ }
556
+
557
+ // Custom detectors keep their findings: they may flag placeholder shapes on
558
+ // purpose, and the residual check must still see them.
559
+ const builtInRuleIds = new Set(builtInRules);
560
+ const builtInRule = (finding) =>
561
+ builtInRuleIds.has(finding.rule) ||
562
+ finding.rule === 'secretlint' ||
563
+ finding.rule.startsWith('gitleaks/');
564
+
521
565
  // Reapply policy to the native/required-engine union without rescanning text.
522
566
  export function reviewFindings(text, findings, options) {
523
567
  findings = placeholderNameFindings(text, findings, options);
524
568
  if (findings.length > (options.maxFindings ?? 100000)) {
525
569
  throw failure('ERR_LIMIT');
526
570
  }
571
+ findings = findings.filter((f) => policyKept(text, f, options));
527
572
  const unique = new Map();
528
573
  const exempt = findings.filter((f) =>
529
574
  allowed(text, f, options.publicEntities ?? [])
@@ -565,9 +610,9 @@ function coveredByPublic(finding, exempt) {
565
610
  }
566
611
 
567
612
  export function inspectFindingsOnly(text, findings, options) {
568
- const all = [...findings, ...(options.findings ?? [])].map((f) =>
569
- sanitizeFinding(f, text.length)
570
- );
613
+ const all = [...findings, ...(options.findings ?? [])]
614
+ .map((f) => sanitizeFinding(f, text.length))
615
+ .filter((f) => policyKept(text, f, options));
571
616
  if (all.length > (options.maxFindings ?? 100000)) {
572
617
  throw failure('ERR_LIMIT');
573
618
  }