@quantakrypto/core 0.4.3 → 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 (314) hide show
  1. package/README.md +76 -27
  2. package/dist/cbom-merge.d.ts +9 -0
  3. package/dist/cbom-merge.d.ts.map +1 -0
  4. package/dist/cbom-merge.js +121 -0
  5. package/dist/cbom-merge.js.map +1 -0
  6. package/dist/cbom.d.ts +5 -0
  7. package/dist/cbom.d.ts.map +1 -1
  8. package/dist/cbom.js +132 -37
  9. package/dist/cbom.js.map +1 -1
  10. package/dist/comments.d.ts +6 -26
  11. package/dist/comments.d.ts.map +1 -1
  12. package/dist/comments.js +77 -38
  13. package/dist/comments.js.map +1 -1
  14. package/dist/dependencies.d.ts.map +1 -1
  15. package/dist/dependencies.js +1 -1
  16. package/dist/dependencies.js.map +1 -1
  17. package/dist/detect-utils.d.ts +59 -21
  18. package/dist/detect-utils.d.ts.map +1 -1
  19. package/dist/detect-utils.js +143 -8
  20. package/dist/detect-utils.js.map +1 -1
  21. package/dist/detectors/age.d.ts +16 -0
  22. package/dist/detectors/age.d.ts.map +1 -0
  23. package/dist/detectors/age.js +40 -0
  24. package/dist/detectors/age.js.map +1 -0
  25. package/dist/detectors/ansible.d.ts +13 -0
  26. package/dist/detectors/ansible.d.ts.map +1 -0
  27. package/dist/detectors/ansible.js +108 -0
  28. package/dist/detectors/ansible.js.map +1 -0
  29. package/dist/detectors/bicep.d.ts +20 -0
  30. package/dist/detectors/bicep.d.ts.map +1 -0
  31. package/dist/detectors/bicep.js +74 -0
  32. package/dist/detectors/bicep.js.map +1 -0
  33. package/dist/detectors/c.d.ts +4 -2
  34. package/dist/detectors/c.d.ts.map +1 -1
  35. package/dist/detectors/c.js +222 -4
  36. package/dist/detectors/c.js.map +1 -1
  37. package/dist/detectors/cicd.d.ts +27 -0
  38. package/dist/detectors/cicd.d.ts.map +1 -0
  39. package/dist/detectors/cicd.js +129 -0
  40. package/dist/detectors/cicd.js.map +1 -0
  41. package/dist/detectors/cloud-kms.d.ts +24 -0
  42. package/dist/detectors/cloud-kms.d.ts.map +1 -0
  43. package/dist/detectors/cloud-kms.js +99 -0
  44. package/dist/detectors/cloud-kms.js.map +1 -0
  45. package/dist/detectors/cloudformation.d.ts +38 -0
  46. package/dist/detectors/cloudformation.d.ts.map +1 -0
  47. package/dist/detectors/cloudformation.js +201 -0
  48. package/dist/detectors/cloudformation.js.map +1 -0
  49. package/dist/detectors/codesign.d.ts +50 -0
  50. package/dist/detectors/codesign.d.ts.map +1 -0
  51. package/dist/detectors/codesign.js +143 -0
  52. package/dist/detectors/codesign.js.map +1 -0
  53. package/dist/detectors/csharp.d.ts.map +1 -1
  54. package/dist/detectors/csharp.js +13 -3
  55. package/dist/detectors/csharp.js.map +1 -1
  56. package/dist/detectors/dart.d.ts +35 -0
  57. package/dist/detectors/dart.d.ts.map +1 -0
  58. package/dist/detectors/dart.js +177 -0
  59. package/dist/detectors/dart.js.map +1 -0
  60. package/dist/detectors/database.d.ts +19 -0
  61. package/dist/detectors/database.d.ts.map +1 -0
  62. package/dist/detectors/database.js +97 -0
  63. package/dist/detectors/database.js.map +1 -0
  64. package/dist/detectors/dkim.d.ts +54 -0
  65. package/dist/detectors/dkim.d.ts.map +1 -0
  66. package/dist/detectors/dkim.js +92 -0
  67. package/dist/detectors/dkim.js.map +1 -0
  68. package/dist/detectors/dnssec.d.ts +55 -0
  69. package/dist/detectors/dnssec.d.ts.map +1 -0
  70. package/dist/detectors/dnssec.js +116 -0
  71. package/dist/detectors/dnssec.js.map +1 -0
  72. package/dist/detectors/elixir.d.ts +20 -0
  73. package/dist/detectors/elixir.d.ts.map +1 -0
  74. package/dist/detectors/elixir.js +227 -0
  75. package/dist/detectors/elixir.js.map +1 -0
  76. package/dist/detectors/java.d.ts.map +1 -1
  77. package/dist/detectors/java.js +34 -4
  78. package/dist/detectors/java.js.map +1 -1
  79. package/dist/detectors/jose.d.ts +20 -0
  80. package/dist/detectors/jose.d.ts.map +1 -0
  81. package/dist/detectors/jose.js +72 -0
  82. package/dist/detectors/jose.js.map +1 -0
  83. package/dist/detectors/jwk.d.ts +25 -0
  84. package/dist/detectors/jwk.d.ts.map +1 -0
  85. package/dist/detectors/jwk.js +131 -0
  86. package/dist/detectors/jwk.js.map +1 -0
  87. package/dist/detectors/k8s.d.ts +17 -0
  88. package/dist/detectors/k8s.d.ts.map +1 -0
  89. package/dist/detectors/k8s.js +88 -0
  90. package/dist/detectors/k8s.js.map +1 -0
  91. package/dist/detectors/keystore.d.ts +19 -0
  92. package/dist/detectors/keystore.d.ts.map +1 -0
  93. package/dist/detectors/keystore.js +76 -0
  94. package/dist/detectors/keystore.js.map +1 -0
  95. package/dist/detectors/mesh.d.ts +34 -0
  96. package/dist/detectors/mesh.d.ts.map +1 -0
  97. package/dist/detectors/mesh.js +91 -0
  98. package/dist/detectors/mesh.js.map +1 -0
  99. package/dist/detectors/messaging.d.ts +16 -0
  100. package/dist/detectors/messaging.d.ts.map +1 -0
  101. package/dist/detectors/messaging.js +79 -0
  102. package/dist/detectors/messaging.js.map +1 -0
  103. package/dist/detectors/objc.d.ts +41 -0
  104. package/dist/detectors/objc.d.ts.map +1 -0
  105. package/dist/detectors/objc.js +146 -0
  106. package/dist/detectors/objc.js.map +1 -0
  107. package/dist/detectors/openpgp.d.ts +20 -0
  108. package/dist/detectors/openpgp.d.ts.map +1 -0
  109. package/dist/detectors/openpgp.js +151 -0
  110. package/dist/detectors/openpgp.js.map +1 -0
  111. package/dist/detectors/pem.d.ts.map +1 -1
  112. package/dist/detectors/pem.js +33 -1
  113. package/dist/detectors/pem.js.map +1 -1
  114. package/dist/detectors/php.d.ts +25 -0
  115. package/dist/detectors/php.d.ts.map +1 -0
  116. package/dist/detectors/php.js +171 -0
  117. package/dist/detectors/php.js.map +1 -0
  118. package/dist/detectors/pkcs11.d.ts +17 -0
  119. package/dist/detectors/pkcs11.d.ts.map +1 -0
  120. package/dist/detectors/pkcs11.js +87 -0
  121. package/dist/detectors/pkcs11.js.map +1 -0
  122. package/dist/detectors/proxy.d.ts +52 -0
  123. package/dist/detectors/proxy.d.ts.map +1 -0
  124. package/dist/detectors/proxy.js +157 -0
  125. package/dist/detectors/proxy.js.map +1 -0
  126. package/dist/detectors/pulumi.d.ts +19 -0
  127. package/dist/detectors/pulumi.d.ts.map +1 -0
  128. package/dist/detectors/pulumi.js +80 -0
  129. package/dist/detectors/pulumi.js.map +1 -0
  130. package/dist/detectors/python.d.ts.map +1 -1
  131. package/dist/detectors/python.js +70 -0
  132. package/dist/detectors/python.js.map +1 -1
  133. package/dist/detectors/rust.d.ts.map +1 -1
  134. package/dist/detectors/rust.js +73 -0
  135. package/dist/detectors/rust.js.map +1 -1
  136. package/dist/detectors/secrets.d.ts +24 -0
  137. package/dist/detectors/secrets.d.ts.map +1 -0
  138. package/dist/detectors/secrets.js +63 -0
  139. package/dist/detectors/secrets.js.map +1 -0
  140. package/dist/detectors/solidity.d.ts +50 -0
  141. package/dist/detectors/solidity.d.ts.map +1 -0
  142. package/dist/detectors/solidity.js +108 -0
  143. package/dist/detectors/solidity.js.map +1 -0
  144. package/dist/detectors/source.d.ts.map +1 -1
  145. package/dist/detectors/source.js +243 -53
  146. package/dist/detectors/source.js.map +1 -1
  147. package/dist/detectors/spire.d.ts +49 -0
  148. package/dist/detectors/spire.d.ts.map +1 -0
  149. package/dist/detectors/spire.js +77 -0
  150. package/dist/detectors/spire.js.map +1 -0
  151. package/dist/detectors/ssh-ca.d.ts +72 -0
  152. package/dist/detectors/ssh-ca.d.ts.map +1 -0
  153. package/dist/detectors/ssh-ca.js +119 -0
  154. package/dist/detectors/ssh-ca.js.map +1 -0
  155. package/dist/detectors/stateful-hbs.d.ts.map +1 -1
  156. package/dist/detectors/stateful-hbs.js +9 -6
  157. package/dist/detectors/stateful-hbs.js.map +1 -1
  158. package/dist/detectors/supply-chain.d.ts +17 -0
  159. package/dist/detectors/supply-chain.d.ts.map +1 -0
  160. package/dist/detectors/supply-chain.js +89 -0
  161. package/dist/detectors/supply-chain.js.map +1 -0
  162. package/dist/detectors/swift.d.ts +22 -0
  163. package/dist/detectors/swift.d.ts.map +1 -0
  164. package/dist/detectors/swift.js +120 -0
  165. package/dist/detectors/swift.js.map +1 -0
  166. package/dist/detectors/terraform.d.ts +21 -0
  167. package/dist/detectors/terraform.d.ts.map +1 -0
  168. package/dist/detectors/terraform.js +150 -0
  169. package/dist/detectors/terraform.js.map +1 -0
  170. package/dist/detectors/vault.d.ts +15 -0
  171. package/dist/detectors/vault.d.ts.map +1 -0
  172. package/dist/detectors/vault.js +97 -0
  173. package/dist/detectors/vault.js.map +1 -0
  174. package/dist/detectors/vpn.d.ts +22 -0
  175. package/dist/detectors/vpn.d.ts.map +1 -0
  176. package/dist/detectors/vpn.js +73 -0
  177. package/dist/detectors/vpn.js.map +1 -0
  178. package/dist/detectors/weak-hash.d.ts +71 -0
  179. package/dist/detectors/weak-hash.d.ts.map +1 -0
  180. package/dist/detectors/weak-hash.js +116 -0
  181. package/dist/detectors/weak-hash.js.map +1 -0
  182. package/dist/detectors/webauthn.d.ts +61 -0
  183. package/dist/detectors/webauthn.d.ts.map +1 -0
  184. package/dist/detectors/webauthn.js +109 -0
  185. package/dist/detectors/webauthn.js.map +1 -0
  186. package/dist/detectors/xmldsig.d.ts +23 -0
  187. package/dist/detectors/xmldsig.d.ts.map +1 -0
  188. package/dist/detectors/xmldsig.js +84 -0
  189. package/dist/detectors/xmldsig.js.map +1 -0
  190. package/dist/evidence.d.ts +79 -4
  191. package/dist/evidence.d.ts.map +1 -1
  192. package/dist/evidence.js +76 -0
  193. package/dist/evidence.js.map +1 -1
  194. package/dist/index.d.ts +17 -9
  195. package/dist/index.d.ts.map +1 -1
  196. package/dist/index.js +21 -9
  197. package/dist/index.js.map +1 -1
  198. package/dist/inventory.d.ts +0 -2
  199. package/dist/inventory.d.ts.map +1 -1
  200. package/dist/inventory.js +15 -6
  201. package/dist/inventory.js.map +1 -1
  202. package/dist/policy.d.ts +67 -0
  203. package/dist/policy.d.ts.map +1 -0
  204. package/dist/policy.js +115 -0
  205. package/dist/policy.js.map +1 -0
  206. package/dist/registry.d.ts +9 -4
  207. package/dist/registry.d.ts.map +1 -1
  208. package/dist/registry.js +81 -4
  209. package/dist/registry.js.map +1 -1
  210. package/dist/remediate-pipeline.d.ts +0 -3
  211. package/dist/remediate-pipeline.d.ts.map +1 -1
  212. package/dist/remediate-pipeline.js +23 -2
  213. package/dist/remediate-pipeline.js.map +1 -1
  214. package/dist/remediation.d.ts +10 -0
  215. package/dist/remediation.d.ts.map +1 -1
  216. package/dist/remediation.js +32 -0
  217. package/dist/remediation.js.map +1 -1
  218. package/dist/report.d.ts +9 -0
  219. package/dist/report.d.ts.map +1 -1
  220. package/dist/report.js +38 -1
  221. package/dist/report.js.map +1 -1
  222. package/dist/scan-worker.js +5 -3
  223. package/dist/scan-worker.js.map +1 -1
  224. package/dist/scan.d.ts.map +1 -1
  225. package/dist/scan.js +35 -6
  226. package/dist/scan.js.map +1 -1
  227. package/dist/standards-profiles.d.ts +58 -0
  228. package/dist/standards-profiles.d.ts.map +1 -0
  229. package/dist/standards-profiles.js +100 -0
  230. package/dist/standards-profiles.js.map +1 -0
  231. package/dist/standards.d.ts +96 -0
  232. package/dist/standards.d.ts.map +1 -0
  233. package/dist/standards.js +107 -0
  234. package/dist/standards.js.map +1 -0
  235. package/dist/types.d.ts +6 -5
  236. package/dist/types.d.ts.map +1 -1
  237. package/dist/types.js.map +1 -1
  238. package/dist/version.d.ts +1 -1
  239. package/dist/version.js +1 -1
  240. package/dist/version.js.map +1 -1
  241. package/dist/vex.d.ts +39 -0
  242. package/dist/vex.d.ts.map +1 -0
  243. package/dist/vex.js +87 -0
  244. package/dist/vex.js.map +1 -0
  245. package/dist/walk.d.ts +8 -3
  246. package/dist/walk.d.ts.map +1 -1
  247. package/dist/walk.js +32 -1
  248. package/dist/walk.js.map +1 -1
  249. package/package.json +1 -1
  250. package/src/cbom-merge.ts +146 -0
  251. package/src/cbom.ts +153 -39
  252. package/src/comments.ts +84 -39
  253. package/src/dependencies.ts +2 -1
  254. package/src/detect-utils.ts +146 -12
  255. package/src/detectors/age.ts +60 -0
  256. package/src/detectors/ansible.ts +140 -0
  257. package/src/detectors/bicep.ts +107 -0
  258. package/src/detectors/c.ts +240 -6
  259. package/src/detectors/cicd.ts +171 -0
  260. package/src/detectors/cloud-kms.ts +141 -0
  261. package/src/detectors/cloudformation.ts +250 -0
  262. package/src/detectors/codesign.ts +214 -0
  263. package/src/detectors/csharp.ts +13 -3
  264. package/src/detectors/dart.ts +237 -0
  265. package/src/detectors/database.ts +141 -0
  266. package/src/detectors/dkim.ts +172 -0
  267. package/src/detectors/dnssec.ts +195 -0
  268. package/src/detectors/elixir.ts +268 -0
  269. package/src/detectors/java.ts +39 -4
  270. package/src/detectors/jose.ts +110 -0
  271. package/src/detectors/jwk.ts +170 -0
  272. package/src/detectors/k8s.ts +115 -0
  273. package/src/detectors/keystore.ts +109 -0
  274. package/src/detectors/mesh.ts +130 -0
  275. package/src/detectors/messaging.ts +106 -0
  276. package/src/detectors/objc.ts +209 -0
  277. package/src/detectors/openpgp.ts +194 -0
  278. package/src/detectors/pem.ts +31 -1
  279. package/src/detectors/php.ts +230 -0
  280. package/src/detectors/pkcs11.ts +113 -0
  281. package/src/detectors/proxy.ts +236 -0
  282. package/src/detectors/pulumi.ts +106 -0
  283. package/src/detectors/python.ts +71 -0
  284. package/src/detectors/rust.ts +76 -0
  285. package/src/detectors/secrets.ts +103 -0
  286. package/src/detectors/solidity.ts +176 -0
  287. package/src/detectors/source.ts +283 -73
  288. package/src/detectors/spire.ts +143 -0
  289. package/src/detectors/ssh-ca.ts +215 -0
  290. package/src/detectors/stateful-hbs.ts +9 -6
  291. package/src/detectors/supply-chain.ts +117 -0
  292. package/src/detectors/swift.ts +149 -0
  293. package/src/detectors/terraform.ts +188 -0
  294. package/src/detectors/vault.ts +120 -0
  295. package/src/detectors/vpn.ts +103 -0
  296. package/src/detectors/weak-hash.ts +217 -0
  297. package/src/detectors/webauthn.ts +205 -0
  298. package/src/detectors/xmldsig.ts +115 -0
  299. package/src/evidence.ts +138 -4
  300. package/src/index.ts +50 -12
  301. package/src/inventory.ts +15 -7
  302. package/src/policy.ts +180 -0
  303. package/src/registry.ts +81 -4
  304. package/src/remediate-pipeline.ts +26 -3
  305. package/src/remediation.ts +39 -0
  306. package/src/report.ts +43 -1
  307. package/src/scan-worker.ts +5 -3
  308. package/src/scan.ts +41 -6
  309. package/src/standards-profiles.ts +136 -0
  310. package/src/standards.ts +186 -0
  311. package/src/types.ts +11 -4
  312. package/src/version.ts +1 -1
  313. package/src/vex.ts +122 -0
  314. package/src/walk.ts +33 -2
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Config detector: classical **code-signing CLI** invocations in build scripts —
3
+ * the tools that sign long-lived, distributable artifacts (Windows installers,
4
+ * Android APKs, RPM/deb packages, NuGet packages, macOS apps) with a classical
5
+ * RSA/ECDSA signing identity.
6
+ *
7
+ * Why this is quantum-migration debt: a code signature produced today keeps
8
+ * verifying against its classical public key for the life of the artifact
9
+ * (installers and packages linger on mirrors and machines for years). Once a
10
+ * cryptographically-relevant quantum computer (CRQC) can recover the signing
11
+ * key from that public key, every such signature becomes *forgeable* — an
12
+ * attacker can mint a validly-signed trojaned installer. This is the
13
+ * signature-side analogue of harvest-now-decrypt-later: there is no
14
+ * confidentiality to harvest, so findings are `category:"signature"`,
15
+ * `hndl:false`, but they are real debt to inventory now.
16
+ *
17
+ * How this differs from the two neighbouring signing detectors — kept
18
+ * deliberately non-overlapping:
19
+ *
20
+ * - `cicd.ts` (cicdDetector) is gated to CI *pipeline* files
21
+ * (`.github/workflows/*.yml`, `.gitlab-ci.yml`, Jenkinsfile, azure-pipelines,
22
+ * CircleCI) and matches the release-automation signers there
23
+ * (cosign / gpg / jarsigner / codesign / minisign). It intentionally does
24
+ * NOT fire on a plain `build.sh`, `build.ps1`, `build.gradle`, or Makefile.
25
+ * - `supply-chain.ts` (supplyChainDetector) covers container/artifact signing
26
+ * (Docker Content Trust, CNCF Notation, in-toto) in CI files, Dockerfiles,
27
+ * and shell scripts.
28
+ *
29
+ * This detector fills the gap: the *native platform* code-signing CLIs
30
+ * (`signtool`, `osslsigncode`, `Set-AuthenticodeSignature`, `apksigner`, Gradle
31
+ * `signingConfigs`, `rpmsign`/`dpkg-sig`, `nuget sign`, `notarytool`) as they
32
+ * appear in a build script of ANY extension — because that is where developers
33
+ * actually run them. It applies everywhere except documentation
34
+ * (a README showing `signtool sign` is prose, not a build step). One token
35
+ * (`codesign`) can also be matched by `cicd.ts` when it appears inside a CI
36
+ * file; a duplicate finding across the two detectors is acceptable, and keeping
37
+ * `codesign` here means a `codesign --sign` in a hand-written `build.sh` — which
38
+ * `cicd.ts`'s CI-file gate deliberately skips — is still caught.
39
+ *
40
+ * Precision comes from two gates, mirroring `dnssec.ts`: a cheap file-level
41
+ * fast-reject (bail unless some signing-command marker is present) and
42
+ * comment-line masking (`#` for shell/PowerShell/Makefile/Gradle, `//` for
43
+ * Gradle/Groovy) so a commented-out signing step never fires. The rule regexes
44
+ * themselves key on distinctive `<tool> sign` command shapes, so the residual
45
+ * false-positive risk is low and confidence is `high`.
46
+ */
47
+ import type { Detector } from "../types.js";
48
+ /** Detects classical code-signing CLI invocations in build scripts. */
49
+ export declare const codesignDetector: Detector;
50
+ //# sourceMappingURL=codesign.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codesign.d.ts","sourceRoot":"","sources":["../../src/detectors/codesign.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,aAAa,CAAC;AAwI/D,uEAAuE;AACvE,eAAO,MAAM,gBAAgB,EAAE,QA8B9B,CAAC"}
@@ -0,0 +1,143 @@
1
+ import { eachMatch, findingFromRule, hasExtension, maskCommentLines, DOC_EXTENSIONS, } from "../detect-utils.js";
2
+ import { CWE_BROKEN_CRYPTO } from "../cwe.js";
3
+ /** Shared one-line explanation, parameterised by the signing tool named in the finding. */
4
+ function signMessage(tool) {
5
+ return (`${tool} signs an artifact with a classical RSA/ECDSA key; the signature is ` +
6
+ `forgeable once a CRQC can recover the signing key — inventory the signing ` +
7
+ `identity and plan PQC migration.`);
8
+ }
9
+ /** Shared remediation: no PQC code-signing format is broadly standardized yet. */
10
+ const REMEDIATION = "No PQC code-signing format is broadly standardized yet; track platform roadmaps " +
11
+ "(e.g. Sigstore/PQC, Authenticode); keep signing-key rotation ready.";
12
+ /**
13
+ * Distinctive markers for the file-level fast-reject. Kept as a SUPERSET of the
14
+ * rule tokens below so the cheap gate can never exclude a file one of the rules
15
+ * would match: it includes every rule's trigger token (`--addsign`, `%_gpg_name`,
16
+ * `codesign`, `nuget`, …), not only the headline command names.
17
+ */
18
+ const MARKER_RE = /signtool|osslsigncode|AuthenticodeSignature|apksigner|signingConfigs|rpmsign|--addsign|%_gpg_name|dpkg-sig|nuget|notarytool|codesign/;
19
+ const CS_RULES = [
20
+ {
21
+ // Windows Authenticode: `signtool sign …` (optionally `signtool.exe`),
22
+ // `osslsigncode sign …`, or the PowerShell `Set-AuthenticodeSignature` cmdlet.
23
+ re: /\bsigntool(?:\.exe)?\s+sign\b|\bosslsigncode\s+sign\b|\bSet-AuthenticodeSignature\b/g,
24
+ meta: {
25
+ id: "codesign-authenticode",
26
+ title: "Windows Authenticode code signing (RSA)",
27
+ description: "signtool / osslsigncode / Set-AuthenticodeSignature Authenticode signing",
28
+ category: "signature",
29
+ severity: "medium",
30
+ confidence: "high",
31
+ algorithm: "RSA",
32
+ hndl: false,
33
+ cwe: CWE_BROKEN_CRYPTO,
34
+ message: signMessage("Windows Authenticode (signtool/osslsigncode/Set-AuthenticodeSignature)"),
35
+ remediation: REMEDIATION,
36
+ },
37
+ },
38
+ {
39
+ // Android: `apksigner sign …` (covers `--ks` / `--ks-key-alias` forms), or a
40
+ // Gradle `signingConfigs { … }` block (which carries `storeFile`/`keyAlias`).
41
+ re: /\bapksigner\s+sign\b|\bsigningConfigs\s*\{/g,
42
+ meta: {
43
+ id: "codesign-apk",
44
+ title: "Android APK signing (RSA)",
45
+ description: "apksigner / Gradle signingConfigs APK signing",
46
+ category: "signature",
47
+ severity: "medium",
48
+ confidence: "high",
49
+ algorithm: "RSA",
50
+ hndl: false,
51
+ cwe: CWE_BROKEN_CRYPTO,
52
+ message: signMessage("Android APK signing (apksigner/Gradle signingConfigs)"),
53
+ remediation: REMEDIATION,
54
+ },
55
+ },
56
+ {
57
+ // RPM/deb: `rpmsign --addsign`, `rpm --addsign`, the `%_gpg_name` rpmmacro, or
58
+ // `dpkg-sig --sign`. All ultimately GPG (classically RSA) signatures.
59
+ re: /\brpmsign\s+--addsign\b|\brpm\s+--addsign\b|%_gpg_name\b|\bdpkg-sig\s+--sign\b/g,
60
+ meta: {
61
+ id: "codesign-rpm",
62
+ title: "RPM/deb package signing (RSA)",
63
+ description: "rpmsign / rpm --addsign / %_gpg_name / dpkg-sig package signing",
64
+ category: "signature",
65
+ severity: "medium",
66
+ confidence: "high",
67
+ algorithm: "RSA",
68
+ hndl: false,
69
+ cwe: CWE_BROKEN_CRYPTO,
70
+ message: signMessage("RPM/deb package signing (rpmsign/rpm --addsign/dpkg-sig, GPG)"),
71
+ remediation: REMEDIATION,
72
+ },
73
+ },
74
+ {
75
+ // NuGet: `nuget sign …` — also matches `dotnet nuget sign …` (the `nuget sign`
76
+ // token is a substring of it), typically paired with `--certificate-*` flags.
77
+ re: /\bnuget\s+sign\b/g,
78
+ meta: {
79
+ id: "codesign-nuget",
80
+ title: "NuGet package signing (RSA)",
81
+ description: "nuget sign / dotnet nuget sign package signing",
82
+ category: "signature",
83
+ severity: "medium",
84
+ confidence: "high",
85
+ algorithm: "RSA",
86
+ hndl: false,
87
+ cwe: CWE_BROKEN_CRYPTO,
88
+ message: signMessage("NuGet package signing (nuget sign/dotnet nuget sign)"),
89
+ remediation: REMEDIATION,
90
+ },
91
+ },
92
+ {
93
+ // Apple: `xcrun notarytool submit …`, or `codesign --sign` / `codesign -s`.
94
+ // Allow intervening flags before `--sign`/`-s`, bounded to the codesign
95
+ // invocation so it can't latch onto a later command's flag across `&&`/`|`/`;`
96
+ // (same shape as cicd.ts's codesign rule). Algorithm is "unknown": an Apple
97
+ // signing identity may be RSA or ECDSA.
98
+ re: /\bnotarytool\s+submit\b|\bcodesign\b[^\n&|;]{0,120}?\s(?:-s\b|--sign\b)/g,
99
+ meta: {
100
+ id: "codesign-apple",
101
+ title: "Apple code signing / notarization",
102
+ description: "codesign --sign / xcrun notarytool submit macOS signing",
103
+ category: "signature",
104
+ severity: "medium",
105
+ confidence: "high",
106
+ algorithm: "unknown",
107
+ hndl: false,
108
+ cwe: CWE_BROKEN_CRYPTO,
109
+ message: signMessage("Apple code signing (codesign/notarytool)"),
110
+ remediation: REMEDIATION,
111
+ },
112
+ },
113
+ ];
114
+ /** Detects classical code-signing CLI invocations in build scripts. */
115
+ export const codesignDetector = {
116
+ id: "codesign-signing",
117
+ description: "Classical code-signing CLIs in build scripts (Authenticode, APK, RPM, NuGet, Apple)",
118
+ scope: "config",
119
+ language: "any",
120
+ rules: CS_RULES.map((r) => r.meta),
121
+ // Applies to build scripts of any extension EXCEPT documentation: a README that
122
+ // shows `signtool sign` in an example is prose, not a build step.
123
+ appliesTo: (f) => !hasExtension(f, DOC_EXTENSIONS),
124
+ detect({ file, content }) {
125
+ // Cheap fast-reject: bail unless some signing-command marker is present, so
126
+ // the per-rule regexes never run on the overwhelming majority of files.
127
+ if (!MARKER_RE.test(content))
128
+ return [];
129
+ // Mask whole comment lines so a commented-out signing step can't fire.
130
+ // `#` covers shell / PowerShell / Makefile / Gradle(Groovy & Kotlin DSL);
131
+ // `//` covers Gradle/Groovy. Offsets are preserved so finding locations stay
132
+ // exact (see maskCommentLines).
133
+ const scan = maskCommentLines(content, ["#", "//"]);
134
+ const findings = [];
135
+ for (const rule of CS_RULES) {
136
+ eachMatch(rule.re, scan, (m) => {
137
+ findings.push(findingFromRule(rule.meta, { file, content, index: m.index, matchLength: m[0].length }));
138
+ });
139
+ }
140
+ return findings;
141
+ },
142
+ };
143
+ //# sourceMappingURL=codesign.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codesign.js","sourceRoot":"","sources":["../../src/detectors/codesign.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Config detector: classical **code-signing CLI** invocations in build scripts —\n * the tools that sign long-lived, distributable artifacts (Windows installers,\n * Android APKs, RPM/deb packages, NuGet packages, macOS apps) with a classical\n * RSA/ECDSA signing identity.\n *\n * Why this is quantum-migration debt: a code signature produced today keeps\n * verifying against its classical public key for the life of the artifact\n * (installers and packages linger on mirrors and machines for years). Once a\n * cryptographically-relevant quantum computer (CRQC) can recover the signing\n * key from that public key, every such signature becomes *forgeable* — an\n * attacker can mint a validly-signed trojaned installer. This is the\n * signature-side analogue of harvest-now-decrypt-later: there is no\n * confidentiality to harvest, so findings are `category:\"signature\"`,\n * `hndl:false`, but they are real debt to inventory now.\n *\n * How this differs from the two neighbouring signing detectors — kept\n * deliberately non-overlapping:\n *\n * - `cicd.ts` (cicdDetector) is gated to CI *pipeline* files\n * (`.github/workflows/*.yml`, `.gitlab-ci.yml`, Jenkinsfile, azure-pipelines,\n * CircleCI) and matches the release-automation signers there\n * (cosign / gpg / jarsigner / codesign / minisign). It intentionally does\n * NOT fire on a plain `build.sh`, `build.ps1`, `build.gradle`, or Makefile.\n * - `supply-chain.ts` (supplyChainDetector) covers container/artifact signing\n * (Docker Content Trust, CNCF Notation, in-toto) in CI files, Dockerfiles,\n * and shell scripts.\n *\n * This detector fills the gap: the *native platform* code-signing CLIs\n * (`signtool`, `osslsigncode`, `Set-AuthenticodeSignature`, `apksigner`, Gradle\n * `signingConfigs`, `rpmsign`/`dpkg-sig`, `nuget sign`, `notarytool`) as they\n * appear in a build script of ANY extension — because that is where developers\n * actually run them. It applies everywhere except documentation\n * (a README showing `signtool sign` is prose, not a build step). One token\n * (`codesign`) can also be matched by `cicd.ts` when it appears inside a CI\n * file; a duplicate finding across the two detectors is acceptable, and keeping\n * `codesign` here means a `codesign --sign` in a hand-written `build.sh` — which\n * `cicd.ts`'s CI-file gate deliberately skips — is still caught.\n *\n * Precision comes from two gates, mirroring `dnssec.ts`: a cheap file-level\n * fast-reject (bail unless some signing-command marker is present) and\n * comment-line masking (`#` for shell/PowerShell/Makefile/Gradle, `//` for\n * Gradle/Groovy) so a commented-out signing step never fires. The rule regexes\n * themselves key on distinctive `<tool> sign` command shapes, so the residual\n * false-positive risk is low and confidence is `high`.\n */\nimport type { Detector, Finding, RuleMeta } from \"../types.js\";\nimport {\n eachMatch,\n findingFromRule,\n hasExtension,\n maskCommentLines,\n DOC_EXTENSIONS,\n} from \"../detect-utils.js\";\nimport { CWE_BROKEN_CRYPTO } from \"../cwe.js\";\n\n/** Shared one-line explanation, parameterised by the signing tool named in the finding. */\nfunction signMessage(tool: string): string {\n return (\n `${tool} signs an artifact with a classical RSA/ECDSA key; the signature is ` +\n `forgeable once a CRQC can recover the signing key — inventory the signing ` +\n `identity and plan PQC migration.`\n );\n}\n\n/** Shared remediation: no PQC code-signing format is broadly standardized yet. */\nconst REMEDIATION =\n \"No PQC code-signing format is broadly standardized yet; track platform roadmaps \" +\n \"(e.g. Sigstore/PQC, Authenticode); keep signing-key rotation ready.\";\n\n/**\n * Distinctive markers for the file-level fast-reject. Kept as a SUPERSET of the\n * rule tokens below so the cheap gate can never exclude a file one of the rules\n * would match: it includes every rule's trigger token (`--addsign`, `%_gpg_name`,\n * `codesign`, `nuget`, …), not only the headline command names.\n */\nconst MARKER_RE =\n /signtool|osslsigncode|AuthenticodeSignature|apksigner|signingConfigs|rpmsign|--addsign|%_gpg_name|dpkg-sig|nuget|notarytool|codesign/;\n\ninterface CsRule {\n re: RegExp;\n meta: RuleMeta;\n}\n\nconst CS_RULES: CsRule[] = [\n {\n // Windows Authenticode: `signtool sign …` (optionally `signtool.exe`),\n // `osslsigncode sign …`, or the PowerShell `Set-AuthenticodeSignature` cmdlet.\n re: /\\bsigntool(?:\\.exe)?\\s+sign\\b|\\bosslsigncode\\s+sign\\b|\\bSet-AuthenticodeSignature\\b/g,\n meta: {\n id: \"codesign-authenticode\",\n title: \"Windows Authenticode code signing (RSA)\",\n description: \"signtool / osslsigncode / Set-AuthenticodeSignature Authenticode signing\",\n category: \"signature\",\n severity: \"medium\",\n confidence: \"high\",\n algorithm: \"RSA\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message: signMessage(\n \"Windows Authenticode (signtool/osslsigncode/Set-AuthenticodeSignature)\",\n ),\n remediation: REMEDIATION,\n },\n },\n {\n // Android: `apksigner sign …` (covers `--ks` / `--ks-key-alias` forms), or a\n // Gradle `signingConfigs { … }` block (which carries `storeFile`/`keyAlias`).\n re: /\\bapksigner\\s+sign\\b|\\bsigningConfigs\\s*\\{/g,\n meta: {\n id: \"codesign-apk\",\n title: \"Android APK signing (RSA)\",\n description: \"apksigner / Gradle signingConfigs APK signing\",\n category: \"signature\",\n severity: \"medium\",\n confidence: \"high\",\n algorithm: \"RSA\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message: signMessage(\"Android APK signing (apksigner/Gradle signingConfigs)\"),\n remediation: REMEDIATION,\n },\n },\n {\n // RPM/deb: `rpmsign --addsign`, `rpm --addsign`, the `%_gpg_name` rpmmacro, or\n // `dpkg-sig --sign`. All ultimately GPG (classically RSA) signatures.\n re: /\\brpmsign\\s+--addsign\\b|\\brpm\\s+--addsign\\b|%_gpg_name\\b|\\bdpkg-sig\\s+--sign\\b/g,\n meta: {\n id: \"codesign-rpm\",\n title: \"RPM/deb package signing (RSA)\",\n description: \"rpmsign / rpm --addsign / %_gpg_name / dpkg-sig package signing\",\n category: \"signature\",\n severity: \"medium\",\n confidence: \"high\",\n algorithm: \"RSA\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message: signMessage(\"RPM/deb package signing (rpmsign/rpm --addsign/dpkg-sig, GPG)\"),\n remediation: REMEDIATION,\n },\n },\n {\n // NuGet: `nuget sign …` — also matches `dotnet nuget sign …` (the `nuget sign`\n // token is a substring of it), typically paired with `--certificate-*` flags.\n re: /\\bnuget\\s+sign\\b/g,\n meta: {\n id: \"codesign-nuget\",\n title: \"NuGet package signing (RSA)\",\n description: \"nuget sign / dotnet nuget sign package signing\",\n category: \"signature\",\n severity: \"medium\",\n confidence: \"high\",\n algorithm: \"RSA\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message: signMessage(\"NuGet package signing (nuget sign/dotnet nuget sign)\"),\n remediation: REMEDIATION,\n },\n },\n {\n // Apple: `xcrun notarytool submit …`, or `codesign --sign` / `codesign -s`.\n // Allow intervening flags before `--sign`/`-s`, bounded to the codesign\n // invocation so it can't latch onto a later command's flag across `&&`/`|`/`;`\n // (same shape as cicd.ts's codesign rule). Algorithm is \"unknown\": an Apple\n // signing identity may be RSA or ECDSA.\n re: /\\bnotarytool\\s+submit\\b|\\bcodesign\\b[^\\n&|;]{0,120}?\\s(?:-s\\b|--sign\\b)/g,\n meta: {\n id: \"codesign-apple\",\n title: \"Apple code signing / notarization\",\n description: \"codesign --sign / xcrun notarytool submit macOS signing\",\n category: \"signature\",\n severity: \"medium\",\n confidence: \"high\",\n algorithm: \"unknown\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message: signMessage(\"Apple code signing (codesign/notarytool)\"),\n remediation: REMEDIATION,\n },\n },\n];\n\n/** Detects classical code-signing CLI invocations in build scripts. */\nexport const codesignDetector: Detector = {\n id: \"codesign-signing\",\n description:\n \"Classical code-signing CLIs in build scripts (Authenticode, APK, RPM, NuGet, Apple)\",\n scope: \"config\",\n language: \"any\",\n rules: CS_RULES.map((r) => r.meta),\n // Applies to build scripts of any extension EXCEPT documentation: a README that\n // shows `signtool sign` in an example is prose, not a build step.\n appliesTo: (f) => !hasExtension(f, DOC_EXTENSIONS),\n detect({ file, content }): Finding[] {\n // Cheap fast-reject: bail unless some signing-command marker is present, so\n // the per-rule regexes never run on the overwhelming majority of files.\n if (!MARKER_RE.test(content)) return [];\n\n // Mask whole comment lines so a commented-out signing step can't fire.\n // `#` covers shell / PowerShell / Makefile / Gradle(Groovy & Kotlin DSL);\n // `//` covers Gradle/Groovy. Offsets are preserved so finding locations stay\n // exact (see maskCommentLines).\n const scan = maskCommentLines(content, [\"#\", \"//\"]);\n const findings: Finding[] = [];\n for (const rule of CS_RULES) {\n eachMatch(rule.re, scan, (m) => {\n findings.push(\n findingFromRule(rule.meta, { file, content, index: m.index, matchLength: m[0].length }),\n );\n });\n }\n return findings;\n },\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"csharp.d.ts","sourceRoot":"","sources":["../../src/detectors/csharp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,aAAa,CAAC;AA8L/D,gFAAgF;AAChF,eAAO,MAAM,cAAc,EAAE,QA8C5B,CAAC"}
1
+ {"version":3,"file":"csharp.d.ts","sourceRoot":"","sources":["../../src/detectors/csharp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,aAAa,CAAC;AAwM/D,gFAAgF;AAChF,eAAO,MAAM,cAAc,EAAE,QA8C5B,CAAC"}
@@ -12,13 +12,23 @@ const RE_CS_DSA = /\bDSA\.Create\s*\(|\bnew\s+DSACryptoServiceProvider\s*\(|\bne
12
12
  // - SslProtocols.Ssl3 / .Tls / .Tls11 → deprecated SSL 3.0 / TLS 1.0 / 1.1.
13
13
  // `SslProtocols.Tls` (no suffix) is the legacy TLS 1.0 constant; `Tls12`/`Tls13`
14
14
  // are excluded by the trailing \b (the following digit is a word char).
15
- const RE_CS_TLS_CERT_VALIDATION = /\bDangerousAcceptAnyServerCertificateValidator\b|ServerCertificateCustomValidationCallback\s*=/g;
15
+ // Only the genuinely-permissive forms: the built-in accept-any validator, or a
16
+ // callback assigned an always-`true` lambda. A callback assigned a NAMED validator
17
+ // method is typically certificate PINNING (stricter than default) and must NOT fire.
18
+ // An accept-any server-certificate callback: the BouncyCastle helper, or a
19
+ // ServerCertificateCustomValidationCallback that unconditionally yields `true` — as an
20
+ // expression lambda (`=> true`), a block-body lambda (`=> { return true; }`), or a
21
+ // `delegate { return true; }`. Requiring a literal `true` (not just any `=>`) keeps
22
+ // certificate PINNING — which returns a comparison, `=> cert.Thumbprint == pinned` —
23
+ // from being flagged as a disabled validator.
24
+ const RE_CS_TLS_CERT_VALIDATION = /\bDangerousAcceptAnyServerCertificateValidator\b|ServerCertificateCustomValidationCallback\s*=\s*(?:[^;\n]{0,80}=>\s*(?:true\b|\{\s*return\s+true\b)|delegate\s*(?:\([^)]{0,80}\))?\s*\{\s*return\s+true\b)/g;
16
25
  const RE_CS_TLS_LEGACY_VERSION = /\bSslProtocols\.(?:Tls|Tls11|Ssl3)\b/g;
17
26
  // Identifier-form JWT/JOSE signature algorithms (audit F7). The quoted-string
18
27
  // alg token ("RS256") is caught by the language-agnostic jwt-jose detector, but
19
28
  // Microsoft.IdentityModel passes the alg as an IDENTIFIER, not a string literal:
20
- // SecurityAlgorithms.RsaSha256 / SecurityAlgorithms.EcdsaSha256.
21
- const RE_CS_JWT_ALG = /\bSecurityAlgorithms\.(?:Rsa|Ecdsa)Sha(?:256|384|512)\b/g;
29
+ // SecurityAlgorithms.RsaSha256 / SecurityAlgorithms.EcdsaSha256, and the
30
+ // `…Signature`-suffixed constants used in SigningCredentials (RsaSha256Signature).
31
+ const RE_CS_JWT_ALG = /\bSecurityAlgorithms\.(?:Rsa|Ecdsa)Sha(?:256|384|512)(?:Signature)?\b/g;
22
32
  // BouncyCastle (Org.BouncyCastle) modern-curve and finite-field DH primitives,
23
33
  // which System.Security.Cryptography does not expose directly. Each regex is
24
34
  // anchored to the distinctive BouncyCastle class names for one family so it
@@ -1 +1 @@
1
- {"version":3,"file":"csharp.js","sourceRoot":"","sources":["../../src/detectors/csharp.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACjG,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEtF,MAAM,SAAS,GACb,uGAAuG,CAAC;AAC1G,MAAM,WAAW,GAAG,uEAAuE,CAAC;AAC5F,MAAM,UAAU,GACd,qGAAqG,CAAC;AACxG,MAAM,SAAS,GAAG,+EAA+E,CAAC;AAClG,gFAAgF;AAChF,iFAAiF;AACjF,0DAA0D;AAC1D,8DAA8D;AAC9D,2EAA2E;AAC3E,8EAA8E;AAC9E,iFAAiF;AACjF,wEAAwE;AACxE,MAAM,yBAAyB,GAC7B,iGAAiG,CAAC;AACpG,MAAM,wBAAwB,GAAG,uCAAuC,CAAC;AACzE,8EAA8E;AAC9E,gFAAgF;AAChF,iFAAiF;AACjF,iEAAiE;AACjE,MAAM,aAAa,GAAG,0DAA0D,CAAC;AACjF,+EAA+E;AAC/E,6EAA6E;AAC7E,4EAA4E;AAC5E,0CAA0C;AAC1C,oFAAoF;AACpF,qFAAqF;AACrF,6EAA6E;AAC7E,+FAA+F;AAC/F,+EAA+E;AAC/E,4EAA4E;AAC5E,MAAM,cAAc,GAAG,8DAA8D,CAAC;AACtF,MAAM,eAAe,GAAG,gEAAgE,CAAC;AACzF,MAAM,aAAa,GAAG,8DAA8D,CAAC;AACrF,MAAM,WAAW,GACf,iGAAiG,CAAC;AAEpG,MAAM,WAAW,GAAa;IAC5B,EAAE,EAAE,YAAY;IAChB,KAAK,EAAE,kBAAkB;IACzB,WAAW,EAAE,6EAA6E;IAC1F,QAAQ,EAAE,KAAK;IACf,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,MAAM;IAClB,SAAS,EAAE,KAAK;IAChB,IAAI,EAAE,IAAI;IACV,GAAG,EAAE,iBAAiB;IACtB,OAAO,EAAE,8EAA8E;CACxF,CAAC;AACF,MAAM,aAAa,GAAa;IAC9B,EAAE,EAAE,cAAc;IAClB,KAAK,EAAE,oBAAoB;IAC3B,WAAW,EAAE,sDAAsD;IACnE,QAAQ,EAAE,WAAW;IACrB,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,MAAM;IAClB,SAAS,EAAE,OAAO;IAClB,IAAI,EAAE,KAAK;IACX,GAAG,EAAE,iBAAiB;IACtB,OAAO,EAAE,oEAAoE;IAC7E,WAAW,EAAE,4CAA4C;CAC1D,CAAC;AACF,MAAM,YAAY,GAAa;IAC7B,EAAE,EAAE,aAAa;IACjB,KAAK,EAAE,uBAAuB;IAC9B,WAAW,EAAE,0EAA0E;IACvF,QAAQ,EAAE,cAAc;IACxB,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,MAAM;IAClB,SAAS,EAAE,MAAM;IACjB,IAAI,EAAE,IAAI;IACV,GAAG,EAAE,iBAAiB;IACtB,OAAO,EACL,iGAAiG;CACpG,CAAC;AACF,MAAM,WAAW,GAAa;IAC5B,EAAE,EAAE,YAAY;IAChB,KAAK,EAAE,sBAAsB;IAC7B,WAAW,EAAE,oEAAoE;IACjF,QAAQ,EAAE,WAAW;IACrB,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,MAAM;IAClB,SAAS,EAAE,KAAK;IAChB,IAAI,EAAE,KAAK;IACX,GAAG,EAAE,iBAAiB;IACtB,OAAO,EAAE,yEAAyE;IAClF,WAAW,EAAE,qDAAqD;CACnE,CAAC;AACF,MAAM,gBAAgB,GAAa;IACjC,EAAE,EAAE,4BAA4B;IAChC,KAAK,EAAE,0CAA0C;IACjD,WAAW,EACT,mGAAmG;IACrG,QAAQ,EAAE,KAAK;IACf,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,MAAM;IAClB,IAAI,EAAE,KAAK;IACX,GAAG,EAAE,mBAAmB;IACxB,OAAO,EAAE,qFAAqF;IAC9F,WAAW,EACT,+FAA+F;CAClG,CAAC;AACF,MAAM,kBAAkB,GAAa;IACnC,EAAE,EAAE,2BAA2B;IAC/B,KAAK,EAAE,kCAAkC;IACzC,WAAW,EAAE,iDAAiD;IAC9D,QAAQ,EAAE,KAAK;IACf,QAAQ,EAAE,QAAQ;IAClB,UAAU,EAAE,MAAM;IAClB,IAAI,EAAE,KAAK;IACX,GAAG,EAAE,iBAAiB;IACtB,OAAO,EACL,yFAAyF;IAC3F,WAAW,EAAE,uEAAuE;CACrF,CAAC;AACF,MAAM,eAAe,GAAa;IAChC,EAAE,EAAE,gBAAgB;IACpB,KAAK,EAAE,uCAAuC;IAC9C,WAAW,EAAE,gEAAgE;IAC7E,QAAQ,EAAE,WAAW;IACrB,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,MAAM;IAClB,SAAS,EAAE,SAAS;IACpB,IAAI,EAAE,KAAK;IACX,GAAG,EAAE,iBAAiB;IACtB,OAAO,EACL,4GAA4G;IAC9G,WAAW,EAAE,2DAA2D;CACzE,CAAC;AACF,MAAM,gBAAgB,GAAa;IACjC,EAAE,EAAE,2BAA2B;IAC/B,KAAK,EAAE,qCAAqC;IAC5C,WAAW,EACT,wFAAwF;IAC1F,QAAQ,EAAE,WAAW;IACrB,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,MAAM;IAClB,SAAS,EAAE,OAAO;IAClB,IAAI,EAAE,KAAK;IACX,GAAG,EAAE,iBAAiB;IACtB,OAAO,EAAE,8EAA8E;IACvF,WAAW,EAAE,4CAA4C;CAC1D,CAAC;AACF,MAAM,iBAAiB,GAAa;IAClC,EAAE,EAAE,4BAA4B;IAChC,KAAK,EAAE,wCAAwC;IAC/C,WAAW,EACT,wFAAwF;IAC1F,QAAQ,EAAE,cAAc;IACxB,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,MAAM;IAClB,SAAS,EAAE,QAAQ;IACnB,IAAI,EAAE,IAAI;IACV,GAAG,EAAE,iBAAiB;IACtB,OAAO,EACL,+GAA+G;CAClH,CAAC;AACF,MAAM,eAAe,GAAa;IAChC,EAAE,EAAE,0BAA0B;IAC9B,KAAK,EAAE,sCAAsC;IAC7C,WAAW,EAAE,kFAAkF;IAC/F,QAAQ,EAAE,cAAc;IACxB,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,MAAM;IAClB,SAAS,EAAE,MAAM;IACjB,IAAI,EAAE,IAAI;IACV,GAAG,EAAE,iBAAiB;IACtB,OAAO,EACL,6GAA6G;CAChH,CAAC;AACF,MAAM,aAAa,GAAa;IAC9B,EAAE,EAAE,wBAAwB;IAC5B,KAAK,EAAE,+CAA+C;IACtD,WAAW,EACT,+FAA+F;IACjG,QAAQ,EAAE,cAAc;IACxB,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,MAAM;IAClB,SAAS,EAAE,IAAI;IACf,IAAI,EAAE,IAAI;IACV,GAAG,EAAE,iBAAiB;IACtB,OAAO,EACL,uGAAuG;CAC1G,CAAC;AAEF,gFAAgF;AAChF,MAAM,CAAC,MAAM,cAAc,GAAa;IACtC,EAAE,EAAE,eAAe;IACnB,WAAW,EACT,+FAA+F;IACjG,KAAK,EAAE,QAAQ;IACf,QAAQ,EAAE,QAAQ;IAClB,KAAK,EAAE;QACL,WAAW;QACX,aAAa;QACb,YAAY;QACZ,WAAW;QACX,gBAAgB;QAChB,kBAAkB;QAClB,eAAe;QACf,gBAAgB;QAChB,iBAAiB;QACjB,eAAe;QACf,aAAa;KACd;IACD,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,iBAAiB,CAAC;IACpD,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE;QACtB,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,CAAC,EAAU,EAAE,IAAc,EAAE,EAAE,CACzC,SAAS,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAC3B,QAAQ,CAAC,IAAI,CACX,eAAe,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CACnF,CACF,CAAC;QACJ,gEAAgE;QAChE,GAAG,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;QAChC,GAAG,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QAC9B,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QAC5B,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QAC5B,yEAAyE;QACzE,GAAG,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,CAAC;QACjD,GAAG,CAAC,wBAAwB,EAAE,kBAAkB,CAAC,CAAC;QAClD,2EAA2E;QAC3E,GAAG,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;QACpC,0EAA0E;QAC1E,yDAAyD;QACzD,GAAG,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;QACtC,GAAG,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAAC;QACxC,GAAG,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;QACpC,GAAG,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;QAChC,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC","sourcesContent":["/**\n * Source-code detector for classical asymmetric cryptography in C# / .NET\n * (`System.Security.Cryptography`). Same lexical strategy as the other packs.\n * .NET exposes each algorithm through a factory (`RSA.Create()`,\n * `ECDsa.Create()`, `ECDiffieHellman.Create()`) or a concrete CSP/CNG class\n * (`RSACryptoServiceProvider`, `ECDsaCng`, …), all of which are precise signals.\n *\n * HNDL: RSA (keygen/encryption) and (EC)DH key agreement are harvest-now-\n * decrypt-later exposed (hndl:true); ECDSA/DSA signatures are hndl:false but\n * forgeable by a quantum attacker.\n */\nimport type { Detector, Finding, RuleMeta } from \"../types.js\";\nimport { CSHARP_EXTENSIONS, eachMatch, findingFromRule, hasExtension } from \"../detect-utils.js\";\nimport { CWE_BROKEN_CRYPTO, CWE_CERT_VALIDATION, CWE_WEAK_STRENGTH } from \"../cwe.js\";\n\nconst RE_CS_RSA =\n /\\bRSA\\.Create\\s*\\(|\\bnew\\s+RSACryptoServiceProvider\\s*\\(|\\bnew\\s+RSACng\\s*\\(|\\bnew\\s+RSAOpenSsl\\s*\\(/g;\nconst RE_CS_ECDSA = /\\bECDsa\\.Create\\s*\\(|\\bnew\\s+ECDsaCng\\s*\\(|\\bnew\\s+ECDsaOpenSsl\\s*\\(/g;\nconst RE_CS_ECDH =\n /\\bECDiffieHellman\\.Create\\s*\\(|\\bnew\\s+ECDiffieHellmanCng\\s*\\(|\\bnew\\s+ECDiffieHellmanOpenSsl\\s*\\(/g;\nconst RE_CS_DSA = /\\bDSA\\.Create\\s*\\(|\\bnew\\s+DSACryptoServiceProvider\\s*\\(|\\bnew\\s+DSACng\\s*\\(/g;\n// Insecure TLS configuration (.NET). Mirrors source.ts's tlsDetector split of a\n// cert-verification-disabled rule (tls-reject-unauthorized) and a legacy-version\n// rule (tls-legacy-version) for the equivalent C# idioms:\n// - DangerousAcceptAnyServerCertificateValidator / a custom\n// ServerCertificateCustomValidationCallback → accepts any cert (MITM).\n// - SslProtocols.Ssl3 / .Tls / .Tls11 → deprecated SSL 3.0 / TLS 1.0 / 1.1.\n// `SslProtocols.Tls` (no suffix) is the legacy TLS 1.0 constant; `Tls12`/`Tls13`\n// are excluded by the trailing \\b (the following digit is a word char).\nconst RE_CS_TLS_CERT_VALIDATION =\n /\\bDangerousAcceptAnyServerCertificateValidator\\b|ServerCertificateCustomValidationCallback\\s*=/g;\nconst RE_CS_TLS_LEGACY_VERSION = /\\bSslProtocols\\.(?:Tls|Tls11|Ssl3)\\b/g;\n// Identifier-form JWT/JOSE signature algorithms (audit F7). The quoted-string\n// alg token (\"RS256\") is caught by the language-agnostic jwt-jose detector, but\n// Microsoft.IdentityModel passes the alg as an IDENTIFIER, not a string literal:\n// SecurityAlgorithms.RsaSha256 / SecurityAlgorithms.EcdsaSha256.\nconst RE_CS_JWT_ALG = /\\bSecurityAlgorithms\\.(?:Rsa|Ecdsa)Sha(?:256|384|512)\\b/g;\n// BouncyCastle (Org.BouncyCastle) modern-curve and finite-field DH primitives,\n// which System.Security.Cryptography does not expose directly. Each regex is\n// anchored to the distinctive BouncyCastle class names for one family so it\n// can't misfire on unrelated identifiers:\n// - Ed25519KeyPairGenerator / Ed25519Signer / Ed25519PrivateKeyParameters → EdDSA\n// - X25519KeyPairGenerator / X25519Agreement / X25519PrivateKeyParameters → X25519\n// - X448KeyPairGenerator / X448Agreement / X448PrivateKeyParameters → X448\n// - DHParametersGenerator / DHBasicAgreement / DH(Basic)KeyPairGenerator / DHParameters → DH\n// The trailing \\b keeps each token whole (e.g. Ed25519KeyGenerationParameters,\n// X25519PublicKeyParameters and DHKeyGenerationParameters are NOT matched).\nconst RE_CS_BC_EDDSA = /\\bEd25519(?:KeyPairGenerator|Signer|PrivateKeyParameters)\\b/g;\nconst RE_CS_BC_X25519 = /\\bX25519(?:KeyPairGenerator|Agreement|PrivateKeyParameters)\\b/g;\nconst RE_CS_BC_X448 = /\\bX448(?:KeyPairGenerator|Agreement|PrivateKeyParameters)\\b/g;\nconst RE_CS_BC_DH =\n /\\bDH(?:ParametersGenerator|BasicAgreement|BasicKeyPairGenerator|KeyPairGenerator|Parameters)\\b/g;\n\nconst RULE_CS_RSA: RuleMeta = {\n id: \"csharp-rsa\",\n title: \"C# RSA key/usage\",\n description: \"System.Security.Cryptography RSA.Create / RSACryptoServiceProvider / RSACng\",\n category: \"kem\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"RSA\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message: \"Classical RSA (.NET) is not quantum-safe and RSA encryption is HNDL-exposed.\",\n};\nconst RULE_CS_ECDSA: RuleMeta = {\n id: \"csharp-ecdsa\",\n title: \"C# ECDSA signature\",\n description: \"System.Security.Cryptography ECDsa.Create / ECDsaCng\",\n category: \"signature\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"ECDSA\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message: \"Classical ECDSA signing (.NET) is forgeable by a quantum attacker.\",\n remediation: \"ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205)\",\n};\nconst RULE_CS_ECDH: RuleMeta = {\n id: \"csharp-ecdh\",\n title: \"C# ECDH key agreement\",\n description: \"System.Security.Cryptography ECDiffieHellman.Create / ECDiffieHellmanCng\",\n category: \"key-exchange\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"ECDH\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"Elliptic-curve Diffie-Hellman (.NET) is broken by Shor's algorithm (harvest-now-decrypt-later).\",\n};\nconst RULE_CS_DSA: RuleMeta = {\n id: \"csharp-dsa\",\n title: \"C# DSA key/signature\",\n description: \"System.Security.Cryptography DSA.Create / DSACryptoServiceProvider\",\n category: \"signature\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"DSA\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message: \"Classical DSA (.NET) is deprecated and forgeable by a quantum attacker.\",\n remediation: \"Rotate off DSA and migrate to ML-DSA-65 (FIPS 204).\",\n};\nconst RULE_CS_TLS_CERT: RuleMeta = {\n id: \"csharp-tls-cert-validation\",\n title: \"C# TLS certificate verification disabled\",\n description:\n \"DangerousAcceptAnyServerCertificateValidator / ServerCertificateCustomValidationCallback override\",\n category: \"tls\",\n severity: \"high\",\n confidence: \"high\",\n hndl: false,\n cwe: CWE_CERT_VALIDATION,\n message: \"Accepting any server certificate disables TLS certificate verification (MITM risk).\",\n remediation:\n \"Remove the custom validator and verify certificates properly; prefer PQC-hybrid key exchange.\",\n};\nconst RULE_CS_TLS_LEGACY: RuleMeta = {\n id: \"csharp-tls-legacy-version\",\n title: \"C# legacy TLS/SSL version pinned\",\n description: \"SslProtocols pinned to Ssl3 / TLS 1.0 / TLS 1.1\",\n category: \"tls\",\n severity: \"medium\",\n confidence: \"high\",\n hndl: false,\n cwe: CWE_WEAK_STRENGTH,\n message:\n \"SSL 3.0 / TLS 1.0 / TLS 1.1 are deprecated and insecure; require TLS 1.2+ (prefer 1.3).\",\n remediation: \"Use SslProtocols.Tls13 (or Tls12) and prefer PQC-hybrid key exchange.\",\n};\nconst RULE_CS_JWT_ALG: RuleMeta = {\n id: \"csharp-jwt-alg\",\n title: \"C# identifier-form JWT/JOSE algorithm\",\n description: \"Microsoft.IdentityModel SecurityAlgorithms.RsaSha* / EcdsaSha*\",\n category: \"signature\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"unknown\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"A classical JWT/JOSE signature algorithm (.NET, identifier form) is used, forgeable by a quantum attacker.\",\n remediation: \"ML-DSA-65 (FIPS 204); track IETF PQC JOSE/COSE algorithms\",\n};\nconst RULE_CS_BC_EDDSA: RuleMeta = {\n id: \"csharp-bouncycastle-eddsa\",\n title: \"C# Ed25519 signature (BouncyCastle)\",\n description:\n \"Org.BouncyCastle Ed25519KeyPairGenerator / Ed25519Signer / Ed25519PrivateKeyParameters\",\n category: \"signature\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"EdDSA\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message: \"Classical Ed25519 signing (BouncyCastle) is forgeable by a quantum attacker.\",\n remediation: \"ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205)\",\n};\nconst RULE_CS_BC_X25519: RuleMeta = {\n id: \"csharp-bouncycastle-x25519\",\n title: \"C# X25519 key agreement (BouncyCastle)\",\n description:\n \"Org.BouncyCastle X25519KeyPairGenerator / X25519Agreement / X25519PrivateKeyParameters\",\n category: \"key-exchange\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"X25519\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"X25519 Diffie-Hellman key agreement (BouncyCastle) is broken by Shor's algorithm (harvest-now-decrypt-later).\",\n};\nconst RULE_CS_BC_X448: RuleMeta = {\n id: \"csharp-bouncycastle-x448\",\n title: \"C# X448 key agreement (BouncyCastle)\",\n description: \"Org.BouncyCastle X448KeyPairGenerator / X448Agreement / X448PrivateKeyParameters\",\n category: \"key-exchange\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"X448\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"X448 Diffie-Hellman key agreement (BouncyCastle) is broken by Shor's algorithm (harvest-now-decrypt-later).\",\n};\nconst RULE_CS_BC_DH: RuleMeta = {\n id: \"csharp-bouncycastle-dh\",\n title: \"C# finite-field Diffie-Hellman (BouncyCastle)\",\n description:\n \"Org.BouncyCastle DHParametersGenerator / DHBasicAgreement / DHKeyPairGenerator / DHParameters\",\n category: \"key-exchange\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"DH\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"Finite-field Diffie-Hellman (BouncyCastle) is broken by Shor's algorithm (harvest-now-decrypt-later).\",\n};\n\n/** Detects classical asymmetric crypto in C# (System.Security.Cryptography). */\nexport const csharpDetector: Detector = {\n id: \"csharp-crypto\",\n description:\n \"Classical asymmetric crypto (System.Security.Cryptography) and insecure TLS config in C#/.NET\",\n scope: \"source\",\n language: \"csharp\",\n rules: [\n RULE_CS_RSA,\n RULE_CS_ECDSA,\n RULE_CS_ECDH,\n RULE_CS_DSA,\n RULE_CS_TLS_CERT,\n RULE_CS_TLS_LEGACY,\n RULE_CS_JWT_ALG,\n RULE_CS_BC_EDDSA,\n RULE_CS_BC_X25519,\n RULE_CS_BC_X448,\n RULE_CS_BC_DH,\n ],\n appliesTo: (f) => hasExtension(f, CSHARP_EXTENSIONS),\n detect({ file, content }): Finding[] {\n const findings: Finding[] = [];\n const add = (re: RegExp, rule: RuleMeta) =>\n eachMatch(re, content, (m) =>\n findings.push(\n findingFromRule(rule, { file, content, index: m.index, matchLength: m[0].length }),\n ),\n );\n // ECDSA / ECDH before RSA/DSA so the specific EC factories win.\n add(RE_CS_ECDSA, RULE_CS_ECDSA);\n add(RE_CS_ECDH, RULE_CS_ECDH);\n add(RE_CS_RSA, RULE_CS_RSA);\n add(RE_CS_DSA, RULE_CS_DSA);\n // Insecure TLS configuration (disjoint from the crypto factories above).\n add(RE_CS_TLS_CERT_VALIDATION, RULE_CS_TLS_CERT);\n add(RE_CS_TLS_LEGACY_VERSION, RULE_CS_TLS_LEGACY);\n // Identifier-form JWT/JOSE signature algorithms (Microsoft.IdentityModel).\n add(RE_CS_JWT_ALG, RULE_CS_JWT_ALG);\n // BouncyCastle (Org.BouncyCastle) curve / finite-field DH primitives that\n // System.Security.Cryptography does not expose directly.\n add(RE_CS_BC_EDDSA, RULE_CS_BC_EDDSA);\n add(RE_CS_BC_X25519, RULE_CS_BC_X25519);\n add(RE_CS_BC_X448, RULE_CS_BC_X448);\n add(RE_CS_BC_DH, RULE_CS_BC_DH);\n return findings;\n },\n};\n"]}
1
+ {"version":3,"file":"csharp.js","sourceRoot":"","sources":["../../src/detectors/csharp.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Source-code detector for classical asymmetric cryptography in C# / .NET\n * (`System.Security.Cryptography`). Same lexical strategy as the other packs.\n * .NET exposes each algorithm through a factory (`RSA.Create()`,\n * `ECDsa.Create()`, `ECDiffieHellman.Create()`) or a concrete CSP/CNG class\n * (`RSACryptoServiceProvider`, `ECDsaCng`, …), all of which are precise signals.\n *\n * HNDL: RSA (keygen/encryption) and (EC)DH key agreement are harvest-now-\n * decrypt-later exposed (hndl:true); ECDSA/DSA signatures are hndl:false but\n * forgeable by a quantum attacker.\n */\nimport type { Detector, Finding, RuleMeta } from \"../types.js\";\nimport { CSHARP_EXTENSIONS, eachMatch, findingFromRule, hasExtension } from \"../detect-utils.js\";\nimport { CWE_BROKEN_CRYPTO, CWE_CERT_VALIDATION, CWE_WEAK_STRENGTH } from \"../cwe.js\";\n\nconst RE_CS_RSA =\n /\\bRSA\\.Create\\s*\\(|\\bnew\\s+RSACryptoServiceProvider\\s*\\(|\\bnew\\s+RSACng\\s*\\(|\\bnew\\s+RSAOpenSsl\\s*\\(/g;\nconst RE_CS_ECDSA = /\\bECDsa\\.Create\\s*\\(|\\bnew\\s+ECDsaCng\\s*\\(|\\bnew\\s+ECDsaOpenSsl\\s*\\(/g;\nconst RE_CS_ECDH =\n /\\bECDiffieHellman\\.Create\\s*\\(|\\bnew\\s+ECDiffieHellmanCng\\s*\\(|\\bnew\\s+ECDiffieHellmanOpenSsl\\s*\\(/g;\nconst RE_CS_DSA = /\\bDSA\\.Create\\s*\\(|\\bnew\\s+DSACryptoServiceProvider\\s*\\(|\\bnew\\s+DSACng\\s*\\(/g;\n// Insecure TLS configuration (.NET). Mirrors source.ts's tlsDetector split of a\n// cert-verification-disabled rule (tls-reject-unauthorized) and a legacy-version\n// rule (tls-legacy-version) for the equivalent C# idioms:\n// - DangerousAcceptAnyServerCertificateValidator / a custom\n// ServerCertificateCustomValidationCallback → accepts any cert (MITM).\n// - SslProtocols.Ssl3 / .Tls / .Tls11 → deprecated SSL 3.0 / TLS 1.0 / 1.1.\n// `SslProtocols.Tls` (no suffix) is the legacy TLS 1.0 constant; `Tls12`/`Tls13`\n// are excluded by the trailing \\b (the following digit is a word char).\n// Only the genuinely-permissive forms: the built-in accept-any validator, or a\n// callback assigned an always-`true` lambda. A callback assigned a NAMED validator\n// method is typically certificate PINNING (stricter than default) and must NOT fire.\n// An accept-any server-certificate callback: the BouncyCastle helper, or a\n// ServerCertificateCustomValidationCallback that unconditionally yields `true` — as an\n// expression lambda (`=> true`), a block-body lambda (`=> { return true; }`), or a\n// `delegate { return true; }`. Requiring a literal `true` (not just any `=>`) keeps\n// certificate PINNING — which returns a comparison, `=> cert.Thumbprint == pinned` —\n// from being flagged as a disabled validator.\nconst RE_CS_TLS_CERT_VALIDATION =\n /\\bDangerousAcceptAnyServerCertificateValidator\\b|ServerCertificateCustomValidationCallback\\s*=\\s*(?:[^;\\n]{0,80}=>\\s*(?:true\\b|\\{\\s*return\\s+true\\b)|delegate\\s*(?:\\([^)]{0,80}\\))?\\s*\\{\\s*return\\s+true\\b)/g;\nconst RE_CS_TLS_LEGACY_VERSION = /\\bSslProtocols\\.(?:Tls|Tls11|Ssl3)\\b/g;\n// Identifier-form JWT/JOSE signature algorithms (audit F7). The quoted-string\n// alg token (\"RS256\") is caught by the language-agnostic jwt-jose detector, but\n// Microsoft.IdentityModel passes the alg as an IDENTIFIER, not a string literal:\n// SecurityAlgorithms.RsaSha256 / SecurityAlgorithms.EcdsaSha256, and the\n// `…Signature`-suffixed constants used in SigningCredentials (RsaSha256Signature).\nconst RE_CS_JWT_ALG = /\\bSecurityAlgorithms\\.(?:Rsa|Ecdsa)Sha(?:256|384|512)(?:Signature)?\\b/g;\n// BouncyCastle (Org.BouncyCastle) modern-curve and finite-field DH primitives,\n// which System.Security.Cryptography does not expose directly. Each regex is\n// anchored to the distinctive BouncyCastle class names for one family so it\n// can't misfire on unrelated identifiers:\n// - Ed25519KeyPairGenerator / Ed25519Signer / Ed25519PrivateKeyParameters → EdDSA\n// - X25519KeyPairGenerator / X25519Agreement / X25519PrivateKeyParameters → X25519\n// - X448KeyPairGenerator / X448Agreement / X448PrivateKeyParameters → X448\n// - DHParametersGenerator / DHBasicAgreement / DH(Basic)KeyPairGenerator / DHParameters → DH\n// The trailing \\b keeps each token whole (e.g. Ed25519KeyGenerationParameters,\n// X25519PublicKeyParameters and DHKeyGenerationParameters are NOT matched).\nconst RE_CS_BC_EDDSA = /\\bEd25519(?:KeyPairGenerator|Signer|PrivateKeyParameters)\\b/g;\nconst RE_CS_BC_X25519 = /\\bX25519(?:KeyPairGenerator|Agreement|PrivateKeyParameters)\\b/g;\nconst RE_CS_BC_X448 = /\\bX448(?:KeyPairGenerator|Agreement|PrivateKeyParameters)\\b/g;\nconst RE_CS_BC_DH =\n /\\bDH(?:ParametersGenerator|BasicAgreement|BasicKeyPairGenerator|KeyPairGenerator|Parameters)\\b/g;\n\nconst RULE_CS_RSA: RuleMeta = {\n id: \"csharp-rsa\",\n title: \"C# RSA key/usage\",\n description: \"System.Security.Cryptography RSA.Create / RSACryptoServiceProvider / RSACng\",\n category: \"kem\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"RSA\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message: \"Classical RSA (.NET) is not quantum-safe and RSA encryption is HNDL-exposed.\",\n};\nconst RULE_CS_ECDSA: RuleMeta = {\n id: \"csharp-ecdsa\",\n title: \"C# ECDSA signature\",\n description: \"System.Security.Cryptography ECDsa.Create / ECDsaCng\",\n category: \"signature\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"ECDSA\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message: \"Classical ECDSA signing (.NET) is forgeable by a quantum attacker.\",\n remediation: \"ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205)\",\n};\nconst RULE_CS_ECDH: RuleMeta = {\n id: \"csharp-ecdh\",\n title: \"C# ECDH key agreement\",\n description: \"System.Security.Cryptography ECDiffieHellman.Create / ECDiffieHellmanCng\",\n category: \"key-exchange\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"ECDH\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"Elliptic-curve Diffie-Hellman (.NET) is broken by Shor's algorithm (harvest-now-decrypt-later).\",\n};\nconst RULE_CS_DSA: RuleMeta = {\n id: \"csharp-dsa\",\n title: \"C# DSA key/signature\",\n description: \"System.Security.Cryptography DSA.Create / DSACryptoServiceProvider\",\n category: \"signature\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"DSA\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message: \"Classical DSA (.NET) is deprecated and forgeable by a quantum attacker.\",\n remediation: \"Rotate off DSA and migrate to ML-DSA-65 (FIPS 204).\",\n};\nconst RULE_CS_TLS_CERT: RuleMeta = {\n id: \"csharp-tls-cert-validation\",\n title: \"C# TLS certificate verification disabled\",\n description:\n \"DangerousAcceptAnyServerCertificateValidator / ServerCertificateCustomValidationCallback override\",\n category: \"tls\",\n severity: \"high\",\n confidence: \"high\",\n hndl: false,\n cwe: CWE_CERT_VALIDATION,\n message: \"Accepting any server certificate disables TLS certificate verification (MITM risk).\",\n remediation:\n \"Remove the custom validator and verify certificates properly; prefer PQC-hybrid key exchange.\",\n};\nconst RULE_CS_TLS_LEGACY: RuleMeta = {\n id: \"csharp-tls-legacy-version\",\n title: \"C# legacy TLS/SSL version pinned\",\n description: \"SslProtocols pinned to Ssl3 / TLS 1.0 / TLS 1.1\",\n category: \"tls\",\n severity: \"medium\",\n confidence: \"high\",\n hndl: false,\n cwe: CWE_WEAK_STRENGTH,\n message:\n \"SSL 3.0 / TLS 1.0 / TLS 1.1 are deprecated and insecure; require TLS 1.2+ (prefer 1.3).\",\n remediation: \"Use SslProtocols.Tls13 (or Tls12) and prefer PQC-hybrid key exchange.\",\n};\nconst RULE_CS_JWT_ALG: RuleMeta = {\n id: \"csharp-jwt-alg\",\n title: \"C# identifier-form JWT/JOSE algorithm\",\n description: \"Microsoft.IdentityModel SecurityAlgorithms.RsaSha* / EcdsaSha*\",\n category: \"signature\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"unknown\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"A classical JWT/JOSE signature algorithm (.NET, identifier form) is used, forgeable by a quantum attacker.\",\n remediation: \"ML-DSA-65 (FIPS 204); track IETF PQC JOSE/COSE algorithms\",\n};\nconst RULE_CS_BC_EDDSA: RuleMeta = {\n id: \"csharp-bouncycastle-eddsa\",\n title: \"C# Ed25519 signature (BouncyCastle)\",\n description:\n \"Org.BouncyCastle Ed25519KeyPairGenerator / Ed25519Signer / Ed25519PrivateKeyParameters\",\n category: \"signature\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"EdDSA\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message: \"Classical Ed25519 signing (BouncyCastle) is forgeable by a quantum attacker.\",\n remediation: \"ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205)\",\n};\nconst RULE_CS_BC_X25519: RuleMeta = {\n id: \"csharp-bouncycastle-x25519\",\n title: \"C# X25519 key agreement (BouncyCastle)\",\n description:\n \"Org.BouncyCastle X25519KeyPairGenerator / X25519Agreement / X25519PrivateKeyParameters\",\n category: \"key-exchange\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"X25519\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"X25519 Diffie-Hellman key agreement (BouncyCastle) is broken by Shor's algorithm (harvest-now-decrypt-later).\",\n};\nconst RULE_CS_BC_X448: RuleMeta = {\n id: \"csharp-bouncycastle-x448\",\n title: \"C# X448 key agreement (BouncyCastle)\",\n description: \"Org.BouncyCastle X448KeyPairGenerator / X448Agreement / X448PrivateKeyParameters\",\n category: \"key-exchange\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"X448\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"X448 Diffie-Hellman key agreement (BouncyCastle) is broken by Shor's algorithm (harvest-now-decrypt-later).\",\n};\nconst RULE_CS_BC_DH: RuleMeta = {\n id: \"csharp-bouncycastle-dh\",\n title: \"C# finite-field Diffie-Hellman (BouncyCastle)\",\n description:\n \"Org.BouncyCastle DHParametersGenerator / DHBasicAgreement / DHKeyPairGenerator / DHParameters\",\n category: \"key-exchange\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"DH\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"Finite-field Diffie-Hellman (BouncyCastle) is broken by Shor's algorithm (harvest-now-decrypt-later).\",\n};\n\n/** Detects classical asymmetric crypto in C# (System.Security.Cryptography). */\nexport const csharpDetector: Detector = {\n id: \"csharp-crypto\",\n description:\n \"Classical asymmetric crypto (System.Security.Cryptography) and insecure TLS config in C#/.NET\",\n scope: \"source\",\n language: \"csharp\",\n rules: [\n RULE_CS_RSA,\n RULE_CS_ECDSA,\n RULE_CS_ECDH,\n RULE_CS_DSA,\n RULE_CS_TLS_CERT,\n RULE_CS_TLS_LEGACY,\n RULE_CS_JWT_ALG,\n RULE_CS_BC_EDDSA,\n RULE_CS_BC_X25519,\n RULE_CS_BC_X448,\n RULE_CS_BC_DH,\n ],\n appliesTo: (f) => hasExtension(f, CSHARP_EXTENSIONS),\n detect({ file, content }): Finding[] {\n const findings: Finding[] = [];\n const add = (re: RegExp, rule: RuleMeta) =>\n eachMatch(re, content, (m) =>\n findings.push(\n findingFromRule(rule, { file, content, index: m.index, matchLength: m[0].length }),\n ),\n );\n // ECDSA / ECDH before RSA/DSA so the specific EC factories win.\n add(RE_CS_ECDSA, RULE_CS_ECDSA);\n add(RE_CS_ECDH, RULE_CS_ECDH);\n add(RE_CS_RSA, RULE_CS_RSA);\n add(RE_CS_DSA, RULE_CS_DSA);\n // Insecure TLS configuration (disjoint from the crypto factories above).\n add(RE_CS_TLS_CERT_VALIDATION, RULE_CS_TLS_CERT);\n add(RE_CS_TLS_LEGACY_VERSION, RULE_CS_TLS_LEGACY);\n // Identifier-form JWT/JOSE signature algorithms (Microsoft.IdentityModel).\n add(RE_CS_JWT_ALG, RULE_CS_JWT_ALG);\n // BouncyCastle (Org.BouncyCastle) curve / finite-field DH primitives that\n // System.Security.Cryptography does not expose directly.\n add(RE_CS_BC_EDDSA, RULE_CS_BC_EDDSA);\n add(RE_CS_BC_X25519, RULE_CS_BC_X25519);\n add(RE_CS_BC_X448, RULE_CS_BC_X448);\n add(RE_CS_BC_DH, RULE_CS_BC_DH);\n return findings;\n },\n};\n"]}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Source detector for classical asymmetric cryptography in Dart / Flutter.
3
+ *
4
+ * Dart has no asymmetric crypto in its standard library, so real-world code
5
+ * reaches for one of the two dominant pub.dev packages, and both expose their
6
+ * primitives through distinctive class names — which makes a lexical scan (the
7
+ * same zero-dependency strategy as every other language pack here) precise:
8
+ *
9
+ * - package:pointycastle (a Bouncy Castle port). RSA via `RSAKeyGenerator`,
10
+ * `RSAEngine`, `RSASigner`, `PSSSigner`; EC via `ECKeyGenerator`,
11
+ * `ECDSASigner`, `ECDHBasicAgreement`; Edwards via `Ed25519`.
12
+ * - package:cryptography (Dart-native). RSA via `RsaPss`, `RsaSsaPkcs1v15`;
13
+ * EC via `Ecdsa`, `Ecdh`; modern curves via `Ed25519`, `X25519`.
14
+ *
15
+ * HNDL (harvest-now-decrypt-later) reasoning — the field that drives urgency:
16
+ * - RSA encryption (`RSAEngine`) and RSA key generation (`RSAKeyGenerator`,
17
+ * which yields keys that can decrypt) are confidentiality surfaces → hndl:true.
18
+ * - (EC)DH key agreement (`ECDHBasicAgreement`, `Ecdh`, `X25519`) is the classic
19
+ * HNDL target — recorded ciphertext is decryptable once the curve falls → hndl:true.
20
+ * - Signatures (`RSASigner`/`PSSSigner`/`RsaPss`/`RsaSsaPkcs1v15`, `ECDSASigner`/
21
+ * `Ecdsa`, `Ed25519`) are forgeable by a quantum attacker but not retroactively
22
+ * breakable → hndl:false.
23
+ * - `ECKeyGenerator` is ambiguous (an EC key can feed either ECDSA or ECDH); it is
24
+ * classified conservatively as an ECDSA signing key (hndl:false), the Dart default.
25
+ *
26
+ * Comment suppression is C-style (`//` line + `/* … *\/` block), matching Dart's
27
+ * lexer, so commented-out crypto is not reported. The regexes are `\b`-anchored on
28
+ * the library-specific identifiers above; none matches a bare `RSA`/`EC` substring,
29
+ * keeping false positives low. A cheap substring fast-reject skips the regex work on
30
+ * the overwhelming majority of `.dart` files that touch no asymmetric crypto.
31
+ */
32
+ import type { Detector } from "../types.js";
33
+ /** Detects classical asymmetric crypto in Dart / Flutter (pointycastle, cryptography). */
34
+ export declare const dartDetector: Detector;
35
+ //# sourceMappingURL=dart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dart.d.ts","sourceRoot":"","sources":["../../src/detectors/dart.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,aAAa,CAAC;AA8J/D,0FAA0F;AAC1F,eAAO,MAAM,YAAY,EAAE,QA8C1B,CAAC"}
@@ -0,0 +1,177 @@
1
+ import { eachMatch, findingFromRule, hasExtension, maskBlockComments, maskCommentLines, DART_EXTENSIONS, } from "../detect-utils.js";
2
+ import { CWE_BROKEN_CRYPTO } from "../cwe.js";
3
+ // RSA key generation / raw RSA encryption engine (pointycastle). Both are
4
+ // confidentiality-capable (a keypair can decrypt; the engine encrypts) → kem.
5
+ const RE_DART_RSA_KEYGEN = /\b(?:RSAKeyGenerator|RSAEngine)\b/g;
6
+ // RSA signature schemes: pointycastle `RSASigner`/`PSSSigner`, cryptography
7
+ // `RsaPss`/`RsaSsaPkcs1v15`. Distinct casing keeps these off the keygen rule.
8
+ const RE_DART_RSA_SIGN = /\b(?:RSASigner|PSSSigner|RsaPss|RsaSsaPkcs1v15)\b/g;
9
+ // ECDSA SIGNING: pointycastle `ECDSASigner`, cryptography `Ecdsa`. `\bEcdsa\b`
10
+ // requires a boundary, so `EcdsaP256`-style concatenations (rare) and the all-caps
11
+ // `ECDSASigner` don't double-fire here. (EC keygen is a SEPARATE, HNDL-exposed rule.)
12
+ const RE_DART_ECDSA = /\b(?:ECDSASigner|Ecdsa)\b/g;
13
+ // EC KEY GENERATION (pointycastle `ECKeyGenerator`) is ambiguous — an EC key can
14
+ // feed ECDSA signing OR ECDH agreement — so it is classified key-exchange/ECDH/
15
+ // hndl:true (the fleet's HNDL-safe convention), NOT folded into the signing rule.
16
+ const RE_DART_EC_KEYGEN = /\bECKeyGenerator\b/g;
17
+ // ECDH key agreement: pointycastle `ECDHBasicAgreement`, cryptography `Ecdh`.
18
+ // `\bEcdh\b` cannot match inside `Ecdsa` (different letters), so no overlap.
19
+ const RE_DART_ECDH = /\b(?:ECDHBasicAgreement|Ecdh)\b/g;
20
+ // Ed25519 signer (both packages spell it `Ed25519`).
21
+ const RE_DART_ED25519 = /\bEd25519\b/g;
22
+ // X25519 key agreement (cryptography `X25519`).
23
+ const RE_DART_X25519 = /\bX25519\b/g;
24
+ // Cheap fast-reject: distinctive substrings that gate the (precise) regex work.
25
+ // If none is present the file cannot contain any of the tracked identifiers.
26
+ const DART_FAST_REJECT = [
27
+ "RSA",
28
+ "Rsa",
29
+ "ECDSA",
30
+ "Ecdsa",
31
+ "ECDH",
32
+ "Ecdh",
33
+ "ECKeyGenerator",
34
+ "PSSSigner",
35
+ "Ed25519",
36
+ "X25519",
37
+ ];
38
+ const RULE_DART_RSA_KEYGEN = {
39
+ id: "dart-rsa-keygen",
40
+ title: "Dart RSA key generation / encryption",
41
+ description: "pointycastle RSAKeyGenerator / RSAEngine",
42
+ category: "kem",
43
+ severity: "high",
44
+ confidence: "high",
45
+ algorithm: "RSA",
46
+ hndl: true,
47
+ cwe: CWE_BROKEN_CRYPTO,
48
+ message: "Classical RSA key generation / encryption (Dart, pointycastle) is not quantum-safe and RSA encryption is harvest-now-decrypt-later exposed.",
49
+ remediation: "Migrate to PQC (ML-KEM-768 for encryption / key transport) as Dart crypto packages add support.",
50
+ };
51
+ const RULE_DART_RSA_SIGN = {
52
+ id: "dart-rsa-sign",
53
+ title: "Dart RSA signature",
54
+ description: "pointycastle RSASigner/PSSSigner, cryptography RsaPss/RsaSsaPkcs1v15",
55
+ category: "signature",
56
+ // `high`, consistent with every sibling pack's signature severity (go/java/php/
57
+ // objc/elixir RSA-sign) — the same primitive must not flip CI exit codes by language.
58
+ severity: "high",
59
+ confidence: "high",
60
+ algorithm: "RSA",
61
+ hndl: false,
62
+ cwe: CWE_BROKEN_CRYPTO,
63
+ message: "Classical RSA signature (Dart) is forgeable by a quantum attacker.",
64
+ remediation: "Migrate to PQC signatures (ML-DSA-65, FIPS 204) as Dart crypto packages add support.",
65
+ };
66
+ const RULE_DART_ECDSA = {
67
+ id: "dart-ecdsa",
68
+ title: "Dart ECDSA signature",
69
+ description: "pointycastle ECDSASigner, cryptography Ecdsa",
70
+ category: "signature",
71
+ severity: "high",
72
+ confidence: "high",
73
+ algorithm: "ECDSA",
74
+ hndl: false,
75
+ cwe: CWE_BROKEN_CRYPTO,
76
+ message: "Classical ECDSA signing (Dart) is forgeable by a quantum attacker.",
77
+ remediation: "Migrate to PQC signatures (ML-DSA-65, FIPS 204) as Dart crypto packages add support.",
78
+ };
79
+ const RULE_DART_EC_KEYGEN = {
80
+ id: "dart-ec-keygen",
81
+ title: "Dart EC key generation",
82
+ description: "pointycastle ECKeyGenerator (ambiguous EC key: ECDSA or ECDH)",
83
+ // Ambiguous EC keygen → key-exchange/ECDH/hndl:true (fleet HNDL-safe convention),
84
+ // since the key may feed ECDH agreement (harvest-now-decrypt-later exposed).
85
+ category: "key-exchange",
86
+ severity: "high",
87
+ confidence: "high",
88
+ algorithm: "ECDH",
89
+ hndl: true,
90
+ cwe: CWE_BROKEN_CRYPTO,
91
+ message: "EC key generation (Dart, pointycastle); an EC key can feed ECDH key agreement (harvest-now-decrypt-later exposed) as well as ECDSA signing, and is not quantum-safe.",
92
+ remediation: "For key agreement migrate to hybrid X25519MLKEM768 (ML-KEM-768); for signatures ML-DSA-65 — as Dart crypto packages add support.",
93
+ };
94
+ const RULE_DART_ECDH = {
95
+ id: "dart-ecdh",
96
+ title: "Dart ECDH key agreement",
97
+ description: "pointycastle ECDHBasicAgreement, cryptography Ecdh",
98
+ category: "key-exchange",
99
+ severity: "high",
100
+ confidence: "high",
101
+ algorithm: "ECDH",
102
+ hndl: true,
103
+ cwe: CWE_BROKEN_CRYPTO,
104
+ message: "Elliptic-curve Diffie-Hellman key agreement (Dart) is broken by Shor's algorithm (harvest-now-decrypt-later).",
105
+ remediation: "Migrate key agreement to hybrid X25519MLKEM768 (ML-KEM-768) as Dart crypto packages add support.",
106
+ };
107
+ const RULE_DART_ED25519 = {
108
+ id: "dart-ed25519",
109
+ title: "Dart Ed25519 signature",
110
+ description: "pointycastle / cryptography Ed25519 signer",
111
+ category: "signature",
112
+ // `low`, aligned with Ed25519 across the other source packs (swift/rust/go/…) —
113
+ // the same primitive must not flip CI exit codes based on which language wrote it.
114
+ severity: "low",
115
+ confidence: "high",
116
+ algorithm: "EdDSA",
117
+ hndl: false,
118
+ cwe: CWE_BROKEN_CRYPTO,
119
+ message: "Ed25519 (Dart) is a modern but still classical signature scheme, forgeable by a quantum attacker.",
120
+ remediation: "Migrate to PQC signatures (ML-DSA-65, FIPS 204) as Dart crypto packages add support.",
121
+ };
122
+ const RULE_DART_X25519 = {
123
+ id: "dart-x25519",
124
+ title: "Dart X25519 key agreement",
125
+ description: "cryptography X25519 key agreement",
126
+ category: "key-exchange",
127
+ severity: "medium",
128
+ confidence: "high",
129
+ algorithm: "X25519",
130
+ hndl: true,
131
+ cwe: CWE_BROKEN_CRYPTO,
132
+ message: "X25519 (Dart) is modern but still classical key agreement — harvest-now-decrypt-later exposed.",
133
+ remediation: "Migrate key agreement to hybrid X25519MLKEM768 (ML-KEM-768) as Dart crypto packages add support.",
134
+ };
135
+ /** Detects classical asymmetric crypto in Dart / Flutter (pointycastle, cryptography). */
136
+ export const dartDetector = {
137
+ id: "dart-crypto",
138
+ description: "Classical asymmetric crypto in Dart / Flutter (pointycastle, cryptography)",
139
+ scope: "source",
140
+ language: "dart",
141
+ rules: [
142
+ RULE_DART_RSA_KEYGEN,
143
+ RULE_DART_RSA_SIGN,
144
+ RULE_DART_ECDSA,
145
+ RULE_DART_EC_KEYGEN,
146
+ RULE_DART_ECDH,
147
+ RULE_DART_ED25519,
148
+ RULE_DART_X25519,
149
+ ],
150
+ appliesTo: (f) => hasExtension(f, DART_EXTENSIONS),
151
+ detect({ file, content }) {
152
+ // Fast-reject: nothing to do unless a distinctive token appears.
153
+ if (!DART_FAST_REJECT.some((t) => content.includes(t)))
154
+ return [];
155
+ // Suppress C-style comments so commented-out crypto isn't reported. Offsets
156
+ // are preserved (chars → spaces), so finding line/column stay exact.
157
+ const masked = maskCommentLines(maskBlockComments(content), ["//"]);
158
+ const findings = [];
159
+ // Scan the masked text, but build the finding (its snippet) from the ORIGINAL
160
+ // `content` so a line with a trailing comment renders live, not blanked.
161
+ const add = (re, rule) => eachMatch(re, masked, (m) => findings.push(findingFromRule(rule, {
162
+ file,
163
+ content,
164
+ index: m.index,
165
+ matchLength: m[0].length,
166
+ })));
167
+ add(RE_DART_RSA_KEYGEN, RULE_DART_RSA_KEYGEN);
168
+ add(RE_DART_RSA_SIGN, RULE_DART_RSA_SIGN);
169
+ add(RE_DART_ECDSA, RULE_DART_ECDSA);
170
+ add(RE_DART_EC_KEYGEN, RULE_DART_EC_KEYGEN);
171
+ add(RE_DART_ECDH, RULE_DART_ECDH);
172
+ add(RE_DART_ED25519, RULE_DART_ED25519);
173
+ add(RE_DART_X25519, RULE_DART_X25519);
174
+ return findings;
175
+ },
176
+ };
177
+ //# sourceMappingURL=dart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dart.js","sourceRoot":"","sources":["../../src/detectors/dart.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Source detector for classical asymmetric cryptography in Dart / Flutter.\n *\n * Dart has no asymmetric crypto in its standard library, so real-world code\n * reaches for one of the two dominant pub.dev packages, and both expose their\n * primitives through distinctive class names — which makes a lexical scan (the\n * same zero-dependency strategy as every other language pack here) precise:\n *\n * - package:pointycastle (a Bouncy Castle port). RSA via `RSAKeyGenerator`,\n * `RSAEngine`, `RSASigner`, `PSSSigner`; EC via `ECKeyGenerator`,\n * `ECDSASigner`, `ECDHBasicAgreement`; Edwards via `Ed25519`.\n * - package:cryptography (Dart-native). RSA via `RsaPss`, `RsaSsaPkcs1v15`;\n * EC via `Ecdsa`, `Ecdh`; modern curves via `Ed25519`, `X25519`.\n *\n * HNDL (harvest-now-decrypt-later) reasoning — the field that drives urgency:\n * - RSA encryption (`RSAEngine`) and RSA key generation (`RSAKeyGenerator`,\n * which yields keys that can decrypt) are confidentiality surfaces → hndl:true.\n * - (EC)DH key agreement (`ECDHBasicAgreement`, `Ecdh`, `X25519`) is the classic\n * HNDL target — recorded ciphertext is decryptable once the curve falls → hndl:true.\n * - Signatures (`RSASigner`/`PSSSigner`/`RsaPss`/`RsaSsaPkcs1v15`, `ECDSASigner`/\n * `Ecdsa`, `Ed25519`) are forgeable by a quantum attacker but not retroactively\n * breakable → hndl:false.\n * - `ECKeyGenerator` is ambiguous (an EC key can feed either ECDSA or ECDH); it is\n * classified conservatively as an ECDSA signing key (hndl:false), the Dart default.\n *\n * Comment suppression is C-style (`//` line + `/* … *\\/` block), matching Dart's\n * lexer, so commented-out crypto is not reported. The regexes are `\\b`-anchored on\n * the library-specific identifiers above; none matches a bare `RSA`/`EC` substring,\n * keeping false positives low. A cheap substring fast-reject skips the regex work on\n * the overwhelming majority of `.dart` files that touch no asymmetric crypto.\n */\nimport type { Detector, Finding, RuleMeta } from \"../types.js\";\nimport {\n eachMatch,\n findingFromRule,\n hasExtension,\n maskBlockComments,\n maskCommentLines,\n DART_EXTENSIONS,\n} from \"../detect-utils.js\";\nimport { CWE_BROKEN_CRYPTO } from \"../cwe.js\";\n\n// RSA key generation / raw RSA encryption engine (pointycastle). Both are\n// confidentiality-capable (a keypair can decrypt; the engine encrypts) → kem.\nconst RE_DART_RSA_KEYGEN = /\\b(?:RSAKeyGenerator|RSAEngine)\\b/g;\n// RSA signature schemes: pointycastle `RSASigner`/`PSSSigner`, cryptography\n// `RsaPss`/`RsaSsaPkcs1v15`. Distinct casing keeps these off the keygen rule.\nconst RE_DART_RSA_SIGN = /\\b(?:RSASigner|PSSSigner|RsaPss|RsaSsaPkcs1v15)\\b/g;\n// ECDSA SIGNING: pointycastle `ECDSASigner`, cryptography `Ecdsa`. `\\bEcdsa\\b`\n// requires a boundary, so `EcdsaP256`-style concatenations (rare) and the all-caps\n// `ECDSASigner` don't double-fire here. (EC keygen is a SEPARATE, HNDL-exposed rule.)\nconst RE_DART_ECDSA = /\\b(?:ECDSASigner|Ecdsa)\\b/g;\n// EC KEY GENERATION (pointycastle `ECKeyGenerator`) is ambiguous — an EC key can\n// feed ECDSA signing OR ECDH agreement — so it is classified key-exchange/ECDH/\n// hndl:true (the fleet's HNDL-safe convention), NOT folded into the signing rule.\nconst RE_DART_EC_KEYGEN = /\\bECKeyGenerator\\b/g;\n// ECDH key agreement: pointycastle `ECDHBasicAgreement`, cryptography `Ecdh`.\n// `\\bEcdh\\b` cannot match inside `Ecdsa` (different letters), so no overlap.\nconst RE_DART_ECDH = /\\b(?:ECDHBasicAgreement|Ecdh)\\b/g;\n// Ed25519 signer (both packages spell it `Ed25519`).\nconst RE_DART_ED25519 = /\\bEd25519\\b/g;\n// X25519 key agreement (cryptography `X25519`).\nconst RE_DART_X25519 = /\\bX25519\\b/g;\n\n// Cheap fast-reject: distinctive substrings that gate the (precise) regex work.\n// If none is present the file cannot contain any of the tracked identifiers.\nconst DART_FAST_REJECT: readonly string[] = [\n \"RSA\",\n \"Rsa\",\n \"ECDSA\",\n \"Ecdsa\",\n \"ECDH\",\n \"Ecdh\",\n \"ECKeyGenerator\",\n \"PSSSigner\",\n \"Ed25519\",\n \"X25519\",\n];\n\nconst RULE_DART_RSA_KEYGEN: RuleMeta = {\n id: \"dart-rsa-keygen\",\n title: \"Dart RSA key generation / encryption\",\n description: \"pointycastle RSAKeyGenerator / RSAEngine\",\n category: \"kem\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"RSA\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"Classical RSA key generation / encryption (Dart, pointycastle) is not quantum-safe and RSA encryption is harvest-now-decrypt-later exposed.\",\n remediation:\n \"Migrate to PQC (ML-KEM-768 for encryption / key transport) as Dart crypto packages add support.\",\n};\nconst RULE_DART_RSA_SIGN: RuleMeta = {\n id: \"dart-rsa-sign\",\n title: \"Dart RSA signature\",\n description: \"pointycastle RSASigner/PSSSigner, cryptography RsaPss/RsaSsaPkcs1v15\",\n category: \"signature\",\n // `high`, consistent with every sibling pack's signature severity (go/java/php/\n // objc/elixir RSA-sign) — the same primitive must not flip CI exit codes by language.\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"RSA\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message: \"Classical RSA signature (Dart) is forgeable by a quantum attacker.\",\n remediation:\n \"Migrate to PQC signatures (ML-DSA-65, FIPS 204) as Dart crypto packages add support.\",\n};\nconst RULE_DART_ECDSA: RuleMeta = {\n id: \"dart-ecdsa\",\n title: \"Dart ECDSA signature\",\n description: \"pointycastle ECDSASigner, cryptography Ecdsa\",\n category: \"signature\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"ECDSA\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message: \"Classical ECDSA signing (Dart) is forgeable by a quantum attacker.\",\n remediation:\n \"Migrate to PQC signatures (ML-DSA-65, FIPS 204) as Dart crypto packages add support.\",\n};\nconst RULE_DART_EC_KEYGEN: RuleMeta = {\n id: \"dart-ec-keygen\",\n title: \"Dart EC key generation\",\n description: \"pointycastle ECKeyGenerator (ambiguous EC key: ECDSA or ECDH)\",\n // Ambiguous EC keygen → key-exchange/ECDH/hndl:true (fleet HNDL-safe convention),\n // since the key may feed ECDH agreement (harvest-now-decrypt-later exposed).\n category: \"key-exchange\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"ECDH\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"EC key generation (Dart, pointycastle); an EC key can feed ECDH key agreement (harvest-now-decrypt-later exposed) as well as ECDSA signing, and is not quantum-safe.\",\n remediation:\n \"For key agreement migrate to hybrid X25519MLKEM768 (ML-KEM-768); for signatures ML-DSA-65 — as Dart crypto packages add support.\",\n};\nconst RULE_DART_ECDH: RuleMeta = {\n id: \"dart-ecdh\",\n title: \"Dart ECDH key agreement\",\n description: \"pointycastle ECDHBasicAgreement, cryptography Ecdh\",\n category: \"key-exchange\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"ECDH\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"Elliptic-curve Diffie-Hellman key agreement (Dart) is broken by Shor's algorithm (harvest-now-decrypt-later).\",\n remediation:\n \"Migrate key agreement to hybrid X25519MLKEM768 (ML-KEM-768) as Dart crypto packages add support.\",\n};\nconst RULE_DART_ED25519: RuleMeta = {\n id: \"dart-ed25519\",\n title: \"Dart Ed25519 signature\",\n description: \"pointycastle / cryptography Ed25519 signer\",\n category: \"signature\",\n // `low`, aligned with Ed25519 across the other source packs (swift/rust/go/…) —\n // the same primitive must not flip CI exit codes based on which language wrote it.\n severity: \"low\",\n confidence: \"high\",\n algorithm: \"EdDSA\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"Ed25519 (Dart) is a modern but still classical signature scheme, forgeable by a quantum attacker.\",\n remediation:\n \"Migrate to PQC signatures (ML-DSA-65, FIPS 204) as Dart crypto packages add support.\",\n};\nconst RULE_DART_X25519: RuleMeta = {\n id: \"dart-x25519\",\n title: \"Dart X25519 key agreement\",\n description: \"cryptography X25519 key agreement\",\n category: \"key-exchange\",\n severity: \"medium\",\n confidence: \"high\",\n algorithm: \"X25519\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"X25519 (Dart) is modern but still classical key agreement — harvest-now-decrypt-later exposed.\",\n remediation:\n \"Migrate key agreement to hybrid X25519MLKEM768 (ML-KEM-768) as Dart crypto packages add support.\",\n};\n\n/** Detects classical asymmetric crypto in Dart / Flutter (pointycastle, cryptography). */\nexport const dartDetector: Detector = {\n id: \"dart-crypto\",\n description: \"Classical asymmetric crypto in Dart / Flutter (pointycastle, cryptography)\",\n scope: \"source\",\n language: \"dart\",\n rules: [\n RULE_DART_RSA_KEYGEN,\n RULE_DART_RSA_SIGN,\n RULE_DART_ECDSA,\n RULE_DART_EC_KEYGEN,\n RULE_DART_ECDH,\n RULE_DART_ED25519,\n RULE_DART_X25519,\n ],\n appliesTo: (f) => hasExtension(f, DART_EXTENSIONS),\n detect({ file, content }): Finding[] {\n // Fast-reject: nothing to do unless a distinctive token appears.\n if (!DART_FAST_REJECT.some((t) => content.includes(t))) return [];\n\n // Suppress C-style comments so commented-out crypto isn't reported. Offsets\n // are preserved (chars → spaces), so finding line/column stay exact.\n const masked = maskCommentLines(maskBlockComments(content), [\"//\"]);\n\n const findings: Finding[] = [];\n // Scan the masked text, but build the finding (its snippet) from the ORIGINAL\n // `content` so a line with a trailing comment renders live, not blanked.\n const add = (re: RegExp, rule: RuleMeta) =>\n eachMatch(re, masked, (m) =>\n findings.push(\n findingFromRule(rule, {\n file,\n content,\n index: m.index,\n matchLength: m[0].length,\n }),\n ),\n );\n add(RE_DART_RSA_KEYGEN, RULE_DART_RSA_KEYGEN);\n add(RE_DART_RSA_SIGN, RULE_DART_RSA_SIGN);\n add(RE_DART_ECDSA, RULE_DART_ECDSA);\n add(RE_DART_EC_KEYGEN, RULE_DART_EC_KEYGEN);\n add(RE_DART_ECDH, RULE_DART_ECDH);\n add(RE_DART_ED25519, RULE_DART_ED25519);\n add(RE_DART_X25519, RULE_DART_X25519);\n return findings;\n },\n};\n"]}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Config detector: classical crypto in database usage — public-key encryption of
3
+ * stored data (pgcrypto) and weak client TLS posture. Data-at-rest is the sharpest
4
+ * harvest-now-decrypt-later target: a column encrypted to an RSA key today is a
5
+ * time capsule an adversary can hold until key recovery is cheap.
6
+ *
7
+ * Covered:
8
+ * - pgcrypto `pgp_pub_encrypt` / `pgp_pub_decrypt` in `.sql` (RSA/ElGamal public-key
9
+ * encryption of column data) → `hndl:true`.
10
+ * - libpq `sslmode = allow | prefer | require` in any config/connection file — a
11
+ * mode that does NOT verify the server certificate, so the classical TLS session
12
+ * it negotiates is both MITM-able and harvestable. `disable` is excluded: it
13
+ * negotiates no TLS at all, so there is no key exchange to harvest (a plaintext
14
+ * concern, out of scope for a PQC-readiness scanner).
15
+ */
16
+ import type { Detector } from "../types.js";
17
+ /** Detects classical database at-rest / transport crypto. */
18
+ export declare const databaseDetector: Detector;
19
+ //# sourceMappingURL=database.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/detectors/database.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,aAAa,CAAC;AAoE/D,6DAA6D;AAC7D,eAAO,MAAM,gBAAgB,EAAE,QAwD9B,CAAC"}