@quantakrypto/core 0.4.2 → 0.4.4

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 (223) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +38 -10
  3. package/dist/agent-types.js.map +1 -1
  4. package/dist/baseline.js.map +1 -1
  5. package/dist/cache.js.map +1 -1
  6. package/dist/cbom-merge.d.ts +9 -0
  7. package/dist/cbom-merge.d.ts.map +1 -0
  8. package/dist/cbom-merge.js +99 -0
  9. package/dist/cbom-merge.js.map +1 -0
  10. package/dist/cbom.js.map +1 -1
  11. package/dist/changed.js.map +1 -1
  12. package/dist/codemods/config-toggle.js.map +1 -1
  13. package/dist/codemods/registry.js.map +1 -1
  14. package/dist/comments.d.ts +29 -2
  15. package/dist/comments.d.ts.map +1 -1
  16. package/dist/comments.js +178 -18
  17. package/dist/comments.js.map +1 -1
  18. package/dist/config.js.map +1 -1
  19. package/dist/cwe.js.map +1 -1
  20. package/dist/dependencies.d.ts +3 -2
  21. package/dist/dependencies.d.ts.map +1 -1
  22. package/dist/dependencies.js +138 -2
  23. package/dist/dependencies.js.map +1 -1
  24. package/dist/detect-utils.d.ts +19 -4
  25. package/dist/detect-utils.d.ts.map +1 -1
  26. package/dist/detect-utils.js +43 -6
  27. package/dist/detect-utils.js.map +1 -1
  28. package/dist/detectors/c.d.ts +4 -2
  29. package/dist/detectors/c.d.ts.map +1 -1
  30. package/dist/detectors/c.js +382 -3
  31. package/dist/detectors/c.js.map +1 -1
  32. package/dist/detectors/cicd.d.ts +27 -0
  33. package/dist/detectors/cicd.d.ts.map +1 -0
  34. package/dist/detectors/cicd.js +116 -0
  35. package/dist/detectors/cicd.js.map +1 -0
  36. package/dist/detectors/cloud-kms.d.ts +21 -0
  37. package/dist/detectors/cloud-kms.d.ts.map +1 -0
  38. package/dist/detectors/cloud-kms.js +57 -0
  39. package/dist/detectors/cloud-kms.js.map +1 -0
  40. package/dist/detectors/cloudformation.d.ts +30 -0
  41. package/dist/detectors/cloudformation.d.ts.map +1 -0
  42. package/dist/detectors/cloudformation.js +170 -0
  43. package/dist/detectors/cloudformation.js.map +1 -0
  44. package/dist/detectors/csharp.d.ts.map +1 -1
  45. package/dist/detectors/csharp.js +141 -3
  46. package/dist/detectors/csharp.js.map +1 -1
  47. package/dist/detectors/database.d.ts +17 -0
  48. package/dist/detectors/database.d.ts.map +1 -0
  49. package/dist/detectors/database.js +60 -0
  50. package/dist/detectors/database.js.map +1 -0
  51. package/dist/detectors/dnssec.d.ts +55 -0
  52. package/dist/detectors/dnssec.d.ts.map +1 -0
  53. package/dist/detectors/dnssec.js +107 -0
  54. package/dist/detectors/dnssec.js.map +1 -0
  55. package/dist/detectors/elixir.d.ts +20 -0
  56. package/dist/detectors/elixir.d.ts.map +1 -0
  57. package/dist/detectors/elixir.js +195 -0
  58. package/dist/detectors/elixir.js.map +1 -0
  59. package/dist/detectors/go.d.ts +5 -3
  60. package/dist/detectors/go.d.ts.map +1 -1
  61. package/dist/detectors/go.js +187 -3
  62. package/dist/detectors/go.js.map +1 -1
  63. package/dist/detectors/java.d.ts.map +1 -1
  64. package/dist/detectors/java.js +169 -4
  65. package/dist/detectors/java.js.map +1 -1
  66. package/dist/detectors/jose.d.ts +20 -0
  67. package/dist/detectors/jose.d.ts.map +1 -0
  68. package/dist/detectors/jose.js +62 -0
  69. package/dist/detectors/jose.js.map +1 -0
  70. package/dist/detectors/jwk.d.ts +25 -0
  71. package/dist/detectors/jwk.d.ts.map +1 -0
  72. package/dist/detectors/jwk.js +95 -0
  73. package/dist/detectors/jwk.js.map +1 -0
  74. package/dist/detectors/k8s.d.ts +17 -0
  75. package/dist/detectors/k8s.d.ts.map +1 -0
  76. package/dist/detectors/k8s.js +85 -0
  77. package/dist/detectors/k8s.js.map +1 -0
  78. package/dist/detectors/mesh.d.ts +35 -0
  79. package/dist/detectors/mesh.d.ts.map +1 -0
  80. package/dist/detectors/mesh.js +109 -0
  81. package/dist/detectors/mesh.js.map +1 -0
  82. package/dist/detectors/messaging.d.ts +16 -0
  83. package/dist/detectors/messaging.d.ts.map +1 -0
  84. package/dist/detectors/messaging.js +72 -0
  85. package/dist/detectors/messaging.js.map +1 -0
  86. package/dist/detectors/pem.d.ts.map +1 -1
  87. package/dist/detectors/pem.js +50 -2
  88. package/dist/detectors/pem.js.map +1 -1
  89. package/dist/detectors/php.d.ts +24 -0
  90. package/dist/detectors/php.d.ts.map +1 -0
  91. package/dist/detectors/php.js +167 -0
  92. package/dist/detectors/php.js.map +1 -0
  93. package/dist/detectors/python.d.ts.map +1 -1
  94. package/dist/detectors/python.js +144 -3
  95. package/dist/detectors/python.js.map +1 -1
  96. package/dist/detectors/ruby.d.ts +9 -5
  97. package/dist/detectors/ruby.d.ts.map +1 -1
  98. package/dist/detectors/ruby.js +122 -2
  99. package/dist/detectors/ruby.js.map +1 -1
  100. package/dist/detectors/rust.d.ts +8 -3
  101. package/dist/detectors/rust.d.ts.map +1 -1
  102. package/dist/detectors/rust.js +253 -3
  103. package/dist/detectors/rust.js.map +1 -1
  104. package/dist/detectors/secrets.d.ts +21 -0
  105. package/dist/detectors/secrets.d.ts.map +1 -0
  106. package/dist/detectors/secrets.js +79 -0
  107. package/dist/detectors/secrets.js.map +1 -0
  108. package/dist/detectors/source.d.ts.map +1 -1
  109. package/dist/detectors/source.js +305 -52
  110. package/dist/detectors/source.js.map +1 -1
  111. package/dist/detectors/stateful-hbs.d.ts +22 -0
  112. package/dist/detectors/stateful-hbs.d.ts.map +1 -0
  113. package/dist/detectors/stateful-hbs.js +142 -0
  114. package/dist/detectors/stateful-hbs.js.map +1 -0
  115. package/dist/detectors/terraform.d.ts +21 -0
  116. package/dist/detectors/terraform.d.ts.map +1 -0
  117. package/dist/detectors/terraform.js +123 -0
  118. package/dist/detectors/terraform.js.map +1 -0
  119. package/dist/detectors/vpn.d.ts +22 -0
  120. package/dist/detectors/vpn.d.ts.map +1 -0
  121. package/dist/detectors/vpn.js +99 -0
  122. package/dist/detectors/vpn.js.map +1 -0
  123. package/dist/errors.js.map +1 -1
  124. package/dist/evidence.d.ts +53 -0
  125. package/dist/evidence.d.ts.map +1 -0
  126. package/dist/evidence.js +81 -0
  127. package/dist/evidence.js.map +1 -0
  128. package/dist/index.d.ts +9 -2
  129. package/dist/index.d.ts.map +1 -1
  130. package/dist/index.js +10 -2
  131. package/dist/index.js.map +1 -1
  132. package/dist/inventory.d.ts +2 -0
  133. package/dist/inventory.d.ts.map +1 -1
  134. package/dist/inventory.js +27 -1
  135. package/dist/inventory.js.map +1 -1
  136. package/dist/parallel.js.map +1 -1
  137. package/dist/patch-policy.js.map +1 -1
  138. package/dist/policy.d.ts +67 -0
  139. package/dist/policy.d.ts.map +1 -0
  140. package/dist/policy.js +115 -0
  141. package/dist/policy.js.map +1 -0
  142. package/dist/redact.d.ts.map +1 -1
  143. package/dist/redact.js +39 -0
  144. package/dist/redact.js.map +1 -1
  145. package/dist/registry.d.ts +2 -2
  146. package/dist/registry.d.ts.map +1 -1
  147. package/dist/registry.js +34 -2
  148. package/dist/registry.js.map +1 -1
  149. package/dist/remediate-pipeline.d.ts +3 -0
  150. package/dist/remediate-pipeline.d.ts.map +1 -1
  151. package/dist/remediate-pipeline.js +71 -0
  152. package/dist/remediate-pipeline.js.map +1 -1
  153. package/dist/remediate-request.js.map +1 -1
  154. package/dist/remediation.d.ts +9 -3
  155. package/dist/remediation.d.ts.map +1 -1
  156. package/dist/remediation.js +17 -5
  157. package/dist/remediation.js.map +1 -1
  158. package/dist/report.d.ts +9 -0
  159. package/dist/report.d.ts.map +1 -1
  160. package/dist/report.js +38 -0
  161. package/dist/report.js.map +1 -1
  162. package/dist/scan-worker.js.map +1 -1
  163. package/dist/scan.d.ts.map +1 -1
  164. package/dist/scan.js +8 -1
  165. package/dist/scan.js.map +1 -1
  166. package/dist/severity.js.map +1 -1
  167. package/dist/standards.d.ts +96 -0
  168. package/dist/standards.d.ts.map +1 -0
  169. package/dist/standards.js +107 -0
  170. package/dist/standards.js.map +1 -0
  171. package/dist/triage.js.map +1 -1
  172. package/dist/types.d.ts +2 -2
  173. package/dist/types.d.ts.map +1 -1
  174. package/dist/types.js.map +1 -1
  175. package/dist/verify.js.map +1 -1
  176. package/dist/version.d.ts +1 -1
  177. package/dist/version.js +1 -1
  178. package/dist/version.js.map +1 -1
  179. package/dist/walk.js.map +1 -1
  180. package/dist/worktree.js.map +1 -1
  181. package/package.json +1 -1
  182. package/src/cbom-merge.ts +116 -0
  183. package/src/comments.ts +183 -18
  184. package/src/dependencies.ts +144 -4
  185. package/src/detect-utils.ts +47 -6
  186. package/src/detectors/c.ts +411 -5
  187. package/src/detectors/cicd.ts +158 -0
  188. package/src/detectors/cloud-kms.ts +87 -0
  189. package/src/detectors/cloudformation.ts +215 -0
  190. package/src/detectors/csharp.ts +154 -3
  191. package/src/detectors/database.ts +88 -0
  192. package/src/detectors/dnssec.ts +186 -0
  193. package/src/detectors/elixir.ts +237 -0
  194. package/src/detectors/go.ts +209 -6
  195. package/src/detectors/java.ts +191 -4
  196. package/src/detectors/jose.ts +94 -0
  197. package/src/detectors/jwk.ts +128 -0
  198. package/src/detectors/k8s.ts +112 -0
  199. package/src/detectors/mesh.ts +154 -0
  200. package/src/detectors/messaging.ts +98 -0
  201. package/src/detectors/pem.ts +54 -2
  202. package/src/detectors/php.ts +225 -0
  203. package/src/detectors/python.ts +153 -3
  204. package/src/detectors/ruby.ts +138 -7
  205. package/src/detectors/rust.ts +282 -7
  206. package/src/detectors/secrets.ts +114 -0
  207. package/src/detectors/source.ts +382 -72
  208. package/src/detectors/stateful-hbs.ts +180 -0
  209. package/src/detectors/terraform.ts +154 -0
  210. package/src/detectors/vpn.ts +131 -0
  211. package/src/evidence.ts +135 -0
  212. package/src/index.ts +15 -1
  213. package/src/inventory.ts +31 -1
  214. package/src/policy.ts +180 -0
  215. package/src/redact.ts +41 -0
  216. package/src/registry.ts +34 -2
  217. package/src/remediate-pipeline.ts +78 -0
  218. package/src/remediation.ts +23 -8
  219. package/src/report.ts +48 -2
  220. package/src/scan.ts +13 -1
  221. package/src/standards.ts +186 -0
  222. package/src/types.ts +3 -1
  223. package/src/version.ts +1 -1
@@ -0,0 +1,72 @@
1
+ import { eachMatch, findingFromRule, hasExtension } from "../detect-utils.js";
2
+ import { CWE_RISKY_PRIMITIVE, CWE_BROKEN_CRYPTO } from "../cwe.js";
3
+ const MQ_EXTENSIONS = [".properties", ".conf", ".cfg", ".ini"];
4
+ const MQ_RULES = [
5
+ {
6
+ // Match TLSv1 (=1.0) and TLSv1.1 but never TLSv1.2 / TLSv1.3: the negative
7
+ // lookahead stops "TLSv1" from matching the "TLSv1" inside "TLSv1.3".
8
+ re: /\bssl\.(?:enabled\.)?protocols?\s*=\s*[^\n]*\bTLSv1(?:\.1)?(?![.\d])/gi,
9
+ meta: {
10
+ id: "mq-kafka-legacy-tls",
11
+ title: "Kafka legacy TLS protocol",
12
+ description: "Kafka ssl.protocol / ssl.enabled.protocols permits TLS 1.0 / 1.1",
13
+ category: "tls",
14
+ severity: "medium",
15
+ confidence: "high",
16
+ hndl: false,
17
+ cwe: CWE_RISKY_PRIMITIVE,
18
+ message: "Kafka broker permits legacy TLS 1.0/1.1; its classical key exchange is weak and harvestable.",
19
+ remediation: "Require TLS 1.3 and track PQC-hybrid KEX (X25519MLKEM768).",
20
+ },
21
+ },
22
+ {
23
+ re: /\btls_version\s+tlsv1(?:\.1)?(?![.\d])/gi,
24
+ meta: {
25
+ id: "mq-mqtt-legacy-tls",
26
+ title: "MQTT legacy TLS version",
27
+ description: "Mosquitto/MQTT tls_version permits TLS 1.0 / 1.1",
28
+ category: "tls",
29
+ severity: "medium",
30
+ confidence: "high",
31
+ hndl: false,
32
+ cwe: CWE_RISKY_PRIMITIVE,
33
+ message: "MQTT broker permits legacy TLS 1.0/1.1; its classical key exchange is weak and harvestable.",
34
+ remediation: "Require TLS 1.3 and track PQC-hybrid KEX for device fleets.",
35
+ },
36
+ },
37
+ {
38
+ re: /\bssl\.cipher\.suites\s*=\s*[^\n]*(?:ECDHE_RSA|ECDHE_ECDSA|TLS_RSA|_DHE_RSA)/g,
39
+ meta: {
40
+ id: "mq-classical-cipher",
41
+ title: "Broker classical (EC)DHE cipher suite",
42
+ description: "Kafka ssl.cipher.suites names a classical ECDHE/DHE/RSA suite",
43
+ category: "tls",
44
+ severity: "medium",
45
+ confidence: "high",
46
+ algorithm: "ECDH",
47
+ hndl: true,
48
+ cwe: CWE_BROKEN_CRYPTO,
49
+ message: "Broker TLS is pinned to a classical (EC)DHE/RSA cipher suite; the key exchange is harvest-now-decrypt-later exposed.",
50
+ remediation: "Move to TLS 1.3 with a PQC-hybrid group (X25519MLKEM768) once the broker/runtime supports it.",
51
+ },
52
+ },
53
+ ];
54
+ /** Detects classical transport crypto in message-broker / event-stream config. */
55
+ export const messagingDetector = {
56
+ id: "messaging-transport",
57
+ description: "Classical transport crypto in message brokers (Kafka, MQTT, RabbitMQ, NATS)",
58
+ scope: "config",
59
+ language: "any",
60
+ rules: MQ_RULES.map((r) => r.meta),
61
+ appliesTo: (f) => hasExtension(f, MQ_EXTENSIONS),
62
+ detect({ file, content }) {
63
+ const findings = [];
64
+ for (const rule of MQ_RULES) {
65
+ eachMatch(rule.re, content, (m) => {
66
+ findings.push(findingFromRule(rule.meta, { file, content, index: m.index, matchLength: m[0].length }));
67
+ });
68
+ }
69
+ return findings;
70
+ },
71
+ };
72
+ //# sourceMappingURL=messaging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging.js","sourceRoot":"","sources":["../../src/detectors/messaging.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEnE,MAAM,aAAa,GAAsB,CAAC,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAOlF,MAAM,QAAQ,GAAa;IACzB;QACE,2EAA2E;QAC3E,sEAAsE;QACtE,EAAE,EAAE,wEAAwE;QAC5E,IAAI,EAAE;YACJ,EAAE,EAAE,qBAAqB;YACzB,KAAK,EAAE,2BAA2B;YAClC,WAAW,EAAE,kEAAkE;YAC/E,QAAQ,EAAE,KAAK;YACf,QAAQ,EAAE,QAAQ;YAClB,UAAU,EAAE,MAAM;YAClB,IAAI,EAAE,KAAK;YACX,GAAG,EAAE,mBAAmB;YACxB,OAAO,EACL,8FAA8F;YAChG,WAAW,EAAE,4DAA4D;SAC1E;KACF;IACD;QACE,EAAE,EAAE,0CAA0C;QAC9C,IAAI,EAAE;YACJ,EAAE,EAAE,oBAAoB;YACxB,KAAK,EAAE,yBAAyB;YAChC,WAAW,EAAE,kDAAkD;YAC/D,QAAQ,EAAE,KAAK;YACf,QAAQ,EAAE,QAAQ;YAClB,UAAU,EAAE,MAAM;YAClB,IAAI,EAAE,KAAK;YACX,GAAG,EAAE,mBAAmB;YACxB,OAAO,EACL,6FAA6F;YAC/F,WAAW,EAAE,6DAA6D;SAC3E;KACF;IACD;QACE,EAAE,EAAE,+EAA+E;QACnF,IAAI,EAAE;YACJ,EAAE,EAAE,qBAAqB;YACzB,KAAK,EAAE,uCAAuC;YAC9C,WAAW,EAAE,+DAA+D;YAC5E,QAAQ,EAAE,KAAK;YACf,QAAQ,EAAE,QAAQ;YAClB,UAAU,EAAE,MAAM;YAClB,SAAS,EAAE,MAAM;YACjB,IAAI,EAAE,IAAI;YACV,GAAG,EAAE,iBAAiB;YACtB,OAAO,EACL,sHAAsH;YACxH,WAAW,EACT,+FAA+F;SAClG;KACF;CACF,CAAC;AAEF,kFAAkF;AAClF,MAAM,CAAC,MAAM,iBAAiB,GAAa;IACzC,EAAE,EAAE,qBAAqB;IACzB,WAAW,EAAE,6EAA6E;IAC1F,KAAK,EAAE,QAAQ;IACf,QAAQ,EAAE,KAAK;IACf,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAClC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,aAAa,CAAC;IAChD,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE;QACtB,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;gBAChC,QAAQ,CAAC,IAAI,CACX,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CACxF,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC","sourcesContent":["/**\n * Config detector: classical transport crypto in message brokers / event streams\n * (Kafka, RabbitMQ, MQTT/Mosquitto, NATS). Broker traffic is \"communication\n * between things\"; a legacy TLS floor or a classical (EC)DHE cipher suite makes\n * every message in flight harvest-now-decrypt-later exposed.\n *\n * Covered in broker config files (`.properties`, `.conf`, `.cfg`, `.ini`):\n * - Kafka `ssl.protocol` / `ssl.enabled.protocols = TLSv1 | TLSv1.1` (legacy).\n * - MQTT/Mosquitto `tls_version tlsv1 | tlsv1.1` (legacy).\n * - Kafka `ssl.cipher.suites` naming a classical `ECDHE_RSA` / `ECDHE_ECDSA` /\n * `TLS_RSA` suite — the harvestable key-exchange path.\n */\nimport type { Detector, Finding, RuleMeta } from \"../types.js\";\nimport { eachMatch, findingFromRule, hasExtension } from \"../detect-utils.js\";\nimport { CWE_RISKY_PRIMITIVE, CWE_BROKEN_CRYPTO } from \"../cwe.js\";\n\nconst MQ_EXTENSIONS: readonly string[] = [\".properties\", \".conf\", \".cfg\", \".ini\"];\n\ninterface MqRule {\n re: RegExp;\n meta: RuleMeta;\n}\n\nconst MQ_RULES: MqRule[] = [\n {\n // Match TLSv1 (=1.0) and TLSv1.1 but never TLSv1.2 / TLSv1.3: the negative\n // lookahead stops \"TLSv1\" from matching the \"TLSv1\" inside \"TLSv1.3\".\n re: /\\bssl\\.(?:enabled\\.)?protocols?\\s*=\\s*[^\\n]*\\bTLSv1(?:\\.1)?(?![.\\d])/gi,\n meta: {\n id: \"mq-kafka-legacy-tls\",\n title: \"Kafka legacy TLS protocol\",\n description: \"Kafka ssl.protocol / ssl.enabled.protocols permits TLS 1.0 / 1.1\",\n category: \"tls\",\n severity: \"medium\",\n confidence: \"high\",\n hndl: false,\n cwe: CWE_RISKY_PRIMITIVE,\n message:\n \"Kafka broker permits legacy TLS 1.0/1.1; its classical key exchange is weak and harvestable.\",\n remediation: \"Require TLS 1.3 and track PQC-hybrid KEX (X25519MLKEM768).\",\n },\n },\n {\n re: /\\btls_version\\s+tlsv1(?:\\.1)?(?![.\\d])/gi,\n meta: {\n id: \"mq-mqtt-legacy-tls\",\n title: \"MQTT legacy TLS version\",\n description: \"Mosquitto/MQTT tls_version permits TLS 1.0 / 1.1\",\n category: \"tls\",\n severity: \"medium\",\n confidence: \"high\",\n hndl: false,\n cwe: CWE_RISKY_PRIMITIVE,\n message:\n \"MQTT broker permits legacy TLS 1.0/1.1; its classical key exchange is weak and harvestable.\",\n remediation: \"Require TLS 1.3 and track PQC-hybrid KEX for device fleets.\",\n },\n },\n {\n re: /\\bssl\\.cipher\\.suites\\s*=\\s*[^\\n]*(?:ECDHE_RSA|ECDHE_ECDSA|TLS_RSA|_DHE_RSA)/g,\n meta: {\n id: \"mq-classical-cipher\",\n title: \"Broker classical (EC)DHE cipher suite\",\n description: \"Kafka ssl.cipher.suites names a classical ECDHE/DHE/RSA suite\",\n category: \"tls\",\n severity: \"medium\",\n confidence: \"high\",\n algorithm: \"ECDH\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"Broker TLS is pinned to a classical (EC)DHE/RSA cipher suite; the key exchange is harvest-now-decrypt-later exposed.\",\n remediation:\n \"Move to TLS 1.3 with a PQC-hybrid group (X25519MLKEM768) once the broker/runtime supports it.\",\n },\n },\n];\n\n/** Detects classical transport crypto in message-broker / event-stream config. */\nexport const messagingDetector: Detector = {\n id: \"messaging-transport\",\n description: \"Classical transport crypto in message brokers (Kafka, MQTT, RabbitMQ, NATS)\",\n scope: \"config\",\n language: \"any\",\n rules: MQ_RULES.map((r) => r.meta),\n appliesTo: (f) => hasExtension(f, MQ_EXTENSIONS),\n detect({ file, content }): Finding[] {\n const findings: Finding[] = [];\n for (const rule of MQ_RULES) {\n eachMatch(rule.re, content, (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":"pem.d.ts","sourceRoot":"","sources":["../../src/detectors/pem.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,aAAa,CAAC;AAwJ/D,+DAA+D;AAC/D,eAAO,MAAM,WAAW,EAAE,QA2BzB,CAAC"}
1
+ {"version":3,"file":"pem.d.ts","sourceRoot":"","sources":["../../src/detectors/pem.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,aAAa,CAAC;AA4M/D,+DAA+D;AAC/D,eAAO,MAAM,WAAW,EAAE,QA2BzB,CAAC"}
@@ -32,7 +32,7 @@ const PEM_RULES = [
32
32
  cwe: CWE_HARDCODED_KEY,
33
33
  sensitive: true,
34
34
  message: "Embedded EC private key (SEC1 PEM); classical ECDSA/ECDH key, not quantum-safe.",
35
- remediation: "Migrate to ML-DSA (FIPS 204) keys and remove embedded private keys from source.",
35
+ remediation: "Migrate to ML-DSA (FIPS 204) for signatures or hybrid X25519MLKEM768 for key agreement; remove embedded private keys from source.",
36
36
  },
37
37
  },
38
38
  {
@@ -66,7 +66,7 @@ const PEM_RULES = [
66
66
  cwe: CWE_HARDCODED_KEY,
67
67
  sensitive: true,
68
68
  message: "Embedded OpenSSH private key (RSA/ECDSA/Ed25519); classical and not quantum-safe.",
69
- remediation: "Rotate the key; plan migration to PQC-capable SSH (e.g. sntrup761x25519).",
69
+ remediation: "Rotate the key; plan migration to PQC-capable SSH (prefer the mlkem768x25519-sha256 KEX, OpenSSH 10's default since Apr 2025).",
70
70
  },
71
71
  },
72
72
  {
@@ -135,6 +135,54 @@ const PEM_RULES = [
135
135
  remediation: "Plan re-issuance with PQC-capable CAs as ML-DSA certificate profiles mature.",
136
136
  },
137
137
  },
138
+ {
139
+ re: /-----BEGIN (?:RSA )?PUBLIC KEY-----/g,
140
+ meta: {
141
+ id: "pem-public-key",
142
+ title: "Classical public key (PEM)",
143
+ description: "SubjectPublicKeyInfo / PKCS#1 RSA public key block",
144
+ category: "certificate",
145
+ severity: "low",
146
+ confidence: "high",
147
+ algorithm: "unknown",
148
+ hndl: false,
149
+ cwe: CWE_BROKEN_CRYPTO,
150
+ message: "Embedded classical public key (RSA/EC/DSA); its key pair is not quantum-safe — forgeable signatures or classical key exchange.",
151
+ remediation: "Re-issue with PQC keys (ML-DSA / ML-KEM) as the ecosystem adopts them.",
152
+ },
153
+ },
154
+ {
155
+ re: /-----BEGIN DH PARAMETERS-----/g,
156
+ meta: {
157
+ id: "pem-dh-parameters",
158
+ title: "Diffie-Hellman parameters (PEM)",
159
+ description: "Finite-field DH group parameters block",
160
+ category: "key-exchange",
161
+ severity: "medium",
162
+ confidence: "high",
163
+ algorithm: "DH",
164
+ hndl: true,
165
+ cwe: CWE_BROKEN_CRYPTO,
166
+ message: "Embedded finite-field Diffie-Hellman parameters; classical DH key exchange is harvest-now-decrypt-later exposed.",
167
+ remediation: "Migrate key exchange to hybrid X25519MLKEM768 (ML-KEM-768).",
168
+ },
169
+ },
170
+ {
171
+ re: /-----BEGIN (?:NEW )?CERTIFICATE REQUEST-----/g,
172
+ meta: {
173
+ id: "pem-cert-request",
174
+ title: "Certificate signing request (PEM)",
175
+ description: "PKCS#10 certificate request block",
176
+ category: "certificate",
177
+ severity: "low",
178
+ confidence: "high",
179
+ algorithm: "unknown",
180
+ hndl: false,
181
+ cwe: CWE_BROKEN_CRYPTO,
182
+ message: "Embedded PKCS#10 CSR; carries a classical public key and will be signed with classical crypto.",
183
+ remediation: "Re-generate with PQC keys as PQC-capable CAs mature.",
184
+ },
185
+ },
138
186
  ];
139
187
  /** Detects PEM key/certificate material in arbitrary files. */
140
188
  export const pemDetector = {
@@ -1 +1 @@
1
- {"version":3,"file":"pem.js","sourceRoot":"","sources":["../../src/detectors/pem.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pem.js","sourceRoot":"","sources":["../../src/detectors/pem.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Config / certificate detector: finds PEM-encoded cryptographic material in\n * any text file (source, config, .pem, .key, .crt, .env, …). This catches\n * embedded private keys and X.509 certificates regardless of language.\n *\n * Every rule's metadata lives in the {@link RuleMeta} declaration below (the\n * catalog entry); `detect()` builds findings straight from it via\n * `findingFromRule`. All PEM findings are high-confidence exact-marker matches.\n */\nimport type { Detector, Finding, RuleMeta } from \"../types.js\";\nimport { eachMatch, findingFromRule } from \"../detect-utils.js\";\nimport { CWE_BROKEN_CRYPTO, CWE_HARDCODED_KEY } from \"../cwe.js\";\n\n/** A PEM rule: its catalog metadata plus the begin-marker regex that triggers it. */\ninterface PemRule {\n /** Regex matching the PEM begin marker. */\n re: RegExp;\n meta: RuleMeta;\n}\n\nconst PEM_RULES: PemRule[] = [\n {\n re: /-----BEGIN RSA PRIVATE KEY-----/g,\n meta: {\n id: \"pem-rsa-private-key\",\n title: \"RSA private key (PEM)\",\n description: \"PKCS#1 RSA private key block\",\n category: \"certificate\",\n severity: \"critical\",\n confidence: \"high\",\n algorithm: \"RSA\",\n hndl: true,\n cwe: CWE_HARDCODED_KEY,\n sensitive: true,\n message: \"Embedded RSA private key (PKCS#1 PEM); classical and not quantum-safe.\",\n remediation: \"Migrate to ML-DSA / ML-KEM keys and remove embedded private keys from source.\",\n },\n },\n {\n re: /-----BEGIN EC PRIVATE KEY-----/g,\n meta: {\n id: \"pem-ec-private-key\",\n title: \"EC private key (PEM)\",\n description: \"SEC1 EC private key block\",\n category: \"certificate\",\n severity: \"critical\",\n confidence: \"high\",\n algorithm: \"ECDSA\",\n hndl: true,\n cwe: CWE_HARDCODED_KEY,\n sensitive: true,\n message: \"Embedded EC private key (SEC1 PEM); classical ECDSA/ECDH key, not quantum-safe.\",\n remediation:\n \"Migrate to ML-DSA (FIPS 204) for signatures or hybrid X25519MLKEM768 for key agreement; remove embedded private keys from source.\",\n },\n },\n {\n re: /-----BEGIN DSA PRIVATE KEY-----/g,\n meta: {\n id: \"pem-dsa-private-key\",\n title: \"DSA private key (PEM)\",\n description: \"DSA private key block\",\n category: \"certificate\",\n severity: \"critical\",\n confidence: \"high\",\n algorithm: \"DSA\",\n hndl: false,\n cwe: CWE_HARDCODED_KEY,\n sensitive: true,\n message:\n \"Embedded DSA private key (PEM); classical, already deprecated, and not quantum-safe.\",\n remediation: \"Rotate immediately (DSA is deprecated) and migrate to ML-DSA-65 (FIPS 204).\",\n },\n },\n {\n re: /-----BEGIN OPENSSH PRIVATE KEY-----/g,\n meta: {\n id: \"pem-openssh-private-key\",\n title: \"OpenSSH private key\",\n description: \"OpenSSH private key block\",\n category: \"certificate\",\n severity: \"critical\",\n confidence: \"high\",\n algorithm: \"unknown\",\n hndl: true,\n cwe: CWE_HARDCODED_KEY,\n sensitive: true,\n message: \"Embedded OpenSSH private key (RSA/ECDSA/Ed25519); classical and not quantum-safe.\",\n remediation:\n \"Rotate the key; plan migration to PQC-capable SSH (prefer the mlkem768x25519-sha256 KEX, OpenSSH 10's default since Apr 2025).\",\n },\n },\n {\n re: /-----BEGIN PGP PRIVATE KEY BLOCK-----/g,\n meta: {\n id: \"pem-pgp-private-key\",\n title: \"PGP/GPG private key block\",\n description: \"OpenPGP private key block\",\n category: \"certificate\",\n severity: \"critical\",\n confidence: \"high\",\n algorithm: \"unknown\",\n hndl: true,\n cwe: CWE_HARDCODED_KEY,\n sensitive: true,\n message:\n \"Embedded PGP/GPG private key block (RSA/ECDSA/EdDSA/ElGamal); classical and not quantum-safe.\",\n remediation: \"Rotate the key; track OpenPGP PQC drafts for migration.\",\n },\n },\n {\n re: /-----BEGIN PGP MESSAGE-----/g,\n meta: {\n id: \"pem-pgp-message\",\n title: \"PGP/GPG encrypted message\",\n description: \"OpenPGP encrypted message block\",\n category: \"certificate\",\n severity: \"low\",\n confidence: \"high\",\n algorithm: \"unknown\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"Embedded PGP/GPG message; likely encrypted with classical RSA/ElGamal (harvest-now-decrypt-later).\",\n remediation: \"Re-encrypt with PQC-capable tooling as OpenPGP PQC profiles mature.\",\n },\n },\n {\n re: /-----BEGIN (?:ENCRYPTED )?PRIVATE KEY-----/g,\n meta: {\n id: \"pem-pkcs8-private-key\",\n title: \"Private key (PKCS#8 PEM)\",\n description: \"PKCS#8 private key block\",\n category: \"certificate\",\n severity: \"critical\",\n confidence: \"high\",\n algorithm: \"unknown\",\n hndl: true,\n cwe: CWE_HARDCODED_KEY,\n sensitive: true,\n message: \"Embedded PKCS#8 private key; likely classical RSA/EC, not quantum-safe.\",\n remediation: \"Migrate to PQC keys and remove embedded private keys from source.\",\n },\n },\n {\n re: /-----BEGIN CERTIFICATE-----/g,\n meta: {\n id: \"pem-certificate\",\n title: \"X.509 certificate (PEM)\",\n description: \"X.509 certificate block\",\n category: \"certificate\",\n severity: \"low\",\n confidence: \"high\",\n algorithm: \"unknown\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message: \"Embedded X.509 certificate; almost certainly signed with classical RSA/ECDSA.\",\n remediation: \"Plan re-issuance with PQC-capable CAs as ML-DSA certificate profiles mature.\",\n },\n },\n {\n re: /-----BEGIN (?:RSA )?PUBLIC KEY-----/g,\n meta: {\n id: \"pem-public-key\",\n title: \"Classical public key (PEM)\",\n description: \"SubjectPublicKeyInfo / PKCS#1 RSA public key block\",\n category: \"certificate\",\n severity: \"low\",\n confidence: \"high\",\n algorithm: \"unknown\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"Embedded classical public key (RSA/EC/DSA); its key pair is not quantum-safe — forgeable signatures or classical key exchange.\",\n remediation: \"Re-issue with PQC keys (ML-DSA / ML-KEM) as the ecosystem adopts them.\",\n },\n },\n {\n re: /-----BEGIN DH PARAMETERS-----/g,\n meta: {\n id: \"pem-dh-parameters\",\n title: \"Diffie-Hellman parameters (PEM)\",\n description: \"Finite-field DH group parameters block\",\n category: \"key-exchange\",\n severity: \"medium\",\n confidence: \"high\",\n algorithm: \"DH\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"Embedded finite-field Diffie-Hellman parameters; classical DH key exchange is harvest-now-decrypt-later exposed.\",\n remediation: \"Migrate key exchange to hybrid X25519MLKEM768 (ML-KEM-768).\",\n },\n },\n {\n re: /-----BEGIN (?:NEW )?CERTIFICATE REQUEST-----/g,\n meta: {\n id: \"pem-cert-request\",\n title: \"Certificate signing request (PEM)\",\n description: \"PKCS#10 certificate request block\",\n category: \"certificate\",\n severity: \"low\",\n confidence: \"high\",\n algorithm: \"unknown\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"Embedded PKCS#10 CSR; carries a classical public key and will be signed with classical crypto.\",\n remediation: \"Re-generate with PQC keys as PQC-capable CAs mature.\",\n },\n },\n];\n\n/** Detects PEM key/certificate material in arbitrary files. */\nexport const pemDetector: Detector = {\n id: \"pem-material\",\n description: \"PEM-encoded private keys and X.509 certificates in any file\",\n scope: \"config\",\n language: \"any\",\n rules: PEM_RULES.map((r) => r.meta),\n // Applies to every text file; the walker already filters out binaries.\n appliesTo: () => true,\n detect({ file, content }): Finding[] {\n // Fast reject: only proceed if a PEM header is present at all.\n if (!content.includes(\"-----BEGIN \")) return [];\n\n const findings: Finding[] = [];\n for (const rule of PEM_RULES) {\n eachMatch(rule.re, content, (m) => {\n findings.push(\n findingFromRule(rule.meta, {\n file,\n content,\n index: m.index,\n matchLength: m[0].length,\n }),\n );\n });\n }\n return findings;\n },\n};\n"]}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Source-code detector for classical asymmetric cryptography in PHP — one of the
3
+ * most-deployed backend languages, previously uncovered. Handles the three
4
+ * dominant crypto surfaces:
5
+ *
6
+ * - **ext/openssl** — `openssl_pkey_new()` (classified by its
7
+ * `OPENSSL_KEYTYPE_*` config, defaulting to RSA), `openssl_public_encrypt` /
8
+ * `openssl_private_decrypt` (RSA), and `openssl_sign` / `openssl_verify`.
9
+ * - **phpseclib3** — `RSA::createKey()` / `EC::createKey()` / `DSA::createKey()`.
10
+ * - **libsodium** — `sodium_crypto_box`/`kx` keypairs (X25519) and
11
+ * `sodium_crypto_sign` keypairs (Ed25519).
12
+ *
13
+ * Lexical, like the other packs; the `openssl_*` / `sodium_crypto_*` prefixes and
14
+ * `OPENSSL_KEYTYPE_*` constants are distinctive, so the false-positive rate is low.
15
+ *
16
+ * HNDL: RSA encryption and (EC/X)DH key agreement are harvest-now-decrypt-later
17
+ * exposed (hndl:true); ECDSA / DSA / Ed25519 signatures are hndl:false but
18
+ * forgeable. `openssl_pkey_new` EC and `EC::createKey` are ambiguous (feed BOTH
19
+ * ECDSA and ECDH), classified conservatively as key-exchange-capable (hndl:true).
20
+ */
21
+ import type { Detector } from "../types.js";
22
+ /** Detects classical asymmetric crypto in PHP (openssl, phpseclib, libsodium). */
23
+ export declare const phpDetector: Detector;
24
+ //# sourceMappingURL=php.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"php.d.ts","sourceRoot":"","sources":["../../src/detectors/php.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,aAAa,CAAC;AAqI/D,kFAAkF;AAClF,eAAO,MAAM,WAAW,EAAE,QAsEzB,CAAC"}
@@ -0,0 +1,167 @@
1
+ import { PHP_EXTENSIONS, eachMatch, findingFromRule, hasExtension } from "../detect-utils.js";
2
+ import { CWE_BROKEN_CRYPTO } from "../cwe.js";
3
+ const RE_PHP_PKEY_NEW = /\bopenssl_pkey_new\s*\(/g;
4
+ const RE_PHP_RSA_CRYPT = /\bopenssl_(?:public_encrypt|private_decrypt)\s*\(/g;
5
+ const RE_PHP_SIGN = /\bopenssl_(?:sign|verify)\s*\(/g;
6
+ // phpseclib3 factory methods. The class names are generic, so require `::createKey`.
7
+ const RE_PHP_SECLIB = /\b(RSA|EC|DSA|DH)::createKey\s*\(/g;
8
+ // libsodium X25519 (box / kx / scalarmult) and Ed25519 (sign) key pairs.
9
+ const RE_PHP_SODIUM_X25519 = /\bsodium_crypto_(?:box|kx)_(?:seed_)?keypair\s*\(|\bsodium_crypto_scalarmult(?:_base)?\s*\(/g;
10
+ const RE_PHP_SODIUM_ED25519 = /\bsodium_crypto_sign_(?:seed_)?keypair\s*\(/g;
11
+ const HYBRID = "hybrid X25519MLKEM768 (ML-KEM-768) for key agreement; ML-DSA-65 (FIPS 204) to sign";
12
+ const RULE_PHP_KEYGEN = {
13
+ id: "php-openssl-keygen",
14
+ title: "PHP openssl key generation",
15
+ description: "openssl_pkey_new (RSA/EC/DSA/DH, by OPENSSL_KEYTYPE_*)",
16
+ category: "kem",
17
+ severity: "high",
18
+ confidence: "high",
19
+ algorithm: "RSA",
20
+ hndl: true,
21
+ cwe: CWE_BROKEN_CRYPTO,
22
+ message: "Generates a classical key pair via PHP openssl_pkey_new — not quantum-safe.",
23
+ };
24
+ const RULE_PHP_RSA_CRYPT = {
25
+ id: "php-openssl-rsa-crypt",
26
+ title: "PHP openssl RSA public-key encryption",
27
+ description: "openssl_public_encrypt / openssl_private_decrypt",
28
+ category: "kem",
29
+ severity: "high",
30
+ confidence: "high",
31
+ algorithm: "RSA",
32
+ hndl: true,
33
+ cwe: CWE_BROKEN_CRYPTO,
34
+ message: "RSA public-key encryption/decryption (PHP openssl) is harvest-now-decrypt-later exposed.",
35
+ };
36
+ const RULE_PHP_SIGN = {
37
+ id: "php-openssl-sign",
38
+ title: "PHP openssl signature",
39
+ description: "openssl_sign / openssl_verify",
40
+ category: "signature",
41
+ severity: "high",
42
+ confidence: "high",
43
+ algorithm: "unknown",
44
+ hndl: false,
45
+ cwe: CWE_BROKEN_CRYPTO,
46
+ message: "Classical signature via PHP openssl (RSA/ECDSA/DSA) is forgeable by a quantum attacker.",
47
+ remediation: "ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205)",
48
+ };
49
+ const RULE_PHP_SECLIB = {
50
+ id: "php-phpseclib-keygen",
51
+ title: "PHP phpseclib key generation",
52
+ description: "phpseclib3 RSA/EC/DSA/DH ::createKey",
53
+ category: "kem",
54
+ severity: "high",
55
+ confidence: "medium",
56
+ algorithm: "RSA",
57
+ hndl: true,
58
+ cwe: CWE_BROKEN_CRYPTO,
59
+ message: "Generates a classical key pair via phpseclib3 (createKey) — not quantum-safe.",
60
+ };
61
+ const RULE_PHP_SODIUM_X25519 = {
62
+ id: "php-sodium-x25519",
63
+ title: "PHP libsodium X25519 key agreement",
64
+ description: "sodium_crypto_box/kx keypair + scalarmult",
65
+ category: "key-exchange",
66
+ severity: "medium",
67
+ confidence: "high",
68
+ algorithm: "X25519",
69
+ hndl: true,
70
+ cwe: CWE_BROKEN_CRYPTO,
71
+ message: "libsodium crypto_box/kx (PHP) uses X25519 key agreement — modern but classical, harvest-now-decrypt-later exposed.",
72
+ };
73
+ const RULE_PHP_SODIUM_ED25519 = {
74
+ id: "php-sodium-ed25519",
75
+ title: "PHP libsodium Ed25519 signature",
76
+ description: "sodium_crypto_sign keypair",
77
+ category: "signature",
78
+ severity: "low",
79
+ confidence: "high",
80
+ algorithm: "EdDSA",
81
+ hndl: false,
82
+ cwe: CWE_BROKEN_CRYPTO,
83
+ message: "libsodium crypto_sign (PHP) uses Ed25519 — classical and forgeable by a quantum attacker.",
84
+ };
85
+ /** phpseclib class name → its classification. */
86
+ const SECLIB_INFO = {
87
+ RSA: { algo: "RSA", cat: "kem", sev: "high", hndl: true, label: "RSA" },
88
+ EC: {
89
+ algo: "ECDH",
90
+ cat: "key-exchange",
91
+ sev: "high",
92
+ hndl: true,
93
+ label: "EC (ECDSA/ECDH)",
94
+ remediation: HYBRID,
95
+ },
96
+ DSA: { algo: "DSA", cat: "signature", sev: "high", hndl: false, label: "DSA" },
97
+ DH: { algo: "DH", cat: "key-exchange", sev: "high", hndl: true, label: "Diffie-Hellman" },
98
+ };
99
+ /** Classify `openssl_pkey_new` by the `OPENSSL_KEYTYPE_*` constant in its config.
100
+ * The window is bounded to the current statement (up to the next `;`, capped at
101
+ * 300 chars) so it can't bleed into a following `openssl_pkey_new` call's key
102
+ * type. Defaults to RSA — openssl_pkey_new's own default private_key_type is RSA
103
+ * when none is given. */
104
+ function classifyPkeyNew(content, index) {
105
+ const semi = content.indexOf(";", index);
106
+ const end = Math.min(index + 300, semi === -1 ? content.length : semi);
107
+ const w = content.slice(index, end);
108
+ if (/\bOPENSSL_KEYTYPE_EC\b/.test(w))
109
+ return SECLIB_INFO.EC;
110
+ if (/\bOPENSSL_KEYTYPE_DSA\b/.test(w))
111
+ return SECLIB_INFO.DSA;
112
+ if (/\bOPENSSL_KEYTYPE_DH\b/.test(w))
113
+ return SECLIB_INFO.DH;
114
+ return SECLIB_INFO.RSA;
115
+ }
116
+ /** Detects classical asymmetric crypto in PHP (openssl, phpseclib, libsodium). */
117
+ export const phpDetector = {
118
+ id: "php-crypto",
119
+ description: "Classical asymmetric crypto in PHP (openssl, phpseclib3, libsodium)",
120
+ scope: "source",
121
+ language: "php",
122
+ rules: [
123
+ RULE_PHP_KEYGEN,
124
+ RULE_PHP_RSA_CRYPT,
125
+ RULE_PHP_SIGN,
126
+ RULE_PHP_SECLIB,
127
+ RULE_PHP_SODIUM_X25519,
128
+ RULE_PHP_SODIUM_ED25519,
129
+ ],
130
+ appliesTo: (f) => hasExtension(f, PHP_EXTENSIONS),
131
+ detect({ file, content }) {
132
+ const findings = [];
133
+ const add = (re, rule) => eachMatch(re, content, (m) => findings.push(findingFromRule(rule, { file, content, index: m.index, matchLength: m[0].length })));
134
+ // openssl_pkey_new — one finding per call, classified by its key-type config.
135
+ eachMatch(RE_PHP_PKEY_NEW, content, (m) => {
136
+ const info = classifyPkeyNew(content, m.index);
137
+ findings.push(findingFromRule(RULE_PHP_KEYGEN, { file, content, index: m.index, matchLength: m[0].length }, {
138
+ title: `PHP openssl ${info.label} key generation`,
139
+ category: info.cat,
140
+ severity: info.sev,
141
+ algorithm: info.algo,
142
+ hndl: info.hndl,
143
+ message: `Generates a classical ${info.label} key pair via PHP openssl_pkey_new — not quantum-safe.`,
144
+ ...(info.remediation ? { remediation: info.remediation } : {}),
145
+ }));
146
+ });
147
+ add(RE_PHP_RSA_CRYPT, RULE_PHP_RSA_CRYPT);
148
+ add(RE_PHP_SIGN, RULE_PHP_SIGN);
149
+ // phpseclib3 ::createKey — classify by the class (RSA/EC/DSA/DH).
150
+ eachMatch(RE_PHP_SECLIB, content, (m) => {
151
+ const info = SECLIB_INFO[m[1]];
152
+ findings.push(findingFromRule(RULE_PHP_SECLIB, { file, content, index: m.index, matchLength: m[0].length }, {
153
+ title: `PHP phpseclib ${info.label} key generation`,
154
+ category: info.cat,
155
+ severity: info.sev,
156
+ algorithm: info.algo,
157
+ hndl: info.hndl,
158
+ message: `Generates a classical ${info.label} key pair via phpseclib3 createKey — not quantum-safe.`,
159
+ ...(info.remediation ? { remediation: info.remediation } : {}),
160
+ }));
161
+ });
162
+ add(RE_PHP_SODIUM_X25519, RULE_PHP_SODIUM_X25519);
163
+ add(RE_PHP_SODIUM_ED25519, RULE_PHP_SODIUM_ED25519);
164
+ return findings;
165
+ },
166
+ };
167
+ //# sourceMappingURL=php.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"php.js","sourceRoot":"","sources":["../../src/detectors/php.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Source-code detector for classical asymmetric cryptography in PHP — one of the\n * most-deployed backend languages, previously uncovered. Handles the three\n * dominant crypto surfaces:\n *\n * - **ext/openssl** — `openssl_pkey_new()` (classified by its\n * `OPENSSL_KEYTYPE_*` config, defaulting to RSA), `openssl_public_encrypt` /\n * `openssl_private_decrypt` (RSA), and `openssl_sign` / `openssl_verify`.\n * - **phpseclib3** — `RSA::createKey()` / `EC::createKey()` / `DSA::createKey()`.\n * - **libsodium** — `sodium_crypto_box`/`kx` keypairs (X25519) and\n * `sodium_crypto_sign` keypairs (Ed25519).\n *\n * Lexical, like the other packs; the `openssl_*` / `sodium_crypto_*` prefixes and\n * `OPENSSL_KEYTYPE_*` constants are distinctive, so the false-positive rate is low.\n *\n * HNDL: RSA encryption and (EC/X)DH key agreement are harvest-now-decrypt-later\n * exposed (hndl:true); ECDSA / DSA / Ed25519 signatures are hndl:false but\n * forgeable. `openssl_pkey_new` EC and `EC::createKey` are ambiguous (feed BOTH\n * ECDSA and ECDH), classified conservatively as key-exchange-capable (hndl:true).\n */\nimport type { Detector, Finding, RuleMeta } from \"../types.js\";\nimport { PHP_EXTENSIONS, eachMatch, findingFromRule, hasExtension } from \"../detect-utils.js\";\nimport { CWE_BROKEN_CRYPTO } from \"../cwe.js\";\n\nconst RE_PHP_PKEY_NEW = /\\bopenssl_pkey_new\\s*\\(/g;\nconst RE_PHP_RSA_CRYPT = /\\bopenssl_(?:public_encrypt|private_decrypt)\\s*\\(/g;\nconst RE_PHP_SIGN = /\\bopenssl_(?:sign|verify)\\s*\\(/g;\n// phpseclib3 factory methods. The class names are generic, so require `::createKey`.\nconst RE_PHP_SECLIB = /\\b(RSA|EC|DSA|DH)::createKey\\s*\\(/g;\n// libsodium X25519 (box / kx / scalarmult) and Ed25519 (sign) key pairs.\nconst RE_PHP_SODIUM_X25519 =\n /\\bsodium_crypto_(?:box|kx)_(?:seed_)?keypair\\s*\\(|\\bsodium_crypto_scalarmult(?:_base)?\\s*\\(/g;\nconst RE_PHP_SODIUM_ED25519 = /\\bsodium_crypto_sign_(?:seed_)?keypair\\s*\\(/g;\n\n/** Key-type classification for `openssl_pkey_new`, keyed by its config constant. */\ninterface KeyInfo {\n algo: Finding[\"algorithm\"];\n cat: Finding[\"category\"];\n sev: Finding[\"severity\"];\n hndl: boolean;\n label: string;\n remediation?: string;\n}\nconst HYBRID = \"hybrid X25519MLKEM768 (ML-KEM-768) for key agreement; ML-DSA-65 (FIPS 204) to sign\";\n\nconst RULE_PHP_KEYGEN: RuleMeta = {\n id: \"php-openssl-keygen\",\n title: \"PHP openssl key generation\",\n description: \"openssl_pkey_new (RSA/EC/DSA/DH, by OPENSSL_KEYTYPE_*)\",\n category: \"kem\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"RSA\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message: \"Generates a classical key pair via PHP openssl_pkey_new — not quantum-safe.\",\n};\nconst RULE_PHP_RSA_CRYPT: RuleMeta = {\n id: \"php-openssl-rsa-crypt\",\n title: \"PHP openssl RSA public-key encryption\",\n description: \"openssl_public_encrypt / openssl_private_decrypt\",\n category: \"kem\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"RSA\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"RSA public-key encryption/decryption (PHP openssl) is harvest-now-decrypt-later exposed.\",\n};\nconst RULE_PHP_SIGN: RuleMeta = {\n id: \"php-openssl-sign\",\n title: \"PHP openssl signature\",\n description: \"openssl_sign / openssl_verify\",\n category: \"signature\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"unknown\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"Classical signature via PHP openssl (RSA/ECDSA/DSA) is forgeable by a quantum attacker.\",\n remediation: \"ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205)\",\n};\nconst RULE_PHP_SECLIB: RuleMeta = {\n id: \"php-phpseclib-keygen\",\n title: \"PHP phpseclib key generation\",\n description: \"phpseclib3 RSA/EC/DSA/DH ::createKey\",\n category: \"kem\",\n severity: \"high\",\n confidence: \"medium\",\n algorithm: \"RSA\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message: \"Generates a classical key pair via phpseclib3 (createKey) — not quantum-safe.\",\n};\nconst RULE_PHP_SODIUM_X25519: RuleMeta = {\n id: \"php-sodium-x25519\",\n title: \"PHP libsodium X25519 key agreement\",\n description: \"sodium_crypto_box/kx keypair + scalarmult\",\n category: \"key-exchange\",\n severity: \"medium\",\n confidence: \"high\",\n algorithm: \"X25519\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"libsodium crypto_box/kx (PHP) uses X25519 key agreement — modern but classical, harvest-now-decrypt-later exposed.\",\n};\nconst RULE_PHP_SODIUM_ED25519: RuleMeta = {\n id: \"php-sodium-ed25519\",\n title: \"PHP libsodium Ed25519 signature\",\n description: \"sodium_crypto_sign keypair\",\n category: \"signature\",\n severity: \"low\",\n confidence: \"high\",\n algorithm: \"EdDSA\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"libsodium crypto_sign (PHP) uses Ed25519 — classical and forgeable by a quantum attacker.\",\n};\n\n/** phpseclib class name → its classification. */\nconst SECLIB_INFO: Record<string, KeyInfo> = {\n RSA: { algo: \"RSA\", cat: \"kem\", sev: \"high\", hndl: true, label: \"RSA\" },\n EC: {\n algo: \"ECDH\",\n cat: \"key-exchange\",\n sev: \"high\",\n hndl: true,\n label: \"EC (ECDSA/ECDH)\",\n remediation: HYBRID,\n },\n DSA: { algo: \"DSA\", cat: \"signature\", sev: \"high\", hndl: false, label: \"DSA\" },\n DH: { algo: \"DH\", cat: \"key-exchange\", sev: \"high\", hndl: true, label: \"Diffie-Hellman\" },\n};\n\n/** Classify `openssl_pkey_new` by the `OPENSSL_KEYTYPE_*` constant in its config.\n * The window is bounded to the current statement (up to the next `;`, capped at\n * 300 chars) so it can't bleed into a following `openssl_pkey_new` call's key\n * type. Defaults to RSA — openssl_pkey_new's own default private_key_type is RSA\n * when none is given. */\nfunction classifyPkeyNew(content: string, index: number): KeyInfo {\n const semi = content.indexOf(\";\", index);\n const end = Math.min(index + 300, semi === -1 ? content.length : semi);\n const w = content.slice(index, end);\n if (/\\bOPENSSL_KEYTYPE_EC\\b/.test(w)) return SECLIB_INFO.EC;\n if (/\\bOPENSSL_KEYTYPE_DSA\\b/.test(w)) return SECLIB_INFO.DSA;\n if (/\\bOPENSSL_KEYTYPE_DH\\b/.test(w)) return SECLIB_INFO.DH;\n return SECLIB_INFO.RSA;\n}\n\n/** Detects classical asymmetric crypto in PHP (openssl, phpseclib, libsodium). */\nexport const phpDetector: Detector = {\n id: \"php-crypto\",\n description: \"Classical asymmetric crypto in PHP (openssl, phpseclib3, libsodium)\",\n scope: \"source\",\n language: \"php\",\n rules: [\n RULE_PHP_KEYGEN,\n RULE_PHP_RSA_CRYPT,\n RULE_PHP_SIGN,\n RULE_PHP_SECLIB,\n RULE_PHP_SODIUM_X25519,\n RULE_PHP_SODIUM_ED25519,\n ],\n appliesTo: (f) => hasExtension(f, PHP_EXTENSIONS),\n detect({ file, content }): Finding[] {\n const findings: Finding[] = [];\n const add = (re: RegExp, rule: RuleMeta): void =>\n eachMatch(re, content, (m) =>\n findings.push(\n findingFromRule(rule, { file, content, index: m.index, matchLength: m[0].length }),\n ),\n );\n\n // openssl_pkey_new — one finding per call, classified by its key-type config.\n eachMatch(RE_PHP_PKEY_NEW, content, (m) => {\n const info = classifyPkeyNew(content, m.index);\n findings.push(\n findingFromRule(\n RULE_PHP_KEYGEN,\n { file, content, index: m.index, matchLength: m[0].length },\n {\n title: `PHP openssl ${info.label} key generation`,\n category: info.cat,\n severity: info.sev,\n algorithm: info.algo,\n hndl: info.hndl,\n message: `Generates a classical ${info.label} key pair via PHP openssl_pkey_new — not quantum-safe.`,\n ...(info.remediation ? { remediation: info.remediation } : {}),\n },\n ),\n );\n });\n\n add(RE_PHP_RSA_CRYPT, RULE_PHP_RSA_CRYPT);\n add(RE_PHP_SIGN, RULE_PHP_SIGN);\n\n // phpseclib3 ::createKey — classify by the class (RSA/EC/DSA/DH).\n eachMatch(RE_PHP_SECLIB, content, (m) => {\n const info = SECLIB_INFO[m[1]];\n findings.push(\n findingFromRule(\n RULE_PHP_SECLIB,\n { file, content, index: m.index, matchLength: m[0].length },\n {\n title: `PHP phpseclib ${info.label} key generation`,\n category: info.cat,\n severity: info.sev,\n algorithm: info.algo,\n hndl: info.hndl,\n message: `Generates a classical ${info.label} key pair via phpseclib3 createKey — not quantum-safe.`,\n ...(info.remediation ? { remediation: info.remediation } : {}),\n },\n ),\n );\n });\n\n add(RE_PHP_SODIUM_X25519, RULE_PHP_SODIUM_X25519);\n add(RE_PHP_SODIUM_ED25519, RULE_PHP_SODIUM_ED25519);\n return findings;\n },\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"python.d.ts","sourceRoot":"","sources":["../../src/detectors/python.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,aAAa,CAAC;AAsJ/D,4DAA4D;AAC5D,eAAO,MAAM,cAAc,EAAE,QAsC5B,CAAC"}
1
+ {"version":3,"file":"python.d.ts","sourceRoot":"","sources":["../../src/detectors/python.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,aAAa,CAAC;AAsR/D,4DAA4D;AAC5D,eAAO,MAAM,cAAc,EAAE,QA4D5B,CAAC"}