hi-secure 1.0.16 → 1.0.18
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/dist/adapters/ArgonAdapter.d.ts.map +1 -1
- package/dist/adapters/ArgonAdapter.js +0 -36
- package/dist/adapters/ArgonAdapter.js.map +1 -1
- package/dist/adapters/BcryptAdapter.d.ts.map +1 -1
- package/dist/adapters/BcryptAdapter.js +0 -36
- package/dist/adapters/BcryptAdapter.js.map +1 -1
- package/dist/adapters/ExpressRLAdapter.d.ts.map +1 -1
- package/dist/adapters/ExpressRLAdapter.js +0 -38
- package/dist/adapters/ExpressRLAdapter.js.map +1 -1
- package/dist/adapters/ExpressValidatorAdapter.d.ts.map +1 -1
- package/dist/adapters/ExpressValidatorAdapter.js +0 -36
- package/dist/adapters/ExpressValidatorAdapter.js.map +1 -1
- package/dist/adapters/GoogleAdapter.d.ts.map +1 -1
- package/dist/adapters/GoogleAdapter.js +0 -63
- package/dist/adapters/GoogleAdapter.js.map +1 -1
- package/dist/adapters/JWTAdapter.d.ts.map +1 -1
- package/dist/adapters/JWTAdapter.js +0 -79
- package/dist/adapters/JWTAdapter.js.map +1 -1
- package/dist/adapters/RLFlexibleAdapter.d.ts.map +1 -1
- package/dist/adapters/RLFlexibleAdapter.js +0 -64
- package/dist/adapters/RLFlexibleAdapter.js.map +1 -1
- package/dist/adapters/SanitizeHtmlAdapter.d.ts.map +1 -1
- package/dist/adapters/SanitizeHtmlAdapter.js +0 -64
- package/dist/adapters/SanitizeHtmlAdapter.js.map +1 -1
- package/dist/adapters/XSSAdapter.d.ts.map +1 -1
- package/dist/adapters/XSSAdapter.js +0 -116
- package/dist/adapters/XSSAdapter.js.map +1 -1
- package/dist/adapters/ZodAdapter.d.ts.map +1 -1
- package/dist/adapters/ZodAdapter.js +0 -3
- package/dist/adapters/ZodAdapter.js.map +1 -1
- package/dist/core/HiSecure.d.ts.map +1 -1
- package/dist/core/HiSecure.js +0 -16
- package/dist/core/HiSecure.js.map +1 -1
- package/dist/logging/index.d.ts.map +1 -1
- package/dist/logging/index.js +0 -2
- package/dist/logging/index.js.map +1 -1
- package/dist/logging/morganSetup.d.ts.map +1 -1
- package/dist/logging/morganSetup.js +0 -14
- package/dist/logging/morganSetup.js.map +1 -1
- package/dist/logging/winstonSetup.d.ts.map +1 -1
- package/dist/logging/winstonSetup.js +2 -46
- package/dist/logging/winstonSetup.js.map +1 -1
- package/dist/managers/AuthManager.d.ts.map +1 -1
- package/dist/managers/AuthManager.js +0 -108
- package/dist/managers/AuthManager.js.map +1 -1
- package/dist/managers/CorsManager.d.ts.map +1 -1
- package/dist/managers/CorsManager.js +0 -28
- package/dist/managers/CorsManager.js.map +1 -1
- package/dist/managers/HashManager.d.ts.map +1 -1
- package/dist/managers/HashManager.js +0 -92
- package/dist/managers/HashManager.js.map +1 -1
- package/dist/managers/JsonManager.d.ts.map +1 -1
- package/dist/managers/JsonManager.js +0 -55
- package/dist/managers/JsonManager.js.map +1 -1
- package/dist/managers/RateLimitManager.d.ts.map +1 -1
- package/dist/managers/RateLimitManager.js +0 -3
- package/dist/managers/RateLimitManager.js.map +1 -1
- package/dist/managers/SanitizerManager.d.ts.map +1 -1
- package/dist/managers/SanitizerManager.js +0 -80
- package/dist/managers/SanitizerManager.js.map +1 -1
- package/dist/managers/ValidatorManager.d.ts.map +1 -1
- package/dist/managers/ValidatorManager.js +0 -59
- package/dist/managers/ValidatorManager.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/ArgonAdapter.ts +0 -45
- package/src/adapters/BcryptAdapter.ts +0 -49
- package/src/adapters/ExpressRLAdapter.ts +0 -48
- package/src/adapters/ExpressValidatorAdapter.ts +0 -50
- package/src/adapters/GoogleAdapter.ts +0 -82
- package/src/adapters/JWTAdapter.ts +0 -96
- package/src/adapters/RLFlexibleAdapter.ts +0 -82
- package/src/adapters/SanitizeHtmlAdapter.ts +1 -84
- package/src/adapters/XSSAdapter.ts +1 -150
- package/src/adapters/ZodAdapter.ts +0 -46
- package/src/core/HiSecure.ts +1 -369
- package/src/logging/index.ts +0 -6
- package/src/logging/morganSetup.ts +0 -25
- package/src/logging/winstonSetup.ts +2 -64
- package/src/managers/AuthManager.ts +0 -141
- package/src/managers/CorsManager.ts +0 -40
- package/src/managers/HashManager.ts +0 -108
- package/src/managers/JsonManager.ts +0 -62
- package/src/managers/RateLimitManager.ts +0 -113
- package/src/managers/SanitizerManager.ts +0 -103
- package/src/managers/ValidatorManager.ts +0 -75
|
@@ -1,70 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// import { RateLimiterMemory, RateLimiterRes } from "rate-limiter-flexible";
|
|
3
|
-
// import { logger } from "../logging/index.js";
|
|
4
|
-
// import { AdapterError } from "../core/errors/AdapterError.js";
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.RLFlexibleAdapter = void 0;
|
|
7
|
-
// export interface RLOptions {
|
|
8
|
-
// points?: number;
|
|
9
|
-
// duration?: number;
|
|
10
|
-
// message?: any;
|
|
11
|
-
// blockDuration?: number;
|
|
12
|
-
// }
|
|
13
|
-
// export class RLFlexibleAdapter {
|
|
14
|
-
// getMiddleware(options: RLOptions = {}) {
|
|
15
|
-
// try {
|
|
16
|
-
// const defaultOptions = {
|
|
17
|
-
// points: 100,
|
|
18
|
-
// duration: 60,
|
|
19
|
-
// message: "Too many requests, slow down.",
|
|
20
|
-
// blockDuration: 0
|
|
21
|
-
// };
|
|
22
|
-
// const finalOptions = { ...defaultOptions, ...options };
|
|
23
|
-
// const limiter = new RateLimiterMemory({
|
|
24
|
-
// points: finalOptions.points,
|
|
25
|
-
// duration: finalOptions.duration,
|
|
26
|
-
// blockDuration: finalOptions.blockDuration
|
|
27
|
-
// });
|
|
28
|
-
// return async (req: any, res: any, next: any) => {
|
|
29
|
-
// const ip = this.extractIP(req);
|
|
30
|
-
// try {
|
|
31
|
-
// await limiter.consume(ip);
|
|
32
|
-
// next();
|
|
33
|
-
// } catch (err: any) {
|
|
34
|
-
// const rlErr = err as RateLimiterRes;
|
|
35
|
-
// logger.warn("RLFlexibleAdapter: rate limit exceeded", {
|
|
36
|
-
// ip,
|
|
37
|
-
// path: req.path,
|
|
38
|
-
// method: req.method,
|
|
39
|
-
// retryAfter: rlErr.msBeforeNext
|
|
40
|
-
// });
|
|
41
|
-
// res.setHeader('Retry-After', Math.ceil(rlErr.msBeforeNext / 1000));
|
|
42
|
-
// return res.status(429).json({
|
|
43
|
-
// success: false,
|
|
44
|
-
// error: "RATE_LIMIT_EXCEEDED",
|
|
45
|
-
// retryAfter: Math.ceil(rlErr.msBeforeNext / 1000),
|
|
46
|
-
// message: finalOptions.message
|
|
47
|
-
// });
|
|
48
|
-
// }
|
|
49
|
-
// };
|
|
50
|
-
// } catch (err: any) {
|
|
51
|
-
// logger.error("RLFlexibleAdapter: failed to initialize limiter", {
|
|
52
|
-
// error: err?.message || err
|
|
53
|
-
// });
|
|
54
|
-
// throw new AdapterError("RateLimiterFlexible creation failed.");
|
|
55
|
-
// }
|
|
56
|
-
// }
|
|
57
|
-
// private extractIP(req: any): string {
|
|
58
|
-
// return (
|
|
59
|
-
// req.headers['x-real-ip'] ||
|
|
60
|
-
// req.headers['x-forwarded-for']?.split(',')[0]?.trim() ||
|
|
61
|
-
// req.ip ||
|
|
62
|
-
// req.connection?.remoteAddress ||
|
|
63
|
-
// req.socket?.remoteAddress ||
|
|
64
|
-
// 'unknown'
|
|
65
|
-
// );
|
|
66
|
-
// }
|
|
67
|
-
// }
|
|
68
4
|
const rate_limiter_flexible_1 = require("rate-limiter-flexible");
|
|
69
5
|
const logging_1 = require("../logging");
|
|
70
6
|
const AdapterError_1 = require("../core/errors/AdapterError");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RLFlexibleAdapter.js","sourceRoot":"","sources":["../../src/adapters/RLFlexibleAdapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"RLFlexibleAdapter.js","sourceRoot":"","sources":["../../src/adapters/RLFlexibleAdapter.ts"],"names":[],"mappings":";;;AAAA,iEAA0E;AAC1E,wCAAoC;AACpC,8DAA2D;AAS3D,MAAa,iBAAiB;IAC1B,aAAa,CAAC,UAAqB,EAAE;QACjC,IAAI,CAAC;YACD,MAAM,cAAc,GAAG;gBACnB,MAAM,EAAE,GAAG;gBACX,QAAQ,EAAE,EAAE;gBACZ,OAAO,EAAE,+BAA+B;gBACxC,aAAa,EAAE,CAAC;aACnB,CAAC;YAEF,MAAM,YAAY,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,OAAO,EAAE,CAAC;YAEvD,MAAM,OAAO,GAAG,IAAI,yCAAiB,CAAC;gBAClC,MAAM,EAAE,YAAY,CAAC,MAAM;gBAC3B,QAAQ,EAAE,YAAY,CAAC,QAAQ;gBAC/B,aAAa,EAAE,YAAY,CAAC,aAAa;aAC5C,CAAC,CAAC;YAGH,gBAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE;gBACpC,OAAO,EAAE,uBAAuB;gBAChC,SAAS,EAAE,MAAM;gBACjB,MAAM,EAAE,YAAY,CAAC,MAAM;gBAC3B,QAAQ,EAAE,YAAY,CAAC,QAAQ;gBAC/B,aAAa,EAAE,YAAY,CAAC,aAAa;aAC5C,CAAC,CAAC;YAEH,OAAO,KAAK,EAAE,GAAQ,EAAE,GAAQ,EAAE,IAAS,EAAE,EAAE;gBAC3C,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;gBAE/B,IAAI,CAAC;oBACD,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;oBAC1B,IAAI,EAAE,CAAC;gBACX,CAAC;gBAAC,OAAO,GAAQ,EAAE,CAAC;oBAChB,MAAM,KAAK,GAAG,GAAqB,CAAC;oBAEpC,gBAAM,CAAC,IAAI,CAAC,qBAAqB,EAAE;wBAC/B,OAAO,EAAE,uBAAuB;wBAChC,SAAS,EAAE,SAAS;wBACpB,EAAE;wBACF,MAAM,EAAE,GAAG,CAAC,MAAM;wBAClB,IAAI,EAAE,GAAG,CAAC,IAAI;wBACd,YAAY,EAAE,KAAK,CAAC,YAAY;qBACnC,CAAC,CAAC;oBAEH,GAAG,CAAC,SAAS,CACT,aAAa,EACb,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CACvC,CAAC;oBAEF,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;wBACxB,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE,qBAAqB;wBAC5B,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;wBAChD,OAAO,EAAE,YAAY,CAAC,OAAO;qBAChC,CAAC,CAAC;gBACP,CAAC;YACL,CAAC,CAAC;QACN,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAChB,gBAAM,CAAC,KAAK,CAAC,oCAAoC,EAAE;gBAC/C,OAAO,EAAE,uBAAuB;gBAChC,SAAS,EAAE,MAAM;gBACjB,MAAM,EAAE,GAAG,EAAE,OAAO;aACvB,CAAC,CAAC;YAEH,MAAM,IAAI,2BAAY,CAAC,sCAAsC,CAAC,CAAC;QACnE,CAAC;IACL,CAAC;IAEO,SAAS,CAAC,GAAQ;QACtB,OAAO,CACH,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC;YACxB,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE;YACrD,GAAG,CAAC,EAAE;YACN,GAAG,CAAC,UAAU,EAAE,aAAa;YAC7B,GAAG,CAAC,MAAM,EAAE,aAAa;YACzB,SAAS,CACZ,CAAC;IACN,CAAC;CACJ;AA/ED,8CA+EC","sourcesContent":["import { RateLimiterMemory, RateLimiterRes } from \"rate-limiter-flexible\";\r\nimport { logger } from \"../logging\";\r\nimport { AdapterError } from \"../core/errors/AdapterError\";\r\n\r\nexport interface RLOptions {\r\n points?: number;\r\n duration?: number;\r\n message?: any;\r\n blockDuration?: number;\r\n}\r\n\r\nexport class RLFlexibleAdapter {\r\n getMiddleware(options: RLOptions = {}) {\r\n try {\r\n const defaultOptions = {\r\n points: 100,\r\n duration: 60,\r\n message: \"Too many requests, slow down.\",\r\n blockDuration: 0\r\n };\r\n\r\n const finalOptions = { ...defaultOptions, ...options };\r\n\r\n const limiter = new RateLimiterMemory({\r\n points: finalOptions.points,\r\n duration: finalOptions.duration,\r\n blockDuration: finalOptions.blockDuration\r\n });\r\n\r\n \r\n logger.info(\"Rate limiter initialized\", {\r\n adapter: \"rate-limiter-flexible\",\r\n operation: \"init\",\r\n points: finalOptions.points,\r\n duration: finalOptions.duration,\r\n blockDuration: finalOptions.blockDuration\r\n });\r\n\r\n return async (req: any, res: any, next: any) => {\r\n const ip = this.extractIP(req);\r\n\r\n try {\r\n await limiter.consume(ip);\r\n next();\r\n } catch (err: any) {\r\n const rlErr = err as RateLimiterRes;\r\n\r\n logger.warn(\"Rate limit exceeded\", {\r\n adapter: \"rate-limiter-flexible\",\r\n operation: \"consume\",\r\n ip,\r\n method: req.method,\r\n path: req.path,\r\n retryAfterMs: rlErr.msBeforeNext\r\n });\r\n\r\n res.setHeader(\r\n \"Retry-After\",\r\n Math.ceil(rlErr.msBeforeNext / 1000)\r\n );\r\n\r\n return res.status(429).json({\r\n success: false,\r\n error: \"RATE_LIMIT_EXCEEDED\",\r\n retryAfter: Math.ceil(rlErr.msBeforeNext / 1000),\r\n message: finalOptions.message\r\n });\r\n }\r\n };\r\n } catch (err: any) {\r\n logger.error(\"Rate limiter initialization failed\", {\r\n adapter: \"rate-limiter-flexible\",\r\n operation: \"init\",\r\n reason: err?.message\r\n });\r\n\r\n throw new AdapterError(\"RateLimiterFlexible creation failed.\");\r\n }\r\n }\r\n\r\n private extractIP(req: any): string {\r\n return (\r\n req.headers[\"x-real-ip\"] ||\r\n req.headers[\"x-forwarded-for\"]?.split(\",\")[0]?.trim() ||\r\n req.ip ||\r\n req.connection?.remoteAddress ||\r\n req.socket?.remoteAddress ||\r\n \"unknown\"\r\n );\r\n }\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SanitizeHtmlAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/SanitizeHtmlAdapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SanitizeHtmlAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/SanitizeHtmlAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAC;AAIzC,qBAAa,mBAAmB;IAC5B,OAAO,CAAC,aAAa,CAAwB;gBAEjC,OAAO,GAAE,YAAY,CAAC,QAAa;IAI/C,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,GAAG,GAAG,MAAM;IAmBrD,OAAO,CAAC,YAAY;IA+BpB,UAAU,CAAC,cAAc,CAAC,EAAE,GAAG,IACnB,KAAK,GAAG,EAAE,MAAM,GAAG,EAAE,MAAM,GAAG;CAyB7C"}
|
|
@@ -1,72 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// import sanitizeHtml from "sanitize-html";
|
|
3
|
-
// import { AdapterError } from "../core/errors/AdapterError.js";
|
|
4
|
-
// import { logger } from "../logging/index.js";
|
|
5
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
4
|
};
|
|
8
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
6
|
exports.SanitizeHtmlAdapter = void 0;
|
|
10
|
-
// export class SanitizeHtmlAdapter {
|
|
11
|
-
// private globalOptions: sanitizeHtml.IOptions;
|
|
12
|
-
// constructor(options: sanitizeHtml.IOptions = {}) {
|
|
13
|
-
// this.globalOptions = options;
|
|
14
|
-
// }
|
|
15
|
-
// sanitize(input: string, dynamicOptions?: any): string {
|
|
16
|
-
// try {
|
|
17
|
-
// const opts = { ...this.globalOptions, ...(dynamicOptions || {}) };
|
|
18
|
-
// const clean = sanitizeHtml(input, opts);
|
|
19
|
-
// return typeof clean === "string" ? clean : String(clean);
|
|
20
|
-
// } catch (err: any) {
|
|
21
|
-
// logger.error("sanitize-html failed", {
|
|
22
|
-
// error: err?.message || err,
|
|
23
|
-
// preview: typeof input === "string" ? input.slice(0, 100) : undefined
|
|
24
|
-
// });
|
|
25
|
-
// throw new AdapterError("sanitize-html adapter failed.");
|
|
26
|
-
// }
|
|
27
|
-
// }
|
|
28
|
-
// // Deep Sanitization - Recursively
|
|
29
|
-
// private deepSanitize(obj: any, dynamicOptions?: any, visited = new WeakSet()): any {
|
|
30
|
-
// if (obj && typeof obj === "object") {
|
|
31
|
-
// if (visited.has(obj)) {
|
|
32
|
-
// return obj;
|
|
33
|
-
// }
|
|
34
|
-
// visited.add(obj);
|
|
35
|
-
// }
|
|
36
|
-
// if (typeof obj === "string") {
|
|
37
|
-
// return this.sanitize(obj, dynamicOptions);
|
|
38
|
-
// }
|
|
39
|
-
// if (Array.isArray(obj)) {
|
|
40
|
-
// return obj.map((item) => this.deepSanitize(item, dynamicOptions, visited));
|
|
41
|
-
// }
|
|
42
|
-
// if (obj && typeof obj === "object") {
|
|
43
|
-
// const result: any = {};
|
|
44
|
-
// for (const key of Object.keys(obj)) {
|
|
45
|
-
// result[key] = this.deepSanitize(obj[key], dynamicOptions, visited);
|
|
46
|
-
// }
|
|
47
|
-
// return result;
|
|
48
|
-
// }
|
|
49
|
-
// return obj;
|
|
50
|
-
// }
|
|
51
|
-
// middleware(dynamicOptions?: any) {
|
|
52
|
-
// return (req: any, _res: any, next: any) => {
|
|
53
|
-
// try {
|
|
54
|
-
// if (req.body) {
|
|
55
|
-
// req.body = this.deepSanitize(req.body, dynamicOptions);
|
|
56
|
-
// logger.debug("sanitize-html applied", {
|
|
57
|
-
// keys: Object.keys(req.body)
|
|
58
|
-
// });
|
|
59
|
-
// }
|
|
60
|
-
// next();
|
|
61
|
-
// } catch (err: any) {
|
|
62
|
-
// logger.error("sanitize-html middleware failed", {
|
|
63
|
-
// error: err?.message || err
|
|
64
|
-
// });
|
|
65
|
-
// next(err);
|
|
66
|
-
// }
|
|
67
|
-
// };
|
|
68
|
-
// }
|
|
69
|
-
// }
|
|
70
7
|
const sanitize_html_1 = __importDefault(require("sanitize-html"));
|
|
71
8
|
const AdapterError_1 = require("../core/errors/AdapterError");
|
|
72
9
|
const logging_1 = require("../logging");
|
|
@@ -116,7 +53,6 @@ class SanitizeHtmlAdapter {
|
|
|
116
53
|
try {
|
|
117
54
|
if (req.body) {
|
|
118
55
|
req.body = this.deepSanitize(req.body, dynamicOptions);
|
|
119
|
-
// ✅ visible + safe info log
|
|
120
56
|
logging_1.logger.info("HTML sanitization applied", {
|
|
121
57
|
adapter: "sanitize-html",
|
|
122
58
|
operation: "middleware",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SanitizeHtmlAdapter.js","sourceRoot":"","sources":["../../src/adapters/SanitizeHtmlAdapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SanitizeHtmlAdapter.js","sourceRoot":"","sources":["../../src/adapters/SanitizeHtmlAdapter.ts"],"names":[],"mappings":";;;;;;AAAA,kEAAyC;AACzC,8DAA2D;AAC3D,wCAAoC;AAEpC,MAAa,mBAAmB;IAG5B,YAAY,UAAiC,EAAE;QAC3C,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;IACjC,CAAC;IAED,QAAQ,CAAC,KAAa,EAAE,cAAoB;QACxC,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC,EAAE,CAAC;YAClE,MAAM,KAAK,GAAG,IAAA,uBAAY,EAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAExC,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAE7D,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAChB,gBAAM,CAAC,KAAK,CAAC,0BAA0B,EAAE;gBACrC,OAAO,EAAE,eAAe;gBACxB,SAAS,EAAE,UAAU;gBACrB,MAAM,EAAE,GAAG,EAAE,OAAO;aACvB,CAAC,CAAC;YAEH,MAAM,IAAI,2BAAY,CAAC,+BAA+B,CAAC,CAAC;QAC5D,CAAC;IACL,CAAC;IAED,kCAAkC;IAC1B,YAAY,CAAC,GAAQ,EAAE,cAAoB,EAAE,OAAO,GAAG,IAAI,OAAO,EAAE;QACxE,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YACjC,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,OAAO,GAAG,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;QAED,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,OAAO,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAClB,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,CAAC,CACnD,CAAC;QACN,CAAC;QAED,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YACjC,MAAM,MAAM,GAAQ,EAAE,CAAC;YACvB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACjC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,YAAY,CAC3B,GAAG,CAAC,GAAG,CAAC,EACR,cAAc,EACd,OAAO,CACV,CAAC;YACN,CAAC;YACD,OAAO,MAAM,CAAC;QAClB,CAAC;QAED,OAAO,GAAG,CAAC;IACf,CAAC;IAED,UAAU,CAAC,cAAoB;QAC3B,OAAO,CAAC,GAAQ,EAAE,IAAS,EAAE,IAAS,EAAE,EAAE;YACtC,IAAI,CAAC;gBACD,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;oBACX,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;oBAGvD,gBAAM,CAAC,IAAI,CAAC,2BAA2B,EAAE;wBACrC,OAAO,EAAE,eAAe;wBACxB,SAAS,EAAE,YAAY;wBACvB,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;qBAC9B,CAAC,CAAC;gBACP,CAAC;gBAED,IAAI,EAAE,CAAC;YACX,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAChB,gBAAM,CAAC,KAAK,CAAC,qCAAqC,EAAE;oBAChD,OAAO,EAAE,eAAe;oBACxB,SAAS,EAAE,YAAY;oBACvB,MAAM,EAAE,GAAG,EAAE,OAAO;iBACvB,CAAC,CAAC;gBAEH,IAAI,CAAC,GAAG,CAAC,CAAC;YACd,CAAC;QACL,CAAC,CAAC;IACN,CAAC;CACJ;AAnFD,kDAmFC","sourcesContent":["import sanitizeHtml from \"sanitize-html\";\r\nimport { AdapterError } from \"../core/errors/AdapterError\";\r\nimport { logger } from \"../logging\";\r\n\r\nexport class SanitizeHtmlAdapter {\r\n private globalOptions: sanitizeHtml.IOptions;\r\n\r\n constructor(options: sanitizeHtml.IOptions = {}) {\r\n this.globalOptions = options;\r\n }\r\n\r\n sanitize(input: string, dynamicOptions?: any): string {\r\n try {\r\n const opts = { ...this.globalOptions, ...(dynamicOptions || {}) };\r\n const clean = sanitizeHtml(input, opts);\r\n\r\n return typeof clean === \"string\" ? clean : String(clean);\r\n\r\n } catch (err: any) {\r\n logger.error(\"HTML sanitization failed\", {\r\n adapter: \"sanitize-html\",\r\n operation: \"sanitize\",\r\n reason: err?.message\r\n });\r\n\r\n throw new AdapterError(\"sanitize-html adapter failed.\");\r\n }\r\n }\r\n\r\n // Deep Sanitization - recursively\r\n private deepSanitize(obj: any, dynamicOptions?: any, visited = new WeakSet()): any {\r\n if (obj && typeof obj === \"object\") {\r\n if (visited.has(obj)) return obj;\r\n visited.add(obj);\r\n }\r\n\r\n if (typeof obj === \"string\") {\r\n return this.sanitize(obj, dynamicOptions);\r\n }\r\n\r\n if (Array.isArray(obj)) {\r\n return obj.map(item =>\r\n this.deepSanitize(item, dynamicOptions, visited)\r\n );\r\n }\r\n\r\n if (obj && typeof obj === \"object\") {\r\n const result: any = {};\r\n for (const key of Object.keys(obj)) {\r\n result[key] = this.deepSanitize(\r\n obj[key],\r\n dynamicOptions,\r\n visited\r\n );\r\n }\r\n return result;\r\n }\r\n\r\n return obj;\r\n }\r\n\r\n middleware(dynamicOptions?: any) {\r\n return (req: any, _res: any, next: any) => {\r\n try {\r\n if (req.body) {\r\n req.body = this.deepSanitize(req.body, dynamicOptions);\r\n\r\n \r\n logger.info(\"HTML sanitization applied\", {\r\n adapter: \"sanitize-html\",\r\n operation: \"middleware\",\r\n keys: Object.keys(req.body)\r\n });\r\n }\r\n\r\n next();\r\n } catch (err: any) {\r\n logger.error(\"HTML sanitization middleware failed\", {\r\n adapter: \"sanitize-html\",\r\n operation: \"middleware\",\r\n reason: err?.message\r\n });\r\n\r\n next(err);\r\n }\r\n };\r\n }\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"XSSAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/XSSAdapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"XSSAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/XSSAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,SAAS,EAAE,MAAM,KAAK,CAAC;AAIhE,MAAM,WAAW,UAAU;IACvB,SAAS,CAAC,EAAE,OAAO,SAAS,CAAC;IAC7B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,GAAG,CAAC,EAAE,OAAO,GAAG;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IAC3C,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,MAAM,CAAC;IAC5D,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,KAAK,MAAM,CAAC;IACvF,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,MAAM,CAAC;IAClE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,qBAAa,UAAU;IACnB,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,aAAa,CAAY;gBAErB,OAAO,GAAE,UAAe;IAwBpC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,UAAU,GAAG,MAAM;IAwB5D,UAAU,CAAC,cAAc,CAAC,EAAE,UAAU,IAC1B,KAAK,GAAG,EAAE,MAAM,GAAG,EAAE,MAAM,GAAG;IA8C1C,OAAO,CAAC,YAAY;CAwBvB"}
|
|
@@ -1,121 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// import { FilterXSS, getDefaultWhiteList, whiteList } from 'xss';
|
|
3
|
-
// import { AdapterError } from "../core/errors/AdapterError.js";
|
|
4
|
-
// import { logger } from "../logging/index.js";
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.XSSAdapter = void 0;
|
|
7
|
-
// export interface XSSOptions {
|
|
8
|
-
// whiteList?: typeof whiteList;
|
|
9
|
-
// stripIgnoreTag?: boolean;
|
|
10
|
-
// stripIgnoreTagBody?: string[];
|
|
11
|
-
// allowCommentTag?: boolean;
|
|
12
|
-
// css?: boolean | { [key: string]: boolean };
|
|
13
|
-
// onTag?: (tag: string, html: string, options: any) => string;
|
|
14
|
-
// onTagAttr?: (tag: string, name: string, value: string, isWhiteAttr: boolean) => string;
|
|
15
|
-
// onIgnoreTag?: (tag: string, html: string, options: any) => string;
|
|
16
|
-
// [key: string]: any;
|
|
17
|
-
// }
|
|
18
|
-
// export class XSSAdapter {
|
|
19
|
-
// private globalOptions: XSSOptions;
|
|
20
|
-
// private defaultFilter: FilterXSS;
|
|
21
|
-
// constructor(options: XSSOptions = {}) {
|
|
22
|
-
// this.globalOptions = options;
|
|
23
|
-
// // Default safe configuration
|
|
24
|
-
// const defaultOptions: XSSOptions = {
|
|
25
|
-
// whiteList: getDefaultWhiteList(),
|
|
26
|
-
// stripIgnoreTag: true,
|
|
27
|
-
// stripIgnoreTagBody: ['script', 'style', 'iframe', 'object', 'embed'],
|
|
28
|
-
// allowCommentTag: false,
|
|
29
|
-
// css: false,
|
|
30
|
-
// onTag: (tag, html, options) => {
|
|
31
|
-
// if (tag === 'a') {
|
|
32
|
-
// return html.replace(/<a /i, '<a target="_blank" rel="noopener noreferrer" ');
|
|
33
|
-
// }
|
|
34
|
-
// return html;
|
|
35
|
-
// }
|
|
36
|
-
// };
|
|
37
|
-
// const finalOptions = { ...defaultOptions, ...options };
|
|
38
|
-
// this.defaultFilter = new FilterXSS(finalOptions);
|
|
39
|
-
// }
|
|
40
|
-
// sanitize(input: string, dynamicOptions?: XSSOptions): string {
|
|
41
|
-
// try {
|
|
42
|
-
// if (typeof input !== "string") {
|
|
43
|
-
// return input as any;
|
|
44
|
-
// }
|
|
45
|
-
// if (!dynamicOptions || Object.keys(dynamicOptions).length === 0) {
|
|
46
|
-
// return this.defaultFilter.process(input);
|
|
47
|
-
// }
|
|
48
|
-
// const mergedOptions = { ...this.globalOptions, ...dynamicOptions };
|
|
49
|
-
// const customFilter = new FilterXSS(mergedOptions);
|
|
50
|
-
// return customFilter.process(input);
|
|
51
|
-
// } catch (err: any) {
|
|
52
|
-
// logger.error("XSS sanitizer failed", {
|
|
53
|
-
// error: err?.message,
|
|
54
|
-
// preview: input?.slice?.(0, 80)
|
|
55
|
-
// });
|
|
56
|
-
// throw new AdapterError("XSS sanitizer failed.");
|
|
57
|
-
// }
|
|
58
|
-
// }
|
|
59
|
-
// middleware(dynamicOptions?: XSSOptions) {
|
|
60
|
-
// return (req: any, _res: any, next: any) => {
|
|
61
|
-
// try {
|
|
62
|
-
// if (req.body && typeof req.body === "object") {
|
|
63
|
-
// const originalBody = req.body;
|
|
64
|
-
// const sanitizedBody: any = Array.isArray(originalBody) ? [] : {};
|
|
65
|
-
// for (const key of Object.keys(originalBody)) {
|
|
66
|
-
// const val = originalBody[key];
|
|
67
|
-
// if (typeof val === "string") {
|
|
68
|
-
// sanitizedBody[key] = this.sanitize(val, dynamicOptions);
|
|
69
|
-
// } else if (Array.isArray(val)) {
|
|
70
|
-
// sanitizedBody[key] = val.map((v) =>
|
|
71
|
-
// typeof v === "string"
|
|
72
|
-
// ? this.sanitize(v, dynamicOptions)
|
|
73
|
-
// : v
|
|
74
|
-
// );
|
|
75
|
-
// } else if (val && typeof val === "object") {
|
|
76
|
-
// sanitizedBody[key] = this.deepSanitize(val, dynamicOptions);
|
|
77
|
-
// } else {
|
|
78
|
-
// sanitizedBody[key] = val;
|
|
79
|
-
// }
|
|
80
|
-
// }
|
|
81
|
-
// req.sanitizedBody = sanitizedBody;
|
|
82
|
-
// logger.debug("XSS sanitizer applied", {
|
|
83
|
-
// originalKeys: Object.keys(originalBody),
|
|
84
|
-
// sanitizedKeys: Object.keys(sanitizedBody)
|
|
85
|
-
// });
|
|
86
|
-
// }
|
|
87
|
-
// next();
|
|
88
|
-
// } catch (err: any) {
|
|
89
|
-
// logger.error("XSS middleware failed", {
|
|
90
|
-
// error: err?.message || err
|
|
91
|
-
// });
|
|
92
|
-
// next(err);
|
|
93
|
-
// }
|
|
94
|
-
// };
|
|
95
|
-
// }
|
|
96
|
-
// private deepSanitize(obj: any, options?: XSSOptions, visited = new WeakSet()): any {
|
|
97
|
-
// if (obj && typeof obj === "object") {
|
|
98
|
-
// if (visited.has(obj)) {
|
|
99
|
-
// return obj;
|
|
100
|
-
// }
|
|
101
|
-
// visited.add(obj);
|
|
102
|
-
// }
|
|
103
|
-
// if (typeof obj === "string") {
|
|
104
|
-
// return this.sanitize(obj, options);
|
|
105
|
-
// }
|
|
106
|
-
// if (Array.isArray(obj)) {
|
|
107
|
-
// return obj.map(item => this.deepSanitize(item, options, visited));
|
|
108
|
-
// }
|
|
109
|
-
// if (obj && typeof obj === "object") {
|
|
110
|
-
// const result: any = {};
|
|
111
|
-
// for (const key of Object.keys(obj)) {
|
|
112
|
-
// result[key] = this.deepSanitize(obj[key], options, visited);
|
|
113
|
-
// }
|
|
114
|
-
// return result;
|
|
115
|
-
// }
|
|
116
|
-
// return obj;
|
|
117
|
-
// }
|
|
118
|
-
// }
|
|
119
4
|
const xss_1 = require("xss");
|
|
120
5
|
const AdapterError_1 = require("../core/errors/AdapterError");
|
|
121
6
|
const logging_1 = require("../logging");
|
|
@@ -182,7 +67,6 @@ class XSSAdapter {
|
|
|
182
67
|
}
|
|
183
68
|
}
|
|
184
69
|
req.sanitizedBody = sanitizedBody;
|
|
185
|
-
// ✅ visible + safe info log
|
|
186
70
|
logging_1.logger.info("XSS sanitization applied", {
|
|
187
71
|
adapter: "xss",
|
|
188
72
|
operation: "middleware",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"XSSAdapter.js","sourceRoot":"","sources":["../../src/adapters/XSSAdapter.ts"],"names":[],"mappings":"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","sourcesContent":["// import { FilterXSS, getDefaultWhiteList, whiteList } from 'xss';\r\n// import { AdapterError } from \"../core/errors/AdapterError.js\";\r\n// import { logger } from \"../logging/index.js\";\r\n\r\n// export interface XSSOptions {\r\n// whiteList?: typeof whiteList;\r\n// stripIgnoreTag?: boolean;\r\n// stripIgnoreTagBody?: string[];\r\n// allowCommentTag?: boolean;\r\n// css?: boolean | { [key: string]: boolean };\r\n// onTag?: (tag: string, html: string, options: any) => string;\r\n// onTagAttr?: (tag: string, name: string, value: string, isWhiteAttr: boolean) => string;\r\n// onIgnoreTag?: (tag: string, html: string, options: any) => string;\r\n// [key: string]: any;\r\n// }\r\n\r\n// export class XSSAdapter {\r\n// private globalOptions: XSSOptions;\r\n// private defaultFilter: FilterXSS;\r\n\r\n// constructor(options: XSSOptions = {}) {\r\n// this.globalOptions = options;\r\n \r\n// // Default safe configuration\r\n// const defaultOptions: XSSOptions = {\r\n// whiteList: getDefaultWhiteList(),\r\n// stripIgnoreTag: true, \r\n// stripIgnoreTagBody: ['script', 'style', 'iframe', 'object', 'embed'],\r\n// allowCommentTag: false,\r\n// css: false, \r\n// onTag: (tag, html, options) => {\r\n \r\n// if (tag === 'a') {\r\n// return html.replace(/<a /i, '<a target=\"_blank\" rel=\"noopener noreferrer\" ');\r\n// }\r\n// return html;\r\n// }\r\n// };\r\n\r\n// const finalOptions = { ...defaultOptions, ...options };\r\n// this.defaultFilter = new FilterXSS(finalOptions);\r\n// }\r\n\r\n \r\n// sanitize(input: string, dynamicOptions?: XSSOptions): string {\r\n// try {\r\n// if (typeof input !== \"string\") {\r\n// return input as any;\r\n// }\r\n\r\n \r\n// if (!dynamicOptions || Object.keys(dynamicOptions).length === 0) {\r\n// return this.defaultFilter.process(input);\r\n// }\r\n\r\n \r\n// const mergedOptions = { ...this.globalOptions, ...dynamicOptions };\r\n// const customFilter = new FilterXSS(mergedOptions);\r\n \r\n// return customFilter.process(input);\r\n\r\n// } catch (err: any) {\r\n// logger.error(\"XSS sanitizer failed\", {\r\n// error: err?.message,\r\n// preview: input?.slice?.(0, 80)\r\n// });\r\n// throw new AdapterError(\"XSS sanitizer failed.\");\r\n// }\r\n// }\r\n\r\n \r\n// middleware(dynamicOptions?: XSSOptions) {\r\n// return (req: any, _res: any, next: any) => {\r\n// try {\r\n// if (req.body && typeof req.body === \"object\") {\r\n// const originalBody = req.body;\r\n// const sanitizedBody: any = Array.isArray(originalBody) ? [] : {};\r\n \r\n// for (const key of Object.keys(originalBody)) {\r\n// const val = originalBody[key];\r\n\r\n// if (typeof val === \"string\") {\r\n// sanitizedBody[key] = this.sanitize(val, dynamicOptions);\r\n// } else if (Array.isArray(val)) {\r\n// sanitizedBody[key] = val.map((v) =>\r\n// typeof v === \"string\"\r\n// ? this.sanitize(v, dynamicOptions)\r\n// : v\r\n// );\r\n// } else if (val && typeof val === \"object\") {\r\n \r\n// sanitizedBody[key] = this.deepSanitize(val, dynamicOptions);\r\n// } else {\r\n// sanitizedBody[key] = val;\r\n// }\r\n// }\r\n \r\n \r\n// req.sanitizedBody = sanitizedBody;\r\n \r\n// logger.debug(\"XSS sanitizer applied\", {\r\n// originalKeys: Object.keys(originalBody),\r\n// sanitizedKeys: Object.keys(sanitizedBody)\r\n// });\r\n// }\r\n\r\n// next();\r\n// } catch (err: any) {\r\n// logger.error(\"XSS middleware failed\", {\r\n// error: err?.message || err\r\n// });\r\n// next(err);\r\n// }\r\n// };\r\n// }\r\n\r\n \r\n// private deepSanitize(obj: any, options?: XSSOptions, visited = new WeakSet()): any {\r\n \r\n// if (obj && typeof obj === \"object\") {\r\n// if (visited.has(obj)) {\r\n// return obj;\r\n// }\r\n// visited.add(obj);\r\n// }\r\n\r\n// if (typeof obj === \"string\") {\r\n// return this.sanitize(obj, options);\r\n// }\r\n\r\n// if (Array.isArray(obj)) {\r\n// return obj.map(item => this.deepSanitize(item, options, visited));\r\n// }\r\n\r\n// if (obj && typeof obj === \"object\") {\r\n// const result: any = {};\r\n// for (const key of Object.keys(obj)) {\r\n// result[key] = this.deepSanitize(obj[key], options, visited);\r\n// }\r\n// return result;\r\n// }\r\n\r\n// return obj;\r\n// }\r\n// }\r\n\r\n\r\n\r\n\r\nimport { FilterXSS, getDefaultWhiteList, whiteList } from \"xss\";\r\nimport { AdapterError } from \"../core/errors/AdapterError\";\r\nimport { logger } from \"../logging\";\r\n\r\nexport interface XSSOptions {\r\n whiteList?: typeof whiteList;\r\n stripIgnoreTag?: boolean;\r\n stripIgnoreTagBody?: string[];\r\n allowCommentTag?: boolean;\r\n css?: boolean | { [key: string]: boolean };\r\n onTag?: (tag: string, html: string, options: any) => string;\r\n onTagAttr?: (tag: string, name: string, value: string, isWhiteAttr: boolean) => string;\r\n onIgnoreTag?: (tag: string, html: string, options: any) => string;\r\n [key: string]: any;\r\n}\r\n\r\nexport class XSSAdapter {\r\n private globalOptions: XSSOptions;\r\n private defaultFilter: FilterXSS;\r\n\r\n constructor(options: XSSOptions = {}) {\r\n this.globalOptions = options;\r\n\r\n const defaultOptions: XSSOptions = {\r\n whiteList: getDefaultWhiteList(),\r\n stripIgnoreTag: true,\r\n stripIgnoreTagBody: [\"script\", \"style\", \"iframe\", \"object\", \"embed\"],\r\n allowCommentTag: false,\r\n css: false,\r\n onTag: (tag, html) => {\r\n if (tag === \"a\") {\r\n return html.replace(\r\n /<a /i,\r\n '<a target=\"_blank\" rel=\"noopener noreferrer\" '\r\n );\r\n }\r\n return html;\r\n }\r\n };\r\n\r\n const finalOptions = { ...defaultOptions, ...options };\r\n this.defaultFilter = new FilterXSS(finalOptions);\r\n }\r\n\r\n sanitize(input: string, dynamicOptions?: XSSOptions): string {\r\n try {\r\n if (typeof input !== \"string\") return input as any;\r\n\r\n if (!dynamicOptions || Object.keys(dynamicOptions).length === 0) {\r\n return this.defaultFilter.process(input);\r\n }\r\n\r\n const mergedOptions = { ...this.globalOptions, ...dynamicOptions };\r\n const customFilter = new FilterXSS(mergedOptions);\r\n\r\n return customFilter.process(input);\r\n\r\n } catch (err: any) {\r\n logger.error(\"XSS sanitization failed\", {\r\n adapter: \"xss\",\r\n operation: \"sanitize\",\r\n reason: err?.message\r\n });\r\n\r\n throw new AdapterError(\"XSS sanitizer failed.\");\r\n }\r\n }\r\n\r\n middleware(dynamicOptions?: XSSOptions) {\r\n return (req: any, _res: any, next: any) => {\r\n try {\r\n if (req.body && typeof req.body === \"object\") {\r\n const originalBody = req.body;\r\n const sanitizedBody: any = Array.isArray(originalBody) ? [] : {};\r\n\r\n for (const key of Object.keys(originalBody)) {\r\n const val = originalBody[key];\r\n\r\n if (typeof val === \"string\") {\r\n sanitizedBody[key] = this.sanitize(val, dynamicOptions);\r\n } else if (Array.isArray(val)) {\r\n sanitizedBody[key] = val.map(v =>\r\n typeof v === \"string\"\r\n ? this.sanitize(v, dynamicOptions)\r\n : v\r\n );\r\n } else if (val && typeof val === \"object\") {\r\n sanitizedBody[key] = this.deepSanitize(val, dynamicOptions);\r\n } else {\r\n sanitizedBody[key] = val;\r\n }\r\n }\r\n\r\n req.sanitizedBody = sanitizedBody;\r\n\r\n // ✅ visible + safe info log\r\n logger.info(\"XSS sanitization applied\", {\r\n adapter: \"xss\",\r\n operation: \"middleware\",\r\n keys: Object.keys(sanitizedBody)\r\n });\r\n }\r\n\r\n next();\r\n } catch (err: any) {\r\n logger.error(\"XSS middleware failed\", {\r\n adapter: \"xss\",\r\n operation: \"middleware\",\r\n reason: err?.message\r\n });\r\n next(err);\r\n }\r\n };\r\n }\r\n\r\n private deepSanitize(obj: any, options?: XSSOptions, visited = new WeakSet()): any {\r\n if (obj && typeof obj === \"object\") {\r\n if (visited.has(obj)) return obj;\r\n visited.add(obj);\r\n }\r\n\r\n if (typeof obj === \"string\") {\r\n return this.sanitize(obj, options);\r\n }\r\n\r\n if (Array.isArray(obj)) {\r\n return obj.map(item => this.deepSanitize(item, options, visited));\r\n }\r\n\r\n if (obj && typeof obj === \"object\") {\r\n const result: any = {};\r\n for (const key of Object.keys(obj)) {\r\n result[key] = this.deepSanitize(obj[key], options, visited);\r\n }\r\n return result;\r\n }\r\n\r\n return obj;\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"XSSAdapter.js","sourceRoot":"","sources":["../../src/adapters/XSSAdapter.ts"],"names":[],"mappings":"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","sourcesContent":["import { FilterXSS, getDefaultWhiteList, whiteList } from \"xss\";\r\nimport { AdapterError } from \"../core/errors/AdapterError\";\r\nimport { logger } from \"../logging\";\r\n\r\nexport interface XSSOptions {\r\n whiteList?: typeof whiteList;\r\n stripIgnoreTag?: boolean;\r\n stripIgnoreTagBody?: string[];\r\n allowCommentTag?: boolean;\r\n css?: boolean | { [key: string]: boolean };\r\n onTag?: (tag: string, html: string, options: any) => string;\r\n onTagAttr?: (tag: string, name: string, value: string, isWhiteAttr: boolean) => string;\r\n onIgnoreTag?: (tag: string, html: string, options: any) => string;\r\n [key: string]: any;\r\n}\r\n\r\nexport class XSSAdapter {\r\n private globalOptions: XSSOptions;\r\n private defaultFilter: FilterXSS;\r\n\r\n constructor(options: XSSOptions = {}) {\r\n this.globalOptions = options;\r\n\r\n const defaultOptions: XSSOptions = {\r\n whiteList: getDefaultWhiteList(),\r\n stripIgnoreTag: true,\r\n stripIgnoreTagBody: [\"script\", \"style\", \"iframe\", \"object\", \"embed\"],\r\n allowCommentTag: false,\r\n css: false,\r\n onTag: (tag, html) => {\r\n if (tag === \"a\") {\r\n return html.replace(\r\n /<a /i,\r\n '<a target=\"_blank\" rel=\"noopener noreferrer\" '\r\n );\r\n }\r\n return html;\r\n }\r\n };\r\n\r\n const finalOptions = { ...defaultOptions, ...options };\r\n this.defaultFilter = new FilterXSS(finalOptions);\r\n }\r\n\r\n sanitize(input: string, dynamicOptions?: XSSOptions): string {\r\n try {\r\n if (typeof input !== \"string\") return input as any;\r\n\r\n if (!dynamicOptions || Object.keys(dynamicOptions).length === 0) {\r\n return this.defaultFilter.process(input);\r\n }\r\n\r\n const mergedOptions = { ...this.globalOptions, ...dynamicOptions };\r\n const customFilter = new FilterXSS(mergedOptions);\r\n\r\n return customFilter.process(input);\r\n\r\n } catch (err: any) {\r\n logger.error(\"XSS sanitization failed\", {\r\n adapter: \"xss\",\r\n operation: \"sanitize\",\r\n reason: err?.message\r\n });\r\n\r\n throw new AdapterError(\"XSS sanitizer failed.\");\r\n }\r\n }\r\n\r\n middleware(dynamicOptions?: XSSOptions) {\r\n return (req: any, _res: any, next: any) => {\r\n try {\r\n if (req.body && typeof req.body === \"object\") {\r\n const originalBody = req.body;\r\n const sanitizedBody: any = Array.isArray(originalBody) ? [] : {};\r\n\r\n for (const key of Object.keys(originalBody)) {\r\n const val = originalBody[key];\r\n\r\n if (typeof val === \"string\") {\r\n sanitizedBody[key] = this.sanitize(val, dynamicOptions);\r\n } else if (Array.isArray(val)) {\r\n sanitizedBody[key] = val.map(v =>\r\n typeof v === \"string\"\r\n ? this.sanitize(v, dynamicOptions)\r\n : v\r\n );\r\n } else if (val && typeof val === \"object\") {\r\n sanitizedBody[key] = this.deepSanitize(val, dynamicOptions);\r\n } else {\r\n sanitizedBody[key] = val;\r\n }\r\n }\r\n\r\n req.sanitizedBody = sanitizedBody;\r\n\r\n \r\n logger.info(\"XSS sanitization applied\", {\r\n adapter: \"xss\",\r\n operation: \"middleware\",\r\n keys: Object.keys(sanitizedBody)\r\n });\r\n }\r\n\r\n next();\r\n } catch (err: any) {\r\n logger.error(\"XSS middleware failed\", {\r\n adapter: \"xss\",\r\n operation: \"middleware\",\r\n reason: err?.message\r\n });\r\n next(err);\r\n }\r\n };\r\n }\r\n\r\n private deepSanitize(obj: any, options?: XSSOptions, visited = new WeakSet()): any {\r\n if (obj && typeof obj === \"object\") {\r\n if (visited.has(obj)) return obj;\r\n visited.add(obj);\r\n }\r\n\r\n if (typeof obj === \"string\") {\r\n return this.sanitize(obj, options);\r\n }\r\n\r\n if (Array.isArray(obj)) {\r\n return obj.map(item => this.deepSanitize(item, options, visited));\r\n }\r\n\r\n if (obj && typeof obj === \"object\") {\r\n const result: any = {};\r\n for (const key of Object.keys(obj)) {\r\n result[key] = this.deepSanitize(obj[key], options, visited);\r\n }\r\n return result;\r\n }\r\n\r\n return obj;\r\n }\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ZodAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/ZodAdapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ZodAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/ZodAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAY,MAAM,KAAK,CAAC;AAI1C,qBAAa,UAAU;IACnB,OAAO,CAAC,YAAY,CAAC,CAAY;gBAErB,YAAY,CAAC,EAAE,SAAS;IAIpC,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,IACtB,KAAK,GAAG,EAAE,MAAM,GAAG,EAAE,MAAM,GAAG;CA6B7C"}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// import { ZodSchema, ZodError } from "zod";
|
|
3
|
-
// import { ValidationError } from "../core/errors/ValidationError.js";
|
|
4
|
-
// import { logger } from "../logging/index.js";
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.ZodAdapter = void 0;
|
|
7
4
|
const ValidationError_1 = require("../core/errors/ValidationError");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ZodAdapter.js","sourceRoot":"","sources":["../../src/adapters/ZodAdapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ZodAdapter.js","sourceRoot":"","sources":["../../src/adapters/ZodAdapter.ts"],"names":[],"mappings":";;;AACA,oEAAiE;AACjE,wCAAoC;AAEpC,MAAa,UAAU;IAGnB,YAAY,YAAwB;QAChC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACrC,CAAC;IAED,QAAQ,CAAC,aAAyB;QAC9B,OAAO,CAAC,GAAQ,EAAE,IAAS,EAAE,IAAS,EAAE,EAAE;YACtC,MAAM,MAAM,GAAG,aAAa,IAAI,IAAI,CAAC,YAAY,CAAC;YAClD,IAAI,CAAC,MAAM;gBAAE,OAAO,IAAI,EAAE,CAAC;YAE3B,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,MAAM,CAAC,OAAO;gBAAE,OAAO,IAAI,EAAE,CAAC;YAElC,MAAM,MAAM,GAAa,MAAM,CAAC,KAAK,CAAC;YAEtC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBACvC,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;gBAC1B,IAAI,EAAE,KAAK,CAAC,IAAI;aACnB,CAAC,CAAC,CAAC;YAEJ,gBAAM,CAAC,IAAI,CAAC,uBAAuB,EAAE;gBACjC,OAAO,EAAE,KAAK;gBACd,SAAS,EAAE,UAAU;gBACrB,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,UAAU,EAAE,MAAM,CAAC,MAAM;gBACzB,MAAM;aACT,CAAC,CAAC;YAEH,OAAO,IAAI,CACP,IAAI,iCAAe,CAAC,oBAAoB,EAAE,MAAa,CAAC,CAC3D,CAAC;QACN,CAAC,CAAC;IACN,CAAC;CACJ;AArCD,gCAqCC","sourcesContent":["import { ZodSchema, ZodError } from \"zod\";\r\nimport { ValidationError } from \"../core/errors/ValidationError\";\r\nimport { logger } from \"../logging\";\r\n\r\nexport class ZodAdapter {\r\n private globalSchema?: ZodSchema;\r\n\r\n constructor(globalSchema?: ZodSchema) {\r\n this.globalSchema = globalSchema;\r\n }\r\n\r\n validate(dynamicSchema?: ZodSchema) {\r\n return (req: any, _res: any, next: any) => {\r\n const schema = dynamicSchema || this.globalSchema;\r\n if (!schema) return next();\r\n\r\n const result = schema.safeParse(req.body);\r\n if (result.success) return next();\r\n\r\n const zodErr: ZodError = result.error;\r\n\r\n const issues = zodErr.issues.map(issue => ({\r\n message: issue.message,\r\n path: issue.path.join(\".\"),\r\n code: issue.code\r\n }));\r\n\r\n logger.warn(\"Zod validation failed\", {\r\n adapter: \"zod\",\r\n operation: \"validate\",\r\n method: req.method,\r\n path: req.path,\r\n issueCount: issues.length,\r\n issues\r\n });\r\n\r\n return next(\r\n new ValidationError(\"Validation failed.\", issues as any)\r\n );\r\n };\r\n }\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HiSecure.d.ts","sourceRoot":"","sources":["../../src/core/HiSecure.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"HiSecure.d.ts","sourceRoot":"","sources":["../../src/core/HiSecure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAkB3D,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AASzD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE3E,qBAAa,QAAQ;IACjB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAyB;IAChD,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,WAAW,CAAS;IAGrB,WAAW,EAAG,WAAW,CAAC;IAC1B,gBAAgB,EAAG,gBAAgB,CAAC;IACpC,gBAAgB,EAAG,gBAAgB,CAAC;IACpC,gBAAgB,EAAG,gBAAgB,CAAC;IACpC,WAAW,EAAG,WAAW,CAAC;IAC1B,WAAW,EAAG,WAAW,CAAC;IAC1B,WAAW,CAAC,EAAE,WAAW,CAAC;IAGjC,OAAO,CAAC,cAAc,CAAM;IAC5B,OAAO,CAAC,eAAe,CAAM;IAC7B,OAAO,CAAC,kBAAkB,CAAM;IAChC,OAAO,CAAC,mBAAmB,CAAM;IACjC,OAAO,CAAC,gBAAgB,CAAM;IAC9B,OAAO,CAAC,iBAAiB,CAAM;IAE/B,OAAO;IAMP,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,QAAQ;IAW9D,MAAM,CAAC,aAAa,IAAI,IAAI;IAI5B,IAAI,IAAI,IAAI;IA6BZ,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE;IAQ9D,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,gBAAgB;IAIxC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,GAAG;IAI7B,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM;IAoB9D,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG;kBAlHK,CAAC;;;iBAID,CAAC;IAkH/B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG;WAUZ,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;WAMpC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlE,MAAM,CAAC,GAAG;wBACU,MAAM,YAAY,GAAG;wBAGrB,MAAM;;qCAIO,MAAM;;MAGrC;IAIF,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ;IAuBvE,OAAO,CAAC,aAAa;IA0CrB,OAAO,CAAC,aAAa;IA6BrB,OAAO,CAAC,oBAAoB;IAuB5B,OAAO,CAAC,qBAAqB;CAyBhC"}
|
package/dist/core/HiSecure.js
CHANGED
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// import { HiSecureConfig } from "./types/HiSecureConfig.js";
|
|
3
|
-
// import { defaultConfig } from "./config.js";
|
|
4
|
-
// import { LIB_NAME, LIB_VERSION } from "./constants.js";
|
|
5
|
-
// import { deepMerge } from "../utils/deepMerge.js";
|
|
6
|
-
// import { deepFreeze } from "../utils/deepFreeze.js";
|
|
7
|
-
// import { logger } from "../logging/index.js";
|
|
8
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
4
|
};
|
|
@@ -42,9 +36,7 @@ class HiSecure {
|
|
|
42
36
|
this.initialized = false;
|
|
43
37
|
this.config = (0, deepMerge_js_1.deepMerge)(config_js_1.defaultConfig, userConfig);
|
|
44
38
|
}
|
|
45
|
-
// =========================
|
|
46
39
|
// Singleton & Init
|
|
47
|
-
// =========================
|
|
48
40
|
static getInstance(config) {
|
|
49
41
|
if (!HiSecure.instance) {
|
|
50
42
|
logging_1.logger.info("Creating HiSecure singleton", {
|
|
@@ -79,9 +71,7 @@ class HiSecure {
|
|
|
79
71
|
layer: "hisecure-core"
|
|
80
72
|
});
|
|
81
73
|
}
|
|
82
|
-
// =========================
|
|
83
74
|
// Public Fluent APIs
|
|
84
|
-
// =========================
|
|
85
75
|
static auth(options) {
|
|
86
76
|
const instance = this.getInstance();
|
|
87
77
|
if (!instance.authManager) {
|
|
@@ -121,9 +111,7 @@ class HiSecure {
|
|
|
121
111
|
instance.jsonManager.urlencoded()
|
|
122
112
|
];
|
|
123
113
|
}
|
|
124
|
-
// =========================
|
|
125
114
|
// Utilities
|
|
126
|
-
// =========================
|
|
127
115
|
static async hash(value) {
|
|
128
116
|
const instance = this.getInstance();
|
|
129
117
|
const result = await instance.hashManager.hash(value, { allowFallback: true });
|
|
@@ -132,9 +120,7 @@ class HiSecure {
|
|
|
132
120
|
static async verify(value, hash) {
|
|
133
121
|
return this.getInstance().hashManager.verify(value, hash);
|
|
134
122
|
}
|
|
135
|
-
// =========================
|
|
136
123
|
// Global Middleware
|
|
137
|
-
// =========================
|
|
138
124
|
static middleware(options) {
|
|
139
125
|
const instance = this.getInstance();
|
|
140
126
|
if (typeof options === "string") {
|
|
@@ -151,9 +137,7 @@ class HiSecure {
|
|
|
151
137
|
}
|
|
152
138
|
return instance.createMiddlewareChain(options || {});
|
|
153
139
|
}
|
|
154
|
-
// =========================
|
|
155
140
|
// Internal Setup
|
|
156
|
-
// =========================
|
|
157
141
|
setupAdapters() {
|
|
158
142
|
logging_1.logger.info("Adapters setup started", {
|
|
159
143
|
layer: "hisecure-core"
|