@greenarmor/ges-audit-engine 0.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 (36) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.d.ts +7 -0
  3. package/dist/index.js +87 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/scanners/auth-scanner.d.ts +12 -0
  6. package/dist/scanners/auth-scanner.js +176 -0
  7. package/dist/scanners/auth-scanner.js.map +1 -0
  8. package/dist/scanners/code-security-scanner.d.ts +5 -0
  9. package/dist/scanners/code-security-scanner.js +91 -0
  10. package/dist/scanners/code-security-scanner.js.map +1 -0
  11. package/dist/scanners/config-scanner.d.ts +12 -0
  12. package/dist/scanners/config-scanner.js +210 -0
  13. package/dist/scanners/config-scanner.js.map +1 -0
  14. package/dist/scanners/crypto-scanner.d.ts +5 -0
  15. package/dist/scanners/crypto-scanner.js +92 -0
  16. package/dist/scanners/crypto-scanner.js.map +1 -0
  17. package/dist/scanners/database-scanner.d.ts +7 -0
  18. package/dist/scanners/database-scanner.js +82 -0
  19. package/dist/scanners/database-scanner.js.map +1 -0
  20. package/dist/scanners/secrets-scanner.d.ts +5 -0
  21. package/dist/scanners/secrets-scanner.js +69 -0
  22. package/dist/scanners/secrets-scanner.js.map +1 -0
  23. package/dist/scanners/types.d.ts +22 -0
  24. package/dist/scanners/types.js +2 -0
  25. package/dist/scanners/types.js.map +1 -0
  26. package/package.json +26 -0
  27. package/src/index.ts +97 -0
  28. package/src/scanners/auth-scanner.ts +198 -0
  29. package/src/scanners/code-security-scanner.ts +102 -0
  30. package/src/scanners/config-scanner.ts +224 -0
  31. package/src/scanners/crypto-scanner.ts +103 -0
  32. package/src/scanners/database-scanner.ts +92 -0
  33. package/src/scanners/secrets-scanner.ts +75 -0
  34. package/src/scanners/types.ts +24 -0
  35. package/tsconfig.json +6 -0
  36. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-scanner.js","sourceRoot":"","sources":["../../src/scanners/config-scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { Scanner, Finding, ScanContext } from "./types.js";
2
+ export declare class CryptoScanner implements Scanner {
3
+ name: string;
4
+ scan(ctx: ScanContext): Finding[];
5
+ }
@@ -0,0 +1,92 @@
1
+ const WEAK_HASH_PATTERNS = [
2
+ { pattern: /\bmd5\s*\(/gi, algo: "MD5" },
3
+ { pattern: /\bsha1\s*\(/gi, algo: "SHA1" },
4
+ { pattern: /\bcreateHash\s*\(\s*['"]md5['"]\s*\)/gi, algo: "MD5 (Node.js crypto)" },
5
+ { pattern: /\bcreateHash\s*\(\s*['"]sha1['"]\s*\)/gi, algo: "SHA1 (Node.js crypto)" },
6
+ { pattern: /\.digest\s*\(\s*['"]md5['"]\s*\)/gi, algo: "MD5 digest" },
7
+ { pattern: /hashlib\.md5\(/gi, algo: "MD5 (Python)" },
8
+ { pattern: /hashlib\.sha1\(/gi, algo: "SHA1 (Python)" },
9
+ ];
10
+ const WEAK_CRYPTO_PATTERNS = [
11
+ { pattern: /\bDES\b|\b3DES\b|\bBlowfish\b/g, algo: "Weak encryption algorithm" },
12
+ { pattern: /\bcreateCipheriv\s*\(\s*['"]aes-128/gi, algo: "AES-128 (use AES-256)" },
13
+ { pattern: /\bcreateCipher\b\s*\(/g, algo: "Deprecated createCipher (use createCipheriv)" },
14
+ { pattern: /\btc_aes_encrypt\b/gi, algo: "AES-128 (use AES-256)" },
15
+ { pattern: /\bAES.*ECB\b/gi, algo: "AES ECB mode (use GCM or CBC)" },
16
+ { pattern: /Cipher\s*\(\s*['"]des/gi, algo: "DES cipher (deprecated)" },
17
+ { pattern: /\btls\.connect\s*\([^)]*rejectUnauthorized\s*:\s*false/gi, algo: "TLS with certificate verification disabled" },
18
+ { pattern: /process\.env\.NODE_TLS_REJECT_UNAUTHORIZED\s*=\s*['"]0['"]/gi, algo: "TLS verification globally disabled" },
19
+ ];
20
+ const INSECURE_PASSWORD_PATTERNS = [
21
+ { pattern: /\.compare\s*\(.*,\s*.*\)|bcrypt\.compare|argon2\.verify/gi, check: false, desc: "Secure password comparison" },
22
+ { pattern: /password\s*===?\s*|password\s*!==?\s*|\.equals\s*\(\s*password/gi, check: true, desc: "Plaintext password comparison (use Argon2id/bcrypt)" },
23
+ ];
24
+ const SCAN_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".jsx", ".py", ".rb", ".go", ".java", ".php", ".cs"]);
25
+ export class CryptoScanner {
26
+ name = "crypto";
27
+ scan(ctx) {
28
+ const findings = [];
29
+ for (const [filePath, content] of ctx.fileContents) {
30
+ const ext = filePath.substring(filePath.lastIndexOf("."));
31
+ if (!SCAN_EXTENSIONS.has(ext))
32
+ continue;
33
+ const lines = content.split("\n");
34
+ for (let i = 0; i < lines.length; i++) {
35
+ const line = lines[i];
36
+ for (const { pattern, algo } of WEAK_HASH_PATTERNS) {
37
+ pattern.lastIndex = 0;
38
+ if (pattern.test(line)) {
39
+ findings.push({
40
+ ruleId: "CRYPTO-001",
41
+ severity: "critical",
42
+ category: "authentication",
43
+ title: `Weak hashing algorithm: ${algo}`,
44
+ description: `${algo} is cryptographically broken and must not be used for passwords or security-sensitive operations. Use Argon2id for passwords, SHA-256+ for general hashing.`,
45
+ file: filePath,
46
+ line: i + 1,
47
+ evidence: line.trim(),
48
+ controlIds: ["GDPR-ART32-004", "OWASP-ASVS-003"],
49
+ fix: `Replace ${algo} with Argon2id (passwords) or SHA-256+ (general hashing).`,
50
+ });
51
+ }
52
+ }
53
+ for (const { pattern, algo } of WEAK_CRYPTO_PATTERNS) {
54
+ pattern.lastIndex = 0;
55
+ if (pattern.test(line)) {
56
+ findings.push({
57
+ ruleId: "CRYPTO-002",
58
+ severity: "high",
59
+ category: "encryption",
60
+ title: `Insecure encryption: ${algo}`,
61
+ description: `${algo} is not approved for use. Use AES-256-GCM or ChaCha20-Poly1305.`,
62
+ file: filePath,
63
+ line: i + 1,
64
+ evidence: line.trim(),
65
+ controlIds: ["GDPR-ART32-002", "GDPR-ART32-003"],
66
+ fix: "Replace with AES-256-GCM or ChaCha20-Poly1305 for data at rest, TLS 1.3 for data in transit.",
67
+ });
68
+ }
69
+ }
70
+ for (const { pattern, check, desc } of INSECURE_PASSWORD_PATTERNS) {
71
+ pattern.lastIndex = 0;
72
+ if (check && pattern.test(line)) {
73
+ findings.push({
74
+ ruleId: "CRYPTO-003",
75
+ severity: "critical",
76
+ category: "authentication",
77
+ title: desc,
78
+ description: "Passwords must be hashed using Argon2id before comparison. Never compare plaintext passwords.",
79
+ file: filePath,
80
+ line: i + 1,
81
+ evidence: line.trim(),
82
+ controlIds: ["GDPR-ART32-004", "OWASP-ASVS-003"],
83
+ fix: "Use argon2.verify(hashedPassword, inputPassword) for password comparison.",
84
+ });
85
+ }
86
+ }
87
+ }
88
+ }
89
+ return findings;
90
+ }
91
+ }
92
+ //# sourceMappingURL=crypto-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto-scanner.js","sourceRoot":"","sources":["../../src/scanners/crypto-scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Scanner, Finding, ScanContext } from "./types.js";
2
+ export declare class DatabaseScanner implements Scanner {
3
+ name: string;
4
+ scan(ctx: ScanContext): Finding[];
5
+ private checkSchemaPatterns;
6
+ private checkORMConfig;
7
+ }
@@ -0,0 +1,82 @@
1
+ export class DatabaseScanner {
2
+ name = "database";
3
+ scan(ctx) {
4
+ const findings = [];
5
+ this.checkSchemaPatterns(ctx, findings);
6
+ this.checkORMConfig(ctx, findings);
7
+ return findings;
8
+ }
9
+ checkSchemaPatterns(ctx, findings) {
10
+ const requiredAuditColumns = ["created_at", "updated_at"];
11
+ const recommendedAuditColumns = ["deleted_at", "created_by", "updated_by"];
12
+ const codeExtensions = new Set([".ts", ".tsx", ".js", ".jsx", ".prisma", ".sql"]);
13
+ for (const [filePath, content] of ctx.fileContents) {
14
+ const ext = filePath.substring(filePath.lastIndexOf("."));
15
+ if (!codeExtensions.has(ext))
16
+ continue;
17
+ const hasTimestamps = /\b(?:timestamps|created_at|createdAt)\s*[:\(]/i.test(content);
18
+ const hasSoftDelete = /\b(?:deleted_at|deletedAt|softDelete|paranoid)\s*[:\(]/i.test(content);
19
+ const hasUserAudit = /\b(?:created_by|createdBy|updated_by|updatedBy)\s*[:\(]/i.test(content);
20
+ if (/\b(?:model|schema|entity|table)\b.*\{/i.test(content) || /\bCREATE\s+TABLE\b/i.test(content)) {
21
+ if (!hasTimestamps) {
22
+ findings.push({
23
+ ruleId: "DB-001",
24
+ severity: "high",
25
+ category: "database",
26
+ title: "Missing audit timestamps in schema",
27
+ description: "Database schema does not include created_at/updated_at timestamps. These are mandatory for audit trails.",
28
+ file: filePath,
29
+ evidence: "No created_at/updated_at columns detected",
30
+ controlIds: ["GDPR-ART32-006"],
31
+ fix: "Add created_at and updated_at columns to all tables. In Prisma: @@map, in Sequelize: timestamps: true.",
32
+ });
33
+ }
34
+ if (!hasSoftDelete) {
35
+ findings.push({
36
+ ruleId: "DB-002",
37
+ severity: "medium",
38
+ category: "database",
39
+ title: "Missing soft delete pattern",
40
+ description: "No deleted_at column or soft delete pattern found. Hard deletes prevent audit trail and data recovery.",
41
+ file: filePath,
42
+ evidence: "No deleted_at/softDelete pattern detected",
43
+ controlIds: ["GDPR-ART32-007"],
44
+ fix: "Add deleted_at column. In Prisma: add DeletedAt DateTime?, in Sequelize: paranoid: true.",
45
+ });
46
+ }
47
+ if (!hasUserAudit) {
48
+ findings.push({
49
+ ruleId: "DB-003",
50
+ severity: "medium",
51
+ category: "database",
52
+ title: "Missing user audit columns",
53
+ description: "No created_by/updated_by columns found. Track who makes changes for accountability.",
54
+ file: filePath,
55
+ evidence: "No created_by/updated_by columns detected",
56
+ controlIds: ["GDPR-ART32-006"],
57
+ fix: "Add created_by and updated_by columns to track which user made changes.",
58
+ });
59
+ }
60
+ }
61
+ }
62
+ }
63
+ checkORMConfig(ctx, findings) {
64
+ const prismaSchema = ctx.fileContents.get("prisma/schema.prisma");
65
+ if (prismaSchema) {
66
+ if (!/@@map/i.test(prismaSchema) && !/model\s+Audit/i.test(prismaSchema)) {
67
+ findings.push({
68
+ ruleId: "DB-004",
69
+ severity: "medium",
70
+ category: "database",
71
+ title: "No Audit model in Prisma schema",
72
+ description: "Consider adding an Audit model for immutable audit logging.",
73
+ file: "prisma/schema.prisma",
74
+ evidence: "No Audit model found",
75
+ controlIds: ["GDPR-ART32-006"],
76
+ fix: "Add model Audit { id Int @id @default(autoincrement()) userId String action String resource String timestamp DateTime @default(now()) ipAddress String }",
77
+ });
78
+ }
79
+ }
80
+ }
81
+ }
82
+ //# sourceMappingURL=database-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-scanner.js","sourceRoot":"","sources":["../../src/scanners/database-scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { Scanner, Finding, ScanContext } from "./types.js";
2
+ export declare class SecretsScanner implements Scanner {
3
+ name: string;
4
+ scan(ctx: ScanContext): Finding[];
5
+ }
@@ -0,0 +1,69 @@
1
+ const SECRET_PATTERNS = [
2
+ { pattern: /(?:password|passwd|pwd)\s*[:=]\s*['"][^'"]{4,}/gi, name: "Hardcoded password" },
3
+ { pattern: /(?:api[_-]?key|apikey)\s*[:=]\s*['"][^'"]{4,}/gi, name: "Hardcoded API key" },
4
+ { pattern: /(?:secret|token|auth)\s*[:=]\s*['"][^'"]{8,}/gi, name: "Hardcoded secret/token" },
5
+ { pattern: /(?:mongodb|postgres|mysql|redis):\/\/[^\s'"]{10,}/gi, name: "Database connection string with credentials" },
6
+ { pattern: /sk-[a-zA-Z0-9]{20,}/g, name: "OpenAI/API key pattern" },
7
+ { pattern: /AKIA[0-9A-Z]{16}/g, name: "AWS Access Key ID" },
8
+ { pattern: /-----BEGIN (?:RSA |EC )?PRIVATE KEY-----/g, name: "Private key in source" },
9
+ { pattern: /ghp_[a-zA-Z0-9]{36}/g, name: "GitHub personal access token" },
10
+ { pattern: /gho_[a-zA-Z0-9]{36}/g, name: "GitHub OAuth token" },
11
+ { pattern: /glpat-[a-zA-Z0-9\-]{20,}/g, name: "GitLab personal access token" },
12
+ { pattern: /xox[bpsa]-[a-zA-Z0-9\-]{10,}/g, name: "Slack token" },
13
+ { pattern: /eyJ[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}/g, name: "JWT token in source" },
14
+ { pattern: /(?:CONNECTION_STRING|DATABASE_URL|DB_PASSWORD|SECRET_KEY|PRIVATE_KEY)\s*[:=]\s*['"][^'"]{4,}/gi, name: "Sensitive environment variable with value" },
15
+ ];
16
+ const IGNORE_DIRS = new Set([
17
+ "node_modules", ".git", "dist", "build", ".next", ".nuxt", "coverage",
18
+ ".ges", "vendor", "__pycache__", ".venv", "venv",
19
+ ]);
20
+ const IGNORE_FILES = new Set([
21
+ ".gitignore", "package-lock.json", "pnpm-lock.yaml", "yarn.lock",
22
+ ]);
23
+ function shouldScanFile(filePath) {
24
+ const parts = filePath.split("/");
25
+ if (parts.some(p => IGNORE_DIRS.has(p)))
26
+ return false;
27
+ if (IGNORE_FILES.has(parts[parts.length - 1] || ""))
28
+ return false;
29
+ return true;
30
+ }
31
+ export class SecretsScanner {
32
+ name = "secrets";
33
+ scan(ctx) {
34
+ const findings = [];
35
+ for (const [filePath, content] of ctx.fileContents) {
36
+ if (!shouldScanFile(filePath))
37
+ continue;
38
+ const lines = content.split("\n");
39
+ for (let i = 0; i < lines.length; i++) {
40
+ const line = lines[i];
41
+ for (const { pattern, name } of SECRET_PATTERNS) {
42
+ pattern.lastIndex = 0;
43
+ const match = pattern.exec(line);
44
+ if (match) {
45
+ findings.push({
46
+ ruleId: "SECRETS-001",
47
+ severity: "critical",
48
+ category: "secrets",
49
+ title: name,
50
+ description: "A secret or credential was found in source code. Secrets must never be committed to repositories.",
51
+ file: filePath,
52
+ line: i + 1,
53
+ evidence: maskSecret(match[0]),
54
+ controlIds: ["OWASP-ASVS-005", "GDPR-ART32-002"],
55
+ fix: "Move this secret to a secure vault (Vault, AWS KMS, etc.) or environment variable. Never commit secrets to source control.",
56
+ });
57
+ }
58
+ }
59
+ }
60
+ }
61
+ return findings;
62
+ }
63
+ }
64
+ function maskSecret(secret) {
65
+ if (secret.length <= 8)
66
+ return "***";
67
+ return secret.slice(0, 4) + "***" + secret.slice(-4);
68
+ }
69
+ //# sourceMappingURL=secrets-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets-scanner.js","sourceRoot":"","sources":["../../src/scanners/secrets-scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export interface Finding {
2
+ ruleId: string;
3
+ severity: "critical" | "high" | "medium" | "low";
4
+ category: string;
5
+ title: string;
6
+ description: string;
7
+ file: string;
8
+ line?: number;
9
+ evidence: string;
10
+ controlIds: string[];
11
+ fix: string;
12
+ }
13
+ export interface ScanContext {
14
+ root: string;
15
+ files: string[];
16
+ fileContents: Map<string, string>;
17
+ config?: Record<string, unknown>;
18
+ }
19
+ export interface Scanner {
20
+ name: string;
21
+ scan(ctx: ScanContext): Finding[];
22
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/scanners/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@greenarmor/ges-audit-engine",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "GESF Audit Engine - Audit trails and compliance evaluation",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "dependencies": {
15
+ "@greenarmor/ges-core": "0.1.0"
16
+ },
17
+ "devDependencies": {
18
+ "typescript": "^6.0.0",
19
+ "@types/node": "^22.0.0"
20
+ },
21
+ "scripts": {
22
+ "build": "tsc",
23
+ "clean": "rm -rf dist tsconfig.tsbuildinfo",
24
+ "test": "echo \"no tests yet\""
25
+ }
26
+ }
package/src/index.ts ADDED
@@ -0,0 +1,97 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import type { Finding, ScanContext } from "./scanners/types.js";
4
+ import { SecretsScanner } from "./scanners/secrets-scanner.js";
5
+ import { CryptoScanner } from "./scanners/crypto-scanner.js";
6
+ import { CodeSecurityScanner } from "./scanners/code-security-scanner.js";
7
+ import { AuthScanner } from "./scanners/auth-scanner.js";
8
+ import { ConfigScanner } from "./scanners/config-scanner.js";
9
+ import { DatabaseScanner } from "./scanners/database-scanner.js";
10
+
11
+ export type { Finding } from "./scanners/types.js";
12
+
13
+ const IGNORE_DIRS = new Set([
14
+ "node_modules", ".git", "dist", "build", ".next", ".nuxt", "coverage",
15
+ ".ges", "vendor", "__pycache__", ".venv", "venv", ".turbo", ".cache",
16
+ "reports", "compliance", "security", "controls", "policies", "checklists", "docs",
17
+ ]);
18
+
19
+ const IGNORE_EXTENSIONS = new Set([
20
+ ".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg", ".ico", ".woff",
21
+ ".woff2", ".ttf", ".eot", ".mp4", ".mp3", ".zip", ".gz", ".tar",
22
+ ".lock", ".map", ".wasm",
23
+ ]);
24
+
25
+ function collectFiles(root: string): string[] {
26
+ const files: string[] = [];
27
+
28
+ function walk(dir: string) {
29
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
30
+ for (const entry of entries) {
31
+ if (IGNORE_DIRS.has(entry.name)) continue;
32
+ const fullPath = path.join(dir, entry.name);
33
+ if (entry.isDirectory()) {
34
+ walk(fullPath);
35
+ } else if (entry.isFile()) {
36
+ const ext = path.extname(entry.name);
37
+ if (!IGNORE_EXTENSIONS.has(ext)) {
38
+ files.push(path.relative(root, fullPath));
39
+ }
40
+ }
41
+ }
42
+ }
43
+
44
+ walk(root);
45
+ return files;
46
+ }
47
+
48
+ function readFiles(root: string, files: string[]): Map<string, string> {
49
+ const contents = new Map<string, string>();
50
+ const MAX_FILE_SIZE = 1024 * 1024;
51
+
52
+ for (const file of files) {
53
+ try {
54
+ const fullPath = path.join(root, file);
55
+ const stat = fs.statSync(fullPath);
56
+ if (stat.size > MAX_FILE_SIZE) continue;
57
+ const content = fs.readFileSync(fullPath, "utf-8");
58
+ contents.set(file, content);
59
+ } catch {
60
+ // skip unreadable files
61
+ }
62
+ }
63
+
64
+ return contents;
65
+ }
66
+
67
+ export function runAudit(root: string): { findings: Finding[]; scannedFiles: number } {
68
+ const files = collectFiles(root);
69
+ const fileContents = readFiles(root, files);
70
+ const ctx: ScanContext = { root, files, fileContents };
71
+
72
+ const scanners = [
73
+ new SecretsScanner(),
74
+ new CryptoScanner(),
75
+ new CodeSecurityScanner(),
76
+ new AuthScanner(),
77
+ new ConfigScanner(),
78
+ new DatabaseScanner(),
79
+ ];
80
+
81
+ const allFindings: Finding[] = [];
82
+ for (const scanner of scanners) {
83
+ allFindings.push(...scanner.scan(ctx));
84
+ }
85
+
86
+ return { findings: allFindings, scannedFiles: files.length };
87
+ }
88
+
89
+ export function deduplicateFindings(findings: Finding[]): Finding[] {
90
+ const seen = new Set<string>();
91
+ return findings.filter(f => {
92
+ const key = `${f.ruleId}:${f.file}:${f.line || ""}:${f.evidence}`;
93
+ if (seen.has(key)) return false;
94
+ seen.add(key);
95
+ return true;
96
+ });
97
+ }