@xbg.solutions/bpsk-utils-sanitizer 1.2.3
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/lib/index.d.ts +3 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +4 -0
- package/lib/index.js.map +1 -0
- package/lib/types/sanitizer.types.d.ts +49 -0
- package/lib/types/sanitizer.types.d.ts.map +1 -0
- package/lib/types/sanitizer.types.js +6 -0
- package/lib/types/sanitizer.types.js.map +1 -0
- package/lib/utils/sanitizer.d.ts +63 -0
- package/lib/utils/sanitizer.d.ts.map +1 -0
- package/lib/utils/sanitizer.js +297 -0
- package/lib/utils/sanitizer.js.map +1 -0
- package/package.json +21 -0
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,mBAAmB,yBAAyB,CAAC;AAG7C,cAAc,mBAAmB,CAAC"}
|
package/lib/index.js
ADDED
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAKnC,QAAQ;AACR,cAAc,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/lib/types/sanitizer.types.ts
|
|
3
|
+
* Type definitions for the sanitizer utility
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Sanitization level options
|
|
7
|
+
* - strict: Removes all HTML tags, for high-risk user inputs
|
|
8
|
+
* - medium: Allows selected safe HTML tags, for rich text content
|
|
9
|
+
* - basic: Only escapes HTML special characters
|
|
10
|
+
*/
|
|
11
|
+
export type SanitizationLevel = 'strict' | 'medium' | 'basic';
|
|
12
|
+
/**
|
|
13
|
+
* Options for configuring sanitization behavior
|
|
14
|
+
*/
|
|
15
|
+
export interface SanitizerOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Sanitization level to apply
|
|
18
|
+
* @default 'basic'
|
|
19
|
+
*/
|
|
20
|
+
level?: SanitizationLevel;
|
|
21
|
+
/**
|
|
22
|
+
* Whether to preserve the original case
|
|
23
|
+
* @default true
|
|
24
|
+
*/
|
|
25
|
+
preserveCase?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Whether to preserve whitespace (if false, excess whitespace is normalized)
|
|
28
|
+
* @default true
|
|
29
|
+
*/
|
|
30
|
+
preserveWhitespace?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Maximum allowed length for strings
|
|
33
|
+
* @default undefined (no limit)
|
|
34
|
+
*/
|
|
35
|
+
maxLength?: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Type helper for recursively sanitized values
|
|
39
|
+
* - For strings, returns a sanitized string
|
|
40
|
+
* - For primitive types (number, boolean), returns the type unchanged
|
|
41
|
+
* - For arrays, returns an array with each element recursively processed
|
|
42
|
+
* - For objects, returns an object with each property recursively processed
|
|
43
|
+
*
|
|
44
|
+
* This is a more robust type that prevents TypeScript errors when transforming strings
|
|
45
|
+
*/
|
|
46
|
+
export type RecursivelyProcessed<T> = T extends string ? string : T extends number ? number : T extends boolean ? boolean : T extends null ? null : T extends undefined ? undefined : T extends Array<infer U> ? Array<RecursivelyProcessed<U>> : T extends object ? {
|
|
47
|
+
[K in keyof T]: RecursivelyProcessed<T[K]>;
|
|
48
|
+
} : T extends unknown ? unknown : T;
|
|
49
|
+
//# sourceMappingURL=sanitizer.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizer.types.d.ts","sourceRoot":"","sources":["../../src/types/sanitizer.types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAE1B;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,oBAAoB,CAAC,CAAC,IAChC,CAAC,SAAS,MAAM,GAAG,MAAM,GACzB,CAAC,SAAS,MAAM,GAAG,MAAM,GACzB,CAAC,SAAS,OAAO,GAAG,OAAO,GAC3B,CAAC,SAAS,IAAI,GAAG,IAAI,GACrB,CAAC,SAAS,SAAS,GAAG,SAAS,GAC/B,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,GACzD,CAAC,SAAS,MAAM,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,GACjE,CAAC,SAAS,OAAO,GAAG,OAAO,GAC3B,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizer.types.js","sourceRoot":"","sources":["../../src/types/sanitizer.types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/lib/utils/sanitizer.ts
|
|
3
|
+
* Sanitizer utility
|
|
4
|
+
*
|
|
5
|
+
* A utility for sanitizing user inputs and other data with support for:
|
|
6
|
+
* - Multiple sanitization levels (strict, medium, basic)
|
|
7
|
+
* - XSS prevention and HTML sanitization
|
|
8
|
+
* - Recursive sanitization of complex objects
|
|
9
|
+
* - Type-safe implementation
|
|
10
|
+
* - Integration with error handling
|
|
11
|
+
*/
|
|
12
|
+
import type { SanitizerOptions, RecursivelyProcessed } from '../types/sanitizer.types';
|
|
13
|
+
/**
|
|
14
|
+
* Sanitizes HTML strings by escaping special characters
|
|
15
|
+
*
|
|
16
|
+
* @param input String to sanitize
|
|
17
|
+
* @returns Sanitized string with HTML entities escaped
|
|
18
|
+
*/
|
|
19
|
+
declare function escapeHtml(input: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Sanitizes a string by stripping all HTML tags
|
|
22
|
+
*
|
|
23
|
+
* @param input String to sanitize
|
|
24
|
+
* @returns String with all HTML tags removed
|
|
25
|
+
*/
|
|
26
|
+
declare function stripHtml(input: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Sanitizes a string by allowing only specified HTML tags
|
|
29
|
+
*
|
|
30
|
+
* @param input String to sanitize
|
|
31
|
+
* @returns String with only allowed HTML tags
|
|
32
|
+
*/
|
|
33
|
+
declare function sanitizeHtml(input: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Main sanitizer function
|
|
36
|
+
*
|
|
37
|
+
* @param input Input to sanitize
|
|
38
|
+
* @param options Sanitization options
|
|
39
|
+
* @returns Sanitized output
|
|
40
|
+
*/
|
|
41
|
+
declare function sanitize<T>(input: T, options?: SanitizerOptions): RecursivelyProcessed<T>;
|
|
42
|
+
/**
|
|
43
|
+
* Safely sanitizes input and handles errors
|
|
44
|
+
*
|
|
45
|
+
* @param input Input to sanitize
|
|
46
|
+
* @param options Sanitization options
|
|
47
|
+
* @returns Sanitized output or original input if sanitization fails
|
|
48
|
+
*/
|
|
49
|
+
declare function safeSanitize<T>(input: T, options?: SanitizerOptions): Promise<RecursivelyProcessed<T>>;
|
|
50
|
+
/**
|
|
51
|
+
* Creates a sanitizer function with predefined options
|
|
52
|
+
*
|
|
53
|
+
* @param defaultOptions Default sanitization options
|
|
54
|
+
* @returns Sanitizer function with default options applied
|
|
55
|
+
*/
|
|
56
|
+
declare function createSanitizer(defaultOptions?: SanitizerOptions): <T>(input: T, options?: SanitizerOptions) => RecursivelyProcessed<T>;
|
|
57
|
+
declare const strictSanitizer: <T>(input: T, options?: SanitizerOptions) => RecursivelyProcessed<T>;
|
|
58
|
+
declare const mediumSanitizer: <T>(input: T, options?: SanitizerOptions) => RecursivelyProcessed<T>;
|
|
59
|
+
declare const basicSanitizer: <T>(input: T, options?: SanitizerOptions) => RecursivelyProcessed<T>;
|
|
60
|
+
declare const inputSanitizer: <T>(input: T, options?: SanitizerOptions) => RecursivelyProcessed<T>;
|
|
61
|
+
declare const urlParamSanitizer: <T>(input: T, options?: SanitizerOptions) => RecursivelyProcessed<T>;
|
|
62
|
+
export { sanitize, safeSanitize, createSanitizer, strictSanitizer, mediumSanitizer, basicSanitizer, inputSanitizer, urlParamSanitizer, escapeHtml, stripHtml, sanitizeHtml };
|
|
63
|
+
//# sourceMappingURL=sanitizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizer.d.ts","sourceRoot":"","sources":["../../src/utils/sanitizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AASH,OAAO,KAAK,EACV,gBAAgB,EAEhB,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AA0BlC;;;;;GAKG;AACH,iBAAS,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAYzC;AAED;;;;;GAKG;AACH,iBAAS,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOxC;AAED;;;;;GAKG;AACH,iBAAS,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAkG3C;AA6FD;;;;;;GAMG;AACH,iBAAS,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,GAAE,gBAAqB,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAyBtF;AAED;;;;;;GAMG;AACH,iBAAe,YAAY,CAAC,CAAC,EAC3B,KAAK,EAAE,CAAC,EACR,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAKlC;AAED;;;;;GAKG;AACH,iBAAS,eAAe,CAAC,cAAc,GAAE,gBAAqB,IACpD,CAAC,EAAE,OAAO,CAAC,EAAE,UAAS,gBAAqB,KAAG,oBAAoB,CAAC,CAAC,CAAC,CAS9E;AAGD,QAAA,MAAM,eAAe,GAZX,CAAC,SAAS,CAAC,YAAW,gBAAgB,KAAQ,oBAAoB,CAAC,CAAC,CAYlB,CAAC;AAC7D,QAAA,MAAM,eAAe,GAbX,CAAC,SAAS,CAAC,YAAW,gBAAgB,KAAQ,oBAAoB,CAAC,CAAC,CAalB,CAAC;AAC7D,QAAA,MAAM,cAAc,GAdV,CAAC,SAAS,CAAC,YAAW,gBAAgB,KAAQ,oBAAoB,CAAC,CAAC,CAcpB,CAAC;AAG3D,QAAA,MAAM,cAAc,GAjBV,CAAC,SAAS,CAAC,YAAW,gBAAgB,KAAQ,oBAAoB,CAAC,CAAC,CAoB5E,CAAC;AAGH,QAAA,MAAM,iBAAiB,GAvBb,CAAC,SAAS,CAAC,YAAW,gBAAgB,KAAQ,oBAAoB,CAAC,CAAC,CA4B5E,CAAC;AAGH,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,eAAe,EACf,eAAe,EACf,eAAe,EACf,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,YAAY,EACb,CAAC"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/lib/utils/sanitizer.ts
|
|
3
|
+
* Sanitizer utility
|
|
4
|
+
*
|
|
5
|
+
* A utility for sanitizing user inputs and other data with support for:
|
|
6
|
+
* - Multiple sanitization levels (strict, medium, basic)
|
|
7
|
+
* - XSS prevention and HTML sanitization
|
|
8
|
+
* - Recursive sanitization of complex objects
|
|
9
|
+
* - Type-safe implementation
|
|
10
|
+
* - Integration with error handling
|
|
11
|
+
*/
|
|
12
|
+
import { loggerService, normalizeError, tryCatch } from '@xbg.solutions/bpsk-core';
|
|
13
|
+
// Create a context-aware logger
|
|
14
|
+
const sanitizerLogger = loggerService.withContext('Sanitizer');
|
|
15
|
+
/**
|
|
16
|
+
* List of allowed HTML tags for medium level sanitization
|
|
17
|
+
* Customize this list based on your application's requirements
|
|
18
|
+
*/
|
|
19
|
+
const ALLOWED_TAGS = [
|
|
20
|
+
'p', 'br', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
|
|
21
|
+
'ul', 'ol', 'li', 'blockquote', 'pre', 'code',
|
|
22
|
+
'strong', 'em', 'b', 'i', 'u', 'a', 'span'
|
|
23
|
+
];
|
|
24
|
+
/**
|
|
25
|
+
* List of allowed HTML attributes for medium level sanitization
|
|
26
|
+
* Customize this list based on your application's requirements
|
|
27
|
+
*/
|
|
28
|
+
const ALLOWED_ATTRIBUTES = {
|
|
29
|
+
'a': ['href', 'target', 'rel', 'title'],
|
|
30
|
+
'span': ['class'],
|
|
31
|
+
'code': ['class'],
|
|
32
|
+
'*': ['id', 'class'] // Allowed on all elements
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Sanitizes HTML strings by escaping special characters
|
|
36
|
+
*
|
|
37
|
+
* @param input String to sanitize
|
|
38
|
+
* @returns Sanitized string with HTML entities escaped
|
|
39
|
+
*/
|
|
40
|
+
function escapeHtml(input) {
|
|
41
|
+
if (!input || typeof input !== 'string') {
|
|
42
|
+
return '';
|
|
43
|
+
}
|
|
44
|
+
return input
|
|
45
|
+
.replace(/&/g, '&')
|
|
46
|
+
.replace(/</g, '<')
|
|
47
|
+
.replace(/>/g, '>')
|
|
48
|
+
.replace(/"/g, '"')
|
|
49
|
+
.replace(/'/g, ''')
|
|
50
|
+
.replace(/\//g, '/');
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Sanitizes a string by stripping all HTML tags
|
|
54
|
+
*
|
|
55
|
+
* @param input String to sanitize
|
|
56
|
+
* @returns String with all HTML tags removed
|
|
57
|
+
*/
|
|
58
|
+
function stripHtml(input) {
|
|
59
|
+
if (!input || typeof input !== 'string') {
|
|
60
|
+
return '';
|
|
61
|
+
}
|
|
62
|
+
// Use regex to remove all HTML tags
|
|
63
|
+
return input.replace(/<[^>]*>/g, '');
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Sanitizes a string by allowing only specified HTML tags
|
|
67
|
+
*
|
|
68
|
+
* @param input String to sanitize
|
|
69
|
+
* @returns String with only allowed HTML tags
|
|
70
|
+
*/
|
|
71
|
+
function sanitizeHtml(input) {
|
|
72
|
+
if (!input || typeof input !== 'string') {
|
|
73
|
+
return '';
|
|
74
|
+
}
|
|
75
|
+
// For server-side or environments without DOMParser
|
|
76
|
+
if (typeof DOMParser === 'undefined') {
|
|
77
|
+
// Fallback to regex-based sanitization
|
|
78
|
+
let result = input;
|
|
79
|
+
// Remove disallowed tags - simplified approach
|
|
80
|
+
const allowedTagPattern = ALLOWED_TAGS.join('|');
|
|
81
|
+
const tagPattern = new RegExp(`<(?!\/?(?:${allowedTagPattern})\\b)[^>]+>`, 'gi');
|
|
82
|
+
result = result.replace(tagPattern, '');
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
// This is a simplified implementation
|
|
86
|
+
// In production, consider using libraries like DOMPurify
|
|
87
|
+
try {
|
|
88
|
+
// Create a temporary DOM element
|
|
89
|
+
const doc = new DOMParser().parseFromString(input, 'text/html');
|
|
90
|
+
// Walk through all elements and remove disallowed ones
|
|
91
|
+
const sanitizeNode = (node) => {
|
|
92
|
+
// Create a copy of childNodes to iterate over since we'll be modifying the collection
|
|
93
|
+
const childNodes = Array.from(node.childNodes);
|
|
94
|
+
for (const child of childNodes) {
|
|
95
|
+
if (child.nodeType === Node.ELEMENT_NODE) {
|
|
96
|
+
const element = child;
|
|
97
|
+
const tagName = element.tagName.toLowerCase();
|
|
98
|
+
// Remove element if not in allowed tags
|
|
99
|
+
if (!ALLOWED_TAGS.includes(tagName)) {
|
|
100
|
+
node.removeChild(child);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
// Remove disallowed attributes
|
|
104
|
+
Array.from(element.attributes).forEach(attr => {
|
|
105
|
+
const attributeName = attr.name;
|
|
106
|
+
const isAllowed = (ALLOWED_ATTRIBUTES[tagName] && ALLOWED_ATTRIBUTES[tagName].includes(attributeName)) ||
|
|
107
|
+
(ALLOWED_ATTRIBUTES['*'] && ALLOWED_ATTRIBUTES['*'].includes(attributeName));
|
|
108
|
+
if (!isAllowed) {
|
|
109
|
+
element.removeAttribute(attributeName);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
// Sanitize URLs in href attributes to prevent javascript: protocol
|
|
113
|
+
if (tagName === 'a' && element.hasAttribute('href')) {
|
|
114
|
+
const href = element.getAttribute('href') || '';
|
|
115
|
+
if (href.match(/^\s*javascript:/i)) {
|
|
116
|
+
element.setAttribute('href', '#');
|
|
117
|
+
}
|
|
118
|
+
// Add safety attributes to external links
|
|
119
|
+
if (href.match(/^https?:\/\//i) && !href.match(new RegExp(`^https?://${window.location.hostname}`, 'i'))) {
|
|
120
|
+
element.setAttribute('rel', 'noopener noreferrer');
|
|
121
|
+
element.setAttribute('target', '_blank');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Recursively sanitize child nodes
|
|
125
|
+
sanitizeNode(child);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
// Start sanitizing from the body
|
|
130
|
+
sanitizeNode(doc.body);
|
|
131
|
+
// Use innerHTML to get the complete sanitized HTML
|
|
132
|
+
// The reason we're using this approach is DOMParser might not return the complete HTML
|
|
133
|
+
// For example, it might omit closing tags or normalize tag structure
|
|
134
|
+
const result = doc.body.innerHTML;
|
|
135
|
+
// Ensure complete tags by adding a temporary wrapper and using innerHTML
|
|
136
|
+
// This technique helps create well-formed HTML
|
|
137
|
+
if (result) {
|
|
138
|
+
const wrapper = document.createElement('div');
|
|
139
|
+
wrapper.innerHTML = result;
|
|
140
|
+
return wrapper.innerHTML;
|
|
141
|
+
}
|
|
142
|
+
return doc.body.innerHTML;
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
sanitizerLogger.error('HTML sanitization failed', error instanceof Error ? error : new Error(String(error)), {
|
|
146
|
+
inputLength: input.length
|
|
147
|
+
});
|
|
148
|
+
// Fallback to stripping all HTML
|
|
149
|
+
return stripHtml(input);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Sanitizes input based on the specified level
|
|
154
|
+
*
|
|
155
|
+
* @param input Input to sanitize
|
|
156
|
+
* @param level Sanitization level
|
|
157
|
+
* @returns Sanitized input based on level
|
|
158
|
+
*/
|
|
159
|
+
function sanitizeByLevel(input, level) {
|
|
160
|
+
if (!input || typeof input !== 'string') {
|
|
161
|
+
return '';
|
|
162
|
+
}
|
|
163
|
+
switch (level) {
|
|
164
|
+
case 'strict':
|
|
165
|
+
return stripHtml(input).trim();
|
|
166
|
+
case 'medium':
|
|
167
|
+
return sanitizeHtml(input);
|
|
168
|
+
case 'basic':
|
|
169
|
+
default:
|
|
170
|
+
return escapeHtml(input);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Sanitizes strings, objects, or arrays according to sanitization options
|
|
175
|
+
*
|
|
176
|
+
* @param input Input to sanitize
|
|
177
|
+
* @param options Sanitization options
|
|
178
|
+
* @returns Sanitized output
|
|
179
|
+
*/
|
|
180
|
+
function sanitizeInput(input, options = {}) {
|
|
181
|
+
// Default options
|
|
182
|
+
const { level = 'basic', preserveCase = true, preserveWhitespace = true, maxLength } = options;
|
|
183
|
+
// Handle null or undefined
|
|
184
|
+
if (input === null || input === undefined) {
|
|
185
|
+
return input;
|
|
186
|
+
}
|
|
187
|
+
// Handle strings
|
|
188
|
+
if (typeof input === 'string') {
|
|
189
|
+
let result = input;
|
|
190
|
+
// Apply sanitization based on level
|
|
191
|
+
const sanitized = sanitizeByLevel(result, level);
|
|
192
|
+
// Apply other transformations
|
|
193
|
+
let processed = sanitized;
|
|
194
|
+
if (!preserveCase) {
|
|
195
|
+
processed = processed.toLowerCase();
|
|
196
|
+
}
|
|
197
|
+
if (!preserveWhitespace) {
|
|
198
|
+
processed = processed.trim().replace(/\s+/g, ' ');
|
|
199
|
+
}
|
|
200
|
+
// Apply maximum length if specified
|
|
201
|
+
if (maxLength && maxLength > 0 && processed.length > maxLength) {
|
|
202
|
+
processed = processed.substring(0, maxLength);
|
|
203
|
+
}
|
|
204
|
+
return processed;
|
|
205
|
+
}
|
|
206
|
+
// Handle arrays
|
|
207
|
+
if (Array.isArray(input)) {
|
|
208
|
+
return input.map(item => sanitizeInput(item, options));
|
|
209
|
+
}
|
|
210
|
+
// Handle objects
|
|
211
|
+
if (typeof input === 'object') {
|
|
212
|
+
const result = {};
|
|
213
|
+
for (const key in input) {
|
|
214
|
+
if (Object.prototype.hasOwnProperty.call(input, key)) {
|
|
215
|
+
result[key] = sanitizeInput(input[key], options);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return result;
|
|
219
|
+
}
|
|
220
|
+
// Return other types unchanged
|
|
221
|
+
return input;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Main sanitizer function
|
|
225
|
+
*
|
|
226
|
+
* @param input Input to sanitize
|
|
227
|
+
* @param options Sanitization options
|
|
228
|
+
* @returns Sanitized output
|
|
229
|
+
*/
|
|
230
|
+
function sanitize(input, options = {}) {
|
|
231
|
+
try {
|
|
232
|
+
return sanitizeInput(input, options);
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
const normalizedError = normalizeError(error, 'Sanitization failed', {
|
|
236
|
+
category: 'sanitizer',
|
|
237
|
+
context: { options }
|
|
238
|
+
});
|
|
239
|
+
sanitizerLogger.error('Failed to sanitize input', normalizedError);
|
|
240
|
+
// For errors, return empty string for strings or empty objects/arrays
|
|
241
|
+
if (typeof input === 'string') {
|
|
242
|
+
return '';
|
|
243
|
+
}
|
|
244
|
+
else if (Array.isArray(input)) {
|
|
245
|
+
return [];
|
|
246
|
+
}
|
|
247
|
+
else if (typeof input === 'object' && input !== null) {
|
|
248
|
+
return {};
|
|
249
|
+
}
|
|
250
|
+
return undefined;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Safely sanitizes input and handles errors
|
|
255
|
+
*
|
|
256
|
+
* @param input Input to sanitize
|
|
257
|
+
* @param options Sanitization options
|
|
258
|
+
* @returns Sanitized output or original input if sanitization fails
|
|
259
|
+
*/
|
|
260
|
+
async function safeSanitize(input, options = {}) {
|
|
261
|
+
return tryCatch(async () => sanitize(input, options), () => input);
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Creates a sanitizer function with predefined options
|
|
265
|
+
*
|
|
266
|
+
* @param defaultOptions Default sanitization options
|
|
267
|
+
* @returns Sanitizer function with default options applied
|
|
268
|
+
*/
|
|
269
|
+
function createSanitizer(defaultOptions = {}) {
|
|
270
|
+
return (input, options = {}) => {
|
|
271
|
+
// Merge default options with provided options
|
|
272
|
+
const mergedOptions = {
|
|
273
|
+
...defaultOptions,
|
|
274
|
+
...options
|
|
275
|
+
};
|
|
276
|
+
return sanitize(input, mergedOptions);
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
// Predefined sanitizers for common use cases
|
|
280
|
+
const strictSanitizer = createSanitizer({ level: 'strict' });
|
|
281
|
+
const mediumSanitizer = createSanitizer({ level: 'medium' });
|
|
282
|
+
const basicSanitizer = createSanitizer({ level: 'basic' });
|
|
283
|
+
// For form input sanitization
|
|
284
|
+
const inputSanitizer = createSanitizer({
|
|
285
|
+
level: 'strict',
|
|
286
|
+
preserveWhitespace: false
|
|
287
|
+
});
|
|
288
|
+
// For URL parameters
|
|
289
|
+
const urlParamSanitizer = createSanitizer({
|
|
290
|
+
level: 'strict',
|
|
291
|
+
preserveCase: true,
|
|
292
|
+
preserveWhitespace: false,
|
|
293
|
+
maxLength: 255
|
|
294
|
+
});
|
|
295
|
+
// Export the sanitizer functions
|
|
296
|
+
export { sanitize, safeSanitize, createSanitizer, strictSanitizer, mediumSanitizer, basicSanitizer, inputSanitizer, urlParamSanitizer, escapeHtml, stripHtml, sanitizeHtml };
|
|
297
|
+
//# sourceMappingURL=sanitizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizer.js","sourceRoot":"","sources":["../../src/utils/sanitizer.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xbg.solutions/bpsk-utils-sanitizer",
|
|
3
|
+
"version": "1.2.3",
|
|
4
|
+
"description": "XBG Sanitizer - Input sanitization and XSS prevention",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"types": "lib/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"files": ["lib"],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"build:watch": "tsc --watch",
|
|
12
|
+
"clean": "rm -rf lib",
|
|
13
|
+
"prepublishOnly": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@xbg.solutions/bpsk-core": "^1.0.0"
|
|
20
|
+
}
|
|
21
|
+
}
|