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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 PQCWorld
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,180 @@
1
+ # pqaudit
2
+
3
+ Scan codebases for quantum-vulnerable cryptography. Get a clear picture of what needs to migrate before [Q-Day](https://en.wikipedia.org/wiki/Q-day).
4
+
5
+ pqaudit detects usage of RSA, ECDSA, Ed25519, ECDH, DH, and other algorithms broken by Shor's algorithm. It also identifies already-migrated PQC usage (ML-KEM, ML-DSA, SLH-DSA) so you can track migration progress. Output as human-readable text, JSON, [CycloneDX CBOM](https://cyclonedx.org/capabilities/cbom/), or [SARIF](https://sarifweb.azurewebsites.net/) for GitHub Code Scanning.
6
+
7
+ ## Why now
8
+
9
+ On March 31, 2026, Google published research showing that breaking ECDSA-256 requires [20x fewer qubits than previously estimated](https://research.google/blog/safeguarding-cryptocurrency-by-disclosing-quantum-vulnerabilities-responsibly/) — roughly 1,200 logical qubits and under 500,000 physical qubits. NSA's CNSA 2.0 mandates PQC for new national security systems by 2027. The migration window is open but closing.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npx pqaudit ./my-project
15
+ ```
16
+
17
+ Or install globally:
18
+
19
+ ```bash
20
+ npm install -g pqaudit
21
+ pqaudit ./my-project
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ```bash
27
+ # Scan current directory, human-readable output
28
+ pqaudit .
29
+
30
+ # Only show critical and high findings
31
+ pqaudit ./src --severity high
32
+
33
+ # Generate CycloneDX CBOM
34
+ pqaudit . --format cbom --output cbom.json
35
+
36
+ # Generate SARIF for GitHub Code Scanning
37
+ pqaudit . --format sarif --output results.sarif
38
+
39
+ # CI mode — exit code 1 if critical/high findings exist
40
+ pqaudit . --ci
41
+
42
+ # Skip dependency scanning
43
+ pqaudit . --no-deps
44
+
45
+ # Use custom rules
46
+ pqaudit . --rules ./my-rules.yaml
47
+ ```
48
+
49
+ ## Example output
50
+
51
+ ```
52
+ pqaudit — Post-Quantum Cryptography Readiness Scanner
53
+ Scanned: ./my-project
54
+ Date: 2026-04-01T00:00:00.000Z
55
+
56
+ NOT PQC READY — Quantum-vulnerable cryptography detected
57
+
58
+ Files scanned: 65 | Findings: 18
59
+ Critical: 12 High: 2 Medium: 1 Low: 0 Safe: 3
60
+
61
+ --- CRITICAL (12) ---
62
+
63
+ [!!] Ed25519 — Ed25519 signatures — elliptic curve, vulnerable to Shor's algorithm
64
+ src/crypto/signing.ts:14
65
+ > import { sign, verify } from "@noble/ed25519";
66
+ Fix: ML-DSA-65 (FIPS 204) or hybrid Ed25519+ML-DSA-65
67
+ Confidence: 90% | Effort: moderate | Via: regex
68
+ ...
69
+ ```
70
+
71
+ ## What it detects
72
+
73
+ ### Critical (quantum-vulnerable — must migrate)
74
+
75
+ | Algorithm | Threat | Replacement |
76
+ |-----------|--------|-------------|
77
+ | RSA (any key size) | Shor's algorithm | ML-KEM-768 / ML-DSA-65 |
78
+ | ECDSA / Ed25519 | Shor's on elliptic curves | ML-DSA-65 (FIPS 204) |
79
+ | ECDH / X25519 / DH | Shor's on key exchange | ML-KEM-768 (FIPS 203) |
80
+ | DSA | Shor's algorithm | ML-DSA-65 (FIPS 204) |
81
+
82
+ ### High (weakened by quantum)
83
+
84
+ | Algorithm | Threat | Replacement |
85
+ |-----------|--------|-------------|
86
+ | AES-128 | Grover reduces to 64-bit | AES-256 |
87
+
88
+ ### Safe (already quantum-resistant)
89
+
90
+ ML-KEM (Kyber), ML-DSA (Dilithium), SLH-DSA (SPHINCS+), AES-256, ChaCha20-Poly1305, SHA-256, SHA-3
91
+
92
+ ## Output formats
93
+
94
+ ### CycloneDX CBOM
95
+
96
+ Generates a [Cryptographic Bill of Materials](https://cyclonedx.org/capabilities/cbom/) conforming to CycloneDX 1.6. Each cryptographic finding becomes a `crypto-asset` component with `cryptoProperties`, NIST quantum security levels, and evidence locations.
97
+
98
+ ```bash
99
+ pqaudit . --format cbom --output cbom.json
100
+ ```
101
+
102
+ ### SARIF (GitHub Code Scanning)
103
+
104
+ Generates SARIF 2.1.0 output compatible with GitHub's code scanning. Upload via `github/codeql-action/upload-sarif`.
105
+
106
+ ```bash
107
+ pqaudit . --format sarif --output results.sarif
108
+ ```
109
+
110
+ ## GitHub Action
111
+
112
+ ```yaml
113
+ name: PQC Audit
114
+ on: [push, pull_request]
115
+ jobs:
116
+ pqaudit:
117
+ runs-on: ubuntu-latest
118
+ steps:
119
+ - uses: actions/checkout@v4
120
+ - uses: actions/setup-node@v4
121
+ with:
122
+ node-version: "20"
123
+ - run: npx pqaudit . --format sarif --output pqaudit.sarif --ci
124
+ - uses: github/codeql-action/upload-sarif@v3
125
+ if: always()
126
+ with:
127
+ sarif_file: pqaudit.sarif
128
+ category: pqaudit
129
+ ```
130
+
131
+ ## Dependency scanning
132
+
133
+ pqaudit checks `package.json` for known cryptographic libraries and flags quantum-vulnerable dependencies:
134
+
135
+ - `@noble/ed25519`, `@noble/secp256k1` — ECC signatures
136
+ - `tweetnacl`, `elliptic`, `node-rsa` — various asymmetric crypto
137
+ - `jsonwebtoken`, `jose` — JWT libraries (typically RSA/ECDSA)
138
+ - `@solana/web3.js`, `ethers`, `web3` — blockchain (Ed25519/secp256k1)
139
+ - `@noble/post-quantum` — flagged as **safe**
140
+
141
+ ## Custom rules
142
+
143
+ Rules are defined in YAML:
144
+
145
+ ```yaml
146
+ - id: MY_CUSTOM_RULE
147
+ description: "Custom quantum-vulnerable pattern"
148
+ severity: critical
149
+ category: signature
150
+ algorithm: MyAlgo
151
+ replacement: ML-DSA-65
152
+ effort: complex
153
+ languages: ["javascript", "typescript"]
154
+ patterns:
155
+ - "myVulnerableFunction\\("
156
+ - "import.*myVulnerableLib"
157
+ ```
158
+
159
+ ## Detection methods
160
+
161
+ Currently implements L0 (regex) detection. Planned:
162
+
163
+ - **L1**: AST-based analysis via tree-sitter for semantic understanding and fewer false positives
164
+ - **L2**: Data flow / taint analysis for tracing cryptographic data through call chains
165
+ - **Network scanning**: TLS/SSH endpoint analysis
166
+ - **More languages**: Cargo.toml, build.gradle, requirements.txt dependency scanning
167
+
168
+ ## References
169
+
170
+ - [NIST FIPS 203 — ML-KEM](https://csrc.nist.gov/pubs/fips/203/final)
171
+ - [NIST FIPS 204 — ML-DSA](https://csrc.nist.gov/pubs/fips/204/final)
172
+ - [NIST FIPS 205 — SLH-DSA](https://csrc.nist.gov/pubs/fips/205/final)
173
+ - [NSA CNSA 2.0 Timeline](https://media.defense.gov/2022/Sep/07/2003071836/-1/-1/0/CSI_CNSA_2.0_FAQ_.PDF)
174
+ - [CycloneDX CBOM Specification](https://cyclonedx.org/capabilities/cbom/)
175
+ - [Google PQC Migration Timeline (March 2026)](https://blog.google/innovation-and-ai/technology/safety-security/cryptography-migration-timeline/)
176
+ - [Google Quantum Vulnerability Research (March 2026)](https://research.google/blog/safeguarding-cryptocurrency-by-disclosing-quantum-vulnerabilities-responsibly/)
177
+
178
+ ## License
179
+
180
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env node
2
+ import { writeFileSync } from "node:fs";
3
+ import { Command } from "commander";
4
+ import { scan } from "./scanner/engine.js";
5
+ import { formatText } from "./reporter/text.js";
6
+ import { formatJson } from "./reporter/json.js";
7
+ import { formatCbom } from "./reporter/cbom.js";
8
+ import { formatSarif } from "./reporter/sarif.js";
9
+ const program = new Command();
10
+ program
11
+ .name("pqaudit")
12
+ .description("Scan codebases for quantum-vulnerable cryptography and generate a Cryptographic Bill of Materials (CBOM)")
13
+ .version("0.1.0")
14
+ .argument("[target]", "Directory to scan", ".")
15
+ .option("-f, --format <format>", "Output format: text, json, cbom, sarif", "text")
16
+ .option("-o, --output <file>", "Write output to file instead of stdout")
17
+ .option("-s, --severity <level>", "Minimum severity to report: critical, high, medium, low, safe", "safe")
18
+ .option("--no-deps", "Skip dependency scanning")
19
+ .option("--include <patterns...>", "File patterns to include")
20
+ .option("--exclude <patterns...>", "Additional file patterns to exclude")
21
+ .option("--rules <dir>", "Path to custom rules YAML file")
22
+ .option("--ci", "Exit with code 1 if critical/high findings exist")
23
+ .action(async (target, opts) => {
24
+ const config = {
25
+ target,
26
+ format: opts.format,
27
+ output: opts.output,
28
+ minSeverity: opts.severity,
29
+ scanDependencies: opts.deps !== false,
30
+ include: opts.include,
31
+ exclude: opts.exclude,
32
+ rulesDir: opts.rules,
33
+ };
34
+ const result = await scan(config);
35
+ let output;
36
+ switch (config.format) {
37
+ case "json":
38
+ output = formatJson(result);
39
+ break;
40
+ case "cbom":
41
+ output = formatCbom(result);
42
+ break;
43
+ case "sarif":
44
+ output = formatSarif(result);
45
+ break;
46
+ case "text":
47
+ default:
48
+ output = formatText(result);
49
+ break;
50
+ }
51
+ if (config.output) {
52
+ writeFileSync(config.output, output, "utf-8");
53
+ if (config.format === "text") {
54
+ console.log(`Results written to ${config.output}`);
55
+ }
56
+ }
57
+ else {
58
+ console.log(output);
59
+ }
60
+ // CI mode: exit 1 if critical or high findings
61
+ if (opts.ci) {
62
+ const { critical, high } = result.summary.bySeverity;
63
+ if (critical > 0 || high > 0) {
64
+ process.exit(1);
65
+ }
66
+ }
67
+ });
68
+ program.parse();
69
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export { scan } from "./scanner/engine.js";
2
+ export { formatText } from "./reporter/text.js";
3
+ export { formatJson } from "./reporter/json.js";
4
+ export { formatCbom } from "./reporter/cbom.js";
5
+ export { formatSarif } from "./reporter/sarif.js";
6
+ export type * from "./types.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,mBAAmB,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { scan } from "./scanner/engine.js";
2
+ export { formatText } from "./reporter/text.js";
3
+ export { formatJson } from "./reporter/json.js";
4
+ export { formatCbom } from "./reporter/cbom.js";
5
+ export { formatSarif } from "./reporter/sarif.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ScanResult } from "../types.js";
2
+ /**
3
+ * Generate a CycloneDX 1.6 CBOM (Cryptographic Bill of Materials)
4
+ *
5
+ * Spec: https://cyclonedx.org/capabilities/cbom/
6
+ */
7
+ export declare function formatCbom(result: ScanResult): string;
8
+ //# sourceMappingURL=cbom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cbom.d.ts","sourceRoot":"","sources":["../../src/reporter/cbom.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAW,UAAU,EAAE,MAAM,aAAa,CAAC;AAEvD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CA+BrD"}
@@ -0,0 +1,153 @@
1
+ import { randomUUID } from "node:crypto";
2
+ /**
3
+ * Generate a CycloneDX 1.6 CBOM (Cryptographic Bill of Materials)
4
+ *
5
+ * Spec: https://cyclonedx.org/capabilities/cbom/
6
+ */
7
+ export function formatCbom(result) {
8
+ const components = result.findings.map(findingToComponent);
9
+ const cbom = {
10
+ bomFormat: "CycloneDX",
11
+ specVersion: "1.6",
12
+ serialNumber: `urn:uuid:${randomUUID()}`,
13
+ version: 1,
14
+ metadata: {
15
+ timestamp: result.timestamp,
16
+ tools: {
17
+ components: [
18
+ {
19
+ type: "application",
20
+ name: "pqaudit",
21
+ version: "0.1.0",
22
+ description: "Post-quantum cryptography readiness scanner",
23
+ },
24
+ ],
25
+ },
26
+ component: {
27
+ type: "application",
28
+ name: result.target,
29
+ "bom-ref": "target",
30
+ },
31
+ },
32
+ components,
33
+ };
34
+ return JSON.stringify(cbom, null, 2);
35
+ }
36
+ function findingToComponent(finding) {
37
+ const bomRef = `crypto-${finding.ruleId}-${finding.location.file.replace(/[^a-zA-Z0-9]/g, "-")}-${finding.location.line ?? 0}`;
38
+ return {
39
+ type: "crypto-asset",
40
+ "bom-ref": bomRef,
41
+ name: finding.algorithm,
42
+ description: finding.description,
43
+ cryptoProperties: {
44
+ assetType: categoryToAssetType(finding.category),
45
+ algorithmProperties: {
46
+ primitive: categoryToPrimitive(finding.category),
47
+ variant: finding.algorithm,
48
+ cryptoFunctions: [categoryToFunction(finding.category)],
49
+ },
50
+ classicalSecurityLevel: severityToSecurityLevel(finding.severity),
51
+ nistQuantumSecurityLevel: severityToNistLevel(finding.severity),
52
+ },
53
+ evidence: {
54
+ occurrences: [
55
+ {
56
+ location: finding.location.file,
57
+ line: finding.location.line,
58
+ offset: finding.location.column,
59
+ symbol: finding.location.snippet,
60
+ additionalContext: finding.replacement
61
+ ? `Recommended replacement: ${finding.replacement}`
62
+ : undefined,
63
+ },
64
+ ],
65
+ },
66
+ properties: [
67
+ { name: "pqaudit:severity", value: finding.severity },
68
+ { name: "pqaudit:confidence", value: String(finding.confidence) },
69
+ { name: "pqaudit:effort", value: finding.effort },
70
+ { name: "pqaudit:detectionMethod", value: finding.detectionMethod },
71
+ ...(finding.replacement
72
+ ? [{ name: "pqaudit:replacement", value: finding.replacement }]
73
+ : []),
74
+ ],
75
+ };
76
+ }
77
+ function categoryToAssetType(category) {
78
+ switch (category) {
79
+ case "kem":
80
+ return "algorithm";
81
+ case "signature":
82
+ return "algorithm";
83
+ case "hash":
84
+ return "algorithm";
85
+ case "symmetric":
86
+ return "algorithm";
87
+ case "protocol":
88
+ return "protocol";
89
+ case "kdf":
90
+ return "algorithm";
91
+ }
92
+ }
93
+ function categoryToPrimitive(category) {
94
+ switch (category) {
95
+ case "kem":
96
+ return "pke";
97
+ case "signature":
98
+ return "signature";
99
+ case "hash":
100
+ return "hash";
101
+ case "symmetric":
102
+ return "ae";
103
+ case "protocol":
104
+ return "other";
105
+ case "kdf":
106
+ return "kdf";
107
+ }
108
+ }
109
+ function categoryToFunction(category) {
110
+ switch (category) {
111
+ case "kem":
112
+ return "encapsulate";
113
+ case "signature":
114
+ return "sign";
115
+ case "hash":
116
+ return "digest";
117
+ case "symmetric":
118
+ return "encrypt";
119
+ case "protocol":
120
+ return "other";
121
+ case "kdf":
122
+ return "keygen";
123
+ }
124
+ }
125
+ function severityToSecurityLevel(severity) {
126
+ switch (severity) {
127
+ case "critical":
128
+ return 0; // Broken by quantum
129
+ case "high":
130
+ return 64; // Reduced by Grover
131
+ case "medium":
132
+ return 0; // Already broken classically
133
+ case "low":
134
+ return 128;
135
+ case "safe":
136
+ return 128; // Post-quantum safe
137
+ }
138
+ }
139
+ function severityToNistLevel(severity) {
140
+ switch (severity) {
141
+ case "critical":
142
+ return 0;
143
+ case "high":
144
+ return 1;
145
+ case "medium":
146
+ return 0;
147
+ case "low":
148
+ return 3;
149
+ case "safe":
150
+ return 3;
151
+ }
152
+ }
153
+ //# sourceMappingURL=cbom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cbom.js","sourceRoot":"","sources":["../../src/reporter/cbom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,MAAkB;IAC3C,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAE3D,MAAM,IAAI,GAAG;QACX,SAAS,EAAE,WAAW;QACtB,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,YAAY,UAAU,EAAE,EAAE;QACxC,OAAO,EAAE,CAAC;QACV,QAAQ,EAAE;YACR,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,KAAK,EAAE;gBACL,UAAU,EAAE;oBACV;wBACE,IAAI,EAAE,aAAa;wBACnB,IAAI,EAAE,SAAS;wBACf,OAAO,EAAE,OAAO;wBAChB,WAAW,EACT,6CAA6C;qBAChD;iBACF;aACF;YACD,SAAS,EAAE;gBACT,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE,MAAM,CAAC,MAAM;gBACnB,SAAS,EAAE,QAAQ;aACpB;SACF;QACD,UAAU;KACX,CAAC;IAEF,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAgB;IAC1C,MAAM,MAAM,GAAG,UAAU,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC;IAE/H,OAAO;QACL,IAAI,EAAE,cAAc;QACpB,SAAS,EAAE,MAAM;QACjB,IAAI,EAAE,OAAO,CAAC,SAAS;QACvB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,gBAAgB,EAAE;YAChB,SAAS,EAAE,mBAAmB,CAAC,OAAO,CAAC,QAAQ,CAAC;YAChD,mBAAmB,EAAE;gBACnB,SAAS,EAAE,mBAAmB,CAAC,OAAO,CAAC,QAAQ,CAAC;gBAChD,OAAO,EAAE,OAAO,CAAC,SAAS;gBAC1B,eAAe,EAAE,CAAC,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;aACxD;YACD,sBAAsB,EAAE,uBAAuB,CAAC,OAAO,CAAC,QAAQ,CAAC;YACjE,wBAAwB,EAAE,mBAAmB,CAAC,OAAO,CAAC,QAAQ,CAAC;SAChE;QACD,QAAQ,EAAE;YACR,WAAW,EAAE;gBACX;oBACE,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI;oBAC/B,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI;oBAC3B,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM;oBAC/B,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,OAAO;oBAChC,iBAAiB,EAAE,OAAO,CAAC,WAAW;wBACpC,CAAC,CAAC,4BAA4B,OAAO,CAAC,WAAW,EAAE;wBACnD,CAAC,CAAC,SAAS;iBACd;aACF;SACF;QACD,UAAU,EAAE;YACV,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE;YACrD,EAAE,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;YACjE,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE;YACjD,EAAE,IAAI,EAAE,yBAAyB,EAAE,KAAK,EAAE,OAAO,CAAC,eAAe,EAAE;YACnE,GAAG,CAAC,OAAO,CAAC,WAAW;gBACrB,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,qBAAqB,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;gBAC/D,CAAC,CAAC,EAAE,CAAC;SACR;KACF,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAC1B,QAA6B;IAE7B,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,KAAK;YACR,OAAO,WAAW,CAAC;QACrB,KAAK,WAAW;YACd,OAAO,WAAW,CAAC;QACrB,KAAK,MAAM;YACT,OAAO,WAAW,CAAC;QACrB,KAAK,WAAW;YACd,OAAO,WAAW,CAAC;QACrB,KAAK,UAAU;YACb,OAAO,UAAU,CAAC;QACpB,KAAK,KAAK;YACR,OAAO,WAAW,CAAC;IACvB,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAC1B,QAA6B;IAE7B,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,KAAK;YACR,OAAO,KAAK,CAAC;QACf,KAAK,WAAW;YACd,OAAO,WAAW,CAAC;QACrB,KAAK,MAAM;YACT,OAAO,MAAM,CAAC;QAChB,KAAK,WAAW;YACd,OAAO,IAAI,CAAC;QACd,KAAK,UAAU;YACb,OAAO,OAAO,CAAC;QACjB,KAAK,KAAK;YACR,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CACzB,QAA6B;IAE7B,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,KAAK;YACR,OAAO,aAAa,CAAC;QACvB,KAAK,WAAW;YACd,OAAO,MAAM,CAAC;QAChB,KAAK,MAAM;YACT,OAAO,QAAQ,CAAC;QAClB,KAAK,WAAW;YACd,OAAO,SAAS,CAAC;QACnB,KAAK,UAAU;YACb,OAAO,OAAO,CAAC;QACjB,KAAK,KAAK;YACR,OAAO,QAAQ,CAAC;IACpB,CAAC;AACH,CAAC;AAED,SAAS,uBAAuB,CAAC,QAA6B;IAC5D,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,UAAU;YACb,OAAO,CAAC,CAAC,CAAC,oBAAoB;QAChC,KAAK,MAAM;YACT,OAAO,EAAE,CAAC,CAAC,oBAAoB;QACjC,KAAK,QAAQ;YACX,OAAO,CAAC,CAAC,CAAC,6BAA6B;QACzC,KAAK,KAAK;YACR,OAAO,GAAG,CAAC;QACb,KAAK,MAAM;YACT,OAAO,GAAG,CAAC,CAAC,oBAAoB;IACpC,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,QAA6B;IACxD,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,UAAU;YACb,OAAO,CAAC,CAAC;QACX,KAAK,MAAM;YACT,OAAO,CAAC,CAAC;QACX,KAAK,QAAQ;YACX,OAAO,CAAC,CAAC;QACX,KAAK,KAAK;YACR,OAAO,CAAC,CAAC;QACX,KAAK,MAAM;YACT,OAAO,CAAC,CAAC;IACb,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ScanResult } from "../types.js";
2
+ export declare function formatJson(result: ScanResult): string;
3
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/reporter/json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAErD"}
@@ -0,0 +1,4 @@
1
+ export function formatJson(result) {
2
+ return JSON.stringify(result, null, 2);
3
+ }
4
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/reporter/json.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,UAAU,CAAC,MAAkB;IAC3C,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { ScanResult } from "../types.js";
2
+ /**
3
+ * Generate SARIF output for GitHub Code Scanning integration
4
+ * Spec: https://sarifweb.azurewebsites.net/
5
+ */
6
+ export declare function formatSarif(result: ScanResult): string;
7
+ //# sourceMappingURL=sarif.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sarif.d.ts","sourceRoot":"","sources":["../../src/reporter/sarif.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,UAAU,EAAY,MAAM,aAAa,CAAC;AAEjE;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CA+DtD"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Generate SARIF output for GitHub Code Scanning integration
3
+ * Spec: https://sarifweb.azurewebsites.net/
4
+ */
5
+ export function formatSarif(result) {
6
+ const rules = dedupeRules(result.findings);
7
+ const sarif = {
8
+ $schema: "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/main/sarif-2.1/schema/sarif-schema-2.1.0.json",
9
+ version: "2.1.0",
10
+ runs: [
11
+ {
12
+ tool: {
13
+ driver: {
14
+ name: "pqaudit",
15
+ version: "0.1.0",
16
+ informationUri: "https://github.com/PQCWorld/pqaudit",
17
+ rules: rules.map((r) => ({
18
+ id: r.ruleId,
19
+ shortDescription: { text: r.algorithm },
20
+ fullDescription: { text: r.description },
21
+ defaultConfiguration: {
22
+ level: severityToSarifLevel(r.severity),
23
+ },
24
+ help: {
25
+ text: r.replacement
26
+ ? `Replace with: ${r.replacement}`
27
+ : "No migration needed",
28
+ },
29
+ properties: {
30
+ tags: ["security", "cryptography", "post-quantum"],
31
+ },
32
+ })),
33
+ },
34
+ },
35
+ results: result.findings
36
+ .filter((f) => f.severity !== "safe")
37
+ .map((f) => ({
38
+ ruleId: f.ruleId,
39
+ level: severityToSarifLevel(f.severity),
40
+ message: {
41
+ text: `${f.algorithm}: ${f.description}${f.replacement ? `. Replace with: ${f.replacement}` : ""}`,
42
+ },
43
+ locations: [
44
+ {
45
+ physicalLocation: {
46
+ artifactLocation: {
47
+ uri: f.location.file,
48
+ },
49
+ region: {
50
+ startLine: f.location.line ?? 1,
51
+ startColumn: f.location.column ?? 1,
52
+ },
53
+ },
54
+ },
55
+ ],
56
+ properties: {
57
+ confidence: f.confidence,
58
+ effort: f.effort,
59
+ },
60
+ })),
61
+ },
62
+ ],
63
+ };
64
+ return JSON.stringify(sarif, null, 2);
65
+ }
66
+ function severityToSarifLevel(severity) {
67
+ switch (severity) {
68
+ case "critical":
69
+ return "error";
70
+ case "high":
71
+ return "error";
72
+ case "medium":
73
+ return "warning";
74
+ case "low":
75
+ return "note";
76
+ case "safe":
77
+ return "note";
78
+ }
79
+ }
80
+ function dedupeRules(findings) {
81
+ const seen = new Set();
82
+ const unique = [];
83
+ for (const f of findings) {
84
+ if (!seen.has(f.ruleId)) {
85
+ seen.add(f.ruleId);
86
+ unique.push(f);
87
+ }
88
+ }
89
+ return unique;
90
+ }
91
+ //# sourceMappingURL=sarif.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sarif.js","sourceRoot":"","sources":["../../src/reporter/sarif.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ScanResult } from "../types.js";
2
+ export declare function formatText(result: ScanResult): string;
3
+ //# sourceMappingURL=text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/reporter/text.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAW,UAAU,EAAY,MAAM,aAAa,CAAC;AAkBjE,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAwErD"}