@yognky/premium-security 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/LICENSE +21 -0
  3. package/README.md +8 -0
  4. package/dist/defenses/advanced.d.ts +2 -0
  5. package/dist/defenses/advanced.js +7 -0
  6. package/dist/defenses/advenced.d.ts +2 -0
  7. package/dist/defenses/advenced.js +48 -0
  8. package/dist/defenses/bruteforce.d.ts +2 -0
  9. package/dist/defenses/bruteforce.js +43 -0
  10. package/dist/defenses/curlBot.d.ts +2 -0
  11. package/dist/defenses/curlBot.js +31 -0
  12. package/dist/defenses/ddos.d.ts +2 -0
  13. package/dist/defenses/ddos.js +42 -0
  14. package/dist/defenses/headers.d.ts +2 -0
  15. package/dist/defenses/headers.js +25 -0
  16. package/dist/defenses/malware.d.ts +2 -0
  17. package/dist/defenses/malware.js +34 -0
  18. package/dist/defenses/rateLimit.d.ts +2 -0
  19. package/dist/defenses/rateLimit.js +31 -0
  20. package/dist/defenses/spoofing.d.ts +2 -0
  21. package/dist/defenses/spoofing.js +7 -0
  22. package/dist/defenses/sqlInjection.d.ts +2 -0
  23. package/dist/defenses/sqlInjection.js +40 -0
  24. package/dist/defenses/timingAttack.d.ts +2 -0
  25. package/dist/defenses/timingAttack.js +7 -0
  26. package/dist/defenses/whitelist.d.ts +2 -0
  27. package/dist/defenses/whitelist.js +22 -0
  28. package/dist/defenses/xss.d.ts +2 -0
  29. package/dist/defenses/xss.js +45 -0
  30. package/dist/index.d.ts +7 -0
  31. package/dist/index.js +98 -0
  32. package/dist/type/index.d.ts +41 -0
  33. package/dist/type/index.js +2 -0
  34. package/dist/types/index.d.ts +27 -0
  35. package/dist/types/index.js +2 -0
  36. package/dist/utils/banner.d.ts +3 -0
  37. package/dist/utils/banner.js +71 -0
  38. package/dist/utils/helpers.d.ts +11 -0
  39. package/dist/utils/helpers.js +74 -0
  40. package/dist/utils/index.d.ts +2 -0
  41. package/dist/utils/index.js +18 -0
  42. package/dist/utils/logger.d.ts +44 -0
  43. package/dist/utils/logger.js +148 -0
  44. package/docs/API.md +35 -0
  45. package/docs/EXAMPLE.md +45 -0
  46. package/docs/INSTALLATTION.md +6 -0
  47. package/examples/advenced-server.js +59 -0
  48. package/examples/basic-server.js +33 -0
  49. package/examples/simple-express.js +21 -0
  50. package/examples/with-express.ts +33 -0
  51. package/gitignore +48 -0
  52. package/nodemon.json +11 -0
  53. package/npmignore +36 -0
  54. package/package.json +27 -0
  55. package/src/defenses/advanced.ts +6 -0
  56. package/src/defenses/advenced.ts +54 -0
  57. package/src/defenses/bruteforce.ts +47 -0
  58. package/src/defenses/curlBot.ts +33 -0
  59. package/src/defenses/ddos.ts +46 -0
  60. package/src/defenses/headers.ts +27 -0
  61. package/src/defenses/malware.ts +35 -0
  62. package/src/defenses/rateLimit.ts +34 -0
  63. package/src/defenses/spoofing.ts +5 -0
  64. package/src/defenses/sqlInjection.ts +41 -0
  65. package/src/defenses/timingAttack.ts +5 -0
  66. package/src/defenses/whitelist.ts +23 -0
  67. package/src/defenses/xss.ts +46 -0
  68. package/src/index.ts +125 -0
  69. package/src/type/index.ts +48 -0
  70. package/src/types/index.ts +32 -0
  71. package/src/utils/banner.ts +73 -0
  72. package/src/utils/helpers +237 -0
  73. package/src/utils/helpers.ts +77 -0
  74. package/src/utils/index.ts +2 -0
  75. package/src/utils/logger.ts +174 -0
  76. package/test/bruteforce.test.ts +34 -0
  77. package/test/ddos.test.ts +30 -0
  78. package/test/integration.test.ts +44 -0
  79. package/test/sql.test.ts +39 -0
  80. package/test/xss.test.ts +39 -0
  81. package/test-module.js +23 -0
  82. package/tsconfig.build.json +17 -0
  83. package/tsconfig.json +26 -0
@@ -0,0 +1,33 @@
1
+ import express from 'express';
2
+ import ModulesEz from '../src/index';
3
+
4
+ const app = express();
5
+
6
+ // TypeScript version with full config
7
+ ModulesEz({
8
+ anti_ddos: { maxPerMinute: 60, blockDuration: 60 },
9
+ anti_sql: true,
10
+ anti_xss: true,
11
+ anti_curl: true,
12
+ anti_header: true,
13
+ anti_bruteforce: true,
14
+ anti_rateLimit: { windowMs: 60000, maxRequests: 100 },
15
+ anti_malware: true,
16
+ anti_pengunjung: "127.0.0.1"
17
+ })(app);
18
+
19
+ interface User {
20
+ id: number;
21
+ name: string;
22
+ }
23
+
24
+ app.get<{}, { message: string; user?: User }>('/api/user', (req, res) => {
25
+ res.json({
26
+ message: 'User data protected by YONGKY',
27
+ user: { id: 1, name: 'YONGKY' }
28
+ });
29
+ });
30
+
31
+ app.listen(3000, () => {
32
+ console.log('TypeScript server with YONGKY Security running! 🗿');
33
+ });
package/gitignore ADDED
@@ -0,0 +1,48 @@
1
+ # Dependencies
2
+ node_modules/
3
+ package-lock.json
4
+ yarn.lock
5
+
6
+ # Build output
7
+ dist/
8
+ build/
9
+ *.tsbuildinfo
10
+
11
+ # Logs
12
+ logs/
13
+ *.log
14
+ npm-debug.log*
15
+ yarn-debug.log*
16
+ yarn-error.log*
17
+
18
+ # Runtime data
19
+ pids
20
+ *.pid
21
+ *.seed
22
+ *.pid.lock
23
+
24
+ # Coverage
25
+ coverage/
26
+ .nyc_output/
27
+
28
+ # IDE
29
+ .vscode/
30
+ .idea/
31
+ *.swp
32
+ *.swo
33
+ *~
34
+ .DS_Store
35
+
36
+ # Environment
37
+ .env
38
+ .env.local
39
+ .env.*.local
40
+
41
+ # Testing
42
+ jest.config.js
43
+ test-report.xml
44
+
45
+ # Temporary files
46
+ tmp/
47
+ temp/
48
+ *.tmp
package/nodemon.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "watch": ["src"],
3
+ "ext": "ts,js,json",
4
+ "ignore": ["src/**/*.test.ts", "src/**/*.spec.ts"],
5
+ "exec": "ts-node ./src/index.ts",
6
+ "env": {
7
+ "NODE_ENV": "development"
8
+ },
9
+ "signal": "SIGTERM",
10
+ "delay": 500
11
+ }
package/npmignore ADDED
@@ -0,0 +1,36 @@
1
+
2
+ # Source files
3
+ src/
4
+ tests/
5
+ examples/
6
+ docs/
7
+
8
+ # Config files
9
+ tsconfig.json
10
+ tsconfig.build.json
11
+ .eslintrc
12
+ .prettierrc
13
+ .gitignore
14
+ .npmignore
15
+
16
+ # Development
17
+ node_modules/
18
+ coverage/
19
+ .nyc_output/
20
+
21
+ # Logs
22
+ *.log
23
+ yongky-security.log
24
+
25
+ # IDE
26
+ .vscode/
27
+ .idea/
28
+
29
+ # Test files
30
+ *.test.ts
31
+ *.spec.ts
32
+ jest.config.js
33
+
34
+ # Only keep dist and essential files
35
+ # dist/ will be included
36
+ # README.md, LICENSE, CHANGELOG.md will be included
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@yognky/premium-security",
3
+ "version": "1.0.0",
4
+ "description": "💎 PREMIUM SECURITY - Official Premium Package by YOGNKY",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc -p tsconfig.build.json",
9
+ "build:dev": "tsc",
10
+ "clean": "rm -rf dist",
11
+ "prepublishOnly": "npm run clean && npm run build"
12
+ },
13
+ "keywords": ["premium", "security", "yognky"],
14
+ "author": "YOGNKY",
15
+ "license": "UNLICENSED",
16
+ "dependencies": {
17
+ "express": "^4.18.2",
18
+ "chalk": "^4.1.2",
19
+ "figlet": "^1.6.0",
20
+ "gradient-string": "^2.0.0"
21
+ },
22
+ "devDependencies": {
23
+ "@types/express": "^4.17.21",
24
+ "@types/node": "^20.10.0",
25
+ "typescript": "^5.3.0"
26
+ }
27
+ }
@@ -0,0 +1,6 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+
3
+ export const advancedProtection = (req: Request, res: Response, next: NextFunction) => {
4
+ // Advanced fingerprinting protection
5
+ next();
6
+ };
@@ -0,0 +1,54 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ import crypto from 'crypto';
3
+
4
+ const fingerprintMap = new Map<string, number>();
5
+ const requestHistory = new Map<string, string[]>();
6
+
7
+ // Generate unique fingerprint
8
+ const generateFingerprint = (req: Request): string => {
9
+ const ip = req.ip || '';
10
+ const ua = req.get('user-agent') || '';
11
+ const acceptLang = req.get('accept-language') || '';
12
+ const acceptEncoding = req.get('accept-encoding') || '';
13
+
14
+ return crypto
15
+ .createHash('sha256')
16
+ .update(`${ip}|${ua}|${acceptLang}|${acceptEncoding}`)
17
+ .digest('hex');
18
+ };
19
+
20
+ export const advancedProtection = (req: Request, res: Response, next: NextFunction) => {
21
+ const fingerprint = generateFingerprint(req);
22
+ const requests = fingerprintMap.get(fingerprint) || 0;
23
+
24
+ // Deteksi fingerprint anomali
25
+ if (requests > 100) {
26
+ res.status(403).json({
27
+ error: '🔐 Advanced Detection!',
28
+ message: 'Fingerprint anomaly detected - YOGNKY KNOWS! 🗿',
29
+ by: 'YOGNKY ADVANCED SECURITY'
30
+ });
31
+ return;
32
+ }
33
+
34
+ // Deteksi request pattern mencurigakan
35
+ const urlHistory = requestHistory.get(fingerprint) || [];
36
+ const currentPath = req.path;
37
+
38
+ if (urlHistory.length > 10 && !urlHistory.includes(currentPath)) {
39
+ // Attacker scanning banyak endpoint
40
+ res.status(403).json({
41
+ error: '🔍 Scanning Detected!',
42
+ message: 'Lu lagi scanning ya? YOGNKY tau! 🗿',
43
+ by: 'YOGNKY SECURITY'
44
+ });
45
+ return;
46
+ }
47
+
48
+ urlHistory.push(currentPath);
49
+ if (urlHistory.length > 50) urlHistory.shift();
50
+ requestHistory.set(fingerprint, urlHistory);
51
+
52
+ fingerprintMap.set(fingerprint, requests + 1);
53
+ next();
54
+ };
@@ -0,0 +1,47 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+
3
+ const loginAttempts = new Map<string, { count: number; firstAttempt: number }>();
4
+ const blockedLogins = new Map<string, number>();
5
+
6
+ export const bruteforceProtection = (req: Request, res: Response, next: NextFunction) => {
7
+ if (req.method !== 'POST') return next();
8
+
9
+ const ip = req.ip || req.socket.remoteAddress || 'unknown';
10
+ const now = Date.now();
11
+
12
+ if (blockedLogins.has(ip)) {
13
+ const unblockTime = blockedLogins.get(ip)!;
14
+ if (now < unblockTime) {
15
+ res.status(429).json({
16
+ error: '🔒 Brute Force Protection!',
17
+ message: `Coba lagi ${Math.ceil((unblockTime - now) / 1000)} detik lagi`,
18
+ by: 'YOGNKY SECURITY'
19
+ });
20
+ return;
21
+ } else {
22
+ blockedLogins.delete(ip);
23
+ }
24
+ }
25
+
26
+ const attempts = loginAttempts.get(ip) || { count: 0, firstAttempt: now };
27
+
28
+ if (now - attempts.firstAttempt > 15 * 60 * 1000) {
29
+ attempts.count = 0;
30
+ attempts.firstAttempt = now;
31
+ }
32
+
33
+ attempts.count++;
34
+ loginAttempts.set(ip, attempts);
35
+
36
+ if (attempts.count >= 5) {
37
+ blockedLogins.set(ip, now + 30 * 60 * 1000);
38
+ res.status(429).json({
39
+ error: '⛔ Account Temporary Locked!',
40
+ message: 'Terlalu banyak percobaan login. Coba lagi 30 menit kemudian.',
41
+ by: 'YOGNKY SECURITY'
42
+ });
43
+ return;
44
+ }
45
+
46
+ next();
47
+ };
@@ -0,0 +1,33 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+
3
+ const botSignatures = [
4
+ /curl/i, /wget/i, /python/i, /perl/i, /ruby/i,
5
+ /java/i, /php/i, /libwww/i, /http client/i,
6
+ /scrapy/i, /spider/i, /crawler/i, /bot/i,
7
+ /scraper/i, /fetch/i, /headless/i, /puppeteer/i,
8
+ /selenium/i, /phantomjs/i, /axios/i, /requests/i,
9
+ /go-http-client/i, /okhttp/i, /python-requests/i,
10
+ /node-fetch/i, /got/i, /axios/i, /superagent/i
11
+ ];
12
+
13
+ const suspiciousHeaders = [
14
+ 'x-scrapy', 'x-requested-with', 'x-http-method-override',
15
+ 'x-crawler', 'x-bot', 'x-scraper'
16
+ ];
17
+
18
+ export const curlBotProtection = (req: Request, res: Response, next: NextFunction) => {
19
+ const ua = req.get('user-agent') || '';
20
+ const isBot = botSignatures.some(pattern => pattern.test(ua));
21
+ const hasSuspiciousHeader = suspiciousHeaders.some(header => req.headers[header]);
22
+
23
+ if (isBot || hasSuspiciousHeader) {
24
+ res.status(403).json({
25
+ error: '🤖 Bot Detected!',
26
+ message: 'BOT ga boleh lewat kata YOGNKY 🤣',
27
+ by: 'YOGNKY SECURITY'
28
+ });
29
+ return;
30
+ }
31
+
32
+ next();
33
+ };
@@ -0,0 +1,46 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+
3
+ const requestMap = new Map<string, number[]>();
4
+ const blockedIPs = new Map<string, number>();
5
+
6
+ export const ddosProtection = (config: any = {}) => {
7
+ const maxPerMinute = config.maxPerMinute || 10;
8
+ const blockDuration = (config.blockDuration || 60) * 1000;
9
+
10
+ return (req: Request, res: Response, next: NextFunction) => {
11
+ const ip = req.ip || req.socket.remoteAddress || 'unknown';
12
+ const now = Date.now();
13
+
14
+ // Cek apakah IP diblokir
15
+ if (blockedIPs.has(ip)) {
16
+ const unblockTime = blockedIPs.get(ip)!;
17
+ if (now < unblockTime) {
18
+ res.status(429).json({
19
+ error: '⛔ DDoS Protection',
20
+ message: `IP diblokir ${Math.ceil((unblockTime - now) / 1000)} detik lagi`,
21
+ by: 'YOGNKY SECURITY'
22
+ });
23
+ return;
24
+ } else {
25
+ blockedIPs.delete(ip);
26
+ }
27
+ }
28
+
29
+ const requests = requestMap.get(ip) || [];
30
+ const recent = requests.filter(time => time > now - 60000);
31
+
32
+ if (recent.length >= maxPerMinute) {
33
+ blockedIPs.set(ip, now + blockDuration);
34
+ res.status(429).json({
35
+ error: '🔥 DDoS Attack Detected!',
36
+ message: `IP ${ip} diblokir sementara`,
37
+ by: 'YOGNKY SECURITY'
38
+ });
39
+ return;
40
+ }
41
+
42
+ recent.push(now);
43
+ requestMap.set(ip, recent);
44
+ next();
45
+ };
46
+ };
@@ -0,0 +1,27 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+
3
+ const maliciousHeaders = [
4
+ 'x-forwarded-for', 'x-real-ip', 'x-original-url',
5
+ 'x-http-method-override', 'x-http-method',
6
+ 'x-method-override', 'x-rewrite-url'
7
+ ];
8
+
9
+ export const headerProtection = (req: Request, res: Response, next: NextFunction) => {
10
+ const hasMalicious = maliciousHeaders.some(header => req.headers[header] !== undefined);
11
+
12
+ if (hasMalicious) {
13
+ res.status(400).json({
14
+ error: '🎭 Malicious Headers Detected!',
15
+ message: 'Jangan nakal pake header aneh2 ya 🙏',
16
+ by: 'YOGNKY SECURITY'
17
+ });
18
+ return;
19
+ }
20
+
21
+ res.setHeader('X-Powered-By', 'YOGNKY SECURITY 🗿');
22
+ res.setHeader('X-Content-Type-Options', 'nosniff');
23
+ res.setHeader('X-Frame-Options', 'DENY');
24
+ res.setHeader('X-XSS-Protection', '1; mode=block');
25
+
26
+ next();
27
+ };
@@ -0,0 +1,35 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+
3
+ const malwarePatterns = [
4
+ /base64_decode/i, /eval\(/i, /system\(/i, /shell_exec/i,
5
+ /passthru/i, /proc_open/i, /popen/i, /curl_exec/i,
6
+ /file_get_contents/i, /fopen/i, /readfile/i,
7
+ /\.\.\/|\.\.\\/, /etc\/passwd/i, /wget\s+http/i,
8
+ /cmd\.exe/i, /powershell/i
9
+ ];
10
+
11
+ const checkMalware = (data: any): boolean => {
12
+ if (!data) return false;
13
+ if (typeof data === 'string') {
14
+ return malwarePatterns.some(pattern => pattern.test(data));
15
+ }
16
+ if (typeof data === 'object') {
17
+ return Object.values(data).some(val => checkMalware(val));
18
+ }
19
+ return false;
20
+ };
21
+
22
+ export const malwareProtection = (req: Request, res: Response, next: NextFunction) => {
23
+ const hasMalware = checkMalware(req.query) || checkMalware(req.body);
24
+
25
+ if (hasMalware) {
26
+ res.status(403).json({
27
+ error: '🦠 Malware Detected!',
28
+ message: 'Woi jangan coba2 pake malware 🗿',
29
+ by: 'YOGNKY SECURITY'
30
+ });
31
+ return;
32
+ }
33
+
34
+ next();
35
+ };
@@ -0,0 +1,34 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+
3
+ const rateMap = new Map<string, { count: number; resetTime: number }>();
4
+
5
+ export const rateLimitProtection = (config: any = {}) => {
6
+ const windowMs = config.windowMs || 60000;
7
+ const maxRequests = config.maxRequests || 10;
8
+
9
+ return (req: Request, res: Response, next: NextFunction) => {
10
+ const ip = req.ip || req.socket.remoteAddress || 'unknown';
11
+ const now = Date.now();
12
+ const rate = rateMap.get(ip);
13
+
14
+ if (!rate || now > rate.resetTime) {
15
+ rateMap.set(ip, { count: 1, resetTime: now + windowMs });
16
+ next();
17
+ return;
18
+ }
19
+
20
+ if (rate.count >= maxRequests) {
21
+ res.status(429).json({
22
+ error: '🐌 Rate Limit Exceeded!',
23
+ message: `Maksimal ${maxRequests} request per ${windowMs / 1000} detik`,
24
+ retryAfter: Math.ceil((rate.resetTime - now) / 1000),
25
+ by: 'YOGNKY SECURITY'
26
+ });
27
+ return;
28
+ }
29
+
30
+ rate.count++;
31
+ rateMap.set(ip, rate);
32
+ next();
33
+ };
34
+ };
@@ -0,0 +1,5 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+
3
+ export const antiSpoofing = (req: Request, res: Response, next: NextFunction) => {
4
+ next();
5
+ };
@@ -0,0 +1,41 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+
3
+ const sqlPatterns = [
4
+ /(\%27)|(\')|(\-\-)|(\%23)|(#)/i,
5
+ /select.+from/i,
6
+ /insert.+into/i,
7
+ /delete.+from/i,
8
+ /update.+set/i,
9
+ /drop.+table/i,
10
+ /union.+select/i,
11
+ /exec(\s|\+)+(s|x)p\w+/i,
12
+ /sleep\(/i,
13
+ /benchmark\(/i,
14
+ /information_schema/i
15
+ ];
16
+
17
+ const checkNested = (obj: any): boolean => {
18
+ if (!obj) return false;
19
+ if (typeof obj === 'string') {
20
+ return sqlPatterns.some(pattern => pattern.test(obj));
21
+ }
22
+ if (typeof obj === 'object') {
23
+ return Object.values(obj).some(val => checkNested(val));
24
+ }
25
+ return false;
26
+ };
27
+
28
+ export const sqlInjectionProtection = (req: Request, res: Response, next: NextFunction) => {
29
+ const isInjected = checkNested(req.query) || checkNested(req.body) || checkNested(req.params);
30
+
31
+ if (isInjected) {
32
+ res.status(403).json({
33
+ error: '💉 SQL Injection Detected!',
34
+ message: 'Nice try, tapi YOGNKY gaakan kena 😎',
35
+ by: 'YOGNKY SECURITY'
36
+ });
37
+ return;
38
+ }
39
+
40
+ next();
41
+ };
@@ -0,0 +1,5 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+
3
+ export const antiTimingAttack = (req: Request, res: Response, next: NextFunction) => {
4
+ next();
5
+ };
@@ -0,0 +1,23 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+
3
+ export const whitelistProtection = (allowedIPsStr: string | false) => {
4
+ if (!allowedIPsStr) return (_req: Request, _res: Response, next: NextFunction) => next();
5
+
6
+ const allowedIPs = allowedIPsStr.split(',').map(ip => ip.trim());
7
+
8
+ return (req: Request, res: Response, next: NextFunction) => {
9
+ const clientIP = req.ip || req.socket.remoteAddress || 'unknown';
10
+ const cleanIP = clientIP.replace('::ffff:', '');
11
+
12
+ if (!allowedIPs.includes(cleanIP) && !allowedIPs.includes(clientIP)) {
13
+ res.status(403).json({
14
+ error: '🚫 Access Denied!',
15
+ message: `IP ${clientIP} tidak ada di whitelist`,
16
+ by: 'YOGNKY SECURITY'
17
+ });
18
+ return;
19
+ }
20
+
21
+ next();
22
+ };
23
+ };
@@ -0,0 +1,46 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+
3
+ const xssPatterns = [
4
+ /<script.*?>.*?<\/script>/i,
5
+ /javascript:/i,
6
+ /onerror=/i,
7
+ /onload=/i,
8
+ /onclick=/i,
9
+ /onmouseover=/i,
10
+ /eval\(/i,
11
+ /alert\(/i,
12
+ /prompt\(/i,
13
+ /confirm\(/i,
14
+ /document\./i,
15
+ /window\./i,
16
+ /location\./i,
17
+ /<iframe/i,
18
+ /<object/i,
19
+ /<embed/i
20
+ ];
21
+
22
+ const checkXSS = (data: any): boolean => {
23
+ if (!data) return false;
24
+ if (typeof data === 'string') {
25
+ return xssPatterns.some(pattern => pattern.test(data));
26
+ }
27
+ if (typeof data === 'object') {
28
+ return Object.values(data).some(val => checkXSS(val));
29
+ }
30
+ return false;
31
+ };
32
+
33
+ export const xssProtection = (req: Request, res: Response, next: NextFunction) => {
34
+ const hasXSS = checkXSS(req.query) || checkXSS(req.body) || checkXSS(req.params);
35
+
36
+ if (hasXSS) {
37
+ res.status(403).json({
38
+ error: '⚠️ XSS Attack Detected!',
39
+ message: 'Ga bisa XSS disini, YOGNKY pinter 😤',
40
+ by: 'YOGNKY SECURITY'
41
+ });
42
+ return;
43
+ }
44
+
45
+ next();
46
+ };