@quantakrypto/core 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 (102) hide show
  1. package/README.md +337 -0
  2. package/dist/baseline.d.ts +37 -0
  3. package/dist/baseline.d.ts.map +1 -0
  4. package/dist/baseline.js +99 -0
  5. package/dist/baseline.js.map +1 -0
  6. package/dist/cbom.d.ts +25 -0
  7. package/dist/cbom.d.ts.map +1 -0
  8. package/dist/cbom.js +131 -0
  9. package/dist/cbom.js.map +1 -0
  10. package/dist/changed.d.ts +13 -0
  11. package/dist/changed.d.ts.map +1 -0
  12. package/dist/changed.js +67 -0
  13. package/dist/changed.js.map +1 -0
  14. package/dist/config.d.ts +55 -0
  15. package/dist/config.d.ts.map +1 -0
  16. package/dist/config.js +232 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/cwe.d.ts +16 -0
  19. package/dist/cwe.d.ts.map +1 -0
  20. package/dist/cwe.js +16 -0
  21. package/dist/cwe.js.map +1 -0
  22. package/dist/dependencies.d.ts +25 -0
  23. package/dist/dependencies.d.ts.map +1 -0
  24. package/dist/dependencies.js +276 -0
  25. package/dist/dependencies.js.map +1 -0
  26. package/dist/detect-utils.d.ts +63 -0
  27. package/dist/detect-utils.d.ts.map +1 -0
  28. package/dist/detect-utils.js +113 -0
  29. package/dist/detect-utils.js.map +1 -0
  30. package/dist/detectors/pem.d.ts +9 -0
  31. package/dist/detectors/pem.d.ts.map +1 -0
  32. package/dist/detectors/pem.js +137 -0
  33. package/dist/detectors/pem.js.map +1 -0
  34. package/dist/detectors/source.d.ts +25 -0
  35. package/dist/detectors/source.d.ts.map +1 -0
  36. package/dist/detectors/source.js +575 -0
  37. package/dist/detectors/source.js.map +1 -0
  38. package/dist/index.d.ts +31 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +39 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/inventory.d.ts +15 -0
  43. package/dist/inventory.d.ts.map +1 -0
  44. package/dist/inventory.js +74 -0
  45. package/dist/inventory.js.map +1 -0
  46. package/dist/parallel.d.ts +34 -0
  47. package/dist/parallel.d.ts.map +1 -0
  48. package/dist/parallel.js +237 -0
  49. package/dist/parallel.js.map +1 -0
  50. package/dist/registry.d.ts +42 -0
  51. package/dist/registry.d.ts.map +1 -0
  52. package/dist/registry.js +51 -0
  53. package/dist/registry.js.map +1 -0
  54. package/dist/remediation.d.ts +42 -0
  55. package/dist/remediation.d.ts.map +1 -0
  56. package/dist/remediation.js +131 -0
  57. package/dist/remediation.js.map +1 -0
  58. package/dist/report.d.ts +24 -0
  59. package/dist/report.d.ts.map +1 -0
  60. package/dist/report.js +286 -0
  61. package/dist/report.js.map +1 -0
  62. package/dist/scan-worker.d.ts +2 -0
  63. package/dist/scan-worker.d.ts.map +1 -0
  64. package/dist/scan-worker.js +63 -0
  65. package/dist/scan-worker.js.map +1 -0
  66. package/dist/scan.d.ts +27 -0
  67. package/dist/scan.d.ts.map +1 -0
  68. package/dist/scan.js +168 -0
  69. package/dist/scan.js.map +1 -0
  70. package/dist/types.d.ts +190 -0
  71. package/dist/types.d.ts.map +1 -0
  72. package/dist/types.js +9 -0
  73. package/dist/types.js.map +1 -0
  74. package/dist/version.d.ts +7 -0
  75. package/dist/version.d.ts.map +1 -0
  76. package/dist/version.js +7 -0
  77. package/dist/version.js.map +1 -0
  78. package/dist/walk.d.ts +37 -0
  79. package/dist/walk.d.ts.map +1 -0
  80. package/dist/walk.js +260 -0
  81. package/dist/walk.js.map +1 -0
  82. package/package.json +40 -0
  83. package/src/baseline.ts +111 -0
  84. package/src/cbom.ts +166 -0
  85. package/src/changed.ts +76 -0
  86. package/src/config.ts +295 -0
  87. package/src/cwe.ts +20 -0
  88. package/src/dependencies.ts +299 -0
  89. package/src/detect-utils.ts +157 -0
  90. package/src/detectors/pem.ts +162 -0
  91. package/src/detectors/source.ts +733 -0
  92. package/src/index.ts +79 -0
  93. package/src/inventory.ts +94 -0
  94. package/src/parallel.ts +288 -0
  95. package/src/registry.ts +71 -0
  96. package/src/remediation.ts +173 -0
  97. package/src/report.ts +340 -0
  98. package/src/scan-worker.ts +80 -0
  99. package/src/scan.ts +187 -0
  100. package/src/types.ts +224 -0
  101. package/src/version.ts +6 -0
  102. package/src/walk.ts +289 -0
@@ -0,0 +1,131 @@
1
+ /** Canonical remediation table, keyed by algorithm family. */
2
+ const REMEDIATIONS = {
3
+ RSA: {
4
+ algorithm: "RSA",
5
+ recommendation: "ML-KEM-768 for encryption/KEM; ML-DSA-65 for signatures",
6
+ detail: "RSA is broken by Shor's algorithm. For key transport / encryption move to " +
7
+ "ML-KEM-768 (FIPS 203), ideally as the hybrid X25519MLKEM768. For digital " +
8
+ "signatures move to ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205).",
9
+ },
10
+ ECDH: {
11
+ algorithm: "ECDH",
12
+ recommendation: "hybrid X25519MLKEM768 (ML-KEM-768)",
13
+ detail: "Elliptic-curve Diffie-Hellman is broken by Shor's algorithm and is exposed " +
14
+ "to harvest-now-decrypt-later. Adopt the hybrid X25519MLKEM768 key exchange so " +
15
+ "confidentiality survives even if one component is broken.",
16
+ },
17
+ ECDSA: {
18
+ algorithm: "ECDSA",
19
+ recommendation: "ML-DSA-65 (FIPS 204)",
20
+ detail: "ECDSA signatures can be forged by a quantum attacker via Shor's algorithm. " +
21
+ "Migrate to ML-DSA (Dilithium, FIPS 204) or SLH-DSA (SPHINCS+, FIPS 205) for " +
22
+ "long-lived signatures.",
23
+ },
24
+ EdDSA: {
25
+ algorithm: "EdDSA",
26
+ recommendation: "ML-DSA-65 (FIPS 204)",
27
+ detail: "Ed25519 / Ed448 (EdDSA) are classical signatures broken by Shor's algorithm. " +
28
+ "Replace with ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205) for forgery resistance.",
29
+ },
30
+ DH: {
31
+ algorithm: "DH",
32
+ recommendation: "hybrid X25519MLKEM768 (ML-KEM-768)",
33
+ detail: "Finite-field Diffie-Hellman is broken by Shor's algorithm and exposed to " +
34
+ "harvest-now-decrypt-later. Move to a hybrid PQC KEM such as X25519MLKEM768.",
35
+ },
36
+ DSA: {
37
+ algorithm: "DSA",
38
+ recommendation: "ML-DSA-65 (FIPS 204)",
39
+ detail: "DSA is a classical, quantum-broken signature scheme (and already deprecated). " +
40
+ "Replace with ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205).",
41
+ },
42
+ X25519: {
43
+ algorithm: "X25519",
44
+ recommendation: "hybrid X25519MLKEM768 (ML-KEM-768)",
45
+ detail: "X25519 is a modern, well-built classical key-agreement primitive but is still " +
46
+ "broken by Shor's algorithm. Wrap it in the hybrid X25519MLKEM768 construction " +
47
+ "so it stays useful during the PQC transition.",
48
+ },
49
+ X448: {
50
+ algorithm: "X448",
51
+ recommendation: "hybrid X25519MLKEM768 (ML-KEM-768)",
52
+ detail: "X448 (Goldilocks curve) is a modern classical key-agreement primitive at a " +
53
+ "higher classical security level, but it is still broken by Shor's algorithm. " +
54
+ "Adopt a hybrid PQC KEM (X25519MLKEM768 / ML-KEM-768) during the transition.",
55
+ },
56
+ ECIES: {
57
+ algorithm: "ECIES",
58
+ recommendation: "ML-KEM-768 hybrid encryption",
59
+ detail: "ECIES relies on classical ECDH for its key encapsulation and is exposed to " +
60
+ "harvest-now-decrypt-later. Replace the KEM step with ML-KEM-768 (FIPS 203), " +
61
+ "preferably in a hybrid construction.",
62
+ },
63
+ unknown: {
64
+ algorithm: "unknown",
65
+ recommendation: "review for post-quantum migration",
66
+ detail: "This usage involves classical public-key cryptography. Audit it and plan a " +
67
+ "migration to NIST PQC standards (ML-KEM / FIPS 203, ML-DSA / FIPS 204).",
68
+ },
69
+ };
70
+ /** Look up the recommended post-quantum remediation for a classical algorithm. */
71
+ export function remediationFor(algorithm) {
72
+ return REMEDIATIONS[algorithm];
73
+ }
74
+ /** Convenience: just the short recommendation string for a family (always defined). */
75
+ export function remediationText(algorithm) {
76
+ return REMEDIATIONS[algorithm].recommendation;
77
+ }
78
+ /** Per-tier KEM / signature parameter sets. */
79
+ export const TIER_PARAMS = {
80
+ "category-3": {
81
+ kem: "ML-KEM-768 (FIPS 203)",
82
+ signature: "ML-DSA-65 (FIPS 204)",
83
+ note: "NIST Category 3 — default for general commercial use.",
84
+ },
85
+ "category-5": {
86
+ kem: "ML-KEM-1024 (FIPS 203)",
87
+ signature: "ML-DSA-87 (FIPS 204)",
88
+ note: "NIST Category 5 — CNSA 2.0 for national-security systems and long-lived secrets (2030/2033 milestones).",
89
+ },
90
+ };
91
+ /**
92
+ * Tier-aware remediation. Returns the base family remediation plus the
93
+ * parameter sets for the requested CNSA tier. Category 5 surfaces the
94
+ * ML-KEM-1024 / ML-DSA-87 sets mandated by CNSA 2.0; category 3 is the
95
+ * commercial default.
96
+ */
97
+ export function remediationForTier(algorithm, tier = "category-3") {
98
+ const base = REMEDIATIONS[algorithm];
99
+ const params = TIER_PARAMS[tier];
100
+ // Confidentiality families lean on the KEM; signature families on the signer.
101
+ const isConfidentiality = algorithm === "RSA" ||
102
+ algorithm === "ECDH" ||
103
+ algorithm === "DH" ||
104
+ algorithm === "X25519" ||
105
+ algorithm === "X448" ||
106
+ algorithm === "ECIES";
107
+ const primary = isConfidentiality ? params.kem : params.signature;
108
+ return {
109
+ algorithm,
110
+ recommendation: `${base.recommendation} — ${tier}: ${primary}`,
111
+ detail: `${base.detail} ${params.note} For this tier use ${params.kem} (KEM) and ${params.signature} (signatures).`,
112
+ };
113
+ }
114
+ /**
115
+ * Guidance for stateful hash-based signatures (SP 800-208: LMS / XMSS / HSS).
116
+ * These are NIST-approved for firmware / boot signing but are STATEFUL — each
117
+ * private key may sign a bounded number of messages and the state MUST be
118
+ * managed to avoid catastrophic key reuse. Surfaced where a long-lived,
119
+ * low-volume signing root is appropriate.
120
+ */
121
+ export const STATEFUL_HBS_NOTE = "For firmware / secure-boot signing, the stateful hash-based signatures " +
122
+ "LMS, XMSS and HSS (NIST SP 800-208) are approved alternatives to ML-DSA, " +
123
+ "but they are STATEFUL: the signer must never reuse a one-time key index. " +
124
+ "Use only with rigorous state management; otherwise prefer stateless ML-DSA " +
125
+ "(FIPS 204) or SLH-DSA (FIPS 205).";
126
+ /** True when stateful HBS (SP 800-208) is a reasonable alternative for a family. */
127
+ export function statefulHbsApplies(algorithm) {
128
+ // Signature families only — LMS/XMSS are signatures, not KEMs.
129
+ return (algorithm === "RSA" || algorithm === "ECDSA" || algorithm === "EdDSA" || algorithm === "DSA");
130
+ }
131
+ //# sourceMappingURL=remediation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remediation.js","sourceRoot":"","sources":["../src/remediation.ts"],"names":[],"mappings":"AAQA,8DAA8D;AAC9D,MAAM,YAAY,GAAyC;IACzD,GAAG,EAAE;QACH,SAAS,EAAE,KAAK;QAChB,cAAc,EAAE,yDAAyD;QACzE,MAAM,EACJ,4EAA4E;YAC5E,2EAA2E;YAC3E,gEAAgE;KACnE;IACD,IAAI,EAAE;QACJ,SAAS,EAAE,MAAM;QACjB,cAAc,EAAE,oCAAoC;QACpD,MAAM,EACJ,6EAA6E;YAC7E,gFAAgF;YAChF,2DAA2D;KAC9D;IACD,KAAK,EAAE;QACL,SAAS,EAAE,OAAO;QAClB,cAAc,EAAE,sBAAsB;QACtC,MAAM,EACJ,6EAA6E;YAC7E,8EAA8E;YAC9E,wBAAwB;KAC3B;IACD,KAAK,EAAE;QACL,SAAS,EAAE,OAAO;QAClB,cAAc,EAAE,sBAAsB;QACtC,MAAM,EACJ,+EAA+E;YAC/E,iFAAiF;KACpF;IACD,EAAE,EAAE;QACF,SAAS,EAAE,IAAI;QACf,cAAc,EAAE,oCAAoC;QACpD,MAAM,EACJ,2EAA2E;YAC3E,6EAA6E;KAChF;IACD,GAAG,EAAE;QACH,SAAS,EAAE,KAAK;QAChB,cAAc,EAAE,sBAAsB;QACtC,MAAM,EACJ,gFAAgF;YAChF,0DAA0D;KAC7D;IACD,MAAM,EAAE;QACN,SAAS,EAAE,QAAQ;QACnB,cAAc,EAAE,oCAAoC;QACpD,MAAM,EACJ,gFAAgF;YAChF,gFAAgF;YAChF,+CAA+C;KAClD;IACD,IAAI,EAAE;QACJ,SAAS,EAAE,MAAM;QACjB,cAAc,EAAE,oCAAoC;QACpD,MAAM,EACJ,6EAA6E;YAC7E,+EAA+E;YAC/E,6EAA6E;KAChF;IACD,KAAK,EAAE;QACL,SAAS,EAAE,OAAO;QAClB,cAAc,EAAE,8BAA8B;QAC9C,MAAM,EACJ,6EAA6E;YAC7E,8EAA8E;YAC9E,sCAAsC;KACzC;IACD,OAAO,EAAE;QACP,SAAS,EAAE,SAAS;QACpB,cAAc,EAAE,mCAAmC;QACnD,MAAM,EACJ,6EAA6E;YAC7E,yEAAyE;KAC5E;CACF,CAAC;AAEF,kFAAkF;AAClF,MAAM,UAAU,cAAc,CAAC,SAA0B;IACvD,OAAO,YAAY,CAAC,SAAS,CAAC,CAAC;AACjC,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,eAAe,CAAC,SAA0B;IACxD,OAAO,YAAY,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC;AAChD,CAAC;AAcD,+CAA+C;AAC/C,MAAM,CAAC,MAAM,WAAW,GAA2E;IACjG,YAAY,EAAE;QACZ,GAAG,EAAE,uBAAuB;QAC5B,SAAS,EAAE,sBAAsB;QACjC,IAAI,EAAE,uDAAuD;KAC9D;IACD,YAAY,EAAE;QACZ,GAAG,EAAE,wBAAwB;QAC7B,SAAS,EAAE,sBAAsB;QACjC,IAAI,EAAE,yGAAyG;KAChH;CACF,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAChC,SAA0B,EAC1B,OAAqB,YAAY;IAEjC,MAAM,IAAI,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACjC,8EAA8E;IAC9E,MAAM,iBAAiB,GACrB,SAAS,KAAK,KAAK;QACnB,SAAS,KAAK,MAAM;QACpB,SAAS,KAAK,IAAI;QAClB,SAAS,KAAK,QAAQ;QACtB,SAAS,KAAK,MAAM;QACpB,SAAS,KAAK,OAAO,CAAC;IACxB,MAAM,OAAO,GAAG,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC;IAClE,OAAO;QACL,SAAS;QACT,cAAc,EAAE,GAAG,IAAI,CAAC,cAAc,MAAM,IAAI,KAAK,OAAO,EAAE;QAC9D,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,sBAAsB,MAAM,CAAC,GAAG,cAAc,MAAM,CAAC,SAAS,gBAAgB;KACpH,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAC5B,yEAAyE;IACzE,2EAA2E;IAC3E,2EAA2E;IAC3E,6EAA6E;IAC7E,mCAAmC,CAAC;AAEtC,oFAAoF;AACpF,MAAM,UAAU,kBAAkB,CAAC,SAA0B;IAC3D,+DAA+D;IAC/D,OAAO,CACL,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,OAAO,IAAI,SAAS,KAAK,OAAO,IAAI,SAAS,KAAK,KAAK,CAC7F,CAAC;AACJ,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Reporters: turn a {@link ScanResult} into SARIF 2.1.0, a clean JSON object,
3
+ * or a human-readable text summary. No third-party dependencies — ANSI colour
4
+ * is emitted with raw escape codes and is off by default.
5
+ */
6
+ import type { ScanResult } from "./types.js";
7
+ /** Minimal SARIF 2.1.0 log shape (kept permissive on purpose). */
8
+ export interface SarifLog {
9
+ $schema: string;
10
+ version: "2.1.0";
11
+ runs: unknown[];
12
+ }
13
+ /** Serialize a scan result as SARIF 2.1.0. */
14
+ export declare function toSarif(result: ScanResult): SarifLog;
15
+ /** Serialize a scan result as a plain JSON-friendly object. */
16
+ export declare function toJson(result: ScanResult): Record<string, unknown>;
17
+ /**
18
+ * Render a human-readable summary of a scan result. Colour is off by default;
19
+ * pass `{ color: true }` to emit ANSI escape codes.
20
+ */
21
+ export declare function formatSummary(result: ScanResult, options?: {
22
+ color?: boolean;
23
+ }): string;
24
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,UAAU,EAAY,MAAM,YAAY,CAAC;AAGvD,kEAAkE;AAClE,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,EAAE,CAAC;CACjB;AAoCD,8CAA8C;AAC9C,wBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,QAAQ,CA+GpD;AAkBD,+DAA+D;AAC/D,wBAAgB,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAkClE;AA2CD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CA8EvF"}
package/dist/report.js ADDED
@@ -0,0 +1,286 @@
1
+ import { VERSION } from "./version.js";
2
+ const SARIF_SCHEMA = "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json";
3
+ const INFORMATION_URI = "https://github.com/qproof-tools/qproof";
4
+ /** Map our severity to a SARIF result level. */
5
+ function sarifLevel(severity) {
6
+ switch (severity) {
7
+ case "critical":
8
+ case "high":
9
+ return "error";
10
+ case "medium":
11
+ return "warning";
12
+ default:
13
+ return "note";
14
+ }
15
+ }
16
+ /** Map our severity to a SARIF rule-level default (used in rules[].defaultConfiguration). */
17
+ function sarifRank(severity) {
18
+ switch (severity) {
19
+ case "critical":
20
+ return 100;
21
+ case "high":
22
+ return 80;
23
+ case "medium":
24
+ return 50;
25
+ case "low":
26
+ return 20;
27
+ default:
28
+ return 5;
29
+ }
30
+ }
31
+ /** Serialize a scan result as SARIF 2.1.0. */
32
+ export function toSarif(result) {
33
+ // Build the unique rule set (one rule per ruleId encountered) and collect the
34
+ // set of CWE taxa referenced by any rule.
35
+ const ruleIndex = new Map();
36
+ const rules = [];
37
+ const cweTaxa = new Set();
38
+ for (const f of result.findings) {
39
+ if (f.cwe)
40
+ cweTaxa.add(f.cwe);
41
+ if (ruleIndex.has(f.ruleId))
42
+ continue;
43
+ ruleIndex.set(f.ruleId, rules.length);
44
+ rules.push({
45
+ id: f.ruleId,
46
+ name: f.ruleId,
47
+ shortDescription: { text: f.title },
48
+ fullDescription: { text: f.message },
49
+ defaultConfiguration: { level: sarifLevel(f.severity), rank: sarifRank(f.severity) },
50
+ ...(f.remediation ? { help: { text: `Remediation: ${f.remediation}` } } : {}),
51
+ properties: {
52
+ category: f.category,
53
+ ...(f.algorithm ? { algorithm: f.algorithm } : {}),
54
+ hndl: f.hndl,
55
+ ...(f.cwe ? { cwe: f.cwe, "security-severity": securitySeverity(f.severity) } : {}),
56
+ ...(f.cwe ? { tags: ["security", f.cwe] } : {}),
57
+ },
58
+ ...(f.cwe
59
+ ? {
60
+ relationships: [
61
+ { target: { id: f.cwe, toolComponent: { name: "CWE" } }, kinds: ["relevant"] },
62
+ ],
63
+ }
64
+ : {}),
65
+ });
66
+ }
67
+ const results = result.findings.map((f) => {
68
+ const region = { startLine: f.location.line };
69
+ if (typeof f.location.column === "number")
70
+ region.startColumn = f.location.column;
71
+ if (typeof f.location.endLine === "number")
72
+ region.endLine = f.location.endLine;
73
+ return {
74
+ ruleId: f.ruleId,
75
+ ruleIndex: ruleIndex.get(f.ruleId),
76
+ level: sarifLevel(f.severity),
77
+ message: { text: f.message },
78
+ properties: {
79
+ category: f.category,
80
+ severity: f.severity,
81
+ confidence: f.confidence,
82
+ hndl: f.hndl,
83
+ ...(f.algorithm ? { algorithm: f.algorithm } : {}),
84
+ ...(f.remediation ? { remediation: f.remediation } : {}),
85
+ ...(f.cwe ? { cwe: f.cwe } : {}),
86
+ },
87
+ ...(f.cwe
88
+ ? {
89
+ taxa: [
90
+ {
91
+ target: { id: f.cwe, toolComponent: { name: "CWE" } },
92
+ },
93
+ ],
94
+ }
95
+ : {}),
96
+ locations: [
97
+ {
98
+ physicalLocation: {
99
+ artifactLocation: { uri: f.location.file },
100
+ region: {
101
+ ...region,
102
+ ...(f.location.snippet ? { snippet: { text: f.location.snippet } } : {}),
103
+ },
104
+ },
105
+ },
106
+ ],
107
+ };
108
+ });
109
+ // CWE taxonomy component (SARIF taxonomies), referenced by rules + results.
110
+ const taxonomies = cweTaxa.size > 0
111
+ ? [
112
+ {
113
+ name: "CWE",
114
+ informationUri: "https://cwe.mitre.org/",
115
+ organization: "MITRE",
116
+ shortDescription: { text: "The MITRE Common Weakness Enumeration" },
117
+ taxa: [...cweTaxa].sort().map((id) => ({
118
+ id,
119
+ helpUri: `https://cwe.mitre.org/data/definitions/${id.replace(/^CWE-/, "")}.html`,
120
+ })),
121
+ },
122
+ ]
123
+ : [];
124
+ return {
125
+ $schema: SARIF_SCHEMA,
126
+ version: "2.1.0",
127
+ runs: [
128
+ {
129
+ tool: {
130
+ driver: {
131
+ name: "qScan",
132
+ informationUri: INFORMATION_URI,
133
+ version: result.toolVersion || VERSION,
134
+ rules,
135
+ },
136
+ },
137
+ ...(taxonomies.length > 0 ? { taxonomies } : {}),
138
+ results,
139
+ },
140
+ ],
141
+ };
142
+ }
143
+ /** GitHub-code-scanning `security-severity` (0–10) derived from our severity. */
144
+ function securitySeverity(severity) {
145
+ switch (severity) {
146
+ case "critical":
147
+ return "9.5";
148
+ case "high":
149
+ return "8.0";
150
+ case "medium":
151
+ return "5.0";
152
+ case "low":
153
+ return "3.0";
154
+ default:
155
+ return "1.0";
156
+ }
157
+ }
158
+ /** Serialize a scan result as a plain JSON-friendly object. */
159
+ export function toJson(result) {
160
+ return {
161
+ toolVersion: result.toolVersion,
162
+ root: result.root,
163
+ startedAt: result.startedAt,
164
+ finishedAt: result.finishedAt,
165
+ filesScanned: result.filesScanned,
166
+ inventory: {
167
+ readinessScore: result.inventory.readinessScore,
168
+ hndlCount: result.inventory.hndlCount,
169
+ bySeverity: result.inventory.bySeverity,
170
+ byCategory: result.inventory.byCategory,
171
+ byAlgorithm: result.inventory.byAlgorithm,
172
+ },
173
+ findings: result.findings.map((f) => ({
174
+ ruleId: f.ruleId,
175
+ title: f.title,
176
+ category: f.category,
177
+ severity: f.severity,
178
+ confidence: f.confidence,
179
+ algorithm: f.algorithm,
180
+ hndl: f.hndl,
181
+ message: f.message,
182
+ remediation: f.remediation,
183
+ cwe: f.cwe,
184
+ location: {
185
+ file: f.location.file,
186
+ line: f.location.line,
187
+ column: f.location.column,
188
+ endLine: f.location.endLine,
189
+ snippet: f.location.snippet,
190
+ },
191
+ })),
192
+ };
193
+ }
194
+ /* -------------------------------------------------------------------------- */
195
+ /* Human-readable summary */
196
+ /* -------------------------------------------------------------------------- */
197
+ /** Raw ANSI codes (no chalk). Disabled when colour is off. */
198
+ const ANSI = {
199
+ reset: "\x1b[0m",
200
+ bold: "\x1b[1m",
201
+ dim: "\x1b[2m",
202
+ red: "\x1b[31m",
203
+ green: "\x1b[32m",
204
+ yellow: "\x1b[33m",
205
+ blue: "\x1b[34m",
206
+ magenta: "\x1b[35m",
207
+ cyan: "\x1b[36m",
208
+ };
209
+ /** Severity ordering for grouping / sorting, most → least severe. */
210
+ const SEVERITY_ORDER = ["critical", "high", "medium", "low", "info"];
211
+ function severityColor(sev) {
212
+ switch (sev) {
213
+ case "critical":
214
+ return ANSI.magenta;
215
+ case "high":
216
+ return ANSI.red;
217
+ case "medium":
218
+ return ANSI.yellow;
219
+ case "low":
220
+ return ANSI.blue;
221
+ default:
222
+ return ANSI.dim;
223
+ }
224
+ }
225
+ function scoreColor(score) {
226
+ if (score >= 80)
227
+ return ANSI.green;
228
+ if (score >= 50)
229
+ return ANSI.yellow;
230
+ return ANSI.red;
231
+ }
232
+ /**
233
+ * Render a human-readable summary of a scan result. Colour is off by default;
234
+ * pass `{ color: true }` to emit ANSI escape codes.
235
+ */
236
+ export function formatSummary(result, options) {
237
+ const color = options?.color ?? false;
238
+ const c = (code, text) => (color ? `${code}${text}${ANSI.reset}` : text);
239
+ const lines = [];
240
+ const inv = result.inventory;
241
+ lines.push(c(ANSI.bold, "qScan — post-quantum readiness report"));
242
+ lines.push(c(ANSI.dim, `tool v${result.toolVersion} · root: ${result.root}`));
243
+ lines.push("");
244
+ // Readiness score banner.
245
+ lines.push(`Readiness score: ${c(`${ANSI.bold}${scoreColor(inv.readinessScore)}`, `${inv.readinessScore}/100`)}`);
246
+ lines.push(`Files scanned: ${result.filesScanned} Findings: ${result.findings.length} HNDL-exposed: ${c(inv.hndlCount > 0 ? ANSI.red : ANSI.green, String(inv.hndlCount))}`);
247
+ lines.push("");
248
+ // Severity breakdown.
249
+ const sevParts = SEVERITY_ORDER.filter((s) => inv.bySeverity[s] > 0).map((s) => c(severityColor(s), `${s}: ${inv.bySeverity[s]}`));
250
+ lines.push(`By severity: ${sevParts.length ? sevParts.join(" ") : c(ANSI.green, "none")}`);
251
+ // Algorithm breakdown.
252
+ const algoParts = Object.entries(inv.byAlgorithm)
253
+ .sort((a, b) => b[1] - a[1])
254
+ .map(([k, v]) => `${k}: ${v}`);
255
+ if (algoParts.length)
256
+ lines.push(`By algorithm: ${algoParts.join(" ")}`);
257
+ lines.push("");
258
+ if (result.findings.length === 0) {
259
+ lines.push(c(ANSI.green, "No classical asymmetric cryptography detected. ✓"));
260
+ return lines.join("\n");
261
+ }
262
+ // Top findings, grouped by severity (most severe first), capped for readability.
263
+ const sorted = [...result.findings].sort((a, b) => SEVERITY_ORDER.indexOf(a.severity) - SEVERITY_ORDER.indexOf(b.severity));
264
+ const MAX_SHOWN = 25;
265
+ lines.push(c(ANSI.bold, `Top findings (${Math.min(MAX_SHOWN, sorted.length)} of ${sorted.length}):`));
266
+ for (const f of sorted.slice(0, MAX_SHOWN)) {
267
+ const loc = `${f.location.file}:${f.location.line}${f.location.column ? `:${f.location.column}` : ""}`;
268
+ const tag = c(severityColor(f.severity), `[${f.severity}]`);
269
+ const hndl = f.hndl ? c(ANSI.red, " (HNDL)") : "";
270
+ lines.push(` ${tag} ${f.title}${hndl}`);
271
+ lines.push(c(ANSI.dim, ` ${loc} — ${f.message}`));
272
+ if (f.remediation)
273
+ lines.push(c(ANSI.cyan, ` → ${f.remediation}`));
274
+ }
275
+ if (sorted.length > MAX_SHOWN) {
276
+ lines.push(c(ANSI.dim, ` …and ${sorted.length - MAX_SHOWN} more.`));
277
+ }
278
+ lines.push("");
279
+ if (inv.hndlCount > 0) {
280
+ lines.push(c(ANSI.yellow, `Note: ${inv.hndlCount} finding(s) are exposed to "harvest now, decrypt later" — ` +
281
+ "encrypted traffic captured today can be decrypted once a quantum computer exists. " +
282
+ "Prioritise migrating key exchange / encryption to hybrid PQC (X25519MLKEM768)."));
283
+ }
284
+ return lines.join("\n");
285
+ }
286
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=scan-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-worker.d.ts","sourceRoot":"","sources":["../src/scan-worker.ts"],"names":[],"mappings":""}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Worker-thread entry for {@link scanParallel}. Built to `dist/scan-worker.js`
3
+ * and spawned by `parallel.ts`. Each worker reads its assigned files and runs
4
+ * the SAME pure detector pipeline as the serial scan (`detectFile`), returning
5
+ * `{ findings, filesScanned }` per chunk. No shared mutable state.
6
+ *
7
+ * This file performs side effects (wires up message handlers) only when it is
8
+ * actually running inside a worker thread, so importing it from the main thread
9
+ * (e.g. for coverage) is harmless.
10
+ */
11
+ import { readFileSync } from "node:fs";
12
+ import * as path from "node:path";
13
+ import { parentPort, workerData } from "node:worker_threads";
14
+ import { defaultRegistry } from "./registry.js";
15
+ import { detectFile } from "./scan.js";
16
+ import { looksMinified } from "./walk.js";
17
+ import { isManifestFile } from "./dependencies.js";
18
+ if (parentPort) {
19
+ const data = (workerData ?? {});
20
+ const baseDir = data.baseDir;
21
+ const toggles = data.toggles;
22
+ const dets = defaultRegistry.all();
23
+ const port = parentPort;
24
+ port.on("message", (req) => {
25
+ try {
26
+ const findings = [];
27
+ let filesScanned = 0;
28
+ const scannedNames = [];
29
+ for (const rel of req.files) {
30
+ const abs = path.join(baseDir, ...rel.split("/"));
31
+ let content;
32
+ try {
33
+ content = readFileSync(abs, "utf8");
34
+ }
35
+ catch {
36
+ continue; // vanished / unreadable — skip.
37
+ }
38
+ if (!toggles.scanMinified && !isManifestFile(rel) && looksMinified(content)) {
39
+ continue;
40
+ }
41
+ filesScanned += 1;
42
+ scannedNames.push(rel);
43
+ findings.push(...detectFile(rel, content, dets, {
44
+ source: toggles.source,
45
+ config: toggles.config,
46
+ deps: toggles.deps,
47
+ }));
48
+ }
49
+ port.postMessage({
50
+ index: req.index,
51
+ files: scannedNames,
52
+ result: { findings, filesScanned },
53
+ });
54
+ }
55
+ catch (err) {
56
+ port.postMessage({
57
+ index: req.index,
58
+ error: err instanceof Error ? err.message : String(err),
59
+ });
60
+ }
61
+ });
62
+ }
63
+ //# sourceMappingURL=scan-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-worker.js","sourceRoot":"","sources":["../src/scan-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAG7D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAcnD,IAAI,UAAU,EAAE,CAAC;IACf,MAAM,IAAI,GAAG,CAAC,UAAU,IAAI,EAAE,CAAgD,CAAC;IAC/E,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAC7B,MAAM,IAAI,GAAG,eAAe,CAAC,GAAG,EAAE,CAAC;IACnC,MAAM,IAAI,GAAG,UAAU,CAAC;IAExB,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAiB,EAAE,EAAE;QACvC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAc,EAAE,CAAC;YAC/B,IAAI,YAAY,GAAG,CAAC,CAAC;YACrB,MAAM,YAAY,GAAa,EAAE,CAAC;YAElC,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;gBAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;gBAClD,IAAI,OAAe,CAAC;gBACpB,IAAI,CAAC;oBACH,OAAO,GAAG,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;gBACtC,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS,CAAC,gCAAgC;gBAC5C,CAAC;gBACD,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC5E,SAAS;gBACX,CAAC;gBACD,YAAY,IAAI,CAAC,CAAC;gBAClB,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACvB,QAAQ,CAAC,IAAI,CACX,GAAG,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE;oBAChC,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,IAAI,EAAE,OAAO,CAAC,IAAI;iBACnB,CAAC,CACH,CAAC;YACJ,CAAC;YAED,IAAI,CAAC,WAAW,CAAC;gBACf,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,KAAK,EAAE,YAAY;gBACnB,MAAM,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE;aACnC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,WAAW,CAAC;gBACf,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aACxD,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
package/dist/scan.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ import type { Detector, Finding, ScanOptions, ScanResult } from "./types.js";
2
+ /**
3
+ * The full set of built-in detectors exposed on the public API. The PEM
4
+ * detector applies to every text file; the source detectors apply only to
5
+ * JS/TS. The manifest scanner is handled separately (it parses JSON rather than
6
+ * running a Detector).
7
+ */
8
+ export declare const detectors: Detector[];
9
+ /** Stable comparator: by file, then line, then ruleId. Exported for reuse. */
10
+ export declare function compareFindings(a: Finding, b: Finding): number;
11
+ /**
12
+ * Run all applicable detectors + the manifest scanner over a single file's
13
+ * contents, honouring the source / config / dependencies toggles. Pure: no I/O.
14
+ * Exported so the parallel worker and unit tests can drive it directly.
15
+ */
16
+ export declare function detectFile(file: string, content: string, dets: readonly Detector[], toggles: {
17
+ source: boolean;
18
+ config: boolean;
19
+ deps: boolean;
20
+ }): Finding[];
21
+ /**
22
+ * Recursively scan a directory (or single file, or explicit file list) for
23
+ * classical asymmetric crypto. Honours the source / dependencies / config
24
+ * toggles (all default true) and reports progress through `options.onFile`.
25
+ */
26
+ export declare function scan(options: ScanOptions): Promise<ScanResult>;
27
+ //# sourceMappingURL=scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../src/scan.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAS7E;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE,QAAQ,EAAsC,CAAC;AAEvE,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,MAAM,CAI9D;AAOD;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,QAAQ,EAAE,EACzB,OAAO,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAC3D,OAAO,EAAE,CAeX;AAED;;;;GAIG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAyEpE"}