@chiranthmoger/fortifyjs 1.1.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 (50) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +186 -0
  3. package/bin/fortifyjs.js +135 -0
  4. package/examples/fastify.js +18 -0
  5. package/examples/hono.js +13 -0
  6. package/examples/kitchen-sink.js +50 -0
  7. package/examples/koa.js +14 -0
  8. package/examples/minimal-express.js +13 -0
  9. package/examples/production-express.js +20 -0
  10. package/index.d.ts +101 -0
  11. package/package.json +70 -0
  12. package/src/adapters/express.js +1027 -0
  13. package/src/adapters/fastify.js +56 -0
  14. package/src/adapters/generic.js +15 -0
  15. package/src/adapters/hono.js +77 -0
  16. package/src/adapters/koa.js +58 -0
  17. package/src/adapters/nestjs.js +15 -0
  18. package/src/adapters/nextjs.js +84 -0
  19. package/src/analyzers/adaptive.js +92 -0
  20. package/src/analyzers/behavioral.js +264 -0
  21. package/src/core/confidence.js +23 -0
  22. package/src/core/engine.js +162 -0
  23. package/src/core/normalizer.js +149 -0
  24. package/src/core/whitelist.js +40 -0
  25. package/src/dashboard/handler.js +307 -0
  26. package/src/detectors/cmdi.js +82 -0
  27. package/src/detectors/crlf.js +33 -0
  28. package/src/detectors/graphql.js +56 -0
  29. package/src/detectors/hpp.js +38 -0
  30. package/src/detectors/ldap.js +50 -0
  31. package/src/detectors/nosqli.js +134 -0
  32. package/src/detectors/open-redirect.js +42 -0
  33. package/src/detectors/path-traversal.js +55 -0
  34. package/src/detectors/prototype-pollution.js +65 -0
  35. package/src/detectors/sqli.js +447 -0
  36. package/src/detectors/sqli.js.bak +446 -0
  37. package/src/detectors/ssrf.js +64 -0
  38. package/src/detectors/template-injection.js +34 -0
  39. package/src/detectors/xss.js +191 -0
  40. package/src/detectors/xxe.js +45 -0
  41. package/src/forensics/reporter.js +74 -0
  42. package/src/index.js +132 -0
  43. package/src/logger.js +110 -0
  44. package/src/presets.js +183 -0
  45. package/src/shields/bot-detector.js +88 -0
  46. package/src/shields/cors.js +95 -0
  47. package/src/shields/csrf.js +120 -0
  48. package/src/shields/file-upload.js +160 -0
  49. package/src/shields/headers.js +99 -0
  50. package/src/shields/rate-limiter.js +70 -0
package/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Chiranth Janardhan Moger
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,186 @@
1
+ <div align="center">
2
+
3
+ # 🛡️ FortifyJS
4
+
5
+ **The Zero-Dependency Web Application Firewall for Node.js**
6
+
7
+ [![npm version](https://img.shields.io/npm/v/fortifyjs?color=blue&style=for-the-badge)](https://www.npmjs.com/package/fortifyjs)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg?style=for-the-badge)](https://opensource.org/licenses/MIT)
9
+ [![TypeScript Ready](https://img.shields.io/badge/TypeScript-Ready-blue.svg?style=for-the-badge&logo=typescript)](https://www.typescriptlang.org/)
10
+ [![Zero Dependencies](https://img.shields.io/badge/Dependencies-0-success.svg?style=for-the-badge)](https://www.npmjs.com/package/fortifyjs)
11
+
12
+ *One-line protection against injection, XSS, CSRF, SSRF, and 10+ attack classes.*<br>
13
+ *Replaces `helmet`, `cors`, `csurf`, and `express-rate-limit`.*
14
+
15
+ </div>
16
+
17
+ <hr>
18
+
19
+ ## 🚀 Why FortifyJS?
20
+
21
+ Building secure Node.js applications used to mean juggling half a dozen middlewares, configuring complex rulesets, and hoping you didn't miss a critical vulnerability vector.
22
+
23
+ **Not anymore.** FortifyJS consolidates everything into a single, highly-optimized, zero-dependency engine.
24
+
25
+ ### 📉 What It Replaces
26
+
27
+ | Legacy Package | FortifyJS Feature |
28
+ | :--- | :--- |
29
+ | 🐢 `helmet` | 🛡️ Security Headers Shield |
30
+ | 🐢 `cors` | 🛡️ CORS Shield |
31
+ | 🐢 `csurf` | 🛡️ CSRF Shield |
32
+ | 🐢 `express-rate-limit` | 🛡️ Rate Limiting Shield |
33
+ | 🐢 `express-mongo-sanitize` | 🛡️ NoSQLi Detector |
34
+ | 🐢 `xss-clean` | 🛡️ XSS Detector |
35
+
36
+ ---
37
+
38
+ ## 📦 Quick Start
39
+
40
+ ```bash
41
+ npm install fortifyjs
42
+ ```
43
+
44
+ ### ⚡ Express
45
+ ```javascript
46
+ const express = require('express');
47
+ const { shield } = require('fortifyjs');
48
+
49
+ const app = express();
50
+ app.use(shield('medium')); // That's it. You're protected.
51
+
52
+ app.listen(3000, () => console.log('Server protected by FortifyJS 🛡️'));
53
+ ```
54
+
55
+ ### ⚡ Fastify
56
+ ```javascript
57
+ const fastify = require('fastify')();
58
+ const { fastifyPlugin } = require('fortifyjs/adapters/fastify');
59
+
60
+ fastify.register(fastifyPlugin, { tier: 'medium' });
61
+ fastify.listen({ port: 3000 });
62
+ ```
63
+
64
+ ---
65
+
66
+ ## 🛡️ The 4 Tiers of Protection
67
+
68
+ FortifyJS provides predefined security profiles to match your application's risk profile. No complex configuration needed.
69
+
70
+ | Tier | Detection Level | Headers | Rate Limit | CORS | CSRF | Bot Detection | Behavioral | File Upload | Dashboard |
71
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
72
+ | **🟢 basic** | Balanced | ✅ | 100/15m | Same-origin | ❌ | Flag | Entropy | ❌ | ❌ |
73
+ | **🟡 medium** | Balanced | ✅ | 200/15m | Same-origin | ❌ | Block | ✅ | ✅ | ❌ |
74
+ | **🟠 hard** | Strict | ✅ | 100/15m | Same-origin | ✅ | Block | 5k reqs | ✅ | ❌ |
75
+ | **🔴 advanced**| Strict | ✅ | 100/15m | Same-origin | ✅ | Block | 5k reqs | Scan | ✅ |
76
+
77
+ ---
78
+
79
+ ## 🔍 14 Advanced Detection Engines
80
+
81
+ Under the hood, FortifyJS acts as a complete Web Application Firewall, actively analyzing payloads against 14 distinct attack vectors:
82
+
83
+ 1. 💉 **SQLi**: Identifies SQL injection attempts across popular SQL dialects.
84
+ 2. 🎭 **XSS**: Blocks cross-site scripting attacks including mutations and DOM-based vectors.
85
+ 3. 🍃 **NoSQLi**: Detects query operator injections tailored for MongoDB, CouchDB, and Elasticsearch.
86
+ 4. 💻 **CmdI**: Prevents operating system command injection across Unix and Windows platforms.
87
+ 5. 📂 **Path Traversal**: Stops directory traversal attempts aiming to read arbitrary files.
88
+ 6. 🌐 **SSRF**: Intercepts Server-Side Request Forgery attempts against internal infrastructure.
89
+ 7. 📄 **XXE**: Prevents XML External Entity processing attacks.
90
+ 8. 🧬 **Prototype Pollution**: Detects and stops JavaScript object prototype manipulation.
91
+ 9. 🔀 **HPP**: Mitigates HTTP Parameter Pollution vulnerabilities.
92
+ 10. ↪️ **Open Redirect**: Validates destination paths to prevent malicious redirection.
93
+ 11. ✂️ **CRLF**: Stops HTTP response splitting via carriage return and line feed characters.
94
+ 12. 🧩 **Template Injection**: Blocks server-side template injection (e.g., Jinja2, Twig, EJS).
95
+ 13. 📇 **LDAP Injection**: Identifies unauthorized LDAP query manipulation.
96
+ 14. 🕸️ **GraphQL Abuse**: Limits introspection, deep nesting, and alias batching.
97
+
98
+ ---
99
+
100
+ ## 🔌 Framework Support
101
+
102
+ FortifyJS is framework-agnostic. We provide out-of-the-box adapters for the most popular Node.js web frameworks:
103
+
104
+ <details>
105
+ <summary><b>Koa</b></summary>
106
+
107
+ ```javascript
108
+ const { koaMiddleware } = require('fortifyjs/adapters/koa');
109
+ app.use(koaMiddleware({ tier: 'hard' }));
110
+ ```
111
+ </details>
112
+
113
+ <details>
114
+ <summary><b>Hono</b></summary>
115
+
116
+ ```javascript
117
+ import { honoMiddleware } from 'fortifyjs/adapters/hono';
118
+ app.use('*', honoMiddleware({ tier: 'hard' }));
119
+ ```
120
+ </details>
121
+
122
+ <details>
123
+ <summary><b>NestJS</b></summary>
124
+
125
+ ```typescript
126
+ import { FortifyGuard } from 'fortifyjs/adapters/nestjs';
127
+ @UseGuards(new FortifyGuard('hard'))
128
+ export class AppController {}
129
+ ```
130
+ </details>
131
+
132
+ ---
133
+
134
+ ## ⚙️ Advanced Configuration
135
+
136
+ Need more control? You can easily override tier defaults by passing a configuration object.
137
+
138
+ ```javascript
139
+ const { shield } = require('fortifyjs');
140
+
141
+ app.use(shield('medium', {
142
+ cors: {
143
+ origin: ['https://myapp.com', 'https://admin.myapp.com']
144
+ },
145
+ rateLimit: {
146
+ max: 300,
147
+ windowMs: 10 * 60 * 1000
148
+ }
149
+ }));
150
+ ```
151
+
152
+ ---
153
+
154
+ ## 🛠️ Offline CLI Testing
155
+
156
+ FortifyJS includes a powerful command-line interface for testing payloads and scanning inputs offline in your CI/CD pipelines.
157
+
158
+ Scan a specific string for malicious signatures:
159
+ ```bash
160
+ fortifyjs scan "<test-input>"
161
+ ```
162
+
163
+ Scan a file containing payloads and output results in CSV format:
164
+ ```bash
165
+ fortifyjs scan-file payloads.txt --format csv
166
+ ```
167
+
168
+ ---
169
+
170
+ ## 📊 Security Dashboard
171
+
172
+ The **Advanced tier** includes an interactive, built-in security dashboard for real-time monitoring of blocked requests, rate limits, and behavioral anomalies.
173
+
174
+ Served securely at `/admin/security` when enabled.
175
+
176
+ ---
177
+
178
+ ## 🤝 Contributing & License
179
+
180
+ - 📖 Refer to [CONTRIBUTING.md](CONTRIBUTING.md) for development guidelines.
181
+ - 🔒 Refer to [SECURITY.md](SECURITY.md) for reporting vulnerabilities.
182
+ - 📜 FortifyJS is open-source software licensed under the [MIT License](LICENSE).
183
+
184
+ <div align="center">
185
+ <i>Built with absolute security and zero bloat in mind.</i>
186
+ </div>
@@ -0,0 +1,135 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const readline = require('readline');
6
+ const util = require('util');
7
+ const { DetectionEngine } = require('../src/index');
8
+
9
+ const MAX_CLI_PAYLOAD_LENGTH = 50000;
10
+
11
+ function printHelp() {
12
+ console.log(`
13
+ fortifyjs (Heuristic Scanner)
14
+
15
+ Usage:
16
+ fortifyjs scan <payload> - Scan a single payload
17
+ fortifyjs scan-file <filepath> - Scan a file with one payload per line
18
+
19
+ Options:
20
+ --format <json|csv> - Output format (default: json)
21
+ `);
22
+ }
23
+
24
+ function csvCell(value) {
25
+ const text = String(value)
26
+ .replace(/\r/g, '\\r')
27
+ .replace(/\n/g, '\\n');
28
+ const formulaSafeText = /^[\t ]*[=+\-@]/.test(text) ? `'${text}` : text;
29
+ return `"${formulaSafeText.replace(/"/g, '""')}"`;
30
+ }
31
+
32
+ function payloadForOutput(payload) {
33
+ const text = String(payload);
34
+ if (text.length <= MAX_CLI_PAYLOAD_LENGTH) return text;
35
+ return `${text.slice(0, MAX_CLI_PAYLOAD_LENGTH)}...[truncated ${text.length - MAX_CLI_PAYLOAD_LENGTH} chars]`;
36
+ }
37
+
38
+ async function scanFile(filepath, format, detector) {
39
+ try {
40
+ await fs.promises.access(filepath, fs.constants.R_OK);
41
+ } catch (err) {
42
+ console.error(`Error: Failed to read file at ${filepath} (${err.message})`);
43
+ process.exit(1);
44
+ }
45
+
46
+ const stream = fs.createReadStream(filepath, { encoding: 'utf8' });
47
+ const lines = readline.createInterface({ input: stream, crlfDelay: Infinity });
48
+
49
+ if (format === 'csv') {
50
+ console.log('payload,label,confidence');
51
+ } else {
52
+ process.stdout.write('[\n');
53
+ }
54
+
55
+ let isFirstJsonRow = true;
56
+ try {
57
+ for await (const line of lines) {
58
+ if (line.trim().length === 0) continue;
59
+ const result = detector.detect(line);
60
+ const row = { payload: payloadForOutput(line), result };
61
+ if (format === 'csv') {
62
+ console.log(`${csvCell(row.payload)},${csvCell(result.label)},${result.confidence}`);
63
+ } else {
64
+ process.stdout.write(`${isFirstJsonRow ? '' : ',\n'}${JSON.stringify(row, null, 2)}`);
65
+ isFirstJsonRow = false;
66
+ }
67
+ }
68
+ } catch (err) {
69
+ console.error(`Error: Failed to read file at ${filepath} (${err.message})`);
70
+ process.exit(1);
71
+ }
72
+
73
+ if (format !== 'csv') {
74
+ process.stdout.write(isFirstJsonRow ? ']\n' : '\n]\n');
75
+ }
76
+ }
77
+
78
+ async function main() {
79
+ const { values, positionals } = util.parseArgs({
80
+ args: process.argv.slice(2),
81
+ options: {
82
+ format: { type: 'string', default: 'json' },
83
+ help: { type: 'boolean', short: 'h', default: false }
84
+ },
85
+ allowPositionals: true
86
+ });
87
+
88
+ if (values.help || positionals.length === 0) {
89
+ printHelp();
90
+ process.exit(0);
91
+ }
92
+
93
+ const command = positionals[0];
94
+ const format = values.format;
95
+ const args = positionals; // For compatibility with rest of the code
96
+
97
+ const detector = new DetectionEngine();
98
+
99
+ if (command === 'scan') {
100
+ if (args.length < 2) {
101
+ console.error('Error: Missing payload string');
102
+ process.exit(1);
103
+ }
104
+ const payload = args.slice(1).join(' ');
105
+ const result = detector.detect(payload);
106
+
107
+ if (format === 'csv') {
108
+ console.log('payload,label,confidence');
109
+ console.log(`${csvCell(payloadForOutput(payload))},${csvCell(result.label)},${result.confidence}`);
110
+ } else {
111
+ console.log(JSON.stringify({ payload: payloadForOutput(payload), result }, null, 2));
112
+ }
113
+
114
+ } else if (command === 'scan-file') {
115
+ if (args.length < 2) {
116
+ console.error('Error: Missing filepath');
117
+ process.exit(1);
118
+ }
119
+ const filepath = path.resolve(args[1]);
120
+
121
+ await scanFile(filepath, format, detector);
122
+
123
+ } else {
124
+ console.error(`Unknown command: ${command}`);
125
+ printHelp();
126
+ process.exit(1);
127
+ }
128
+ }
129
+
130
+ main().catch(err => {
131
+ console.error(`Error: ${err.message}`);
132
+ process.exit(1);
133
+ });
134
+
135
+
@@ -0,0 +1,18 @@
1
+ const fastify = require('fastify')({ logger: true });
2
+ const { fastifyPlugin } = require('../src/index.js');
3
+
4
+ fastify.register(fastifyPlugin, { tier: 'medium' });
5
+
6
+ fastify.get('/', async (request, reply) => {
7
+ return { hello: 'world' };
8
+ });
9
+
10
+ const start = async () => {
11
+ try {
12
+ await fastify.listen({ port: 3000 });
13
+ } catch (err) {
14
+ fastify.log.error(err);
15
+ process.exit(1);
16
+ }
17
+ };
18
+ start();
@@ -0,0 +1,13 @@
1
+ const { Hono } = require('hono');
2
+ const { serve } = require('@hono/node-server');
3
+ const { honoMiddleware } = require('../src/index.js');
4
+
5
+ const app = new Hono();
6
+
7
+ app.use('*', honoMiddleware({ tier: 'advanced' }));
8
+
9
+ app.get('/', (c) => c.text('Hello Hono!'));
10
+
11
+ serve({ fetch: app.fetch, port: 3000 }, (info) => {
12
+ console.log(`Listening on http://localhost:${info.port}`);
13
+ });
@@ -0,0 +1,50 @@
1
+ const express = require('express');
2
+ const { shield } = require('../src');
3
+
4
+ const app = express();
5
+
6
+ app.use(express.json());
7
+ app.use(express.urlencoded({ extended: true }));
8
+
9
+ // Enable all shields explicitly with hard preset options
10
+ app.use(shield({
11
+ preset: 'hard',
12
+ shields: {
13
+ headers: true,
14
+ csrf: { cookieName: '_fortify_csrf_kitchen_sink', secret: 'supersecret_kitchen_sink' },
15
+ cors: { origin: 'http://localhost:3000' },
16
+ rateLimiter: { maxRequests: 50, windowMs: 60000 },
17
+ botDetector: { allowHeadless: false }
18
+ },
19
+ detectors: {
20
+ sqli: true,
21
+ xss: true,
22
+ nosqli: true,
23
+ cmdi: true,
24
+ pathTraversal: true,
25
+ ssrf: true,
26
+ xxe: true,
27
+ prototypePollution: true,
28
+ hpp: true,
29
+ openRedirect: true
30
+ },
31
+ behavioral: {
32
+ entropyThreshold: 4.0,
33
+ maxEncodingDepth: 2,
34
+ specialCharRatio: 0.5
35
+ },
36
+ action: 'block'
37
+ }));
38
+
39
+ app.post('/api/data', (req, res) => {
40
+ res.json({ message: 'Data received securely!' });
41
+ });
42
+
43
+ app.get('/', (req, res) => {
44
+ res.send('Kitchen Sink example running.');
45
+ });
46
+
47
+ const PORT = 3000;
48
+ app.listen(PORT, () => {
49
+ console.log(`Kitchen sink server listening on port ${PORT}`);
50
+ });
@@ -0,0 +1,14 @@
1
+ const Koa = require('koa');
2
+ const { koaMiddleware } = require('../src/index.js');
3
+
4
+ const app = new Koa();
5
+
6
+ app.use(koaMiddleware({ tier: 'basic' }));
7
+
8
+ app.use(async ctx => {
9
+ ctx.body = 'Hello World';
10
+ });
11
+
12
+ app.listen(3000, () => {
13
+ console.log('Koa server listening on port 3000');
14
+ });
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+ const express = require('express');
3
+ const { shield } = require('../src/index');
4
+
5
+ const app = express();
6
+
7
+ app.use(shield('basic'));
8
+
9
+ app.get('/', (req, res) => res.send('FortifyJS Protected'));
10
+
11
+ if (require.main === module) {
12
+ app.listen(3000, () => console.log('Listening on port 3000'));
13
+ }
@@ -0,0 +1,20 @@
1
+ 'use strict';
2
+ const express = require('express');
3
+ const { shield } = require('../src/index');
4
+
5
+ const app = express();
6
+
7
+ app.use(express.json());
8
+ app.use(express.urlencoded({ extended: true }));
9
+
10
+ app.use(shield('hard', {
11
+ logRequests: true,
12
+ exposeLogs: true,
13
+ maxSuspiciousRequests: 2
14
+ }));
15
+
16
+ app.post('/api/data', (req, res) => res.json({ status: 'ok', received: req.body }));
17
+
18
+ if (require.main === module) {
19
+ app.listen(3000, () => console.log('Listening on port 3000'));
20
+ }
package/index.d.ts ADDED
@@ -0,0 +1,101 @@
1
+ /// <reference types="node" />
2
+
3
+ declare module 'fortifyjs' {
4
+ export type Tier = 'basic' | 'medium' | 'hard' | 'advanced';
5
+
6
+ export type DetectionLabel = 'sqli' | 'xss' | 'nosqli' | 'cmdi' | 'path-traversal' | 'ssrf' | 'xxe' | 'prototype-pollution' | 'hpp' | 'open-redirect' | 'crlf' | 'templateInjection' | 'ldap' | 'graphql' | 'benign' | 'anomaly' | string;
7
+ export type DetectorType = 'sqli' | 'xss' | 'nosqli' | 'cmdi' | 'path-traversal' | 'ssrf' | 'xxe' | 'prototype-pollution' | 'hpp' | 'open-redirect' | 'crlf' | 'templateInjection' | 'ldap' | 'graphql' | string;
8
+
9
+ export interface RateLimitOptions {
10
+ max?: number;
11
+ windowMs?: number;
12
+ }
13
+
14
+ export interface CorsOptions {
15
+ origin?: string | string[] | RegExp | ((origin: string, cb: (err: Error | null, allow?: boolean) => void) => void);
16
+ methods?: string | string[];
17
+ allowedHeaders?: string | string[];
18
+ exposedHeaders?: string | string[];
19
+ credentials?: boolean;
20
+ maxAge?: number;
21
+ optionsSuccessStatus?: number;
22
+ }
23
+
24
+ export interface CsrfOptions {
25
+ cookieName?: string;
26
+ cookieOptions?: {
27
+ httpOnly?: boolean;
28
+ secure?: boolean;
29
+ sameSite?: boolean | 'lax' | 'strict' | 'none';
30
+ path?: string;
31
+ };
32
+ ignoreMethods?: string[];
33
+ }
34
+
35
+ export interface BotDetectionOptions {
36
+ enabled?: boolean;
37
+ action?: 'flag' | 'block';
38
+ blockList?: string[];
39
+ }
40
+
41
+ export interface BehavioralOptions {
42
+ enabled?: boolean;
43
+ entropyOnly?: boolean;
44
+ learningRequests?: number;
45
+ }
46
+
47
+ export interface FileUploadOptions {
48
+ enabled?: boolean;
49
+ allowedExtensions?: string[];
50
+ blockedExtensions?: string[];
51
+ maxFilenameLength?: number;
52
+ blockDoubleExtensions?: boolean;
53
+ blockNullBytes?: boolean;
54
+ blockPathTraversal?: boolean;
55
+ blockDotFiles?: boolean;
56
+ validateMimeType?: boolean;
57
+ scanFilenameForInjection?: boolean;
58
+ }
59
+
60
+ export interface WhitelistOptions {
61
+ exact?: string[];
62
+ prefix?: string[];
63
+ pattern?: RegExp[];
64
+ }
65
+
66
+ export interface FortifyOptions {
67
+ tier?: Tier;
68
+ level?: 'strict' | 'balanced' | 'permissive';
69
+ headers?: boolean | Record<string, boolean | string>;
70
+ rateLimit?: boolean | RateLimitOptions;
71
+ cors?: boolean | CorsOptions;
72
+ csrf?: boolean | CsrfOptions;
73
+ botDetection?: boolean | BotDetectionOptions;
74
+ behavioral?: boolean | BehavioralOptions;
75
+ fileUpload?: boolean | FileUploadOptions;
76
+ dashboard?: boolean | { enabled?: boolean; path?: string };
77
+ whitelist?: WhitelistOptions;
78
+ mode?: 'input' | 'query';
79
+ logging?: { level?: 'silent' | 'error' | 'warn' | 'info' | 'debug'; format?: 'json' | 'text' };
80
+ }
81
+
82
+ export type ShieldOptions = FortifyOptions;
83
+
84
+ export function shield(tier?: Tier, overrides?: FortifyOptions): (req: any, res: any, next: any) => void;
85
+ export function shield(overrides?: FortifyOptions): (req: any, res: any, next: any) => void;
86
+
87
+ export function fastifyPlugin(fastify: any, options: FortifyOptions, done: () => void): void;
88
+ export function koaMiddleware(options?: FortifyOptions): (ctx: any, next: () => Promise<any>) => Promise<void>;
89
+ export function honoMiddleware(options?: FortifyOptions): (c: any, next: () => Promise<any>) => Promise<void>;
90
+ export function genericAdapter(options?: FortifyOptions): (req: any, res: any, next: any) => void;
91
+
92
+ export class DetectionEngine {
93
+ constructor(options?: any);
94
+ detect(payload: string, context?: { source?: 'query' | 'body' | 'header' | 'cookie' | 'path' | 'filename' | string; route?: string; [key: string]: any }): any;
95
+ }
96
+
97
+ export class Normalizer {
98
+ constructor(options?: any);
99
+ normalizePayload(payload: string | Buffer, options?: any): string;
100
+ }
101
+ }
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@chiranthmoger/fortifyjs",
3
+ "version": "1.1.0",
4
+ "description": "Complete web application firewall for Node.js. One-line protection against injection, XSS, CSRF, SSRF, and 10+ attack classes. Replaces helmet, cors, csurf, and express-rate-limit.",
5
+ "main": "src/index.js",
6
+ "types": "index.d.ts",
7
+ "bin": {
8
+ "fortifyjs": "bin/fortifyjs.js"
9
+ },
10
+ "keywords": [
11
+ "waf",
12
+ "firewall",
13
+ "security",
14
+ "middleware",
15
+ "sql-injection",
16
+ "xss",
17
+ "csrf",
18
+ "cors",
19
+ "ssrf",
20
+ "nosql-injection",
21
+ "command-injection",
22
+ "xxe",
23
+ "helmet",
24
+ "rate-limit",
25
+ "bot-detection",
26
+ "path-traversal",
27
+ "prototype-pollution",
28
+ "express",
29
+ "fastify",
30
+ "koa",
31
+ "hono",
32
+ "nestjs"
33
+ ],
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/Chiranth-Janardhan-moger/fortifyjs.git"
37
+ },
38
+ "license": "MIT",
39
+ "files": [
40
+ "bin",
41
+ "src",
42
+ "examples",
43
+ "index.d.ts"
44
+ ],
45
+ "scripts": {
46
+ "test": "jest",
47
+ "benchmark": "node benchmarks/detection-speed.js && node benchmarks/throughput.js"
48
+ },
49
+ "devDependencies": {
50
+ "express": "^5.2.1",
51
+ "jest": "^30.4.2",
52
+ "supertest": "^7.2.2",
53
+ "typescript": "^7.0.2"
54
+ },
55
+ "peerDependencies": {
56
+ "express": ">=4.18.0 || >=5.0.0"
57
+ },
58
+ "peerDependenciesMeta": {
59
+ "express": {
60
+ "optional": true
61
+ }
62
+ },
63
+ "engines": {
64
+ "node": ">=18.0.0"
65
+ },
66
+ "bugs": {
67
+ "url": "https://github.com/Chiranth-Janardhan-moger/fortifyjs/issues"
68
+ },
69
+ "homepage": "https://github.com/Chiranth-Janardhan-moger/fortifyjs#readme"
70
+ }