@quantakrypto/core 0.4.4 → 0.5.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 (284) hide show
  1. package/README.md +76 -27
  2. package/dist/cbom-merge.d.ts.map +1 -1
  3. package/dist/cbom-merge.js +30 -8
  4. package/dist/cbom-merge.js.map +1 -1
  5. package/dist/cbom.d.ts +5 -0
  6. package/dist/cbom.d.ts.map +1 -1
  7. package/dist/cbom.js +132 -37
  8. package/dist/cbom.js.map +1 -1
  9. package/dist/comments.d.ts +2 -23
  10. package/dist/comments.d.ts.map +1 -1
  11. package/dist/comments.js +24 -5
  12. package/dist/comments.js.map +1 -1
  13. package/dist/detect-utils.d.ts +55 -21
  14. package/dist/detect-utils.d.ts.map +1 -1
  15. package/dist/detect-utils.js +133 -7
  16. package/dist/detect-utils.js.map +1 -1
  17. package/dist/detectors/age.d.ts +16 -0
  18. package/dist/detectors/age.d.ts.map +1 -0
  19. package/dist/detectors/age.js +40 -0
  20. package/dist/detectors/age.js.map +1 -0
  21. package/dist/detectors/ansible.d.ts +13 -0
  22. package/dist/detectors/ansible.d.ts.map +1 -0
  23. package/dist/detectors/ansible.js +108 -0
  24. package/dist/detectors/ansible.js.map +1 -0
  25. package/dist/detectors/bicep.d.ts +20 -0
  26. package/dist/detectors/bicep.d.ts.map +1 -0
  27. package/dist/detectors/bicep.js +74 -0
  28. package/dist/detectors/bicep.js.map +1 -0
  29. package/dist/detectors/c.d.ts.map +1 -1
  30. package/dist/detectors/c.js +30 -3
  31. package/dist/detectors/c.js.map +1 -1
  32. package/dist/detectors/cicd.d.ts.map +1 -1
  33. package/dist/detectors/cicd.js +18 -5
  34. package/dist/detectors/cicd.js.map +1 -1
  35. package/dist/detectors/cloud-kms.d.ts +8 -5
  36. package/dist/detectors/cloud-kms.d.ts.map +1 -1
  37. package/dist/detectors/cloud-kms.js +62 -20
  38. package/dist/detectors/cloud-kms.js.map +1 -1
  39. package/dist/detectors/cloudformation.d.ts +8 -0
  40. package/dist/detectors/cloudformation.d.ts.map +1 -1
  41. package/dist/detectors/cloudformation.js +41 -10
  42. package/dist/detectors/cloudformation.js.map +1 -1
  43. package/dist/detectors/codesign.d.ts +50 -0
  44. package/dist/detectors/codesign.d.ts.map +1 -0
  45. package/dist/detectors/codesign.js +143 -0
  46. package/dist/detectors/codesign.js.map +1 -0
  47. package/dist/detectors/csharp.d.ts.map +1 -1
  48. package/dist/detectors/csharp.js +13 -3
  49. package/dist/detectors/csharp.js.map +1 -1
  50. package/dist/detectors/dart.d.ts +35 -0
  51. package/dist/detectors/dart.d.ts.map +1 -0
  52. package/dist/detectors/dart.js +177 -0
  53. package/dist/detectors/dart.js.map +1 -0
  54. package/dist/detectors/database.d.ts +5 -3
  55. package/dist/detectors/database.d.ts.map +1 -1
  56. package/dist/detectors/database.js +45 -8
  57. package/dist/detectors/database.js.map +1 -1
  58. package/dist/detectors/dkim.d.ts +54 -0
  59. package/dist/detectors/dkim.d.ts.map +1 -0
  60. package/dist/detectors/dkim.js +92 -0
  61. package/dist/detectors/dkim.js.map +1 -0
  62. package/dist/detectors/dnssec.d.ts.map +1 -1
  63. package/dist/detectors/dnssec.js +19 -10
  64. package/dist/detectors/dnssec.js.map +1 -1
  65. package/dist/detectors/elixir.d.ts.map +1 -1
  66. package/dist/detectors/elixir.js +34 -2
  67. package/dist/detectors/elixir.js.map +1 -1
  68. package/dist/detectors/java.d.ts.map +1 -1
  69. package/dist/detectors/java.js +33 -3
  70. package/dist/detectors/java.js.map +1 -1
  71. package/dist/detectors/jose.d.ts.map +1 -1
  72. package/dist/detectors/jose.js +13 -3
  73. package/dist/detectors/jose.js.map +1 -1
  74. package/dist/detectors/jwk.d.ts +7 -7
  75. package/dist/detectors/jwk.d.ts.map +1 -1
  76. package/dist/detectors/jwk.js +44 -8
  77. package/dist/detectors/jwk.js.map +1 -1
  78. package/dist/detectors/k8s.d.ts.map +1 -1
  79. package/dist/detectors/k8s.js +5 -2
  80. package/dist/detectors/k8s.js.map +1 -1
  81. package/dist/detectors/keystore.d.ts +19 -0
  82. package/dist/detectors/keystore.d.ts.map +1 -0
  83. package/dist/detectors/keystore.js +76 -0
  84. package/dist/detectors/keystore.js.map +1 -0
  85. package/dist/detectors/mesh.d.ts +7 -8
  86. package/dist/detectors/mesh.d.ts.map +1 -1
  87. package/dist/detectors/mesh.js +17 -35
  88. package/dist/detectors/mesh.js.map +1 -1
  89. package/dist/detectors/messaging.d.ts +2 -2
  90. package/dist/detectors/messaging.d.ts.map +1 -1
  91. package/dist/detectors/messaging.js +19 -12
  92. package/dist/detectors/messaging.js.map +1 -1
  93. package/dist/detectors/objc.d.ts +41 -0
  94. package/dist/detectors/objc.d.ts.map +1 -0
  95. package/dist/detectors/objc.js +146 -0
  96. package/dist/detectors/objc.js.map +1 -0
  97. package/dist/detectors/openpgp.d.ts +20 -0
  98. package/dist/detectors/openpgp.d.ts.map +1 -0
  99. package/dist/detectors/openpgp.js +151 -0
  100. package/dist/detectors/openpgp.js.map +1 -0
  101. package/dist/detectors/pem.d.ts.map +1 -1
  102. package/dist/detectors/pem.js +32 -0
  103. package/dist/detectors/pem.js.map +1 -1
  104. package/dist/detectors/php.d.ts +2 -1
  105. package/dist/detectors/php.d.ts.map +1 -1
  106. package/dist/detectors/php.js +7 -3
  107. package/dist/detectors/php.js.map +1 -1
  108. package/dist/detectors/pkcs11.d.ts +17 -0
  109. package/dist/detectors/pkcs11.d.ts.map +1 -0
  110. package/dist/detectors/pkcs11.js +87 -0
  111. package/dist/detectors/pkcs11.js.map +1 -0
  112. package/dist/detectors/proxy.d.ts +52 -0
  113. package/dist/detectors/proxy.d.ts.map +1 -0
  114. package/dist/detectors/proxy.js +157 -0
  115. package/dist/detectors/proxy.js.map +1 -0
  116. package/dist/detectors/pulumi.d.ts +19 -0
  117. package/dist/detectors/pulumi.d.ts.map +1 -0
  118. package/dist/detectors/pulumi.js +80 -0
  119. package/dist/detectors/pulumi.js.map +1 -0
  120. package/dist/detectors/rust.d.ts.map +1 -1
  121. package/dist/detectors/rust.js +5 -0
  122. package/dist/detectors/rust.js.map +1 -1
  123. package/dist/detectors/secrets.d.ts +4 -1
  124. package/dist/detectors/secrets.d.ts.map +1 -1
  125. package/dist/detectors/secrets.js +5 -21
  126. package/dist/detectors/secrets.js.map +1 -1
  127. package/dist/detectors/solidity.d.ts +50 -0
  128. package/dist/detectors/solidity.d.ts.map +1 -0
  129. package/dist/detectors/solidity.js +108 -0
  130. package/dist/detectors/solidity.js.map +1 -0
  131. package/dist/detectors/source.d.ts.map +1 -1
  132. package/dist/detectors/source.js +53 -6
  133. package/dist/detectors/source.js.map +1 -1
  134. package/dist/detectors/spire.d.ts +49 -0
  135. package/dist/detectors/spire.d.ts.map +1 -0
  136. package/dist/detectors/spire.js +77 -0
  137. package/dist/detectors/spire.js.map +1 -0
  138. package/dist/detectors/ssh-ca.d.ts +72 -0
  139. package/dist/detectors/ssh-ca.d.ts.map +1 -0
  140. package/dist/detectors/ssh-ca.js +119 -0
  141. package/dist/detectors/ssh-ca.js.map +1 -0
  142. package/dist/detectors/supply-chain.d.ts +17 -0
  143. package/dist/detectors/supply-chain.d.ts.map +1 -0
  144. package/dist/detectors/supply-chain.js +89 -0
  145. package/dist/detectors/supply-chain.js.map +1 -0
  146. package/dist/detectors/swift.d.ts +22 -0
  147. package/dist/detectors/swift.d.ts.map +1 -0
  148. package/dist/detectors/swift.js +120 -0
  149. package/dist/detectors/swift.js.map +1 -0
  150. package/dist/detectors/terraform.d.ts.map +1 -1
  151. package/dist/detectors/terraform.js +35 -8
  152. package/dist/detectors/terraform.js.map +1 -1
  153. package/dist/detectors/vault.d.ts +15 -0
  154. package/dist/detectors/vault.d.ts.map +1 -0
  155. package/dist/detectors/vault.js +97 -0
  156. package/dist/detectors/vault.js.map +1 -0
  157. package/dist/detectors/vpn.d.ts +8 -8
  158. package/dist/detectors/vpn.d.ts.map +1 -1
  159. package/dist/detectors/vpn.js +12 -38
  160. package/dist/detectors/vpn.js.map +1 -1
  161. package/dist/detectors/weak-hash.d.ts +71 -0
  162. package/dist/detectors/weak-hash.d.ts.map +1 -0
  163. package/dist/detectors/weak-hash.js +116 -0
  164. package/dist/detectors/weak-hash.js.map +1 -0
  165. package/dist/detectors/webauthn.d.ts +61 -0
  166. package/dist/detectors/webauthn.d.ts.map +1 -0
  167. package/dist/detectors/webauthn.js +109 -0
  168. package/dist/detectors/webauthn.js.map +1 -0
  169. package/dist/detectors/xmldsig.d.ts +23 -0
  170. package/dist/detectors/xmldsig.d.ts.map +1 -0
  171. package/dist/detectors/xmldsig.js +84 -0
  172. package/dist/detectors/xmldsig.js.map +1 -0
  173. package/dist/evidence.d.ts +74 -4
  174. package/dist/evidence.d.ts.map +1 -1
  175. package/dist/evidence.js +71 -0
  176. package/dist/evidence.js.map +1 -1
  177. package/dist/index.d.ts +14 -11
  178. package/dist/index.d.ts.map +1 -1
  179. package/dist/index.js +17 -11
  180. package/dist/index.js.map +1 -1
  181. package/dist/inventory.d.ts +0 -2
  182. package/dist/inventory.d.ts.map +1 -1
  183. package/dist/inventory.js +15 -6
  184. package/dist/inventory.js.map +1 -1
  185. package/dist/registry.d.ts +9 -4
  186. package/dist/registry.d.ts.map +1 -1
  187. package/dist/registry.js +51 -4
  188. package/dist/registry.js.map +1 -1
  189. package/dist/remediate-pipeline.d.ts +0 -3
  190. package/dist/remediate-pipeline.d.ts.map +1 -1
  191. package/dist/remediate-pipeline.js +1 -1
  192. package/dist/remediate-pipeline.js.map +1 -1
  193. package/dist/remediation.d.ts +10 -0
  194. package/dist/remediation.d.ts.map +1 -1
  195. package/dist/remediation.js +32 -0
  196. package/dist/remediation.js.map +1 -1
  197. package/dist/report.d.ts +9 -0
  198. package/dist/report.d.ts.map +1 -1
  199. package/dist/report.js +31 -1
  200. package/dist/report.js.map +1 -1
  201. package/dist/scan-worker.js +5 -3
  202. package/dist/scan-worker.js.map +1 -1
  203. package/dist/scan.d.ts.map +1 -1
  204. package/dist/scan.js +35 -6
  205. package/dist/scan.js.map +1 -1
  206. package/dist/standards-profiles.d.ts +58 -0
  207. package/dist/standards-profiles.d.ts.map +1 -0
  208. package/dist/standards-profiles.js +100 -0
  209. package/dist/standards-profiles.js.map +1 -0
  210. package/dist/types.d.ts +6 -5
  211. package/dist/types.d.ts.map +1 -1
  212. package/dist/types.js.map +1 -1
  213. package/dist/version.d.ts +1 -1
  214. package/dist/version.js +1 -1
  215. package/dist/version.js.map +1 -1
  216. package/dist/vex.d.ts +39 -0
  217. package/dist/vex.d.ts.map +1 -0
  218. package/dist/vex.js +87 -0
  219. package/dist/vex.js.map +1 -0
  220. package/dist/walk.d.ts +8 -3
  221. package/dist/walk.d.ts.map +1 -1
  222. package/dist/walk.js +32 -1
  223. package/dist/walk.js.map +1 -1
  224. package/package.json +1 -1
  225. package/src/cbom-merge.ts +38 -8
  226. package/src/cbom.ts +153 -39
  227. package/src/comments.ts +25 -6
  228. package/src/detect-utils.ts +133 -11
  229. package/src/detectors/age.ts +60 -0
  230. package/src/detectors/ansible.ts +140 -0
  231. package/src/detectors/bicep.ts +107 -0
  232. package/src/detectors/c.ts +31 -3
  233. package/src/detectors/cicd.ts +18 -5
  234. package/src/detectors/cloud-kms.ts +79 -25
  235. package/src/detectors/cloudformation.ts +45 -10
  236. package/src/detectors/codesign.ts +214 -0
  237. package/src/detectors/csharp.ts +13 -3
  238. package/src/detectors/dart.ts +237 -0
  239. package/src/detectors/database.ts +64 -11
  240. package/src/detectors/dkim.ts +172 -0
  241. package/src/detectors/dnssec.ts +19 -10
  242. package/src/detectors/elixir.ts +33 -2
  243. package/src/detectors/java.ts +37 -3
  244. package/src/detectors/jose.ts +19 -3
  245. package/src/detectors/jwk.ts +59 -17
  246. package/src/detectors/k8s.ts +5 -2
  247. package/src/detectors/keystore.ts +109 -0
  248. package/src/detectors/mesh.ts +21 -45
  249. package/src/detectors/messaging.ts +22 -14
  250. package/src/detectors/objc.ts +209 -0
  251. package/src/detectors/openpgp.ts +194 -0
  252. package/src/detectors/pem.ts +30 -0
  253. package/src/detectors/php.ts +9 -4
  254. package/src/detectors/pkcs11.ts +113 -0
  255. package/src/detectors/proxy.ts +236 -0
  256. package/src/detectors/pulumi.ts +106 -0
  257. package/src/detectors/rust.ts +5 -0
  258. package/src/detectors/secrets.ts +15 -26
  259. package/src/detectors/solidity.ts +176 -0
  260. package/src/detectors/source.ts +48 -5
  261. package/src/detectors/spire.ts +143 -0
  262. package/src/detectors/ssh-ca.ts +215 -0
  263. package/src/detectors/supply-chain.ts +117 -0
  264. package/src/detectors/swift.ts +149 -0
  265. package/src/detectors/terraform.ts +42 -8
  266. package/src/detectors/vault.ts +120 -0
  267. package/src/detectors/vpn.ts +20 -48
  268. package/src/detectors/weak-hash.ts +217 -0
  269. package/src/detectors/webauthn.ts +205 -0
  270. package/src/detectors/xmldsig.ts +115 -0
  271. package/src/evidence.ts +127 -4
  272. package/src/index.ts +41 -13
  273. package/src/inventory.ts +15 -7
  274. package/src/registry.ts +51 -4
  275. package/src/remediate-pipeline.ts +1 -1
  276. package/src/remediation.ts +39 -0
  277. package/src/report.ts +36 -1
  278. package/src/scan-worker.ts +5 -3
  279. package/src/scan.ts +41 -6
  280. package/src/standards-profiles.ts +136 -0
  281. package/src/types.ts +9 -4
  282. package/src/version.ts +1 -1
  283. package/src/vex.ts +122 -0
  284. package/src/walk.ts +33 -2
package/src/index.ts CHANGED
@@ -56,13 +56,14 @@ export type {
56
56
  // Scan cancellation / work-budget errors.
57
57
  export { AbortError, BudgetExceededError } from "./errors.js";
58
58
 
59
- // Parallel scanning (worker_threads pool) + pure merge/chunk helpers.
60
- export { scanParallel, mergeChunkResults, chunkByBytes } from "./parallel.js";
61
- export type { ScanChunk, ChunkResult, SizedFile } from "./parallel.js";
59
+ // Parallel scanning (worker_threads pool). The chunk/merge helpers and their
60
+ // SizedFile/ChunkResult types are internal plumbing (not part of the public API).
61
+ export { scanParallel } from "./parallel.js";
62
+ export type { ScanChunk } from "./parallel.js";
62
63
 
63
- // Detector registry (plugin point) + helpers + the rule catalog.
64
- export { DetectorRegistry, defaultRegistry, detectorScope } from "./registry.js";
65
- export type { RuleCatalogEntry } from "./registry.js";
64
+ // Detector registry (plugin point). `detectorScope` and the rule-catalog type are
65
+ // internal.
66
+ export { DetectorRegistry, defaultRegistry } from "./registry.js";
66
67
 
67
68
  // Canonical baseline (shared by qScan + the Action).
68
69
  export {
@@ -83,7 +84,7 @@ export { loadConfig, ConfigError, CONFIG_FILENAME } from "./config.js";
83
84
  export type { QuantakryptoFileConfig, LoadConfigResult } from "./config.js";
84
85
 
85
86
  // Filesystem walker (relative POSIX paths, default ignores, size/binary filters).
86
- export { walkFiles, isBinaryPath, isGeneratedPath, looksMinified } from "./walk.js";
87
+ export { walkFiles, isBinaryPath, looksMinified } from "./walk.js";
87
88
 
88
89
  // Analyzable-language coverage (which source languages the scanner inspects).
89
90
  export {
@@ -104,7 +105,13 @@ export { vulnerableDependencies, DEP_VULNERABLE_RULE, isManifestFile } from "./d
104
105
  export { SEVERITY_ORDER, severityRank, meetsThreshold, sarifLevel } from "./severity.js";
105
106
 
106
107
  // Reporters.
107
- export { toSarif, toJson, formatSummary, formatTierGuidance } from "./report.js";
108
+ export {
109
+ toSarif,
110
+ toJson,
111
+ formatSummary,
112
+ formatTierGuidance,
113
+ formatProfileGuidance,
114
+ } from "./report.js";
108
115
  export type { ReportOptions } from "./report.js";
109
116
 
110
117
  // CycloneDX 1.6 cryptographic bill of materials (CBOM) export.
@@ -112,18 +119,29 @@ export { toCbom } from "./cbom.js";
112
119
  export type { CycloneDxBom, CbomComponent } from "./cbom.js";
113
120
  // Merge multiple CBOMs (code + infra + live endpoints) into one combined BOM.
114
121
  export { mergeCboms } from "./cbom-merge.js";
122
+ // OpenVEX 0.2.0 export — quantum-readiness posture as VEX statements.
123
+ export { toOpenVex } from "./vex.js";
124
+ export type { OpenVexDocument, OpenVexStatement, OpenVexOptions } from "./vex.js";
115
125
  // ISO/IEC 27001 A.8.24 evidence-chain readiness report.
116
- export { buildReadinessReport } from "./evidence.js";
117
- export type { ReadinessReport, EvidenceFinding, ReadinessReportOptions } from "./evidence.js";
126
+ export { buildReadinessReport, signReadinessReport, verifyReadinessReport } from "./evidence.js";
127
+ export type {
128
+ ReadinessReport,
129
+ EvidenceFinding,
130
+ ReadinessReportOptions,
131
+ EvidenceSigner,
132
+ SignEvidenceOptions,
133
+ VerifyReadinessResult,
134
+ } from "./evidence.js";
118
135
 
119
136
  // Cryptography policy → per-finding verdicts (A.8.24 evidence §4).
120
- export { buildPolicyMapping, parseCryptoPolicy, verdictForAlgorithm } from "./policy.js";
137
+ export { buildPolicyMapping, parseCryptoPolicy } from "./policy.js";
121
138
  export type { CryptoPolicy, PolicyVerdict, PolicyMapping, PolicyFindingVerdict } from "./policy.js";
122
139
 
123
- // Remediation lookup (family + tier-aware) and stateful-HBS guidance.
140
+ // Remediation lookup (family + tier-aware + profile-aware) and stateful-HBS guidance.
124
141
  export {
125
142
  remediationFor,
126
143
  remediationForTier,
144
+ remediationForProfile,
127
145
  TIER_PARAMS,
128
146
  STATEFUL_HBS_NOTE,
129
147
  PQC_TRANSITION_NOTE,
@@ -132,9 +150,19 @@ export {
132
150
  export type { SecurityTier } from "./remediation.js";
133
151
 
134
152
  // Post-quantum standards source of truth + review cadence.
135
- export { PQC_STANDARDS, standardsReviewStatus } from "./standards.js";
153
+ export { PQC_STANDARDS } from "./standards.js";
136
154
  export type { PqcStandards, StandardsCitation, StandardsReviewStatus } from "./standards.js";
137
155
 
156
+ // Selectable standards regime profiles (NIST / CNSA / BSI / ANSSI / NCSC).
157
+ export {
158
+ STANDARDS_PROFILES,
159
+ DEFAULT_PROFILE_ID,
160
+ standardsProfileIds,
161
+ getStandardsProfile,
162
+ defaultStandardsProfile,
163
+ } from "./standards-profiles.js";
164
+ export type { StandardsProfile, HybridStance } from "./standards-profiles.js";
165
+
138
166
  // CWE identifier constants.
139
167
  export {
140
168
  CWE_BROKEN_CRYPTO,
package/src/inventory.ts CHANGED
@@ -48,7 +48,7 @@ const SCORE_SCALE = 100;
48
48
  const TEST_PATH_WEIGHT = 0.15;
49
49
 
50
50
  /** True when a finding's file path is test / fixture / example / documentation. */
51
- export function isTestOrFixturePath(file: string): boolean {
51
+ function isTestOrFixturePath(file: string): boolean {
52
52
  const f = file.toLowerCase().replace(/\\/g, "/");
53
53
  if (
54
54
  /(?:^|\/)(?:tests?|__tests__|testdata|test-data|fixtures?|examples?|demos?|samples?|specs?|mocks?|docs?|benchmarks?|e2e)\//.test(
@@ -75,20 +75,28 @@ export function isTestOrFixturePath(file: string): boolean {
75
75
  export function readinessScore(findings: Finding[]): number {
76
76
  if (findings.length === 0) return 100;
77
77
 
78
- const seen: Record<Severity, number> = {
78
+ // Diminishing-returns occurrence counters, kept SEPARATE for full-weight vs
79
+ // test-path findings. Sharing one counter per severity let whichever finding came
80
+ // first in the (path-sorted) list claim the `1/√1` slot, so a directory rename — or
81
+ // a test finding sorting ahead of a real one — changed the score. Bucketing makes
82
+ // the penalty independent of file order and of test/real interleaving.
83
+ const zero = (): Record<Severity, number> => ({
79
84
  critical: 0,
80
85
  high: 0,
81
86
  medium: 0,
82
87
  low: 0,
83
88
  info: 0,
84
- };
89
+ });
90
+ const seenReal = zero();
91
+ const seenTest = zero();
85
92
 
86
93
  let penalty = 0;
87
94
  for (const f of findings) {
88
- seen[f.severity] += 1;
89
- const weight =
90
- SEVERITY_WEIGHT[f.severity] * (isTestOrFixturePath(f.location.file) ? TEST_PATH_WEIGHT : 1);
91
- penalty += penaltyFor(weight, seen[f.severity]);
95
+ const isTest = isTestOrFixturePath(f.location.file);
96
+ const bucket = isTest ? seenTest : seenReal;
97
+ bucket[f.severity] += 1;
98
+ const weight = SEVERITY_WEIGHT[f.severity] * (isTest ? TEST_PATH_WEIGHT : 1);
99
+ penalty += penaltyFor(weight, bucket[f.severity]);
92
100
  }
93
101
 
94
102
  return Math.max(0, Math.min(100, Math.round(100 * Math.exp(-penalty / SCORE_SCALE))));
package/src/registry.ts CHANGED
@@ -21,6 +21,10 @@ import { rubyDetector } from "./detectors/ruby.js";
21
21
  import { phpDetector } from "./detectors/php.js";
22
22
  import { elixirDetector } from "./detectors/elixir.js";
23
23
  import { cDetector } from "./detectors/c.js";
24
+ import { swiftDetector } from "./detectors/swift.js";
25
+ import { objcDetector } from "./detectors/objc.js";
26
+ import { dartDetector } from "./detectors/dart.js";
27
+ import { solidityDetector } from "./detectors/solidity.js";
24
28
  import { pemDetector } from "./detectors/pem.js";
25
29
  import { jwkDetector } from "./detectors/jwk.js";
26
30
  import { terraformDetector } from "./detectors/terraform.js";
@@ -31,10 +35,27 @@ import { joseDetector } from "./detectors/jose.js";
31
35
  import { k8sDetector } from "./detectors/k8s.js";
32
36
  import { messagingDetector } from "./detectors/messaging.js";
33
37
  import { databaseDetector } from "./detectors/database.js";
38
+ import { xmldsigDetector } from "./detectors/xmldsig.js";
39
+ import { pkcs11Detector } from "./detectors/pkcs11.js";
40
+ import { dkimDetector } from "./detectors/dkim.js";
41
+ import { sshCaDetector } from "./detectors/ssh-ca.js";
42
+ import { spireDetector } from "./detectors/spire.js";
43
+ import { proxyDetector } from "./detectors/proxy.js";
44
+ import { webauthnDetector } from "./detectors/webauthn.js";
45
+ import { codesignDetector } from "./detectors/codesign.js";
46
+ import { weakHashDetector } from "./detectors/weak-hash.js";
34
47
  import { cloudformationDetector } from "./detectors/cloudformation.js";
48
+ import { bicepDetector } from "./detectors/bicep.js";
49
+ import { pulumiDetector } from "./detectors/pulumi.js";
35
50
  import { meshDetector } from "./detectors/mesh.js";
36
51
  import { dnssecDetector } from "./detectors/dnssec.js";
37
52
  import { vpnDetector } from "./detectors/vpn.js";
53
+ import { ansibleDetector } from "./detectors/ansible.js";
54
+ import { ageDetector } from "./detectors/age.js";
55
+ import { supplyChainDetector } from "./detectors/supply-chain.js";
56
+ import { vaultDetector } from "./detectors/vault.js";
57
+ import { keystoreDetector } from "./detectors/keystore.js";
58
+ import { openpgpDetector } from "./detectors/openpgp.js";
38
59
  import { statefulHbsDetector } from "./detectors/stateful-hbs.js";
39
60
 
40
61
  /** Normalised scope of a detector (defaults to "source" when undeclared). */
@@ -125,10 +146,15 @@ export class DetectorRegistry {
125
146
  }
126
147
 
127
148
  /**
128
- * The built-in detectors, in run order: the JS/TS source + config detectors,
129
- * then the per-language detectors (Python, Go, Java, C#, Rust, Ruby, C/C++),
130
- * then the language-agnostic PEM and stateful-HBS (SP 800-208) detectors. The
131
- * manifest (dependency) scanner is handled separately by `scan()`.
149
+ * The built-in detectors, in run order: the JS/TS source + language-agnostic config
150
+ * detectors, the per-language source packs (Python, Go, Java/Kotlin/Scala, C#, Rust,
151
+ * Ruby, PHP, Elixir, C/C++, Swift, Objective-C, Dart, Solidity/Move/Cairo), the
152
+ * infrastructure/config detectors (Terraform, Bicep, Pulumi, CloudFormation, cloud-KMS,
153
+ * k8s, mesh, DNSSEC, Vault, database/TDE, messaging, VPN, Ansible, supply-chain, CI/CD,
154
+ * secrets, age, keystore, OpenPGP, JWK, XML-DSig/SAML, PKCS#11/HSM, DKIM, SSH-CA,
155
+ * SPIFFE/SPIRE, reverse-proxy/gRPC TLS, WebAuthn/FIDO2, code-signing, weak-hash-in-
156
+ * signature), and the stateful-HBS (SP 800-208) detector. The manifest (dependency)
157
+ * scanner is handled separately by `scan()`.
132
158
  *
133
159
  * This is the single source of truth for the default detector set: both
134
160
  * {@link defaultRegistry} and the public `detectors` export (re-exported from
@@ -145,6 +171,10 @@ export const builtinDetectors: Detector[] = [
145
171
  phpDetector,
146
172
  elixirDetector,
147
173
  cDetector,
174
+ swiftDetector,
175
+ objcDetector,
176
+ dartDetector,
177
+ solidityDetector,
148
178
  pemDetector,
149
179
  jwkDetector,
150
180
  terraformDetector,
@@ -155,10 +185,27 @@ export const builtinDetectors: Detector[] = [
155
185
  k8sDetector,
156
186
  messagingDetector,
157
187
  databaseDetector,
188
+ xmldsigDetector,
189
+ pkcs11Detector,
190
+ dkimDetector,
191
+ sshCaDetector,
192
+ spireDetector,
193
+ proxyDetector,
194
+ webauthnDetector,
195
+ codesignDetector,
196
+ weakHashDetector,
158
197
  cloudformationDetector,
198
+ bicepDetector,
199
+ pulumiDetector,
159
200
  meshDetector,
160
201
  dnssecDetector,
161
202
  vpnDetector,
203
+ ansibleDetector,
204
+ ageDetector,
205
+ supplyChainDetector,
206
+ vaultDetector,
207
+ keystoreDetector,
208
+ openpgpDetector,
162
209
  statefulHbsDetector,
163
210
  ];
164
211
 
@@ -69,7 +69,7 @@ const NEW_SINK_LINE_RE = new RegExp(NEW_SINK_RE.source);
69
69
 
70
70
  /** Max changed lines allowed in an auto-verified LLM patch — a real crypto fix
71
71
  * is localized; a sprawling rewrite is not reviewable as "just the fix". */
72
- export const LLM_PATCH_MAX_CHANGED_LINES = 60;
72
+ const LLM_PATCH_MAX_CHANGED_LINES = 60;
73
73
 
74
74
  function countMatches(re: RegExp, s: string): number {
75
75
  return (s.match(re) ?? []).length;
@@ -6,6 +6,7 @@
6
6
  * standards to track are captured in {@link PQC_TRANSITION_NOTE}.
7
7
  */
8
8
  import type { AlgorithmFamily, Remediation } from "./types.js";
9
+ import type { StandardsProfile } from "./standards-profiles.js";
9
10
 
10
11
  /** Canonical remediation table, keyed by algorithm family. */
11
12
  const REMEDIATIONS: Record<AlgorithmFamily, Remediation> = {
@@ -188,6 +189,44 @@ export function remediationForTier(
188
189
  };
189
190
  }
190
191
 
192
+ /**
193
+ * Regime-aware remediation. Composes the base family guidance with a
194
+ * {@link StandardsProfile}'s parameter sets, HYBRID STANCE, and deprecation
195
+ * deadlines, so an ANSSI/BSI audience is told hybrid is *required* while a CNSA 2.0
196
+ * audience is told it is *optional* (and pointed at the 1024-level hybrid). This is
197
+ * the profile-driven successor to {@link remediationForTier}; `--tier category-5`
198
+ * resolves to the `cnsa-2.0` profile.
199
+ */
200
+ export function remediationForProfile(
201
+ algorithm: AlgorithmFamily,
202
+ profile: StandardsProfile,
203
+ ): Remediation {
204
+ const base = REMEDIATIONS[algorithm];
205
+ const isConf = isConfidentialityFamily(algorithm);
206
+ const primary = isConf ? profile.paramSets.kem : profile.paramSets.signature;
207
+ // The hybrid stance governs KEY ESTABLISHMENT, so it is surfaced for confidentiality
208
+ // families; signature families migrate to a stateless PQC signer directly.
209
+ const stanceWord =
210
+ profile.hybridStance === "required"
211
+ ? "hybrid required"
212
+ : profile.hybridStance === "recommended"
213
+ ? "hybrid recommended"
214
+ : "hybrids optional";
215
+ const recommendation = isConf
216
+ ? `${primary} — ${profile.name}: ${stanceWord}`
217
+ : `${primary} — ${profile.name}`;
218
+ const hybridClause = isConf ? ` ${profile.hybridGuidance}` : "";
219
+ return {
220
+ algorithm,
221
+ recommendation,
222
+ detail:
223
+ `${base.detail} Under ${profile.name} (${profile.citation}), use ${profile.paramSets.kem} for ` +
224
+ `key establishment and ${profile.paramSets.signature} for signatures; classical public-key ` +
225
+ `crypto is deprecated after ${profile.deprecateAfter} and disallowed after ${profile.disallowAfter}.` +
226
+ hybridClause,
227
+ };
228
+ }
229
+
191
230
  /**
192
231
  * Guidance for stateful hash-based signatures (SP 800-208: LMS / XMSS / HSS).
193
232
  * These are NIST-approved for firmware / boot signing but are STATEFUL — each
package/src/report.ts CHANGED
@@ -7,8 +7,9 @@ import type { AlgorithmFamily, Finding, RuleMeta, ScanResult, Severity } from ".
7
7
  import { VERSION } from "./version.js";
8
8
  import { SEVERITY_ORDER, sarifLevel } from "./severity.js";
9
9
  import { ANALYZABLE_LANGUAGES_LABEL } from "./detect-utils.js";
10
- import { remediationFor, remediationForTier } from "./remediation.js";
10
+ import { remediationFor, remediationForTier, remediationForProfile } from "./remediation.js";
11
11
  import type { SecurityTier } from "./remediation.js";
12
+ import type { StandardsProfile } from "./standards-profiles.js";
12
13
  import { fingerprintFinding } from "./baseline.js";
13
14
 
14
15
  /** Minimal SARIF 2.1.0 log shape (kept permissive on purpose). */
@@ -475,3 +476,37 @@ export function formatTierGuidance(
475
476
  }
476
477
  return out;
477
478
  }
479
+
480
+ /**
481
+ * Per-family migration targets tailored to a selected {@link StandardsProfile}
482
+ * (`--profile`). Unlike {@link formatTierGuidance} (CNSA-tier only), this surfaces the
483
+ * regime's parameter sets AND its hybrid stance — required (ANSSI/BSI) vs recommended
484
+ * (NIST/NCSC) vs optional (CNSA 2.0) — so guidance isn't regime-wrong. Returns plain
485
+ * (un-coloured) lines; the caller styles them.
486
+ */
487
+ export function formatProfileGuidance(
488
+ byAlgorithm: Record<string, number>,
489
+ profile: StandardsProfile,
490
+ ): string[] {
491
+ const out: string[] = [`${profile.name} migration targets:`];
492
+ const seen = new Set<string>();
493
+ for (const [k, n] of Object.entries(byAlgorithm)) {
494
+ if (n <= 0) continue;
495
+ const fam = k as AlgorithmFamily;
496
+ if (fam === "unknown" || !remediationFor(fam)) continue; // skip unmapped families
497
+ const rem = remediationForProfile(fam, profile);
498
+ if (seen.has(rem.recommendation)) continue;
499
+ seen.add(rem.recommendation);
500
+ out.push(` ${fam} → ${rem.recommendation}`);
501
+ }
502
+ const stance =
503
+ profile.hybridStance === "required"
504
+ ? "requires classical+PQC hybridization"
505
+ : profile.hybridStance === "recommended"
506
+ ? "recommends hybridization"
507
+ : "does not require hybridization";
508
+ out.push(
509
+ ` ${profile.authority} ${stance}; classical public-key crypto disallowed after ${profile.disallowAfter} (${profile.citation}).`,
510
+ );
511
+ return out;
512
+ }
@@ -15,7 +15,7 @@ import { parentPort, workerData } from "node:worker_threads";
15
15
  import type { Finding } from "./types.js";
16
16
  import { defaultRegistry } from "./registry.js";
17
17
  import { detectFile } from "./scan.js";
18
- import { looksMinified } from "./walk.js";
18
+ import { isKeystorePath, looksMinified } from "./walk.js";
19
19
  import { isManifestFile } from "./dependencies.js";
20
20
 
21
21
  interface WorkerToggles {
@@ -48,14 +48,16 @@ if (parentPort) {
48
48
 
49
49
  for (const rel of req.files) {
50
50
  const abs = path.join(baseDir, ...rel.split("/"));
51
+ // Keystores (.jks/.p12/…) are read byte-preserving (latin1); see scan.ts.
52
+ const keystore = isKeystorePath(rel);
51
53
  let content: string;
52
54
  try {
53
- content = readFileSync(abs, "utf8");
55
+ content = readFileSync(abs, keystore ? "latin1" : "utf8");
54
56
  } catch {
55
57
  unreadable += 1;
56
58
  continue;
57
59
  }
58
- if (!toggles.scanMinified && !isManifestFile(rel) && looksMinified(content)) {
60
+ if (!toggles.scanMinified && !isManifestFile(rel) && !keystore && looksMinified(content)) {
59
61
  skippedMinified += 1;
60
62
  continue;
61
63
  }
package/src/scan.ts CHANGED
@@ -13,7 +13,15 @@ import { readFile, stat } from "node:fs/promises";
13
13
  import * as path from "node:path";
14
14
 
15
15
  import type { Detector, Finding, ScanOptions, ScanResult } from "./types.js";
16
- import { walkFiles, toPosix, isBinaryPath, looksMinified, matchesAny } from "./walk.js";
16
+ import {
17
+ walkFiles,
18
+ toPosix,
19
+ isBinaryPath,
20
+ isKeystorePath,
21
+ looksMinified,
22
+ matchesAny,
23
+ DEFAULT_MAX_FILE_SIZE,
24
+ } from "./walk.js";
17
25
  import { isAnalyzableSource } from "./detect-utils.js";
18
26
  import {
19
27
  stripCommentFindings,
@@ -26,7 +34,16 @@ import {
26
34
  * A match inside a string (e.g. `t.Error("SigningMethodPS256 …")`) is prose and
27
35
  * is dropped. Rules that legitimately match quoted tokens are NOT listed here.
28
36
  */
29
- const CODE_ONLY_RULES: ReadonlySet<string> = new Set(["go-jwt-signingmethod"]);
37
+ const CODE_ONLY_RULES: ReadonlySet<string> = new Set([
38
+ "go-jwt-signingmethod",
39
+ // Identifier-form JWT alg constants (jjwt `SignatureAlgorithm.RS256`, auth0
40
+ // `Algorithm.RSA256`, C# `SecurityAlgorithms.*`, Rust `Algorithm::RS256`). Like the
41
+ // Go rule, these are only meaningful as code; the SAME token inside a string literal
42
+ // (an error message that names/forbids the alg) is prose, not a usage.
43
+ "java-jwt-alg",
44
+ "csharp-jwt-alg",
45
+ "rust-jwt-algorithm",
46
+ ]);
30
47
  import { hashContent, loadCache, rulesetFingerprint, saveCache } from "./cache.js";
31
48
  import type { CacheEntry } from "./cache.js";
32
49
  import { builtinDetectors, defaultRegistry, detectorScope } from "./registry.js";
@@ -169,23 +186,41 @@ export async function scan(options: ScanOptions): Promise<ScanResult> {
169
186
 
170
187
  options.onFile?.(reportedPath);
171
188
 
189
+ // Cryptographic keystores (.jks/.p12/…) are binary; read them byte-preserving
190
+ // (latin1) so the keystore detector can inspect magic bytes.
191
+ const keystore = isKeystorePath(reportedPath);
192
+ // Keystores are read whole into memory as latin1. The walker already caps file
193
+ // size, but the explicit-file-list (incremental) path does not — so stat and
194
+ // skip an oversized binary here to avoid reading a huge encrypted archive
195
+ // (`.gpg`) into a string.
196
+ if (keystore) {
197
+ try {
198
+ const { size } = await stat(absPath);
199
+ if (size > (options.maxFileSize ?? DEFAULT_MAX_FILE_SIZE)) continue;
200
+ } catch {
201
+ unreadable += 1;
202
+ continue;
203
+ }
204
+ }
172
205
  let content: string;
173
206
  try {
174
- content = await readFile(absPath, "utf8");
207
+ content = await readFile(absPath, keystore ? "latin1" : "utf8");
175
208
  } catch {
176
209
  unreadable += 1; // permissions / vanished / decode failure — tracked, not silent.
177
210
  continue;
178
211
  }
179
212
 
180
213
  // Skip machine-minified / generated content (unless explicitly enabled).
181
- // Manifests are always scanned (their findings are dependency findings).
182
- if (!scanMinified && !isManifestFile(reportedPath) && looksMinified(content)) {
214
+ // Manifests and keystores are always scanned.
215
+ if (!scanMinified && !isManifestFile(reportedPath) && !keystore && looksMinified(content)) {
183
216
  skippedMinified += 1;
184
217
  continue;
185
218
  }
186
219
 
187
220
  // Cumulative-byte budget: enforced once this file's bytes are accounted for.
188
- bytesScanned += Buffer.byteLength(content, "utf8");
221
+ // Use the read encoding so a latin1 keystore is counted at its on-disk size
222
+ // (a utf8 byteLength would double-count every byte ≥ 0x80).
223
+ bytesScanned += Buffer.byteLength(content, keystore ? "latin1" : "utf8");
189
224
  if (typeof maxBytes === "number" && bytesScanned > maxBytes) {
190
225
  throw new BudgetExceededError(`maxBytes budget exceeded (limit: ${maxBytes}).`);
191
226
  }
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Selectable STANDARDS PROFILES — the regime a scan's remediation, deadlines, and
3
+ * hybrid guidance are tailored to. Different national/regional authorities agree on
4
+ * the PQC primitives (ML-KEM / ML-DSA) but diverge on two things this tool must not
5
+ * hardcode: (a) the required PARAMETER SETS (a commercial ML-KEM-768 vs a
6
+ * national-security ML-KEM-1024), and (b) the HYBRID STANCE — whether classical+PQC
7
+ * hybridization is required, recommended, or optional during the transition. Baking
8
+ * in NIST/CNSA's "hybrids optional" is wrong for an ANSSI or BSI audience, where
9
+ * hybrid is required. `--profile <id>` selects the regime; `--policy` composes an
10
+ * org's own exceptions on top.
11
+ *
12
+ * Like {@link PqcStandards}, every profile carries a citation + `asOf` date and is
13
+ * re-verified on the quarterly standards cadence. These are guidance summaries, not
14
+ * legal advice — consult the cited source of record.
15
+ */
16
+
17
+ /** Whether classical+PQC hybridization is required during the transition, per regime. */
18
+ export type HybridStance = "required" | "recommended" | "optional";
19
+
20
+ /** A regime's PQC guidance profile. */
21
+ export interface StandardsProfile {
22
+ /** Stable id used by `--profile` (kebab-case). */
23
+ readonly id: string;
24
+ /** Human-readable name. */
25
+ readonly name: string;
26
+ /** The authority / document of record. */
27
+ readonly authority: string;
28
+ /** The KEM / signature parameter sets this regime calls for. */
29
+ readonly paramSets: { readonly kem: string; readonly signature: string };
30
+ /** Whether hybridization is required / recommended / optional under this regime. */
31
+ readonly hybridStance: HybridStance;
32
+ /** One-line regime-specific hybrid guidance surfaced in remediation. */
33
+ readonly hybridGuidance: string;
34
+ /** Year after which classical public-key crypto is deprecated under this regime. */
35
+ readonly deprecateAfter: number;
36
+ /** Year after which it is disallowed. */
37
+ readonly disallowAfter: number;
38
+ /** Spec identifier / publication of record. */
39
+ readonly citation: string;
40
+ /** `YYYY-MM` — when this profile was last verified against its source. */
41
+ readonly asOf: string;
42
+ }
43
+
44
+ /** The default profile id when `--profile` is not given. */
45
+ export const DEFAULT_PROFILE_ID = "nist";
46
+
47
+ /**
48
+ * Built-in regime profiles. Facts reflect each authority's published PQC-transition
49
+ * position as of the `asOf` date; verify against the cited source before relying on a
50
+ * deadline or a hybrid mandate for a compliance decision.
51
+ */
52
+ export const STANDARDS_PROFILES: Readonly<Record<string, StandardsProfile>> = {
53
+ nist: {
54
+ id: "nist",
55
+ name: "NIST (general / commercial)",
56
+ authority: "NIST",
57
+ paramSets: { kem: "ML-KEM-768 (FIPS 203)", signature: "ML-DSA-65 (FIPS 204)" },
58
+ hybridStance: "recommended",
59
+ hybridGuidance:
60
+ "Hybrid key establishment (e.g. X25519MLKEM768) is permitted and recommended during the transition; pure ML-KEM is also acceptable (SP 800-227 / IR 8547).",
61
+ deprecateAfter: 2030,
62
+ disallowAfter: 2035,
63
+ citation: "NIST IR 8547 + FIPS 203/204/205",
64
+ asOf: "2026-07",
65
+ },
66
+ "cnsa-2.0": {
67
+ id: "cnsa-2.0",
68
+ name: "NSA CNSA 2.0 (national-security systems)",
69
+ authority: "NSA",
70
+ paramSets: { kem: "ML-KEM-1024 (FIPS 203)", signature: "ML-DSA-87 (FIPS 204)" },
71
+ hybridStance: "optional",
72
+ hybridGuidance:
73
+ "CNSA 2.0 targets pure PQC and does not require hybrids; if a hybrid TLS group is used, it must be SecP384r1MLKEM1024 — X25519MLKEM768's ML-KEM-768 component is sub-CNSA.",
74
+ deprecateAfter: 2030,
75
+ disallowAfter: 2035,
76
+ citation: "NSA CNSA 2.0 (2030/2033/2035 migration milestones)",
77
+ asOf: "2026-07",
78
+ },
79
+ "bsi-tr-02102": {
80
+ id: "bsi-tr-02102",
81
+ name: "BSI TR-02102 (Germany)",
82
+ authority: "BSI",
83
+ paramSets: { kem: "ML-KEM-768 (FIPS 203)", signature: "ML-DSA-65 (FIPS 204)" },
84
+ hybridStance: "required",
85
+ hybridGuidance:
86
+ "BSI requires PQC be deployed in HYBRID with an established classical scheme during the transition (defense-in-depth); FrodoKEM is the conservative KEM alternative to ML-KEM, and XMSS/LMS are approved for firmware signing.",
87
+ deprecateAfter: 2030,
88
+ disallowAfter: 2035,
89
+ citation: "BSI TR-02102-1 (Kryptographische Verfahren)",
90
+ asOf: "2026-07",
91
+ },
92
+ anssi: {
93
+ id: "anssi",
94
+ name: "ANSSI (France)",
95
+ authority: "ANSSI",
96
+ paramSets: { kem: "ML-KEM-1024 (FIPS 203)", signature: "ML-DSA-87 (FIPS 204)" },
97
+ hybridStance: "required",
98
+ hybridGuidance:
99
+ "ANSSI requires HYBRIDIZATION (classical + PQC) throughout the transition phase and does not endorse pure PQC alone yet; use the highest parameter set for long-lived assurance.",
100
+ deprecateAfter: 2030,
101
+ disallowAfter: 2035,
102
+ citation: "ANSSI — PQC transition position papers",
103
+ asOf: "2026-07",
104
+ },
105
+ "uk-ncsc": {
106
+ id: "uk-ncsc",
107
+ name: "UK NCSC",
108
+ authority: "NCSC",
109
+ paramSets: { kem: "ML-KEM-768 (FIPS 203)", signature: "ML-DSA-65 (FIPS 204)" },
110
+ hybridStance: "recommended",
111
+ hybridGuidance:
112
+ "NCSC recommends ML-KEM / ML-DSA and is broadly agnostic on hybridization (recommended, not mandated); its migration milestones are earlier — discovery/plan by 2028, high-priority migration by 2031, complete by 2035.",
113
+ deprecateAfter: 2031,
114
+ disallowAfter: 2035,
115
+ citation: "NCSC — Preparing for quantum-safe cryptography / PQC migration timeline",
116
+ asOf: "2026-07",
117
+ },
118
+ };
119
+
120
+ /** All built-in profile ids, in a stable order (default first). */
121
+ export function standardsProfileIds(): string[] {
122
+ return [
123
+ DEFAULT_PROFILE_ID,
124
+ ...Object.keys(STANDARDS_PROFILES).filter((id) => id !== DEFAULT_PROFILE_ID),
125
+ ];
126
+ }
127
+
128
+ /** Look up a built-in profile by id, or `undefined` when unknown. */
129
+ export function getStandardsProfile(id: string): StandardsProfile | undefined {
130
+ return STANDARDS_PROFILES[id];
131
+ }
132
+
133
+ /** The default profile (NIST). Always defined. */
134
+ export function defaultStandardsProfile(): StandardsProfile {
135
+ return STANDARDS_PROFILES[DEFAULT_PROFILE_ID];
136
+ }
package/src/types.ts CHANGED
@@ -137,6 +137,10 @@ export type DetectorLanguage =
137
137
  | "php"
138
138
  | "elixir"
139
139
  | "c"
140
+ | "swift"
141
+ | "objc"
142
+ | "dart"
143
+ | "solidity"
140
144
  | "any";
141
145
 
142
146
  /**
@@ -344,10 +348,11 @@ export interface ScanResult {
344
348
  */
345
349
  diagnostics?: ScanDiagnostics;
346
350
  /**
347
- * Of `filesScanned`, how many were in a source language the scanner can
348
- * actually analyze for inline crypto (JS/TS, Python, Go, Java). When this is 0 but
349
- * `filesScanned` > 0, the readiness score reflects NO analyzable code the
350
- * crypto likely lives in an unsupported language (Go, Java, Rust, …)and
351
+ * Of `filesScanned`, how many were in a source language the scanner can actually
352
+ * analyze for inline crypto (the 13 packs: JS/TS, Python, Go, Java/Kotlin/Scala,
353
+ * C#, Rust, Ruby, PHP, Elixir, C/C++, Swift, Objective-C, Dart). When this is 0
354
+ * but `filesScanned` > 0, the readiness score reflects NO analyzable codethe
355
+ * crypto likely lives in an unsupported language (Lua, Perl, …) — and
351
356
  * reporters surface that so a bare 100/100 can't read as "safe". Optional for
352
357
  * backward compatibility with hand-built results.
353
358
  */
package/src/version.ts CHANGED
@@ -3,4 +3,4 @@
3
3
  * the scan orchestrator can import it without creating a cycle through index.ts.
4
4
  * Keep in sync with packages/core/package.json.
5
5
  */
6
- export const VERSION = "0.4.4";
6
+ export const VERSION = "0.5.0";