@fortressjs/cli 0.1.3 → 0.1.4
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/ast-scanner.d.ts +5 -0
- package/dist/ast-scanner.js +58 -0
- package/dist/ast-scanner.test.d.ts +1 -0
- package/dist/ast-scanner.test.js +24 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +18 -7
- package/dist/report-generator.d.ts +8 -0
- package/dist/report-generator.js +32 -0
- package/package.json +48 -47
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ASTScanner = void 0;
|
|
7
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
8
|
+
class ASTScanner {
|
|
9
|
+
name = "ASTScanner";
|
|
10
|
+
scan(fileContent) {
|
|
11
|
+
const sourceFile = typescript_1.default.createSourceFile("temp.ts", fileContent, typescript_1.default.ScriptTarget.Latest, true);
|
|
12
|
+
const result = {
|
|
13
|
+
hasCSP: false,
|
|
14
|
+
hasRateLimiting: false,
|
|
15
|
+
hasRequestSizeLimiting: false,
|
|
16
|
+
hasLogger: false,
|
|
17
|
+
hasThreatDetection: false,
|
|
18
|
+
hasHTTPS: false
|
|
19
|
+
};
|
|
20
|
+
const visit = (node) => {
|
|
21
|
+
if (typescript_1.default.isImportDeclaration(node)) {
|
|
22
|
+
const moduleName = node.moduleSpecifier.getText(sourceFile);
|
|
23
|
+
if (moduleName.includes("@fortressjs/core")) {
|
|
24
|
+
result.hasCSP = true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (typescript_1.default.isCallExpression(node)) {
|
|
28
|
+
const expression = node.expression;
|
|
29
|
+
if (typescript_1.default.isPropertyAccessExpression(expression)) {
|
|
30
|
+
if (expression.expression.getText(sourceFile) ===
|
|
31
|
+
"fortress") {
|
|
32
|
+
switch (expression.name.getText(sourceFile)) {
|
|
33
|
+
case "headers":
|
|
34
|
+
result.hasCSP = true;
|
|
35
|
+
break;
|
|
36
|
+
case "rateLimit":
|
|
37
|
+
result.hasRateLimiting = true;
|
|
38
|
+
break;
|
|
39
|
+
case "requestLimit":
|
|
40
|
+
result.hasRequestSizeLimiting = true;
|
|
41
|
+
break;
|
|
42
|
+
case "logger":
|
|
43
|
+
result.hasLogger = true;
|
|
44
|
+
break;
|
|
45
|
+
case "threatDetector":
|
|
46
|
+
result.hasThreatDetection = true;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
typescript_1.default.forEachChild(node, visit);
|
|
53
|
+
};
|
|
54
|
+
visit(sourceFile);
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.ASTScanner = ASTScanner;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const ast_scanner_1 = require("./ast-scanner");
|
|
4
|
+
describe("ASTScanner", () => {
|
|
5
|
+
it("should parse valid code", () => {
|
|
6
|
+
const scanner = new ast_scanner_1.ASTScanner();
|
|
7
|
+
const result = scanner.scan(`
|
|
8
|
+
import express from "express";
|
|
9
|
+
|
|
10
|
+
const app = express();
|
|
11
|
+
|
|
12
|
+
app.get("/", () => {});
|
|
13
|
+
`);
|
|
14
|
+
expect(result).toBeDefined();
|
|
15
|
+
});
|
|
16
|
+
it("should detect fortress imports", () => {
|
|
17
|
+
const scanner = new ast_scanner_1.ASTScanner();
|
|
18
|
+
const result = scanner.scan(`
|
|
19
|
+
import fortress
|
|
20
|
+
from "@fortressjs/core";
|
|
21
|
+
`);
|
|
22
|
+
expect(result.hasCSP).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
});
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function runAudit(targetPath?: string, jsonOutput?: boolean): void;
|
|
1
|
+
export declare function runAudit(targetPath?: string, jsonOutput?: boolean, reportOutput?: boolean): void;
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.runAudit = runAudit;
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const
|
|
9
|
+
const report_generator_1 = require("./report-generator");
|
|
10
|
+
const ast_scanner_1 = require("./ast-scanner");
|
|
10
11
|
// ANSI Terminal Colors
|
|
11
12
|
const C = {
|
|
12
13
|
reset: "\x1b[0m",
|
|
@@ -58,7 +59,7 @@ function getFilesRecursively(dir, fileList = []) {
|
|
|
58
59
|
}
|
|
59
60
|
return fileList;
|
|
60
61
|
}
|
|
61
|
-
function runAudit(targetPath, jsonOutput = false) {
|
|
62
|
+
function runAudit(targetPath, jsonOutput = false, reportOutput = false) {
|
|
62
63
|
const target = path_1.default.resolve(targetPath || process.cwd());
|
|
63
64
|
let files;
|
|
64
65
|
try {
|
|
@@ -82,13 +83,13 @@ function runAudit(targetPath, jsonOutput = false) {
|
|
|
82
83
|
console.log(`${C.yellow}No JavaScript or TypeScript files found to scan in: ${target}${C.reset}`);
|
|
83
84
|
return;
|
|
84
85
|
}
|
|
85
|
-
if (!jsonOutput) {
|
|
86
|
+
if (!jsonOutput && !reportOutput) {
|
|
86
87
|
console.log(`\n${C.bold}${C.cyan}🛡️ FortressJS Security Audit CLI${C.reset}`);
|
|
87
88
|
console.log(`${C.dim}=========================================${C.reset}\n`);
|
|
88
89
|
console.log(`${C.dim}Target: ${target}${C.reset}`);
|
|
89
90
|
console.log(`${C.dim}Scanning ${files.length} file(s)...${C.reset}\n`);
|
|
90
91
|
}
|
|
91
|
-
const scanner = new
|
|
92
|
+
const scanner = new ast_scanner_1.ASTScanner();
|
|
92
93
|
// Aggregate results across all files in the project
|
|
93
94
|
const aggregated = {
|
|
94
95
|
hasCSP: false,
|
|
@@ -160,6 +161,12 @@ function runAudit(targetPath, jsonOutput = false) {
|
|
|
160
161
|
missing,
|
|
161
162
|
recommendations
|
|
162
163
|
};
|
|
164
|
+
if (reportOutput) {
|
|
165
|
+
const markdown = (0, report_generator_1.generateMarkdownReport)(auditResult);
|
|
166
|
+
fs_1.default.writeFileSync("fortress-report.md", markdown);
|
|
167
|
+
console.log("Report generated: fortress-report.md");
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
163
170
|
if (jsonOutput) {
|
|
164
171
|
console.log(JSON.stringify(auditResult, null, 2));
|
|
165
172
|
return;
|
|
@@ -189,9 +196,11 @@ function runAudit(targetPath, jsonOutput = false) {
|
|
|
189
196
|
const args = process.argv.slice(2);
|
|
190
197
|
if (args[0] === "audit") {
|
|
191
198
|
const jsonOutput = args.includes("--json");
|
|
199
|
+
const reportOutput = args.includes("--report");
|
|
192
200
|
const target = args.find((arg) => arg !== "audit" &&
|
|
193
|
-
arg !== "--json"
|
|
194
|
-
|
|
201
|
+
arg !== "--json" &&
|
|
202
|
+
arg !== "--report");
|
|
203
|
+
runAudit(target, jsonOutput, reportOutput);
|
|
195
204
|
}
|
|
196
205
|
else {
|
|
197
206
|
console.log(`\n${C.bold}FortressJS CLI${C.reset}`);
|
|
@@ -199,5 +208,7 @@ else {
|
|
|
199
208
|
console.log(` fortress audit`);
|
|
200
209
|
console.log(` fortress audit .`);
|
|
201
210
|
console.log(` fortress audit ./src`);
|
|
202
|
-
console.log(` fortress audit ./src/app.ts
|
|
211
|
+
console.log(` fortress audit ./src/app.ts`);
|
|
212
|
+
console.log(` fortress audit --json`);
|
|
213
|
+
console.log(` fortress audit --report\n`);
|
|
203
214
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateMarkdownReport = generateMarkdownReport;
|
|
4
|
+
function generateMarkdownReport(auditResult) {
|
|
5
|
+
const date = new Date()
|
|
6
|
+
.toISOString()
|
|
7
|
+
.split("T")[0];
|
|
8
|
+
return `# FortressJS Security Report
|
|
9
|
+
|
|
10
|
+
Generated: ${date}
|
|
11
|
+
|
|
12
|
+
## Target
|
|
13
|
+
|
|
14
|
+
${auditResult.target}
|
|
15
|
+
|
|
16
|
+
## Security Score
|
|
17
|
+
|
|
18
|
+
${auditResult.score}/100
|
|
19
|
+
|
|
20
|
+
## Missing Protections
|
|
21
|
+
|
|
22
|
+
${auditResult.missing
|
|
23
|
+
.map(item => `- ${item}`)
|
|
24
|
+
.join("\n")}
|
|
25
|
+
|
|
26
|
+
## Recommendations
|
|
27
|
+
|
|
28
|
+
${auditResult.recommendations
|
|
29
|
+
.map(item => `- ${item}`)
|
|
30
|
+
.join("\n")}
|
|
31
|
+
`;
|
|
32
|
+
}
|
package/package.json
CHANGED
|
@@ -1,47 +1,48 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@fortressjs/cli",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Security audit CLI for Express applications. Detect missing security headers, rate limits, request validation, and threat protection.",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"author": "Davanesh Saminathan",
|
|
7
|
-
"homepage": "https://github.com/davanesh/fortressjs",
|
|
8
|
-
"bugs": {
|
|
9
|
-
"url": "https://github.com/davanesh/fortressjs/issues"
|
|
10
|
-
},
|
|
11
|
-
"repository": {
|
|
12
|
-
"type": "git",
|
|
13
|
-
"url": "git+https://github.com/davanesh/fortressjs.git"
|
|
14
|
-
},
|
|
15
|
-
"keywords": [
|
|
16
|
-
"security",
|
|
17
|
-
"cli",
|
|
18
|
-
"audit",
|
|
19
|
-
"express",
|
|
20
|
-
"nodejs",
|
|
21
|
-
"middleware",
|
|
22
|
-
"api-security",
|
|
23
|
-
"fortressjs"
|
|
24
|
-
],
|
|
25
|
-
"engines": {
|
|
26
|
-
"node": ">=18"
|
|
27
|
-
},
|
|
28
|
-
"bin": {
|
|
29
|
-
"fortress": "bin/fortress.js"
|
|
30
|
-
},
|
|
31
|
-
"main": "dist/index.js",
|
|
32
|
-
"types": "dist/index.d.ts",
|
|
33
|
-
"files": [
|
|
34
|
-
"dist",
|
|
35
|
-
"bin",
|
|
36
|
-
"README.md"
|
|
37
|
-
],
|
|
38
|
-
"scripts": {
|
|
39
|
-
"build": "tsc"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@fortressjs/cli",
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "Security audit CLI for Express applications. Detect missing security headers, rate limits, request validation, and threat protection.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Davanesh Saminathan",
|
|
7
|
+
"homepage": "https://github.com/davanesh/fortressjs",
|
|
8
|
+
"bugs": {
|
|
9
|
+
"url": "https://github.com/davanesh/fortressjs/issues"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/davanesh/fortressjs.git"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"security",
|
|
17
|
+
"cli",
|
|
18
|
+
"audit",
|
|
19
|
+
"express",
|
|
20
|
+
"nodejs",
|
|
21
|
+
"middleware",
|
|
22
|
+
"api-security",
|
|
23
|
+
"fortressjs"
|
|
24
|
+
],
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=18"
|
|
27
|
+
},
|
|
28
|
+
"bin": {
|
|
29
|
+
"fortress": "bin/fortress.js"
|
|
30
|
+
},
|
|
31
|
+
"main": "dist/index.js",
|
|
32
|
+
"types": "dist/index.d.ts",
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"bin",
|
|
36
|
+
"README.md"
|
|
37
|
+
],
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsc",
|
|
40
|
+
"test": "jest"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@fortressjs/core": "^0.1.2"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"typescript": "^5.0.0"
|
|
47
|
+
}
|
|
48
|
+
}
|