sanitize-contents 1.0.0 → 1.0.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/README.md CHANGED
@@ -1,40 +1,99 @@
1
- # sanitize-content
1
+ # sanitize-contents
2
2
 
3
- A robust, lightweight library to sanitize sensitive information (passwords, tokens, connection strings, etc.) from strings and HTML content.
3
+ ![NPM Version](https://img.shields.io/npm/v/sanitize-contents?style=flat-square)
4
+ ![License](https://img.shields.io/npm/l/sanitize-contents?style=flat-square)
5
+ ![Downloads](https://img.shields.io/npm/dm/sanitize-contents?style=flat-square)
4
6
 
5
- ## Features
7
+ A **robust**, **lightweight**, and **customizable** library to sanitize sensitive information (passwords, tokens, API keys, connection strings, PCI/PII data) from strings and HTML content.
6
8
 
7
- - **Connection Strings**: Redacts user:pass from `mongodb://`, `postgres://`, `redis://`, etc.
8
- - **Query Parameters**: Redacts sensitive keys like `api_key`, `access_token`, `secret`, `password` from URLs.
9
- - **Authorization Headers**: Sanitizes `Bearer` and `Basic` auth tokens.
10
- - **Credential Labels**: Identifies and redacts common patterns like `Password: ...`, `API Key: ...`.
11
- - **CURL Auth**: Sanitizes `-u user:pass` flags in curl commands.
12
- - **Lightweight**: Zero dependencies.
9
+ Perfect for logging, error reporting, and audit trails where you need to keep data clean and safe.
13
10
 
14
- ## Installation
11
+ ## ✨ Features
12
+
13
+ - **🚀 Smart Detection**: Automatically identifies connection strings, raw SQL inserts, query parameters, auth headers, and more.
14
+ - **🛡️ Connection Strings**: Redacts credentials from `mongodb://`, `postgres://`, `redis://`, `mysql://`, and generic URIs.
15
+ - **🔑 Keys & Tokens**: Redacts common keys like `api_key`, `access_token`, `secret`, `jwt`, `bearer` tokens.
16
+ - **📝 Credential Labels**: Identifies patterns like `Password: ...`, `API Key: ...` in unstructured text.
17
+ - **🌐 Network Safe**: Sanitizes `Authorization` headers and `curl` command flags (`-u`).
18
+ - **🎨 Customizable**: Choose your replacement string (e.g., `[HIDDEN]`) or remove content entirely.
19
+ - **📄 HTML Support**: Safely sanitizes text content within HTML while preserving valid structure.
20
+ - **⚡ Lightweight**: Minimal overhead, high performance.
21
+
22
+ ## 📦 Installation
15
23
 
16
24
  ```bash
17
- npm install sanitize-content
25
+ npm install sanitize-contents
18
26
  ```
19
27
 
20
- ## Usage
28
+ ## 🚀 Usage
29
+
30
+ ### Basic Sanitization
21
31
 
22
32
  ```javascript
23
- import { sanitizeContent } from 'sanitize-content';
33
+ import { sanitizeContent } from 'sanitize-contents';
34
+
35
+ // Connection Strings
36
+ const dbUrl = 'mongodb://admin:superSecretPassword@localhost:27017/my_app';
37
+ console.log(sanitizeContent(dbUrl));
38
+ // Output: mongodb://[REDACTED]@localhost:27017/my_app
39
+
40
+ // API Keys in URLs
41
+ const apiUrl = 'https://api.example.com?api_key=sk-123456789&lang=en';
42
+ console.log(sanitizeContent(apiUrl));
43
+ // Output: https://api.example.com?api_key=[REDACTED]&lang=en
44
+
45
+ // Authorization Headers
46
+ const authHeader = 'Authorization: Bearer my-confidential-token-value';
47
+ console.log(sanitizeContent(authHeader));
48
+ // Output: Authorization: Bearer [REDACTED]
49
+ ```
50
+
51
+ ### 🛠️ Custom Options
24
52
 
25
- const rawContent = 'Connecting to mongodb://user:pass123@localhost:27017/db';
26
- const cleanContent = sanitizeContent(rawContent);
27
- // Connecting to mongodb://[REDACTED]@localhost:27017/db
53
+ You can customize the replacement string or behavior using the options object.
28
54
 
29
- const url = 'https://api.example.com?api_key=sk-123456789';
30
- console.log(sanitizeContent(url));
31
- // https://api.example.com?api_key=[REDACTED]
55
+ #### Custom Replacement Text
32
56
 
33
- const header = 'Authorization: Bearer my-secret-token';
34
- console.log(sanitizeContent(header));
35
- // Authorization: Bearer [REDACTED]
57
+ ```javascript
58
+ const log = 'User password=secret123 failed login.';
59
+ console.log(sanitizeContent(log, { replacement: '[HIDDEN]' }));
60
+ // Output: User password=[HIDDEN] failed login.
36
61
  ```
37
62
 
38
- ## License
63
+ #### Complete Removal
64
+
65
+ Pass an empty string to remove the sensitive value entirely.
66
+
67
+ ```javascript
68
+ const sensitive = 'api_key=12345';
69
+ console.log(sanitizeContent(sensitive, { replacement: '' }));
70
+ // Output: api_key=
71
+ ```
72
+
73
+ ### 📄 HTML Content
74
+
75
+ To sanitize content inside HTML without breaking tags:
76
+
77
+ ```javascript
78
+ import { sanitizeDescription } from 'sanitize-contents';
79
+
80
+ const html = '<div class="user-info">Password: <b>secret123</b></div>';
81
+ const result = sanitizeDescription(html);
82
+ console.log(result.sanitized_text);
83
+ // Output: <div class="user-info">Password: <b>[REDACTED]</b></div>
84
+ ```
85
+
86
+ ## 🔍 What it Detects
87
+
88
+ - **Databases**: MongoDB, MySQL, Postgres, Redis connection strings.
89
+ - **Web**: HTTP Query Params (`api_key`, `token`, `password`, `secret`, `session`, etc.).
90
+ - **Headers**: `Authorization` (Bearer/Basic), `Cookie` values (if resembling tokens).
91
+ - **Commands**: `curl` auth flags.
92
+ - **Code**: variable assignments like `PASSWORD = "..."`, `const secret = '...'`.
93
+ - **Text**: Natural language credential dumps (`"password is ..."`, `"login with ..."`).
94
+ - **Formats**: JSON (heuristic), XML tags, URL-encoded values.
95
+
96
+
97
+ ## 📄 License
39
98
 
40
99
  ISC
package/dist/index.d.mts CHANGED
@@ -2,16 +2,27 @@
2
2
  * Sanitizes sensitive information from content.
3
3
  * Redacts passwords, connection strings, API keys, etc.
4
4
  */
5
+ /**
6
+ * Options for sanitization.
7
+ */
8
+ interface SanitizeOptions {
9
+ /**
10
+ * The string to replace sensitive content with.
11
+ * Defaults to "[REDACTED]".
12
+ * set empty string to remove the sensitive content.
13
+ */
14
+ replacement?: string;
15
+ }
5
16
  /**
6
17
  * Sanitizes a string by redacting sensitive patterns.
7
18
  */
8
- declare function sanitizeContent(content: string): string;
19
+ declare function sanitizeContent(content: string, options?: SanitizeOptions): string;
9
20
  /**
10
21
  * Sanitizes HTML content by processing only text nodes.
11
22
  * Matches the API of the user's legacy script.
12
23
  */
13
- declare function sanitizeDescription(html: string): {
24
+ declare function sanitizeDescription(html: string, options?: SanitizeOptions): {
14
25
  sanitized_text: string;
15
26
  };
16
27
 
17
- export { sanitizeContent as default, sanitizeContent, sanitizeDescription };
28
+ export { type SanitizeOptions, sanitizeContent as default, sanitizeContent, sanitizeDescription };
package/dist/index.d.ts CHANGED
@@ -2,16 +2,27 @@
2
2
  * Sanitizes sensitive information from content.
3
3
  * Redacts passwords, connection strings, API keys, etc.
4
4
  */
5
+ /**
6
+ * Options for sanitization.
7
+ */
8
+ interface SanitizeOptions {
9
+ /**
10
+ * The string to replace sensitive content with.
11
+ * Defaults to "[REDACTED]".
12
+ * set empty string to remove the sensitive content.
13
+ */
14
+ replacement?: string;
15
+ }
5
16
  /**
6
17
  * Sanitizes a string by redacting sensitive patterns.
7
18
  */
8
- declare function sanitizeContent(content: string): string;
19
+ declare function sanitizeContent(content: string, options?: SanitizeOptions): string;
9
20
  /**
10
21
  * Sanitizes HTML content by processing only text nodes.
11
22
  * Matches the API of the user's legacy script.
12
23
  */
13
- declare function sanitizeDescription(html: string): {
24
+ declare function sanitizeDescription(html: string, options?: SanitizeOptions): {
14
25
  sanitized_text: string;
15
26
  };
16
27
 
17
- export { sanitizeContent as default, sanitizeContent, sanitizeDescription };
28
+ export { type SanitizeOptions, sanitizeContent as default, sanitizeContent, sanitizeDescription };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var g=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var R=Object.prototype.hasOwnProperty;var b=(r,e)=>{for(var o in e)g(r,o,{get:e[o],enumerable:!0})},C=(r,e,o,_)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of S(e))!R.call(r,a)&&a!==o&&g(r,a,{get:()=>e[a],enumerable:!(_=A(e,a))||_.enumerable});return r};var N=r=>C(g({},"__esModule",{value:!0}),r);var D={};b(D,{default:()=>O,sanitizeContent:()=>T,sanitizeDescription:()=>I});module.exports=N(D);var f=require("jsdom"),d={CONNECTION_STRING:/([a-z0-9+.-]+:\/\/)([^:@\s]+):([^:@\s]+)@/gi,SQL_INSERT:/\bINSERT\s+INTO\b.*?\((?:[^)]*,\s*)?\b(password|pwd|pass|passcode)\b.*?\)\s*VALUES\s*\((?:[^,']*,|[^,"]*,)*\s*['"]([^'"]+)['"]/gi,HTML_INPUT:/<input[^>]+(?:type=["']password["'](?:\s+[^>]*?)?value=["']([^"']*)["']|value=["']([^"']*)["'](?:\s+[^>]*?)?type=["']password["'])/gi,QUERY_PARAM:/([?&])(api[_-]?key|access[_-]?token|secret|password|pass|passwrod|psswrd|pw|pwd|token|key|auth[_-]?token|u|p|user|username|passcode|wifi[_-]?password|p_?w_?d|confirm[_-]?password|confirm[_-]?pwd)=([^&\s<"']+)/gi,AUTH_TOKEN:/\b(authorization|auth[_-]?token)\s*[:=]\s*(bearer|basic|token)?\s*([a-zA-Z0-9.\-_~+/]{8,})|(?:\b(bearer|basic|token)\s+([a-zA-Z0-9.\-_~+/]{8,}))/gi,JWT:/\beyJ[a-zA-Z0-9._-]{10,}\b/gi,BASE64_PASS:/cGFzc3dvcmQ9[a-zA-Z0-9+/=]+/g,USER_PASS:/\b(user(?:name)?|login)\b\s*[:=\s/]\s*([^"'\s,]+)\s*(?:and\s+)?\b(pass(?:word)?|pwd|p|p_?w_?d)\b\s*[:=\s]\s*([^"'\s<,]+)/gi,SLASH_CRED:/\b(admin|user|root|api_?user)\/([^"'\s,;]{3,})\b/gi,CURL_AUTH:/(^|\s)(-u\s+)([^:\s]+):([^:\s\\]+)/gi,ASSIGNMENT:/\b(DB[_-]?PASSWORD|JWT[_-]?SECRET|SECRET[_-]?KEY|AUTH[_-]?PASSWORD|PASSWORD|SECRET|KEY|WIFI[_-]?PASSWORD|PASSCODE|API[_-]?KEY|CONFIRM[_-]?PASSWORD|PASSWROD)\s*[:=]\s*(?:["']?)([^"'\s;<>]{3,})(?:["']?)/gi,XML_TAG:/<([^>]*password|pass|secret|token|key)>([^<]+)<\/\1>/gi,LABEL_HINT:/(?:\b|["'<])(password|pass|passwrod|psswrd|pw|pwd|api[_-]?key|access[_-]?token|auth[_-]?token|credentials|creds|secret|token|key|passcode|wifi[_-]?password|p_?w_?d|u|p|confirm[_-]?password|confirm[_-]?pwd|actual|temp|temporary|new\s+one|old\s+one|new\s+password|old\s+password)(?:\b|["'>])[^a-zA-Z0-9\s]*\s*(?:[:=\s]|was\s+something\s+like|it\s+was\s+something\s+like|was|is|like|should\s+be|actual\s+was|could\s+be|might\s+be|set\s+to|entered)(?:\s+it)?\s*[:=]?\s*(?:["']?)([^"'\s<>&,;?]+)(?:["']?)(?:\s+or\s+([^"'\s<>&,;?]+))?/gi,URL:/\bhttps?:\/\/[^\s"'<>]+/gi,EMAIL:/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,MENTION:/(^|\s|[(\[])(@([a-zA-Z0-9._-]+))/g},p="[REDACTED]",w=/^(value|type|name|id|class|and|or|was|is|it|the|set|to|values|into|select|from|where|union|join|table|input|button|form|label|div|span|script|style|html|body|head|meta|link|header|footer|auth|login|signin|signout|logout|session|cookie|token|true|false|null|undefined|error|success|failed|warn|info|debug|trace|admin|user|root|for|test|testing|staging|placeholder|password|pass|pwd|psswrd|passwrod|token|key|api[_-]?key|secret|hidden|entered|shown|verified)$/i;function l(r,e,o){if(!o||o===p||o.length<1||o.includes(p)||o.includes("__PROTECTED_"))return r;let _=o.replace(/["']/g,"").trim();if(_.length<2||w.test(_)||_.toLowerCase()===e.toLowerCase())return r;let a=r.toLowerCase().indexOf(e.toLowerCase());if(a===-1)return r;let t=r.substring(a+e.length).indexOf(o);if(t===-1)return r;let n=a+e.length+t;return r.substring(0,n)+p+r.substring(n+o.length)}function L(r){return r.replace(/(?<!\w)([A-Za-z\d@$!%*#?&^()_\-+=]{7,64})(?!\w)/g,e=>{if(/^__PROTECTED_/.test(e)||e.includes(p)||w.test(e))return e;let o=/[A-Z]/.test(e),_=/[a-z]/.test(e),a=/\d/.test(e),s=/[@$!%*#?&^()_\-+=]/.test(e);return[o,_,a,s].filter(Boolean).length>=3?p:e})}function T(r){if(!r||typeof r!="string")return r;let e=r;e=e.replace(d.CONNECTION_STRING,"$1"+p+"@"),e=e.replace(d.QUERY_PARAM,"$1$2="+p),e=e.replace(d.XML_TAG,(s,t,n)=>`<${t}>${p}</${t}>`);let o=[];e=e.replace(d.URL,s=>{let t=`__PROTECTED_URL_${o.length}__`;return o.push(s),t});let _=[];e=e.replace(d.EMAIL,s=>{let t=`__PROTECTED_EMAIL_${_.length}__`;return _.push(s),t});let a=[];if(e=e.replace(d.MENTION,(s,t,n)=>{let i=`__PROTECTED_MENTION_${a.length}__`;return a.push(n),t+i}),e=e.replace(d.SQL_INSERT,(s,t,n)=>s.replace(n,p)),e=e.replace(d.HTML_INPUT,(s,t,n)=>{let i=t||n;return i?l(s,"password",i):s}),e=e.replace(d.AUTH_TOKEN,(s,t,n,i,c,u)=>{if(c&&u)return`${c} ${p}`;let E=n?`${n} `:"";return`${t}: ${E}${p}`}),e=e.replace(d.JWT,p),e=e.replace(d.BASE64_PASS,"cGFzc3dvcmQ9W1JFREFDVEVEX1BBU1NXT1JEXQ=="),e=e.replace(d.USER_PASS,(s,t,n,i,c)=>l(s,i,c)),e=e.replace(d.CURL_AUTH,"$1$2$3:"+p),e=e.replace(d.ASSIGNMENT,(s,t,n)=>l(s,t,n)),e=e.replace(d.SLASH_CRED,"$1/"+p),e=e.replace(d.LABEL_HINT,(s,t,n,i)=>{let c=l(s,t,n);return i&&(c=l(c,p,i)),c}),e.toLowerCase().includes("password")&&e.includes(",")){let s=e.split(/\r?\n/),t=-1,n=-1;for(let i=0;i<s.length;i++)if(s[i].includes(",")&&!s[i].toUpperCase().includes("VALUES")){let u=s[i].toLowerCase().split(",").findIndex(E=>E.includes("password")||E.trim()==="pwd");if(u!==-1){t=i,n=u;break}}if(t!==-1){for(let i=t+1;i<s.length;i++){let c=s[i].split(",");c.length>n&&c[n].trim().length>0&&(w.test(c[n].trim())||(c[n]=p,s[i]=c.join(",")))}e=s.join(`
2
- `)}}return e=L(e),e=e.replace(/(\[REDACTED\]\s*){2,}/g,p+" "),o.forEach((s,t)=>{e=e.replace(`__PROTECTED_URL_${t}__`,s)}),_.forEach((s,t)=>{e=e.replace(`__PROTECTED_EMAIL_${t}__`,s)}),a.forEach((s,t)=>{e=e.replace(`__PROTECTED_MENTION_${t}__`,s)}),e}function I(r){if(!r||typeof r!="string")return{sanitized_text:""};let o=new f.JSDOM(`<body>${r}</body>`).window.document,_=a=>{a.nodeType===3?a.textContent&&(a.textContent=T(a.textContent)):a.childNodes.forEach(_)};return _(o.body),{sanitized_text:o.body.innerHTML.trim()}}var O=T;0&&(module.exports={sanitizeContent,sanitizeDescription});
1
+ "use strict";var w=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var C=(n,o)=>{for(var s in o)w(n,s,{get:o[s],enumerable:!0})},N=(n,o,s,e)=>{if(o&&typeof o=="object"||typeof o=="function")for(let p of R(o))!b.call(n,p)&&p!==s&&w(n,p,{get:()=>o[p],enumerable:!(e=A(o,p))||e.enumerable});return n};var L=n=>N(w({},"__esModule",{value:!0}),n);var D={};C(D,{default:()=>$,sanitizeContent:()=>T,sanitizeDescription:()=>h});module.exports=L(D);var S=require("jsdom"),c={CONNECTION_STRING:/([a-z0-9+.-]+:\/\/)([^:@\s]+):([^:@\s]+)@/gi,SQL_INSERT:/\bINSERT\s+INTO\b.*?\((?:[^)]*,\s*)?\b(password|pwd|pass|passcode)\b.*?\)\s*VALUES\s*\((?:[^,']*,|[^,"]*,)*\s*['"]([^'"]+)['"]/gi,HTML_INPUT:/<input[^>]+(?:type=["']password["'](?:\s+[^>]*?)?value=["']([^"']*)["']|value=["']([^"']*)["'](?:\s+[^>]*?)?type=["']password["'])/gi,QUERY_PARAM:/([?&])(api[_-]?key|access[_-]?token|secret|password|pass|passwrod|psswrd|pw|pwd|token|key|auth[_-]?token|u|p|user|username|passcode|wifi[_-]?password|p_?w_?d|confirm[_-]?password|confirm[_-]?pwd)=([^&\s<"']+)/gi,AUTH_TOKEN:/\b(authorization|auth[_-]?token)\s*[:=]\s*(bearer|basic|token)?\s*([a-zA-Z0-9.\-_~+/]{8,})|(?:\b(bearer|basic|token)\s+([a-zA-Z0-9.\-_~+/]{8,}))/gi,JWT:/\beyJ[a-zA-Z0-9._-]{10,}\b/gi,BASE64_PASS:/cGFzc3dvcmQ9[a-zA-Z0-9+/=]+/g,USER_PASS:/\b(user(?:name)?|login)\b\s*[:=\s/]\s*([^"'\s,]+)\s*(?:and\s+)?\b(pass(?:word)?|pwd|p|p_?w_?d)\b\s*[:=\s]\s*([^"'\s<,]+)/gi,SLASH_CRED:/\b(admin|user|root|api_?user)\/([^"'\s,;]{3,})\b/gi,CURL_AUTH:/(^|\s)(-u\s+)([^:\s]+):([^:\s\\]+)/gi,ASSIGNMENT:/\b(DB[_-]?PASSWORD|JWT[_-]?SECRET|SECRET[_-]?KEY|AUTH[_-]?PASSWORD|PASSWORD|SECRET|KEY|WIFI[_-]?PASSWORD|PASSCODE|API[_-]?KEY|CONFIRM[_-]?PASSWORD|PASSWROD)\s*[:=]\s*(?:["']?)([^"'\s;<>]{3,})(?:["']?)/gi,XML_TAG:/<([^>]*password|pass|secret|token|key)>([^<]+)<\/\1>/gi,LABEL_HINT:/(?:\b|["'<])(password|pass|passwrod|psswrd|pw|pwd|api[_-]?key|access[_-]?token|auth[_-]?token|credentials|creds|secret|token|key|passcode|wifi[_-]?password|p_?w_?d|u|p|confirm[_-]?password|confirm[_-]?pwd|actual|temp|temporary|new\s+one|old\s+one|new\s+password|old\s+password)(?:\b|["'>])[^a-zA-Z0-9\s]*\s*(?:[:=\s]|was\s+something\s+like|it\s+was\s+something\s+like|was|is|like|should\s+be|actual\s+was|could\s+be|might\s+be|set\s+to|entered)(?:\s+it)?\s*[:=]?\s*(?:["']?)([^"'\s<>&,;?]+)(?:["']?)(?:\s+or\s+([^"'\s<>&,;?]+))?/gi,URL:/\bhttps?:\/\/[^\s"'<>]+/gi,EMAIL:/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,MENTION:/(^|\s|[(\[])(@([a-zA-Z0-9._-]+))/g},O="[REDACTED]",f=/^(value|type|name|id|class|and|or|was|is|it|the|set|to|values|into|select|from|where|union|join|table|input|button|form|label|div|span|script|style|html|body|head|meta|link|header|footer|auth|login|signin|signout|logout|session|cookie|token|true|false|null|undefined|error|success|failed|warn|info|debug|trace|admin|user|root|for|test|testing|staging|placeholder|password|pass|pwd|psswrd|passwrod|token|key|api[_-]?key|secret|hidden|entered|shown|verified)$/i;function u(n,o,s,e){if(!s||s===e||s.length<1||e.length>0&&s.includes(e)||s.includes("__PROTECTED_"))return n;let p=s.replace(/["']/g,"").trim();if(p.length<2||f.test(p)||p.toLowerCase()===o.toLowerCase())return n;let d=n.toLowerCase().indexOf(o.toLowerCase());if(d===-1)return n;let t=n.substring(d+o.length).indexOf(s);if(t===-1)return n;let r=d+o.length+t;return n.substring(0,r)+e+n.substring(r+s.length)}function I(n,o){return n.replace(/(?<!\w)([A-Za-z\d@$!%*#?&^()_\-+=]{7,64})(?!\w)/g,s=>{if(/^__PROTECTED_/.test(s)||s.includes(o)||f.test(s))return s;let e=/[A-Z]/.test(s),p=/[a-z]/.test(s),d=/\d/.test(s),l=/[@$!%*#?&^()_\-+=]/.test(s);return[e,p,d,l].filter(Boolean).length>=3?o:s})}function T(n,o={}){if(!n||typeof n!="string")return n;let s=o.replacement??O,e=n;e=e.replace(c.CONNECTION_STRING,"$1"+s+"@"),e=e.replace(c.QUERY_PARAM,"$1$2="+s),e=e.replace(c.XML_TAG,(t,r,a)=>`<${r}>${s}</${r}>`);let p=[];e=e.replace(c.URL,t=>{let r=`__PROTECTED_URL_${p.length}__`;return p.push(t),r});let d=[];e=e.replace(c.EMAIL,t=>{let r=`__PROTECTED_EMAIL_${d.length}__`;return d.push(t),r});let l=[];if(e=e.replace(c.MENTION,(t,r,a)=>{let i=`__PROTECTED_MENTION_${l.length}__`;return l.push(a),r+i}),e=e.replace(c.SQL_INSERT,(t,r,a)=>t.replace(a,s)),e=e.replace(c.HTML_INPUT,(t,r,a)=>{let i=r||a;return i?u(t,"password",i,s):t}),e=e.replace(c.AUTH_TOKEN,(t,r,a,i,_,g)=>{if(_&&g)return`${_} ${s}`;let E=a?`${a} `:"";return`${r}: ${E}${s}`}),e=e.replace(c.JWT,s),e=e.replace(c.BASE64_PASS,"cGFzc3dvcmQ9W1JFREFDVEVEX1BBU1NXT1JEXQ=="),e=e.replace(c.USER_PASS,(t,r,a,i,_)=>u(t,i,_,s)),e=e.replace(c.CURL_AUTH,"$1$2$3:"+s),e=e.replace(c.ASSIGNMENT,(t,r,a)=>u(t,r,a,s)),e=e.replace(c.SLASH_CRED,"$1/"+s),e=e.replace(c.LABEL_HINT,(t,r,a,i)=>{let _=u(t,r,a,s);return i&&(_=u(_,s,i,s)),_}),e.toLowerCase().includes("password")&&e.includes(",")){let t=e.split(/\r?\n/),r=-1,a=-1;for(let i=0;i<t.length;i++)if(t[i].includes(",")&&!t[i].toUpperCase().includes("VALUES")){let g=t[i].toLowerCase().split(",").findIndex(E=>E.includes("password")||E.trim()==="pwd");if(g!==-1){r=i,a=g;break}}if(r!==-1){for(let i=r+1;i<t.length;i++){let _=t[i].split(",");_.length>a&&_[a].trim().length>0&&(f.test(_[a].trim())||(_[a]=s,t[i]=_.join(",")))}e=t.join(`
2
+ `)}}if(e=I(e,s),s.length>0){let t=s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=new RegExp(`(${t}\\s*){2,}`,"g");e=e.replace(r,s+" ")}return p.forEach((t,r)=>{e=e.replace(`__PROTECTED_URL_${r}__`,t)}),d.forEach((t,r)=>{e=e.replace(`__PROTECTED_EMAIL_${r}__`,t)}),l.forEach((t,r)=>{e=e.replace(`__PROTECTED_MENTION_${r}__`,t)}),e}function h(n,o={}){if(!n||typeof n!="string")return{sanitized_text:""};let e=new S.JSDOM(`<body>${n}</body>`).window.document,p=d=>{d.nodeType===3?d.textContent&&(d.textContent=T(d.textContent,o)):d.childNodes.forEach(p)};return p(e.body),{sanitized_text:e.body.innerHTML.trim()}}var $=T;0&&(module.exports={sanitizeContent,sanitizeDescription});
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{JSDOM as T}from"jsdom";var p={CONNECTION_STRING:/([a-z0-9+.-]+:\/\/)([^:@\s]+):([^:@\s]+)@/gi,SQL_INSERT:/\bINSERT\s+INTO\b.*?\((?:[^)]*,\s*)?\b(password|pwd|pass|passcode)\b.*?\)\s*VALUES\s*\((?:[^,']*,|[^,"]*,)*\s*['"]([^'"]+)['"]/gi,HTML_INPUT:/<input[^>]+(?:type=["']password["'](?:\s+[^>]*?)?value=["']([^"']*)["']|value=["']([^"']*)["'](?:\s+[^>]*?)?type=["']password["'])/gi,QUERY_PARAM:/([?&])(api[_-]?key|access[_-]?token|secret|password|pass|passwrod|psswrd|pw|pwd|token|key|auth[_-]?token|u|p|user|username|passcode|wifi[_-]?password|p_?w_?d|confirm[_-]?password|confirm[_-]?pwd)=([^&\s<"']+)/gi,AUTH_TOKEN:/\b(authorization|auth[_-]?token)\s*[:=]\s*(bearer|basic|token)?\s*([a-zA-Z0-9.\-_~+/]{8,})|(?:\b(bearer|basic|token)\s+([a-zA-Z0-9.\-_~+/]{8,}))/gi,JWT:/\beyJ[a-zA-Z0-9._-]{10,}\b/gi,BASE64_PASS:/cGFzc3dvcmQ9[a-zA-Z0-9+/=]+/g,USER_PASS:/\b(user(?:name)?|login)\b\s*[:=\s/]\s*([^"'\s,]+)\s*(?:and\s+)?\b(pass(?:word)?|pwd|p|p_?w_?d)\b\s*[:=\s]\s*([^"'\s<,]+)/gi,SLASH_CRED:/\b(admin|user|root|api_?user)\/([^"'\s,;]{3,})\b/gi,CURL_AUTH:/(^|\s)(-u\s+)([^:\s]+):([^:\s\\]+)/gi,ASSIGNMENT:/\b(DB[_-]?PASSWORD|JWT[_-]?SECRET|SECRET[_-]?KEY|AUTH[_-]?PASSWORD|PASSWORD|SECRET|KEY|WIFI[_-]?PASSWORD|PASSCODE|API[_-]?KEY|CONFIRM[_-]?PASSWORD|PASSWROD)\s*[:=]\s*(?:["']?)([^"'\s;<>]{3,})(?:["']?)/gi,XML_TAG:/<([^>]*password|pass|secret|token|key)>([^<]+)<\/\1>/gi,LABEL_HINT:/(?:\b|["'<])(password|pass|passwrod|psswrd|pw|pwd|api[_-]?key|access[_-]?token|auth[_-]?token|credentials|creds|secret|token|key|passcode|wifi[_-]?password|p_?w_?d|u|p|confirm[_-]?password|confirm[_-]?pwd|actual|temp|temporary|new\s+one|old\s+one|new\s+password|old\s+password)(?:\b|["'>])[^a-zA-Z0-9\s]*\s*(?:[:=\s]|was\s+something\s+like|it\s+was\s+something\s+like|was|is|like|should\s+be|actual\s+was|could\s+be|might\s+be|set\s+to|entered)(?:\s+it)?\s*[:=]?\s*(?:["']?)([^"'\s<>&,;?]+)(?:["']?)(?:\s+or\s+([^"'\s<>&,;?]+))?/gi,URL:/\bhttps?:\/\/[^\s"'<>]+/gi,EMAIL:/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,MENTION:/(^|\s|[(\[])(@([a-zA-Z0-9._-]+))/g},a="[REDACTED]",g=/^(value|type|name|id|class|and|or|was|is|it|the|set|to|values|into|select|from|where|union|join|table|input|button|form|label|div|span|script|style|html|body|head|meta|link|header|footer|auth|login|signin|signout|logout|session|cookie|token|true|false|null|undefined|error|success|failed|warn|info|debug|trace|admin|user|root|for|test|testing|staging|placeholder|password|pass|pwd|psswrd|passwrod|token|key|api[_-]?key|secret|hidden|entered|shown|verified)$/i;function l(n,e,i){if(!i||i===a||i.length<1||i.includes(a)||i.includes("__PROTECTED_"))return n;let c=i.replace(/["']/g,"").trim();if(c.length<2||g.test(c)||c.toLowerCase()===e.toLowerCase())return n;let d=n.toLowerCase().indexOf(e.toLowerCase());if(d===-1)return n;let t=n.substring(d+e.length).indexOf(i);if(t===-1)return n;let r=d+e.length+t;return n.substring(0,r)+a+n.substring(r+i.length)}function f(n){return n.replace(/(?<!\w)([A-Za-z\d@$!%*#?&^()_\-+=]{7,64})(?!\w)/g,e=>{if(/^__PROTECTED_/.test(e)||e.includes(a)||g.test(e))return e;let i=/[A-Z]/.test(e),c=/[a-z]/.test(e),d=/\d/.test(e),s=/[@$!%*#?&^()_\-+=]/.test(e);return[i,c,d,s].filter(Boolean).length>=3?a:e})}function w(n){if(!n||typeof n!="string")return n;let e=n;e=e.replace(p.CONNECTION_STRING,"$1"+a+"@"),e=e.replace(p.QUERY_PARAM,"$1$2="+a),e=e.replace(p.XML_TAG,(s,t,r)=>`<${t}>${a}</${t}>`);let i=[];e=e.replace(p.URL,s=>{let t=`__PROTECTED_URL_${i.length}__`;return i.push(s),t});let c=[];e=e.replace(p.EMAIL,s=>{let t=`__PROTECTED_EMAIL_${c.length}__`;return c.push(s),t});let d=[];if(e=e.replace(p.MENTION,(s,t,r)=>{let o=`__PROTECTED_MENTION_${d.length}__`;return d.push(r),t+o}),e=e.replace(p.SQL_INSERT,(s,t,r)=>s.replace(r,a)),e=e.replace(p.HTML_INPUT,(s,t,r)=>{let o=t||r;return o?l(s,"password",o):s}),e=e.replace(p.AUTH_TOKEN,(s,t,r,o,_,u)=>{if(_&&u)return`${_} ${a}`;let E=r?`${r} `:"";return`${t}: ${E}${a}`}),e=e.replace(p.JWT,a),e=e.replace(p.BASE64_PASS,"cGFzc3dvcmQ9W1JFREFDVEVEX1BBU1NXT1JEXQ=="),e=e.replace(p.USER_PASS,(s,t,r,o,_)=>l(s,o,_)),e=e.replace(p.CURL_AUTH,"$1$2$3:"+a),e=e.replace(p.ASSIGNMENT,(s,t,r)=>l(s,t,r)),e=e.replace(p.SLASH_CRED,"$1/"+a),e=e.replace(p.LABEL_HINT,(s,t,r,o)=>{let _=l(s,t,r);return o&&(_=l(_,a,o)),_}),e.toLowerCase().includes("password")&&e.includes(",")){let s=e.split(/\r?\n/),t=-1,r=-1;for(let o=0;o<s.length;o++)if(s[o].includes(",")&&!s[o].toUpperCase().includes("VALUES")){let u=s[o].toLowerCase().split(",").findIndex(E=>E.includes("password")||E.trim()==="pwd");if(u!==-1){t=o,r=u;break}}if(t!==-1){for(let o=t+1;o<s.length;o++){let _=s[o].split(",");_.length>r&&_[r].trim().length>0&&(g.test(_[r].trim())||(_[r]=a,s[o]=_.join(",")))}e=s.join(`
2
- `)}}return e=f(e),e=e.replace(/(\[REDACTED\]\s*){2,}/g,a+" "),i.forEach((s,t)=>{e=e.replace(`__PROTECTED_URL_${t}__`,s)}),c.forEach((s,t)=>{e=e.replace(`__PROTECTED_EMAIL_${t}__`,s)}),d.forEach((s,t)=>{e=e.replace(`__PROTECTED_MENTION_${t}__`,s)}),e}function S(n){if(!n||typeof n!="string")return{sanitized_text:""};let i=new T(`<body>${n}</body>`).window.document,c=d=>{d.nodeType===3?d.textContent&&(d.textContent=w(d.textContent)):d.childNodes.forEach(c)};return c(i.body),{sanitized_text:i.body.innerHTML.trim()}}var R=w;export{R as default,w as sanitizeContent,S as sanitizeDescription};
1
+ import{JSDOM as T}from"jsdom";var a={CONNECTION_STRING:/([a-z0-9+.-]+:\/\/)([^:@\s]+):([^:@\s]+)@/gi,SQL_INSERT:/\bINSERT\s+INTO\b.*?\((?:[^)]*,\s*)?\b(password|pwd|pass|passcode)\b.*?\)\s*VALUES\s*\((?:[^,']*,|[^,"]*,)*\s*['"]([^'"]+)['"]/gi,HTML_INPUT:/<input[^>]+(?:type=["']password["'](?:\s+[^>]*?)?value=["']([^"']*)["']|value=["']([^"']*)["'](?:\s+[^>]*?)?type=["']password["'])/gi,QUERY_PARAM:/([?&])(api[_-]?key|access[_-]?token|secret|password|pass|passwrod|psswrd|pw|pwd|token|key|auth[_-]?token|u|p|user|username|passcode|wifi[_-]?password|p_?w_?d|confirm[_-]?password|confirm[_-]?pwd)=([^&\s<"']+)/gi,AUTH_TOKEN:/\b(authorization|auth[_-]?token)\s*[:=]\s*(bearer|basic|token)?\s*([a-zA-Z0-9.\-_~+/]{8,})|(?:\b(bearer|basic|token)\s+([a-zA-Z0-9.\-_~+/]{8,}))/gi,JWT:/\beyJ[a-zA-Z0-9._-]{10,}\b/gi,BASE64_PASS:/cGFzc3dvcmQ9[a-zA-Z0-9+/=]+/g,USER_PASS:/\b(user(?:name)?|login)\b\s*[:=\s/]\s*([^"'\s,]+)\s*(?:and\s+)?\b(pass(?:word)?|pwd|p|p_?w_?d)\b\s*[:=\s]\s*([^"'\s<,]+)/gi,SLASH_CRED:/\b(admin|user|root|api_?user)\/([^"'\s,;]{3,})\b/gi,CURL_AUTH:/(^|\s)(-u\s+)([^:\s]+):([^:\s\\]+)/gi,ASSIGNMENT:/\b(DB[_-]?PASSWORD|JWT[_-]?SECRET|SECRET[_-]?KEY|AUTH[_-]?PASSWORD|PASSWORD|SECRET|KEY|WIFI[_-]?PASSWORD|PASSCODE|API[_-]?KEY|CONFIRM[_-]?PASSWORD|PASSWROD)\s*[:=]\s*(?:["']?)([^"'\s;<>]{3,})(?:["']?)/gi,XML_TAG:/<([^>]*password|pass|secret|token|key)>([^<]+)<\/\1>/gi,LABEL_HINT:/(?:\b|["'<])(password|pass|passwrod|psswrd|pw|pwd|api[_-]?key|access[_-]?token|auth[_-]?token|credentials|creds|secret|token|key|passcode|wifi[_-]?password|p_?w_?d|u|p|confirm[_-]?password|confirm[_-]?pwd|actual|temp|temporary|new\s+one|old\s+one|new\s+password|old\s+password)(?:\b|["'>])[^a-zA-Z0-9\s]*\s*(?:[:=\s]|was\s+something\s+like|it\s+was\s+something\s+like|was|is|like|should\s+be|actual\s+was|could\s+be|might\s+be|set\s+to|entered)(?:\s+it)?\s*[:=]?\s*(?:["']?)([^"'\s<>&,;?]+)(?:["']?)(?:\s+or\s+([^"'\s<>&,;?]+))?/gi,URL:/\bhttps?:\/\/[^\s"'<>]+/gi,EMAIL:/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,MENTION:/(^|\s|[(\[])(@([a-zA-Z0-9._-]+))/g},S="[REDACTED]",w=/^(value|type|name|id|class|and|or|was|is|it|the|set|to|values|into|select|from|where|union|join|table|input|button|form|label|div|span|script|style|html|body|head|meta|link|header|footer|auth|login|signin|signout|logout|session|cookie|token|true|false|null|undefined|error|success|failed|warn|info|debug|trace|admin|user|root|for|test|testing|staging|placeholder|password|pass|pwd|psswrd|passwrod|token|key|api[_-]?key|secret|hidden|entered|shown|verified)$/i;function u(n,_,s,e){if(!s||s===e||s.length<1||e.length>0&&s.includes(e)||s.includes("__PROTECTED_"))return n;let d=s.replace(/["']/g,"").trim();if(d.length<2||w.test(d)||d.toLowerCase()===_.toLowerCase())return n;let p=n.toLowerCase().indexOf(_.toLowerCase());if(p===-1)return n;let t=n.substring(p+_.length).indexOf(s);if(t===-1)return n;let r=p+_.length+t;return n.substring(0,r)+e+n.substring(r+s.length)}function A(n,_){return n.replace(/(?<!\w)([A-Za-z\d@$!%*#?&^()_\-+=]{7,64})(?!\w)/g,s=>{if(/^__PROTECTED_/.test(s)||s.includes(_)||w.test(s))return s;let e=/[A-Z]/.test(s),d=/[a-z]/.test(s),p=/\d/.test(s),l=/[@$!%*#?&^()_\-+=]/.test(s);return[e,d,p,l].filter(Boolean).length>=3?_:s})}function f(n,_={}){if(!n||typeof n!="string")return n;let s=_.replacement??S,e=n;e=e.replace(a.CONNECTION_STRING,"$1"+s+"@"),e=e.replace(a.QUERY_PARAM,"$1$2="+s),e=e.replace(a.XML_TAG,(t,r,o)=>`<${r}>${s}</${r}>`);let d=[];e=e.replace(a.URL,t=>{let r=`__PROTECTED_URL_${d.length}__`;return d.push(t),r});let p=[];e=e.replace(a.EMAIL,t=>{let r=`__PROTECTED_EMAIL_${p.length}__`;return p.push(t),r});let l=[];if(e=e.replace(a.MENTION,(t,r,o)=>{let i=`__PROTECTED_MENTION_${l.length}__`;return l.push(o),r+i}),e=e.replace(a.SQL_INSERT,(t,r,o)=>t.replace(o,s)),e=e.replace(a.HTML_INPUT,(t,r,o)=>{let i=r||o;return i?u(t,"password",i,s):t}),e=e.replace(a.AUTH_TOKEN,(t,r,o,i,c,g)=>{if(c&&g)return`${c} ${s}`;let E=o?`${o} `:"";return`${r}: ${E}${s}`}),e=e.replace(a.JWT,s),e=e.replace(a.BASE64_PASS,"cGFzc3dvcmQ9W1JFREFDVEVEX1BBU1NXT1JEXQ=="),e=e.replace(a.USER_PASS,(t,r,o,i,c)=>u(t,i,c,s)),e=e.replace(a.CURL_AUTH,"$1$2$3:"+s),e=e.replace(a.ASSIGNMENT,(t,r,o)=>u(t,r,o,s)),e=e.replace(a.SLASH_CRED,"$1/"+s),e=e.replace(a.LABEL_HINT,(t,r,o,i)=>{let c=u(t,r,o,s);return i&&(c=u(c,s,i,s)),c}),e.toLowerCase().includes("password")&&e.includes(",")){let t=e.split(/\r?\n/),r=-1,o=-1;for(let i=0;i<t.length;i++)if(t[i].includes(",")&&!t[i].toUpperCase().includes("VALUES")){let g=t[i].toLowerCase().split(",").findIndex(E=>E.includes("password")||E.trim()==="pwd");if(g!==-1){r=i,o=g;break}}if(r!==-1){for(let i=r+1;i<t.length;i++){let c=t[i].split(",");c.length>o&&c[o].trim().length>0&&(w.test(c[o].trim())||(c[o]=s,t[i]=c.join(",")))}e=t.join(`
2
+ `)}}if(e=A(e,s),s.length>0){let t=s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=new RegExp(`(${t}\\s*){2,}`,"g");e=e.replace(r,s+" ")}return d.forEach((t,r)=>{e=e.replace(`__PROTECTED_URL_${r}__`,t)}),p.forEach((t,r)=>{e=e.replace(`__PROTECTED_EMAIL_${r}__`,t)}),l.forEach((t,r)=>{e=e.replace(`__PROTECTED_MENTION_${r}__`,t)}),e}function b(n,_={}){if(!n||typeof n!="string")return{sanitized_text:""};let e=new T(`<body>${n}</body>`).window.document,d=p=>{p.nodeType===3?p.textContent&&(p.textContent=f(p.textContent,_)):p.childNodes.forEach(d)};return d(e.body),{sanitized_text:e.body.innerHTML.trim()}}var C=f;export{C as default,f as sanitizeContent,b as sanitizeDescription};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sanitize-contents",
3
- "version": "1.0.0",
4
- "description": "A robust library to sanitize sensitive information from content.",
3
+ "version": "1.0.1",
4
+ "description": "A robust, lightweight, and customizable library to sanitize/redact sensitive information (passwords, tokens, API keys, connection strings) from strings and HTML content.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
7
7
  "types": "./dist/index.d.ts",
@@ -28,7 +28,16 @@
28
28
  "security",
29
29
  "password",
30
30
  "sensitive",
31
- "content"
31
+ "content",
32
+ "pii",
33
+ "gdpr",
34
+ "token",
35
+ "auth",
36
+ "secret",
37
+ "cleaner",
38
+ "filter",
39
+ "data-masking",
40
+ "masking"
32
41
  ],
33
42
  "author": "Kishan",
34
43
  "license": "ISC",