@quantakrypto/core 0.4.3 → 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 (163) hide show
  1. package/dist/cbom-merge.d.ts +9 -0
  2. package/dist/cbom-merge.d.ts.map +1 -0
  3. package/dist/cbom-merge.js +99 -0
  4. package/dist/cbom-merge.js.map +1 -0
  5. package/dist/comments.d.ts +4 -3
  6. package/dist/comments.d.ts.map +1 -1
  7. package/dist/comments.js +53 -33
  8. package/dist/comments.js.map +1 -1
  9. package/dist/dependencies.d.ts.map +1 -1
  10. package/dist/dependencies.js +1 -1
  11. package/dist/dependencies.js.map +1 -1
  12. package/dist/detect-utils.d.ts +5 -1
  13. package/dist/detect-utils.d.ts.map +1 -1
  14. package/dist/detect-utils.js +11 -2
  15. package/dist/detect-utils.js.map +1 -1
  16. package/dist/detectors/c.d.ts +4 -2
  17. package/dist/detectors/c.d.ts.map +1 -1
  18. package/dist/detectors/c.js +192 -1
  19. package/dist/detectors/c.js.map +1 -1
  20. package/dist/detectors/cicd.d.ts +27 -0
  21. package/dist/detectors/cicd.d.ts.map +1 -0
  22. package/dist/detectors/cicd.js +116 -0
  23. package/dist/detectors/cicd.js.map +1 -0
  24. package/dist/detectors/cloud-kms.d.ts +21 -0
  25. package/dist/detectors/cloud-kms.d.ts.map +1 -0
  26. package/dist/detectors/cloud-kms.js +57 -0
  27. package/dist/detectors/cloud-kms.js.map +1 -0
  28. package/dist/detectors/cloudformation.d.ts +30 -0
  29. package/dist/detectors/cloudformation.d.ts.map +1 -0
  30. package/dist/detectors/cloudformation.js +170 -0
  31. package/dist/detectors/cloudformation.js.map +1 -0
  32. package/dist/detectors/database.d.ts +17 -0
  33. package/dist/detectors/database.d.ts.map +1 -0
  34. package/dist/detectors/database.js +60 -0
  35. package/dist/detectors/database.js.map +1 -0
  36. package/dist/detectors/dnssec.d.ts +55 -0
  37. package/dist/detectors/dnssec.d.ts.map +1 -0
  38. package/dist/detectors/dnssec.js +107 -0
  39. package/dist/detectors/dnssec.js.map +1 -0
  40. package/dist/detectors/elixir.d.ts +20 -0
  41. package/dist/detectors/elixir.d.ts.map +1 -0
  42. package/dist/detectors/elixir.js +195 -0
  43. package/dist/detectors/elixir.js.map +1 -0
  44. package/dist/detectors/java.d.ts.map +1 -1
  45. package/dist/detectors/java.js +1 -1
  46. package/dist/detectors/java.js.map +1 -1
  47. package/dist/detectors/jose.d.ts +20 -0
  48. package/dist/detectors/jose.d.ts.map +1 -0
  49. package/dist/detectors/jose.js +62 -0
  50. package/dist/detectors/jose.js.map +1 -0
  51. package/dist/detectors/jwk.d.ts +25 -0
  52. package/dist/detectors/jwk.d.ts.map +1 -0
  53. package/dist/detectors/jwk.js +95 -0
  54. package/dist/detectors/jwk.js.map +1 -0
  55. package/dist/detectors/k8s.d.ts +17 -0
  56. package/dist/detectors/k8s.d.ts.map +1 -0
  57. package/dist/detectors/k8s.js +85 -0
  58. package/dist/detectors/k8s.js.map +1 -0
  59. package/dist/detectors/mesh.d.ts +35 -0
  60. package/dist/detectors/mesh.d.ts.map +1 -0
  61. package/dist/detectors/mesh.js +109 -0
  62. package/dist/detectors/mesh.js.map +1 -0
  63. package/dist/detectors/messaging.d.ts +16 -0
  64. package/dist/detectors/messaging.d.ts.map +1 -0
  65. package/dist/detectors/messaging.js +72 -0
  66. package/dist/detectors/messaging.js.map +1 -0
  67. package/dist/detectors/pem.js +1 -1
  68. package/dist/detectors/pem.js.map +1 -1
  69. package/dist/detectors/php.d.ts +24 -0
  70. package/dist/detectors/php.d.ts.map +1 -0
  71. package/dist/detectors/php.js +167 -0
  72. package/dist/detectors/php.js.map +1 -0
  73. package/dist/detectors/python.d.ts.map +1 -1
  74. package/dist/detectors/python.js +70 -0
  75. package/dist/detectors/python.js.map +1 -1
  76. package/dist/detectors/rust.d.ts.map +1 -1
  77. package/dist/detectors/rust.js +68 -0
  78. package/dist/detectors/rust.js.map +1 -1
  79. package/dist/detectors/secrets.d.ts +21 -0
  80. package/dist/detectors/secrets.d.ts.map +1 -0
  81. package/dist/detectors/secrets.js +79 -0
  82. package/dist/detectors/secrets.js.map +1 -0
  83. package/dist/detectors/source.d.ts.map +1 -1
  84. package/dist/detectors/source.js +190 -47
  85. package/dist/detectors/source.js.map +1 -1
  86. package/dist/detectors/stateful-hbs.d.ts.map +1 -1
  87. package/dist/detectors/stateful-hbs.js +9 -6
  88. package/dist/detectors/stateful-hbs.js.map +1 -1
  89. package/dist/detectors/terraform.d.ts +21 -0
  90. package/dist/detectors/terraform.d.ts.map +1 -0
  91. package/dist/detectors/terraform.js +123 -0
  92. package/dist/detectors/terraform.js.map +1 -0
  93. package/dist/detectors/vpn.d.ts +22 -0
  94. package/dist/detectors/vpn.d.ts.map +1 -0
  95. package/dist/detectors/vpn.js +99 -0
  96. package/dist/detectors/vpn.js.map +1 -0
  97. package/dist/evidence.d.ts +5 -0
  98. package/dist/evidence.d.ts.map +1 -1
  99. package/dist/evidence.js +5 -0
  100. package/dist/evidence.js.map +1 -1
  101. package/dist/index.d.ts +5 -0
  102. package/dist/index.d.ts.map +1 -1
  103. package/dist/index.js +6 -0
  104. package/dist/index.js.map +1 -1
  105. package/dist/policy.d.ts +67 -0
  106. package/dist/policy.d.ts.map +1 -0
  107. package/dist/policy.js +115 -0
  108. package/dist/policy.js.map +1 -0
  109. package/dist/registry.d.ts.map +1 -1
  110. package/dist/registry.js +30 -0
  111. package/dist/registry.js.map +1 -1
  112. package/dist/remediate-pipeline.d.ts.map +1 -1
  113. package/dist/remediate-pipeline.js +22 -1
  114. package/dist/remediate-pipeline.js.map +1 -1
  115. package/dist/report.d.ts.map +1 -1
  116. package/dist/report.js +7 -0
  117. package/dist/report.js.map +1 -1
  118. package/dist/standards.d.ts +96 -0
  119. package/dist/standards.d.ts.map +1 -0
  120. package/dist/standards.js +107 -0
  121. package/dist/standards.js.map +1 -0
  122. package/dist/types.d.ts +1 -1
  123. package/dist/types.d.ts.map +1 -1
  124. package/dist/types.js.map +1 -1
  125. package/dist/version.d.ts +1 -1
  126. package/dist/version.js +1 -1
  127. package/dist/version.js.map +1 -1
  128. package/package.json +1 -1
  129. package/src/cbom-merge.ts +116 -0
  130. package/src/comments.ts +59 -33
  131. package/src/dependencies.ts +2 -1
  132. package/src/detect-utils.ts +14 -2
  133. package/src/detectors/c.ts +209 -3
  134. package/src/detectors/cicd.ts +158 -0
  135. package/src/detectors/cloud-kms.ts +87 -0
  136. package/src/detectors/cloudformation.ts +215 -0
  137. package/src/detectors/database.ts +88 -0
  138. package/src/detectors/dnssec.ts +186 -0
  139. package/src/detectors/elixir.ts +237 -0
  140. package/src/detectors/java.ts +2 -1
  141. package/src/detectors/jose.ts +94 -0
  142. package/src/detectors/jwk.ts +128 -0
  143. package/src/detectors/k8s.ts +112 -0
  144. package/src/detectors/mesh.ts +154 -0
  145. package/src/detectors/messaging.ts +98 -0
  146. package/src/detectors/pem.ts +1 -1
  147. package/src/detectors/php.ts +225 -0
  148. package/src/detectors/python.ts +71 -0
  149. package/src/detectors/rust.ts +71 -0
  150. package/src/detectors/secrets.ts +114 -0
  151. package/src/detectors/source.ts +235 -68
  152. package/src/detectors/stateful-hbs.ts +9 -6
  153. package/src/detectors/terraform.ts +154 -0
  154. package/src/detectors/vpn.ts +131 -0
  155. package/src/evidence.ts +11 -0
  156. package/src/index.ts +10 -0
  157. package/src/policy.ts +180 -0
  158. package/src/registry.ts +30 -0
  159. package/src/remediate-pipeline.ts +25 -2
  160. package/src/report.ts +7 -0
  161. package/src/standards.ts +186 -0
  162. package/src/types.ts +2 -0
  163. package/src/version.ts +1 -1
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Config detector: classical crypto in Kubernetes manifests — cert-manager key
3
+ * algorithms and service-mesh (Istio) TLS floors. These mint the certificates
4
+ * and secure the pod-to-pod traffic of a cluster, a surface neither the language
5
+ * packs nor the Terraform detector see.
6
+ *
7
+ * Covered (gated by a cert-manager / Istio marker in the document to keep the
8
+ * generic `algorithm:` / `minProtocolVersion:` keys from firing on unrelated YAML):
9
+ * - cert-manager `Certificate`/`Issuer` `privateKey.algorithm` (or legacy
10
+ * `keyAlgorithm`): `RSA` | `ECDSA` | `Ed25519`.
11
+ * - Istio `minProtocolVersion: TLSV1_0 | TLSV1_1` — a legacy TLS floor on mesh
12
+ * traffic, whose (EC)DHE key exchange is classical and harvestable.
13
+ */
14
+ import type { Detector } from "../types.js";
15
+ /** Detects classical cert-manager keys and legacy Istio TLS floors in K8s YAML. */
16
+ export declare const k8sDetector: Detector;
17
+ //# sourceMappingURL=k8s.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"k8s.d.ts","sourceRoot":"","sources":["../../src/detectors/k8s.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,aAAa,CAAC;AAoE/D,mFAAmF;AACnF,eAAO,MAAM,WAAW,EAAE,QA6BzB,CAAC"}
@@ -0,0 +1,85 @@
1
+ import { eachMatch, findingFromRule, hasExtension } from "../detect-utils.js";
2
+ import { CWE_BROKEN_CRYPTO, CWE_RISKY_PRIMITIVE } from "../cwe.js";
3
+ const K8S_EXTENSIONS = [".yaml", ".yml", ".json"];
4
+ const RE_CM_RSA = /(?:algorithm|keyAlgorithm):\s*["']?RSA\b/g;
5
+ const RE_CM_ECDSA = /(?:algorithm|keyAlgorithm):\s*["']?ECDSA\b/g;
6
+ const RE_CM_ED25519 = /(?:algorithm|keyAlgorithm):\s*["']?Ed25519\b/g;
7
+ const RE_ISTIO_LEGACY_TLS = /minProtocolVersion:\s*["']?TLSV1_[01]\b/g;
8
+ const RULE_CM_RSA = {
9
+ id: "k8s-certmanager-rsa",
10
+ title: "cert-manager RSA key",
11
+ description: "cert-manager Certificate/Issuer privateKey.algorithm = RSA",
12
+ category: "certificate",
13
+ severity: "medium",
14
+ confidence: "high",
15
+ algorithm: "RSA",
16
+ hndl: true,
17
+ cwe: CWE_BROKEN_CRYPTO,
18
+ message: "cert-manager mints certificates with a classical RSA key, which is not quantum-safe.",
19
+ remediation: "Plan migration to PQC certificate keys (ML-DSA-65) as the CA/issuer chain adds support.",
20
+ };
21
+ const RULE_CM_ECDSA = {
22
+ id: "k8s-certmanager-ecdsa",
23
+ title: "cert-manager ECDSA key",
24
+ description: "cert-manager Certificate/Issuer privateKey.algorithm = ECDSA",
25
+ category: "certificate",
26
+ severity: "medium",
27
+ confidence: "high",
28
+ algorithm: "ECDSA",
29
+ hndl: false,
30
+ cwe: CWE_BROKEN_CRYPTO,
31
+ message: "cert-manager mints certificates with a classical ECDSA key, forgeable by a quantum attacker.",
32
+ remediation: "Plan migration to ML-DSA-65 (FIPS 204) certificate keys.",
33
+ };
34
+ const RULE_CM_ED25519 = {
35
+ id: "k8s-certmanager-ed25519",
36
+ title: "cert-manager Ed25519 key",
37
+ description: "cert-manager Certificate/Issuer privateKey.algorithm = Ed25519",
38
+ category: "certificate",
39
+ severity: "low",
40
+ confidence: "high",
41
+ algorithm: "EdDSA",
42
+ hndl: false,
43
+ cwe: CWE_BROKEN_CRYPTO,
44
+ message: "cert-manager mints certificates with a classical Ed25519 key, forgeable by a quantum attacker.",
45
+ remediation: "Plan migration to ML-DSA-65 (FIPS 204) certificate keys.",
46
+ };
47
+ const RULE_ISTIO_LEGACY_TLS = {
48
+ id: "k8s-istio-legacy-tls",
49
+ title: "Istio legacy TLS floor",
50
+ description: "Istio minProtocolVersion allows TLS 1.0 / 1.1 on mesh traffic",
51
+ category: "tls",
52
+ severity: "medium",
53
+ confidence: "high",
54
+ hndl: false,
55
+ cwe: CWE_RISKY_PRIMITIVE,
56
+ message: "Istio mesh TLS floor allows TLS 1.0/1.1; its classical (EC)DHE key exchange is weak and harvestable.",
57
+ remediation: "Raise minProtocolVersion to TLSV1_3 and track PQC-hybrid mesh KEX (X25519MLKEM768).",
58
+ };
59
+ /** Detects classical cert-manager keys and legacy Istio TLS floors in K8s YAML. */
60
+ export const k8sDetector = {
61
+ id: "k8s-crypto",
62
+ description: "Classical crypto in Kubernetes manifests (cert-manager keys, Istio TLS floors)",
63
+ scope: "config",
64
+ language: "any",
65
+ rules: [RULE_CM_RSA, RULE_CM_ECDSA, RULE_CM_ED25519, RULE_ISTIO_LEGACY_TLS],
66
+ appliesTo: (f) => hasExtension(f, K8S_EXTENSIONS),
67
+ detect({ file, content }) {
68
+ const isCertManager = content.includes("cert-manager.io") ||
69
+ /kind:\s*["']?(?:Certificate|Issuer|ClusterIssuer)\b/.test(content);
70
+ const isIstio = content.includes("minProtocolVersion");
71
+ if (!isCertManager && !isIstio)
72
+ return [];
73
+ const findings = [];
74
+ const add = (re, rule) => eachMatch(re, content, (m) => findings.push(findingFromRule(rule, { file, content, index: m.index, matchLength: m[0].length })));
75
+ if (isCertManager) {
76
+ add(RE_CM_RSA, RULE_CM_RSA);
77
+ add(RE_CM_ECDSA, RULE_CM_ECDSA);
78
+ add(RE_CM_ED25519, RULE_CM_ED25519);
79
+ }
80
+ if (isIstio)
81
+ add(RE_ISTIO_LEGACY_TLS, RULE_ISTIO_LEGACY_TLS);
82
+ return findings;
83
+ },
84
+ };
85
+ //# sourceMappingURL=k8s.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"k8s.js","sourceRoot":"","sources":["../../src/detectors/k8s.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Config detector: classical crypto in Kubernetes manifests — cert-manager key\n * algorithms and service-mesh (Istio) TLS floors. These mint the certificates\n * and secure the pod-to-pod traffic of a cluster, a surface neither the language\n * packs nor the Terraform detector see.\n *\n * Covered (gated by a cert-manager / Istio marker in the document to keep the\n * generic `algorithm:` / `minProtocolVersion:` keys from firing on unrelated YAML):\n * - cert-manager `Certificate`/`Issuer` `privateKey.algorithm` (or legacy\n * `keyAlgorithm`): `RSA` | `ECDSA` | `Ed25519`.\n * - Istio `minProtocolVersion: TLSV1_0 | TLSV1_1` — a legacy TLS floor on mesh\n * traffic, whose (EC)DHE key exchange is classical and harvestable.\n */\nimport type { Detector, Finding, RuleMeta } from \"../types.js\";\nimport { eachMatch, findingFromRule, hasExtension } from \"../detect-utils.js\";\nimport { CWE_BROKEN_CRYPTO, CWE_RISKY_PRIMITIVE } from \"../cwe.js\";\n\nconst K8S_EXTENSIONS: readonly string[] = [\".yaml\", \".yml\", \".json\"];\n\nconst RE_CM_RSA = /(?:algorithm|keyAlgorithm):\\s*[\"']?RSA\\b/g;\nconst RE_CM_ECDSA = /(?:algorithm|keyAlgorithm):\\s*[\"']?ECDSA\\b/g;\nconst RE_CM_ED25519 = /(?:algorithm|keyAlgorithm):\\s*[\"']?Ed25519\\b/g;\nconst RE_ISTIO_LEGACY_TLS = /minProtocolVersion:\\s*[\"']?TLSV1_[01]\\b/g;\n\nconst RULE_CM_RSA: RuleMeta = {\n id: \"k8s-certmanager-rsa\",\n title: \"cert-manager RSA key\",\n description: \"cert-manager Certificate/Issuer privateKey.algorithm = RSA\",\n category: \"certificate\",\n severity: \"medium\",\n confidence: \"high\",\n algorithm: \"RSA\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message: \"cert-manager mints certificates with a classical RSA key, which is not quantum-safe.\",\n remediation:\n \"Plan migration to PQC certificate keys (ML-DSA-65) as the CA/issuer chain adds support.\",\n};\nconst RULE_CM_ECDSA: RuleMeta = {\n id: \"k8s-certmanager-ecdsa\",\n title: \"cert-manager ECDSA key\",\n description: \"cert-manager Certificate/Issuer privateKey.algorithm = ECDSA\",\n category: \"certificate\",\n severity: \"medium\",\n confidence: \"high\",\n algorithm: \"ECDSA\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"cert-manager mints certificates with a classical ECDSA key, forgeable by a quantum attacker.\",\n remediation: \"Plan migration to ML-DSA-65 (FIPS 204) certificate keys.\",\n};\nconst RULE_CM_ED25519: RuleMeta = {\n id: \"k8s-certmanager-ed25519\",\n title: \"cert-manager Ed25519 key\",\n description: \"cert-manager Certificate/Issuer privateKey.algorithm = Ed25519\",\n category: \"certificate\",\n severity: \"low\",\n confidence: \"high\",\n algorithm: \"EdDSA\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"cert-manager mints certificates with a classical Ed25519 key, forgeable by a quantum attacker.\",\n remediation: \"Plan migration to ML-DSA-65 (FIPS 204) certificate keys.\",\n};\nconst RULE_ISTIO_LEGACY_TLS: RuleMeta = {\n id: \"k8s-istio-legacy-tls\",\n title: \"Istio legacy TLS floor\",\n description: \"Istio minProtocolVersion allows TLS 1.0 / 1.1 on mesh traffic\",\n category: \"tls\",\n severity: \"medium\",\n confidence: \"high\",\n hndl: false,\n cwe: CWE_RISKY_PRIMITIVE,\n message:\n \"Istio mesh TLS floor allows TLS 1.0/1.1; its classical (EC)DHE key exchange is weak and harvestable.\",\n remediation:\n \"Raise minProtocolVersion to TLSV1_3 and track PQC-hybrid mesh KEX (X25519MLKEM768).\",\n};\n\n/** Detects classical cert-manager keys and legacy Istio TLS floors in K8s YAML. */\nexport const k8sDetector: Detector = {\n id: \"k8s-crypto\",\n description: \"Classical crypto in Kubernetes manifests (cert-manager keys, Istio TLS floors)\",\n scope: \"config\",\n language: \"any\",\n rules: [RULE_CM_RSA, RULE_CM_ECDSA, RULE_CM_ED25519, RULE_ISTIO_LEGACY_TLS],\n appliesTo: (f) => hasExtension(f, K8S_EXTENSIONS),\n detect({ file, content }): Finding[] {\n const isCertManager =\n content.includes(\"cert-manager.io\") ||\n /kind:\\s*[\"']?(?:Certificate|Issuer|ClusterIssuer)\\b/.test(content);\n const isIstio = content.includes(\"minProtocolVersion\");\n if (!isCertManager && !isIstio) return [];\n\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 if (isCertManager) {\n add(RE_CM_RSA, RULE_CM_RSA);\n add(RE_CM_ECDSA, RULE_CM_ECDSA);\n add(RE_CM_ED25519, RULE_CM_ED25519);\n }\n if (isIstio) add(RE_ISTIO_LEGACY_TLS, RULE_ISTIO_LEGACY_TLS);\n return findings;\n },\n};\n"]}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Config detector: classical crypto in SERVICE MESH configuration — the
3
+ * control-plane identity/CA systems and mesh-internal TLS settings of
4
+ * Linkerd, HashiCorp Consul Connect, and Istio. These mint the mTLS identity
5
+ * certificates that secure sidecar-to-sidecar traffic and are configured in
6
+ * their own Helm values / HCL / CRD surfaces, distinct from what `k8s.ts`
7
+ * already covers (cert-manager `Certificate`/`Issuer` keys and Istio's
8
+ * `minProtocolVersion` TLS floor — NOT duplicated here).
9
+ *
10
+ * Covered (gated by a mesh marker in the document to keep generic keys like
11
+ * `scheme:` / `private_key_type` from firing on unrelated YAML/HCL):
12
+ * - Linkerd control-plane identity issuer: Helm values `identityTrustAnchorsPEM`
13
+ * and `identity.issuer.scheme` / nested `issuer.scheme: linkerd.io/tls` — the
14
+ * default self-managed Linkerd identity scheme, which mints workload
15
+ * certificates from an ECDSA P-256 trust anchor. Flagged as a classical mesh
16
+ * CA (certificate, ECDSA, hndl:false) since Linkerd's identity issuer signs
17
+ * forgeable-by-quantum leaf certs, not a confidentiality key.
18
+ * - HashiCorp Consul Connect: the `connect { ca_config { private_key_type =
19
+ * "ec" | "rsa" } } }` mesh CA provider setting (also `ca_provider`). Flagged
20
+ * as a classical mesh CA (certificate; ECDSA for "ec", RSA for "rsa").
21
+ * - Istio `DestinationRule` / `Gateway` `tls.cipherSuites:` listing a classical
22
+ * `ECDHE-RSA-*` / `ECDHE-ECDSA-*` suite — the (EC)DHE key exchange in these
23
+ * suites is classical and harvest-now-decrypt-later exposed (tls, ECDH,
24
+ * hndl:true). This complements, and does not duplicate, `k8s.ts`'s
25
+ * `minProtocolVersion` legacy-TLS-floor rule.
26
+ */
27
+ import type { Detector } from "../types.js";
28
+ /**
29
+ * Detects classical asymmetric crypto in service-mesh configuration: Linkerd's
30
+ * default ECDSA identity issuer, Consul Connect's mesh CA private key type,
31
+ * and classical ECDHE cipher suites in Istio DestinationRule/Gateway TLS
32
+ * policy.
33
+ */
34
+ export declare const meshDetector: Detector;
35
+ //# sourceMappingURL=mesh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mesh.d.ts","sourceRoot":"","sources":["../../src/detectors/mesh.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,aAAa,CAAC;AAuF/D;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,QAkC1B,CAAC"}
@@ -0,0 +1,109 @@
1
+ import { eachMatch, findingFromRule, hasExtension } from "../detect-utils.js";
2
+ import { CWE_BROKEN_CRYPTO, CWE_RISKY_PRIMITIVE } from "../cwe.js";
3
+ const MESH_EXTENSIONS = [".yaml", ".yml", ".hcl"];
4
+ // Linkerd's default self-managed identity scheme (`linkerd.io/tls`, as opposed
5
+ // to a `kubernetes.io/tls` bring-your-own-cert secret) mints its trust anchor
6
+ // and issuer credentials as ECDSA P-256 by default. Matched in both nested
7
+ // YAML form (`scheme: linkerd.io/tls`) and the flattened Helm `--set`/values
8
+ // key form (`identity.issuer.scheme: linkerd.io/tls`), plus the distinctive
9
+ // `identityTrustAnchorsPEM` values key which only exists in Linkerd charts.
10
+ const RE_MESH_LINKERD_ECDSA = /identityTrustAnchorsPEM\b|(?:identity\.issuer\.scheme|scheme)\s*[:=]\s*["']?linkerd\.io\/tls\b/g;
11
+ // Consul Connect's CA provider config: `private_key_type = "ec" | "rsa"`
12
+ // inside a `ca_config` block. Matched in both HCL (`=`) and JSON (`:`) forms,
13
+ // mirroring the terraform.ts attribute-matching convention.
14
+ const RE_MESH_CONSUL_RSA = /(?<![\w"-])"?private_key_type"?\s*[:=]\s*"rsa"/gi;
15
+ const RE_MESH_CONSUL_EC = /(?<![\w"-])"?private_key_type"?\s*[:=]\s*"ec"/gi;
16
+ // Istio mesh TLS cipher suites: OpenSSL-style suite names naming classical
17
+ // ECDHE key exchange combined with an RSA or ECDSA certificate. These are
18
+ // distinctive tokens (no generic-config collision risk).
19
+ const RE_MESH_ISTIO_CLASSICAL_CIPHER = /\bECDHE-(?:RSA|ECDSA)-[A-Z0-9_-]+\b/g;
20
+ const RULE_MESH_LINKERD_ECDSA = {
21
+ id: "mesh-linkerd-identity-ecdsa",
22
+ title: "Linkerd ECDSA identity issuer",
23
+ description: "Linkerd control-plane identity issuer (default ECDSA P-256 mesh CA)",
24
+ category: "certificate",
25
+ severity: "medium",
26
+ confidence: "high",
27
+ algorithm: "ECDSA",
28
+ hndl: false,
29
+ cwe: CWE_BROKEN_CRYPTO,
30
+ message: "Linkerd's control-plane identity issuer mints workload certificates from a classical ECDSA P-256 trust anchor by default, forgeable by a quantum attacker.",
31
+ remediation: "Plan migration to ML-DSA-65 (FIPS 204) once Linkerd's identity issuer supports PQC signing.",
32
+ };
33
+ const RULE_MESH_CONSUL_RSA = {
34
+ id: "mesh-consul-connect-rsa",
35
+ title: "Consul Connect RSA mesh CA",
36
+ description: 'Consul Connect ca_config private_key_type = "rsa"',
37
+ category: "certificate",
38
+ severity: "medium",
39
+ confidence: "high",
40
+ algorithm: "RSA",
41
+ hndl: true,
42
+ cwe: CWE_BROKEN_CRYPTO,
43
+ message: "Consul Connect's mesh CA issues leaf certificates from a classical RSA private key, which is not quantum-safe.",
44
+ remediation: "Plan migration to PQC certificate keys (ML-DSA-65) as the Connect CA provider adds support.",
45
+ };
46
+ const RULE_MESH_CONSUL_EC = {
47
+ id: "mesh-consul-connect-ec",
48
+ title: "Consul Connect EC mesh CA",
49
+ description: 'Consul Connect ca_config private_key_type = "ec"',
50
+ category: "certificate",
51
+ severity: "medium",
52
+ confidence: "high",
53
+ algorithm: "ECDSA",
54
+ hndl: false,
55
+ cwe: CWE_BROKEN_CRYPTO,
56
+ message: "Consul Connect's mesh CA issues leaf certificates from a classical EC private key, forgeable by a quantum attacker.",
57
+ remediation: "Plan migration to ML-DSA-65 (FIPS 204) as the Connect CA provider adds support.",
58
+ };
59
+ const RULE_MESH_ISTIO_CLASSICAL_CIPHER = {
60
+ id: "mesh-istio-classical-cipher",
61
+ title: "Istio classical ECDHE cipher suite",
62
+ description: "Istio DestinationRule/Gateway tls.cipherSuites lists a classical ECDHE-RSA/ECDHE-ECDSA suite",
63
+ category: "tls",
64
+ severity: "medium",
65
+ confidence: "high",
66
+ algorithm: "ECDH",
67
+ hndl: true,
68
+ cwe: CWE_RISKY_PRIMITIVE,
69
+ message: "Istio mesh TLS cipher suite allows classical ECDHE key exchange, which is harvest-now-decrypt-later exposed.",
70
+ remediation: "Prefer TLS 1.3 AEAD suites and track PQC-hybrid mesh key exchange (X25519MLKEM768) as Envoy/BoringSSL adds support.",
71
+ };
72
+ /**
73
+ * Detects classical asymmetric crypto in service-mesh configuration: Linkerd's
74
+ * default ECDSA identity issuer, Consul Connect's mesh CA private key type,
75
+ * and classical ECDHE cipher suites in Istio DestinationRule/Gateway TLS
76
+ * policy.
77
+ */
78
+ export const meshDetector = {
79
+ id: "service-mesh-crypto",
80
+ description: "Classical crypto in service-mesh config (Linkerd identity, Consul Connect CA, Istio cipher suites)",
81
+ scope: "config",
82
+ language: "any",
83
+ rules: [
84
+ RULE_MESH_LINKERD_ECDSA,
85
+ RULE_MESH_CONSUL_RSA,
86
+ RULE_MESH_CONSUL_EC,
87
+ RULE_MESH_ISTIO_CLASSICAL_CIPHER,
88
+ ],
89
+ appliesTo: (f) => hasExtension(f, MESH_EXTENSIONS),
90
+ detect({ file, content }) {
91
+ const isLinkerd = content.includes("linkerd") || content.includes("identityTrustAnchors");
92
+ const isConsulConnect = content.includes("consul") && content.includes("connect");
93
+ const isIstioCipher = content.includes("DestinationRule") || content.includes("cipherSuites");
94
+ if (!isLinkerd && !isConsulConnect && !isIstioCipher)
95
+ return [];
96
+ const findings = [];
97
+ const add = (re, rule) => eachMatch(re, content, (m) => findings.push(findingFromRule(rule, { file, content, index: m.index, matchLength: m[0].length })));
98
+ if (isLinkerd)
99
+ add(RE_MESH_LINKERD_ECDSA, RULE_MESH_LINKERD_ECDSA);
100
+ if (isConsulConnect) {
101
+ add(RE_MESH_CONSUL_RSA, RULE_MESH_CONSUL_RSA);
102
+ add(RE_MESH_CONSUL_EC, RULE_MESH_CONSUL_EC);
103
+ }
104
+ if (isIstioCipher)
105
+ add(RE_MESH_ISTIO_CLASSICAL_CIPHER, RULE_MESH_ISTIO_CLASSICAL_CIPHER);
106
+ return findings;
107
+ },
108
+ };
109
+ //# sourceMappingURL=mesh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mesh.js","sourceRoot":"","sources":["../../src/detectors/mesh.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Config detector: classical crypto in SERVICE MESH configuration — the\n * control-plane identity/CA systems and mesh-internal TLS settings of\n * Linkerd, HashiCorp Consul Connect, and Istio. These mint the mTLS identity\n * certificates that secure sidecar-to-sidecar traffic and are configured in\n * their own Helm values / HCL / CRD surfaces, distinct from what `k8s.ts`\n * already covers (cert-manager `Certificate`/`Issuer` keys and Istio's\n * `minProtocolVersion` TLS floor — NOT duplicated here).\n *\n * Covered (gated by a mesh marker in the document to keep generic keys like\n * `scheme:` / `private_key_type` from firing on unrelated YAML/HCL):\n * - Linkerd control-plane identity issuer: Helm values `identityTrustAnchorsPEM`\n * and `identity.issuer.scheme` / nested `issuer.scheme: linkerd.io/tls` — the\n * default self-managed Linkerd identity scheme, which mints workload\n * certificates from an ECDSA P-256 trust anchor. Flagged as a classical mesh\n * CA (certificate, ECDSA, hndl:false) since Linkerd's identity issuer signs\n * forgeable-by-quantum leaf certs, not a confidentiality key.\n * - HashiCorp Consul Connect: the `connect { ca_config { private_key_type =\n * \"ec\" | \"rsa\" } } }` mesh CA provider setting (also `ca_provider`). Flagged\n * as a classical mesh CA (certificate; ECDSA for \"ec\", RSA for \"rsa\").\n * - Istio `DestinationRule` / `Gateway` `tls.cipherSuites:` listing a classical\n * `ECDHE-RSA-*` / `ECDHE-ECDSA-*` suite — the (EC)DHE key exchange in these\n * suites is classical and harvest-now-decrypt-later exposed (tls, ECDH,\n * hndl:true). This complements, and does not duplicate, `k8s.ts`'s\n * `minProtocolVersion` legacy-TLS-floor rule.\n */\nimport type { Detector, Finding, RuleMeta } from \"../types.js\";\nimport { eachMatch, findingFromRule, hasExtension } from \"../detect-utils.js\";\nimport { CWE_BROKEN_CRYPTO, CWE_RISKY_PRIMITIVE } from \"../cwe.js\";\n\nconst MESH_EXTENSIONS: readonly string[] = [\".yaml\", \".yml\", \".hcl\"];\n\n// Linkerd's default self-managed identity scheme (`linkerd.io/tls`, as opposed\n// to a `kubernetes.io/tls` bring-your-own-cert secret) mints its trust anchor\n// and issuer credentials as ECDSA P-256 by default. Matched in both nested\n// YAML form (`scheme: linkerd.io/tls`) and the flattened Helm `--set`/values\n// key form (`identity.issuer.scheme: linkerd.io/tls`), plus the distinctive\n// `identityTrustAnchorsPEM` values key which only exists in Linkerd charts.\nconst RE_MESH_LINKERD_ECDSA =\n /identityTrustAnchorsPEM\\b|(?:identity\\.issuer\\.scheme|scheme)\\s*[:=]\\s*[\"']?linkerd\\.io\\/tls\\b/g;\n\n// Consul Connect's CA provider config: `private_key_type = \"ec\" | \"rsa\"`\n// inside a `ca_config` block. Matched in both HCL (`=`) and JSON (`:`) forms,\n// mirroring the terraform.ts attribute-matching convention.\nconst RE_MESH_CONSUL_RSA = /(?<![\\w\"-])\"?private_key_type\"?\\s*[:=]\\s*\"rsa\"/gi;\nconst RE_MESH_CONSUL_EC = /(?<![\\w\"-])\"?private_key_type\"?\\s*[:=]\\s*\"ec\"/gi;\n\n// Istio mesh TLS cipher suites: OpenSSL-style suite names naming classical\n// ECDHE key exchange combined with an RSA or ECDSA certificate. These are\n// distinctive tokens (no generic-config collision risk).\nconst RE_MESH_ISTIO_CLASSICAL_CIPHER = /\\bECDHE-(?:RSA|ECDSA)-[A-Z0-9_-]+\\b/g;\n\nconst RULE_MESH_LINKERD_ECDSA: RuleMeta = {\n id: \"mesh-linkerd-identity-ecdsa\",\n title: \"Linkerd ECDSA identity issuer\",\n description: \"Linkerd control-plane identity issuer (default ECDSA P-256 mesh CA)\",\n category: \"certificate\",\n severity: \"medium\",\n confidence: \"high\",\n algorithm: \"ECDSA\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"Linkerd's control-plane identity issuer mints workload certificates from a classical ECDSA P-256 trust anchor by default, forgeable by a quantum attacker.\",\n remediation:\n \"Plan migration to ML-DSA-65 (FIPS 204) once Linkerd's identity issuer supports PQC signing.\",\n};\nconst RULE_MESH_CONSUL_RSA: RuleMeta = {\n id: \"mesh-consul-connect-rsa\",\n title: \"Consul Connect RSA mesh CA\",\n description: 'Consul Connect ca_config private_key_type = \"rsa\"',\n category: \"certificate\",\n severity: \"medium\",\n confidence: \"high\",\n algorithm: \"RSA\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"Consul Connect's mesh CA issues leaf certificates from a classical RSA private key, which is not quantum-safe.\",\n remediation:\n \"Plan migration to PQC certificate keys (ML-DSA-65) as the Connect CA provider adds support.\",\n};\nconst RULE_MESH_CONSUL_EC: RuleMeta = {\n id: \"mesh-consul-connect-ec\",\n title: \"Consul Connect EC mesh CA\",\n description: 'Consul Connect ca_config private_key_type = \"ec\"',\n category: \"certificate\",\n severity: \"medium\",\n confidence: \"high\",\n algorithm: \"ECDSA\",\n hndl: false,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"Consul Connect's mesh CA issues leaf certificates from a classical EC private key, forgeable by a quantum attacker.\",\n remediation: \"Plan migration to ML-DSA-65 (FIPS 204) as the Connect CA provider adds support.\",\n};\nconst RULE_MESH_ISTIO_CLASSICAL_CIPHER: RuleMeta = {\n id: \"mesh-istio-classical-cipher\",\n title: \"Istio classical ECDHE cipher suite\",\n description:\n \"Istio DestinationRule/Gateway tls.cipherSuites lists a classical ECDHE-RSA/ECDHE-ECDSA suite\",\n category: \"tls\",\n severity: \"medium\",\n confidence: \"high\",\n algorithm: \"ECDH\",\n hndl: true,\n cwe: CWE_RISKY_PRIMITIVE,\n message:\n \"Istio mesh TLS cipher suite allows classical ECDHE key exchange, which is harvest-now-decrypt-later exposed.\",\n remediation:\n \"Prefer TLS 1.3 AEAD suites and track PQC-hybrid mesh key exchange (X25519MLKEM768) as Envoy/BoringSSL adds support.\",\n};\n\n/**\n * Detects classical asymmetric crypto in service-mesh configuration: Linkerd's\n * default ECDSA identity issuer, Consul Connect's mesh CA private key type,\n * and classical ECDHE cipher suites in Istio DestinationRule/Gateway TLS\n * policy.\n */\nexport const meshDetector: Detector = {\n id: \"service-mesh-crypto\",\n description:\n \"Classical crypto in service-mesh config (Linkerd identity, Consul Connect CA, Istio cipher suites)\",\n scope: \"config\",\n language: \"any\",\n rules: [\n RULE_MESH_LINKERD_ECDSA,\n RULE_MESH_CONSUL_RSA,\n RULE_MESH_CONSUL_EC,\n RULE_MESH_ISTIO_CLASSICAL_CIPHER,\n ],\n appliesTo: (f) => hasExtension(f, MESH_EXTENSIONS),\n detect({ file, content }): Finding[] {\n const isLinkerd = content.includes(\"linkerd\") || content.includes(\"identityTrustAnchors\");\n const isConsulConnect = content.includes(\"consul\") && content.includes(\"connect\");\n const isIstioCipher = content.includes(\"DestinationRule\") || content.includes(\"cipherSuites\");\n if (!isLinkerd && !isConsulConnect && !isIstioCipher) return [];\n\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 if (isLinkerd) add(RE_MESH_LINKERD_ECDSA, RULE_MESH_LINKERD_ECDSA);\n if (isConsulConnect) {\n add(RE_MESH_CONSUL_RSA, RULE_MESH_CONSUL_RSA);\n add(RE_MESH_CONSUL_EC, RULE_MESH_CONSUL_EC);\n }\n if (isIstioCipher) add(RE_MESH_ISTIO_CLASSICAL_CIPHER, RULE_MESH_ISTIO_CLASSICAL_CIPHER);\n return findings;\n },\n};\n"]}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Config detector: classical transport crypto in message brokers / event streams
3
+ * (Kafka, RabbitMQ, MQTT/Mosquitto, NATS). Broker traffic is "communication
4
+ * between things"; a legacy TLS floor or a classical (EC)DHE cipher suite makes
5
+ * every message in flight harvest-now-decrypt-later exposed.
6
+ *
7
+ * Covered in broker config files (`.properties`, `.conf`, `.cfg`, `.ini`):
8
+ * - Kafka `ssl.protocol` / `ssl.enabled.protocols = TLSv1 | TLSv1.1` (legacy).
9
+ * - MQTT/Mosquitto `tls_version tlsv1 | tlsv1.1` (legacy).
10
+ * - Kafka `ssl.cipher.suites` naming a classical `ECDHE_RSA` / `ECDHE_ECDSA` /
11
+ * `TLS_RSA` suite — the harvestable key-exchange path.
12
+ */
13
+ import type { Detector } from "../types.js";
14
+ /** Detects classical transport crypto in message-broker / event-stream config. */
15
+ export declare const messagingDetector: Detector;
16
+ //# sourceMappingURL=messaging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging.d.ts","sourceRoot":"","sources":["../../src/detectors/messaging.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,aAAa,CAAC;AAkE/D,kFAAkF;AAClF,eAAO,MAAM,iBAAiB,EAAE,QAkB/B,CAAC"}
@@ -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"]}
@@ -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
  {
@@ -1 +1 @@
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) keys and 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"]}
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"}