pqaudit 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 (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +180 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +69 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/index.d.ts +7 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +6 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/reporter/cbom.d.ts +8 -0
  12. package/dist/reporter/cbom.d.ts.map +1 -0
  13. package/dist/reporter/cbom.js +153 -0
  14. package/dist/reporter/cbom.js.map +1 -0
  15. package/dist/reporter/json.d.ts +3 -0
  16. package/dist/reporter/json.d.ts.map +1 -0
  17. package/dist/reporter/json.js +4 -0
  18. package/dist/reporter/json.js.map +1 -0
  19. package/dist/reporter/sarif.d.ts +7 -0
  20. package/dist/reporter/sarif.d.ts.map +1 -0
  21. package/dist/reporter/sarif.js +91 -0
  22. package/dist/reporter/sarif.js.map +1 -0
  23. package/dist/reporter/text.d.ts +3 -0
  24. package/dist/reporter/text.d.ts.map +1 -0
  25. package/dist/reporter/text.js +84 -0
  26. package/dist/reporter/text.js.map +1 -0
  27. package/dist/scanner/dependency-scanner.d.ts +3 -0
  28. package/dist/scanner/dependency-scanner.d.ts.map +1 -0
  29. package/dist/scanner/dependency-scanner.js +133 -0
  30. package/dist/scanner/dependency-scanner.js.map +1 -0
  31. package/dist/scanner/engine.d.ts +3 -0
  32. package/dist/scanner/engine.d.ts.map +1 -0
  33. package/dist/scanner/engine.js +109 -0
  34. package/dist/scanner/engine.js.map +1 -0
  35. package/dist/scanner/file-scanner.d.ts +5 -0
  36. package/dist/scanner/file-scanner.d.ts.map +1 -0
  37. package/dist/scanner/file-scanner.js +163 -0
  38. package/dist/scanner/file-scanner.js.map +1 -0
  39. package/dist/scanner/rules.d.ts +4 -0
  40. package/dist/scanner/rules.d.ts.map +1 -0
  41. package/dist/scanner/rules.js +25 -0
  42. package/dist/scanner/rules.js.map +1 -0
  43. package/dist/types.d.ts +102 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +9 -0
  46. package/dist/types.js.map +1 -0
  47. package/package.json +62 -0
  48. package/rules/crypto-patterns.yaml +350 -0
@@ -0,0 +1,84 @@
1
+ import chalk from "chalk";
2
+ const SEVERITY_COLORS = {
3
+ critical: chalk.red.bold,
4
+ high: chalk.yellow.bold,
5
+ medium: chalk.yellow,
6
+ low: chalk.blue,
7
+ safe: chalk.green,
8
+ };
9
+ const SEVERITY_ICONS = {
10
+ critical: "!!",
11
+ high: "!",
12
+ medium: "~",
13
+ low: "-",
14
+ safe: "ok",
15
+ };
16
+ export function formatText(result) {
17
+ const lines = [];
18
+ lines.push("");
19
+ lines.push(chalk.bold(" pqaudit — Post-Quantum Cryptography Readiness Scanner"));
20
+ lines.push(chalk.dim(` Scanned: ${result.target}`));
21
+ lines.push(chalk.dim(` Date: ${result.timestamp}`));
22
+ lines.push("");
23
+ // Summary bar
24
+ const s = result.summary;
25
+ if (s.pqcReady) {
26
+ lines.push(chalk.green.bold(" PQC READY — No critical or high-severity findings"));
27
+ }
28
+ else {
29
+ lines.push(chalk.red.bold(" NOT PQC READY — Quantum-vulnerable cryptography detected"));
30
+ }
31
+ lines.push("");
32
+ // Stats
33
+ lines.push(` Files scanned: ${s.filesScanned} | Findings: ${s.findingsTotal}`);
34
+ lines.push(` ${chalk.red(`Critical: ${s.bySeverity.critical}`)} ` +
35
+ `${chalk.yellow(`High: ${s.bySeverity.high}`)} ` +
36
+ `${chalk.yellow(`Medium: ${s.bySeverity.medium}`)} ` +
37
+ `${chalk.blue(`Low: ${s.bySeverity.low}`)} ` +
38
+ `${chalk.green(`Safe: ${s.bySeverity.safe}`)}`);
39
+ lines.push("");
40
+ if (result.findings.length === 0) {
41
+ lines.push(" No findings.");
42
+ return lines.join("\n");
43
+ }
44
+ // Group by severity
45
+ const grouped = groupBySeverity(result.findings);
46
+ for (const [severity, findings] of grouped) {
47
+ if (findings.length === 0)
48
+ continue;
49
+ const color = SEVERITY_COLORS[severity];
50
+ lines.push(color(` --- ${severity.toUpperCase()} (${findings.length}) ---`));
51
+ lines.push("");
52
+ for (const f of findings) {
53
+ const icon = SEVERITY_ICONS[f.severity];
54
+ const loc = f.location.line
55
+ ? `${f.location.file}:${f.location.line}`
56
+ : f.location.file;
57
+ lines.push(color(` [${icon}] ${f.algorithm} — ${f.description}`));
58
+ lines.push(chalk.dim(` ${loc}`));
59
+ if (f.location.snippet) {
60
+ lines.push(chalk.dim(` > ${f.location.snippet}`));
61
+ }
62
+ if (f.replacement) {
63
+ lines.push(chalk.cyan(` Fix: ${f.replacement}`));
64
+ }
65
+ lines.push(chalk.dim(` Confidence: ${Math.round(f.confidence * 100)}% | Effort: ${f.effort} | Via: ${f.detectionMethod}`));
66
+ lines.push("");
67
+ }
68
+ }
69
+ return lines.join("\n");
70
+ }
71
+ function groupBySeverity(findings) {
72
+ const groups = {
73
+ critical: [],
74
+ high: [],
75
+ medium: [],
76
+ low: [],
77
+ safe: [],
78
+ };
79
+ for (const f of findings) {
80
+ groups[f.severity].push(f);
81
+ }
82
+ return Object.entries(groups);
83
+ }
84
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/reporter/text.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Finding } from "../types.js";
2
+ export declare function scanNpmDependencies(targetDir: string): Finding[];
3
+ //# sourceMappingURL=dependency-scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-scanner.d.ts","sourceRoot":"","sources":["../../src/scanner/dependency-scanner.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAoG3C,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,EAAE,CAuChE"}
@@ -0,0 +1,133 @@
1
+ import { readFileSync, existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ /** Known npm packages and their cryptographic implications */
4
+ const KNOWN_CRYPTO_PACKAGES = {
5
+ // PQC-safe libraries
6
+ "@noble/post-quantum": {
7
+ algorithm: "ML-KEM / ML-DSA",
8
+ severity: "safe",
9
+ category: "kem",
10
+ description: "Post-quantum cryptography library (ML-KEM, ML-DSA, SLH-DSA)",
11
+ replacement: null,
12
+ },
13
+ // Quantum-vulnerable signature libraries
14
+ "@noble/ed25519": {
15
+ algorithm: "Ed25519",
16
+ severity: "critical",
17
+ category: "signature",
18
+ description: "Ed25519 signatures — vulnerable to Shor's algorithm",
19
+ replacement: "ML-DSA-65 via @noble/post-quantum",
20
+ },
21
+ "@noble/secp256k1": {
22
+ algorithm: "secp256k1 (ECDSA)",
23
+ severity: "critical",
24
+ category: "signature",
25
+ description: "secp256k1 ECDSA — vulnerable to Shor's algorithm",
26
+ replacement: "ML-DSA-65 via @noble/post-quantum",
27
+ },
28
+ "tweetnacl": {
29
+ algorithm: "Ed25519 / X25519",
30
+ severity: "critical",
31
+ category: "signature",
32
+ description: "NaCl crypto (Ed25519 signatures, X25519 key exchange) — both quantum-vulnerable",
33
+ replacement: "ML-DSA-65 + ML-KEM-768 via @noble/post-quantum",
34
+ },
35
+ "elliptic": {
36
+ algorithm: "ECDSA / ECDH",
37
+ severity: "critical",
38
+ category: "signature",
39
+ description: "Elliptic curve library — all ECC is quantum-vulnerable",
40
+ replacement: "ML-DSA-65 + ML-KEM-768",
41
+ },
42
+ "node-rsa": {
43
+ algorithm: "RSA",
44
+ severity: "critical",
45
+ category: "kem",
46
+ description: "RSA encryption/signatures — vulnerable to Shor's algorithm",
47
+ replacement: "ML-KEM-768 + ML-DSA-65",
48
+ },
49
+ "jsonwebtoken": {
50
+ algorithm: "RS256/ES256 (likely)",
51
+ severity: "critical",
52
+ category: "signature",
53
+ description: "JWT library — likely uses RSA or ECDSA for signing",
54
+ replacement: "Consider ML-DSA-based JWT signing when IETF PQC JWT standards emerge",
55
+ },
56
+ "jose": {
57
+ algorithm: "RS256/ES256 (configurable)",
58
+ severity: "critical",
59
+ category: "signature",
60
+ description: "JOSE/JWT library — supports RSA and ECDSA signing",
61
+ replacement: "Monitor IETF PQC JWT standards progress",
62
+ },
63
+ // Solana/blockchain (quantum-vulnerable by design)
64
+ "@solana/web3.js": {
65
+ algorithm: "Ed25519 (Solana)",
66
+ severity: "critical",
67
+ category: "signature",
68
+ description: "Solana Web3 — all Solana keys are Ed25519, quantum-vulnerable",
69
+ replacement: "Blocked by Solana ecosystem PQC migration. Monitor Solana PQC proposals.",
70
+ },
71
+ "ethers": {
72
+ algorithm: "secp256k1 (Ethereum)",
73
+ severity: "critical",
74
+ category: "signature",
75
+ description: "Ethers.js — Ethereum uses secp256k1 ECDSA, quantum-vulnerable",
76
+ replacement: "Blocked by Ethereum PQC migration. Monitor EIP proposals.",
77
+ },
78
+ "web3": {
79
+ algorithm: "secp256k1 (Ethereum)",
80
+ severity: "critical",
81
+ category: "signature",
82
+ description: "Web3.js — Ethereum uses secp256k1 ECDSA, quantum-vulnerable",
83
+ replacement: "Blocked by Ethereum PQC migration. Monitor EIP proposals.",
84
+ },
85
+ // Symmetric / safe
86
+ "libsodium-wrappers": {
87
+ algorithm: "XChaCha20-Poly1305 / Ed25519",
88
+ severity: "critical",
89
+ category: "signature",
90
+ description: "libsodium — symmetric crypto is safe but Ed25519/X25519 are quantum-vulnerable",
91
+ replacement: "Audit usage: keep symmetric ops, migrate asymmetric to PQC",
92
+ },
93
+ };
94
+ export function scanNpmDependencies(targetDir) {
95
+ const packageJsonPath = join(targetDir, "package.json");
96
+ if (!existsSync(packageJsonPath))
97
+ return [];
98
+ let pkg;
99
+ try {
100
+ pkg = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
101
+ }
102
+ catch {
103
+ return [];
104
+ }
105
+ const findings = [];
106
+ const allDeps = {
107
+ ...pkg.dependencies,
108
+ ...pkg.devDependencies,
109
+ };
110
+ for (const [name, version] of Object.entries(allDeps)) {
111
+ const known = KNOWN_CRYPTO_PACKAGES[name];
112
+ if (!known)
113
+ continue;
114
+ findings.push({
115
+ ruleId: `DEP_${name.replace(/[^a-zA-Z0-9]/g, "_").toUpperCase()}`,
116
+ description: known.description,
117
+ severity: known.severity,
118
+ category: known.category,
119
+ algorithm: known.algorithm,
120
+ replacement: known.replacement,
121
+ effort: "complex",
122
+ location: {
123
+ file: "package.json",
124
+ snippet: `"${name}": "${version}"`,
125
+ },
126
+ detectionMethod: "dependency",
127
+ confidence: 0.95,
128
+ });
129
+ }
130
+ return findings;
131
+ }
132
+ // TODO: Add scanCargoDependencies, scanGradleDependencies, scanPipDependencies
133
+ //# sourceMappingURL=dependency-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-scanner.js","sourceRoot":"","sources":["../../src/scanner/dependency-scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ScanConfig, ScanResult } from "../types.js";
2
+ export declare function scan(config: ScanConfig): Promise<ScanResult>;
3
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/scanner/engine.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAGV,UAAU,EACV,UAAU,EAIX,MAAM,aAAa,CAAC;AA0BrB,wBAAsB,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAmElE"}
@@ -0,0 +1,109 @@
1
+ import { resolve, relative } from "node:path";
2
+ import { glob } from "glob";
3
+ import { loadRules } from "./rules.js";
4
+ import { scanFile } from "./file-scanner.js";
5
+ import { scanNpmDependencies } from "./dependency-scanner.js";
6
+ const DEFAULT_EXCLUDE = [
7
+ "**/node_modules/**",
8
+ "**/dist/**",
9
+ "**/build/**",
10
+ "**/.git/**",
11
+ "**/vendor/**",
12
+ "**/target/**",
13
+ "**/__pycache__/**",
14
+ "**/.venv/**",
15
+ "**/coverage/**",
16
+ "**/*.min.js",
17
+ "**/*.map",
18
+ "**/package-lock.json",
19
+ "**/yarn.lock",
20
+ "**/pnpm-lock.yaml",
21
+ "**/Cargo.lock",
22
+ ];
23
+ const SOURCE_EXTENSIONS = "**/*.{js,mjs,cjs,jsx,ts,tsx,mts,cts,py,go,rs,java,kt,kts,cs,c,h,cpp,cc,hpp,swift,rb,php,toml,yaml,yml,json,xml,conf,cfg,ini,env,pem,crt,cer}";
24
+ export async function scan(config) {
25
+ const target = resolve(config.target);
26
+ const rules = loadRules(config.rulesDir);
27
+ // Discover files
28
+ const excludePatterns = [...DEFAULT_EXCLUDE, ...(config.exclude ?? [])];
29
+ const includePatterns = config.include ?? [SOURCE_EXTENSIONS];
30
+ const files = [];
31
+ for (const pattern of includePatterns) {
32
+ const matched = await glob(pattern, {
33
+ cwd: target,
34
+ absolute: true,
35
+ ignore: excludePatterns,
36
+ nodir: true,
37
+ });
38
+ files.push(...matched);
39
+ }
40
+ // Deduplicate
41
+ const uniqueFiles = [...new Set(files)];
42
+ // Scan files
43
+ const allFindings = [];
44
+ for (const file of uniqueFiles) {
45
+ const rel = relative(target, file);
46
+ const fileFindings = scanFile(file, rel, rules);
47
+ allFindings.push(...fileFindings);
48
+ }
49
+ // Scan dependencies
50
+ if (config.scanDependencies) {
51
+ const depFindings = scanNpmDependencies(target);
52
+ allFindings.push(...depFindings);
53
+ }
54
+ // Filter by minimum severity
55
+ const severityOrder = {
56
+ critical: 0,
57
+ high: 1,
58
+ medium: 2,
59
+ low: 3,
60
+ safe: 4,
61
+ };
62
+ const minLevel = severityOrder[config.minSeverity];
63
+ const filtered = allFindings.filter((f) => severityOrder[f.severity] <= minLevel);
64
+ // Sort: critical first, then by file
65
+ filtered.sort((a, b) => {
66
+ const sevDiff = severityOrder[a.severity] - severityOrder[b.severity];
67
+ if (sevDiff !== 0)
68
+ return sevDiff;
69
+ return a.location.file.localeCompare(b.location.file);
70
+ });
71
+ // Build summary
72
+ const summary = buildSummary(filtered, uniqueFiles.length);
73
+ return {
74
+ timestamp: new Date().toISOString(),
75
+ target: config.target,
76
+ findings: filtered,
77
+ summary,
78
+ };
79
+ }
80
+ function buildSummary(findings, filesScanned) {
81
+ const bySeverity = {
82
+ critical: 0,
83
+ high: 0,
84
+ medium: 0,
85
+ low: 0,
86
+ safe: 0,
87
+ };
88
+ const byCategory = {
89
+ kem: 0,
90
+ signature: 0,
91
+ hash: 0,
92
+ symmetric: 0,
93
+ protocol: 0,
94
+ kdf: 0,
95
+ };
96
+ for (const f of findings) {
97
+ bySeverity[f.severity]++;
98
+ byCategory[f.category]++;
99
+ }
100
+ const pqcReady = bySeverity.critical === 0 && bySeverity.high === 0;
101
+ return {
102
+ filesScanned,
103
+ findingsTotal: findings.length,
104
+ bySeverity,
105
+ byCategory,
106
+ pqcReady,
107
+ };
108
+ }
109
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/scanner/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { DetectionRule, Finding } from "../types.js";
2
+ export declare function getLanguage(filePath: string): string | null;
3
+ export declare function isBinary(filePath: string): boolean;
4
+ export declare function scanFile(filePath: string, relativePath: string, rules: DetectionRule[]): Finding[];
5
+ //# sourceMappingURL=file-scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-scanner.d.ts","sourceRoot":"","sources":["../../src/scanner/file-scanner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,OAAO,EAGR,MAAM,aAAa,CAAC;AAqErB,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG3D;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGlD;AAED,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,aAAa,EAAE,GACrB,OAAO,EAAE,CA4EX"}
@@ -0,0 +1,163 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { compilePatterns } from "./rules.js";
3
+ /** File extensions to language mapping */
4
+ const LANG_MAP = {
5
+ ".js": "javascript",
6
+ ".mjs": "javascript",
7
+ ".cjs": "javascript",
8
+ ".jsx": "javascript",
9
+ ".ts": "typescript",
10
+ ".tsx": "typescript",
11
+ ".mts": "typescript",
12
+ ".cts": "typescript",
13
+ ".py": "python",
14
+ ".go": "go",
15
+ ".rs": "rust",
16
+ ".java": "java",
17
+ ".kt": "kotlin",
18
+ ".kts": "kotlin",
19
+ ".cs": "csharp",
20
+ ".c": "c",
21
+ ".h": "c",
22
+ ".cpp": "cpp",
23
+ ".cc": "cpp",
24
+ ".hpp": "cpp",
25
+ ".swift": "swift",
26
+ ".rb": "ruby",
27
+ ".php": "php",
28
+ ".toml": "config",
29
+ ".yaml": "config",
30
+ ".yml": "config",
31
+ ".json": "config",
32
+ ".xml": "config",
33
+ ".conf": "config",
34
+ ".cfg": "config",
35
+ ".ini": "config",
36
+ ".env": "config",
37
+ ".pem": "certificate",
38
+ ".crt": "certificate",
39
+ ".cer": "certificate",
40
+ };
41
+ const BINARY_EXTENSIONS = new Set([
42
+ ".png",
43
+ ".jpg",
44
+ ".jpeg",
45
+ ".gif",
46
+ ".ico",
47
+ ".woff",
48
+ ".woff2",
49
+ ".ttf",
50
+ ".eot",
51
+ ".zip",
52
+ ".gz",
53
+ ".tar",
54
+ ".jar",
55
+ ".class",
56
+ ".so",
57
+ ".dylib",
58
+ ".dll",
59
+ ".exe",
60
+ ".o",
61
+ ".a",
62
+ ".wasm",
63
+ ".mp3",
64
+ ".mp4",
65
+ ".pdf",
66
+ ]);
67
+ export function getLanguage(filePath) {
68
+ const ext = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
69
+ return LANG_MAP[ext] ?? null;
70
+ }
71
+ export function isBinary(filePath) {
72
+ const ext = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
73
+ return BINARY_EXTENSIONS.has(ext);
74
+ }
75
+ export function scanFile(filePath, relativePath, rules) {
76
+ if (isBinary(filePath))
77
+ return [];
78
+ const language = getLanguage(filePath);
79
+ const compiledRules = compilePatterns(rules);
80
+ const findings = [];
81
+ let content;
82
+ try {
83
+ content = readFileSync(filePath, "utf-8");
84
+ }
85
+ catch {
86
+ return [];
87
+ }
88
+ // Skip very large files (likely generated/vendor)
89
+ if (content.length > 1_000_000)
90
+ return [];
91
+ const lines = content.split("\n");
92
+ for (const [rule, regexes] of compiledRules) {
93
+ // Skip rules that don't apply to this language
94
+ if (rule.languages.length > 0 &&
95
+ language &&
96
+ !rule.languages.includes(language)) {
97
+ continue;
98
+ }
99
+ for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
100
+ const line = lines[lineIdx];
101
+ for (const regex of regexes) {
102
+ // Reset regex state (global flag)
103
+ regex.lastIndex = 0;
104
+ const match = regex.exec(line);
105
+ if (match) {
106
+ // Avoid duplicate findings for same rule on same line
107
+ const isDupe = findings.some((f) => f.ruleId === rule.id &&
108
+ f.location.file === relativePath &&
109
+ f.location.line === lineIdx + 1);
110
+ if (!isDupe) {
111
+ const location = {
112
+ file: relativePath,
113
+ line: lineIdx + 1,
114
+ column: match.index + 1,
115
+ snippet: line.trim().slice(0, 120),
116
+ };
117
+ findings.push({
118
+ ruleId: rule.id,
119
+ description: rule.description,
120
+ severity: rule.severity,
121
+ category: rule.category,
122
+ algorithm: rule.algorithm,
123
+ replacement: rule.replacement,
124
+ effort: rule.effort,
125
+ location,
126
+ detectionMethod: "regex",
127
+ confidence: computeConfidence(rule, line, language),
128
+ });
129
+ }
130
+ // Don't check more patterns from this rule on this line
131
+ break;
132
+ }
133
+ }
134
+ }
135
+ }
136
+ return findings;
137
+ }
138
+ /** Compute confidence based on context clues */
139
+ function computeConfidence(rule, line, language) {
140
+ let confidence = 0.7; // Base confidence for regex match
141
+ // Higher confidence if it looks like a code import
142
+ if (/(?:import|require|from|include|use)\b/.test(line)) {
143
+ confidence = 0.9;
144
+ }
145
+ // Higher confidence if it's a function call with the algorithm
146
+ if (/\(.*['"].*['"]\)/.test(line)) {
147
+ confidence = 0.85;
148
+ }
149
+ // Lower confidence in comments
150
+ if (/^\s*(?:\/\/|#|\/\*|\*|--|;)/.test(line)) {
151
+ confidence = 0.3;
152
+ }
153
+ // Lower confidence in strings that might be documentation
154
+ if (language === null) {
155
+ confidence *= 0.8;
156
+ }
157
+ // Safe findings get high confidence (we want to track them)
158
+ if (rule.severity === "safe") {
159
+ confidence = Math.max(confidence, 0.8);
160
+ }
161
+ return Math.round(confidence * 100) / 100;
162
+ }
163
+ //# sourceMappingURL=file-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-scanner.js","sourceRoot":"","sources":["../../src/scanner/file-scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { DetectionRule } from "../types.js";
2
+ export declare function loadRules(rulesPath?: string): DetectionRule[];
3
+ export declare function compilePatterns(rules: DetectionRule[]): Map<DetectionRule, RegExp[]>;
4
+ //# sourceMappingURL=rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/scanner/rules.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAOjD,wBAAgB,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,aAAa,EAAE,CAa7D;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,aAAa,EAAE,GACrB,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC,CAS9B"}
@@ -0,0 +1,25 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { parse as parseYaml } from "yaml";
4
+ const DEFAULT_RULES_PATH = resolve(import.meta.dirname, "../../rules/crypto-patterns.yaml");
5
+ export function loadRules(rulesPath) {
6
+ const path = rulesPath ?? DEFAULT_RULES_PATH;
7
+ const raw = readFileSync(path, "utf-8");
8
+ const parsed = parseYaml(raw);
9
+ // Validate and compile patterns
10
+ for (const rule of parsed) {
11
+ if (!rule.id || !rule.patterns?.length) {
12
+ throw new Error(`Invalid rule: missing id or patterns in ${path}`);
13
+ }
14
+ }
15
+ return parsed;
16
+ }
17
+ export function compilePatterns(rules) {
18
+ const compiled = new Map();
19
+ for (const rule of rules) {
20
+ const regexes = rule.patterns.map((p) => new RegExp(p, "gi"));
21
+ compiled.set(rule, regexes);
22
+ }
23
+ return compiled;
24
+ }
25
+ //# sourceMappingURL=rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/scanner/rules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAG1C,MAAM,kBAAkB,GAAG,OAAO,CAChC,MAAM,CAAC,IAAI,CAAC,OAAO,EACnB,kCAAkC,CACnC,CAAC;AAEF,MAAM,UAAU,SAAS,CAAC,SAAkB;IAC1C,MAAM,IAAI,GAAG,SAAS,IAAI,kBAAkB,CAAC;IAC7C,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAoB,CAAC;IAEjD,gCAAgC;IAChC,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,2CAA2C,IAAI,EAAE,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,KAAsB;IAEtB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;IAEpD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;QAC9D,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC9B,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}