@quantakrypto/core 0.4.1 → 0.4.3

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 (140) 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.d.ts.map +1 -1
  7. package/dist/cbom.js +13 -4
  8. package/dist/cbom.js.map +1 -1
  9. package/dist/changed.js.map +1 -1
  10. package/dist/codemods/config-toggle.js.map +1 -1
  11. package/dist/codemods/registry.js.map +1 -1
  12. package/dist/comments.d.ts +26 -0
  13. package/dist/comments.d.ts.map +1 -1
  14. package/dist/comments.js +141 -1
  15. package/dist/comments.js.map +1 -1
  16. package/dist/config.js.map +1 -1
  17. package/dist/cwe.js.map +1 -1
  18. package/dist/dependencies.d.ts +3 -2
  19. package/dist/dependencies.d.ts.map +1 -1
  20. package/dist/dependencies.js +151 -4
  21. package/dist/dependencies.js.map +1 -1
  22. package/dist/detect-utils.d.ts +14 -3
  23. package/dist/detect-utils.d.ts.map +1 -1
  24. package/dist/detect-utils.js +32 -4
  25. package/dist/detect-utils.js.map +1 -1
  26. package/dist/detectors/c.d.ts.map +1 -1
  27. package/dist/detectors/c.js +190 -2
  28. package/dist/detectors/c.js.map +1 -1
  29. package/dist/detectors/csharp.d.ts.map +1 -1
  30. package/dist/detectors/csharp.js +141 -3
  31. package/dist/detectors/csharp.js.map +1 -1
  32. package/dist/detectors/go.d.ts +5 -3
  33. package/dist/detectors/go.d.ts.map +1 -1
  34. package/dist/detectors/go.js +187 -3
  35. package/dist/detectors/go.js.map +1 -1
  36. package/dist/detectors/java.d.ts.map +1 -1
  37. package/dist/detectors/java.js +168 -3
  38. package/dist/detectors/java.js.map +1 -1
  39. package/dist/detectors/pem.d.ts.map +1 -1
  40. package/dist/detectors/pem.js +49 -1
  41. package/dist/detectors/pem.js.map +1 -1
  42. package/dist/detectors/python.d.ts.map +1 -1
  43. package/dist/detectors/python.js +74 -3
  44. package/dist/detectors/python.js.map +1 -1
  45. package/dist/detectors/ruby.d.ts +9 -5
  46. package/dist/detectors/ruby.d.ts.map +1 -1
  47. package/dist/detectors/ruby.js +122 -2
  48. package/dist/detectors/ruby.js.map +1 -1
  49. package/dist/detectors/rust.d.ts +8 -3
  50. package/dist/detectors/rust.d.ts.map +1 -1
  51. package/dist/detectors/rust.js +185 -3
  52. package/dist/detectors/rust.js.map +1 -1
  53. package/dist/detectors/source.d.ts.map +1 -1
  54. package/dist/detectors/source.js +131 -13
  55. package/dist/detectors/source.js.map +1 -1
  56. package/dist/detectors/stateful-hbs.d.ts +22 -0
  57. package/dist/detectors/stateful-hbs.d.ts.map +1 -0
  58. package/dist/detectors/stateful-hbs.js +139 -0
  59. package/dist/detectors/stateful-hbs.js.map +1 -0
  60. package/dist/errors.js.map +1 -1
  61. package/dist/evidence.d.ts +48 -0
  62. package/dist/evidence.d.ts.map +1 -0
  63. package/dist/evidence.js +76 -0
  64. package/dist/evidence.js.map +1 -0
  65. package/dist/index.d.ts +4 -2
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +4 -2
  68. package/dist/index.js.map +1 -1
  69. package/dist/inventory.d.ts +2 -0
  70. package/dist/inventory.d.ts.map +1 -1
  71. package/dist/inventory.js +27 -1
  72. package/dist/inventory.js.map +1 -1
  73. package/dist/parallel.js +15 -0
  74. package/dist/parallel.js.map +1 -1
  75. package/dist/patch-policy.js.map +1 -1
  76. package/dist/redact.d.ts.map +1 -1
  77. package/dist/redact.js +122 -7
  78. package/dist/redact.js.map +1 -1
  79. package/dist/registry.d.ts +2 -2
  80. package/dist/registry.d.ts.map +1 -1
  81. package/dist/registry.js +4 -2
  82. package/dist/registry.js.map +1 -1
  83. package/dist/remediate-pipeline.d.ts +3 -0
  84. package/dist/remediate-pipeline.d.ts.map +1 -1
  85. package/dist/remediate-pipeline.js +50 -0
  86. package/dist/remediate-pipeline.js.map +1 -1
  87. package/dist/remediate-request.js.map +1 -1
  88. package/dist/remediation.d.ts +9 -3
  89. package/dist/remediation.d.ts.map +1 -1
  90. package/dist/remediation.js +33 -6
  91. package/dist/remediation.js.map +1 -1
  92. package/dist/report.d.ts +9 -0
  93. package/dist/report.d.ts.map +1 -1
  94. package/dist/report.js +31 -0
  95. package/dist/report.js.map +1 -1
  96. package/dist/scan-worker.js.map +1 -1
  97. package/dist/scan.d.ts.map +1 -1
  98. package/dist/scan.js +16 -2
  99. package/dist/scan.js.map +1 -1
  100. package/dist/severity.js.map +1 -1
  101. package/dist/triage.js.map +1 -1
  102. package/dist/types.d.ts +8 -1
  103. package/dist/types.d.ts.map +1 -1
  104. package/dist/types.js.map +1 -1
  105. package/dist/verify.js.map +1 -1
  106. package/dist/version.d.ts +1 -1
  107. package/dist/version.js +1 -1
  108. package/dist/version.js.map +1 -1
  109. package/dist/walk.js.map +1 -1
  110. package/dist/worktree.d.ts.map +1 -1
  111. package/dist/worktree.js +10 -1
  112. package/dist/worktree.js.map +1 -1
  113. package/package.json +1 -1
  114. package/src/cbom.ts +13 -4
  115. package/src/comments.ts +140 -1
  116. package/src/dependencies.ts +156 -6
  117. package/src/detect-utils.ts +33 -4
  118. package/src/detectors/c.ts +202 -2
  119. package/src/detectors/csharp.ts +154 -3
  120. package/src/detectors/go.ts +209 -6
  121. package/src/detectors/java.ts +189 -3
  122. package/src/detectors/pem.ts +53 -1
  123. package/src/detectors/python.ts +82 -3
  124. package/src/detectors/ruby.ts +138 -7
  125. package/src/detectors/rust.ts +211 -7
  126. package/src/detectors/source.ts +163 -12
  127. package/src/detectors/stateful-hbs.ts +177 -0
  128. package/src/evidence.ts +124 -0
  129. package/src/index.ts +5 -1
  130. package/src/inventory.ts +31 -1
  131. package/src/parallel.ts +15 -0
  132. package/src/redact.ts +125 -8
  133. package/src/registry.ts +4 -2
  134. package/src/remediate-pipeline.ts +55 -0
  135. package/src/remediation.ts +41 -9
  136. package/src/report.ts +41 -2
  137. package/src/scan.ts +21 -2
  138. package/src/types.ts +8 -1
  139. package/src/version.ts +1 -1
  140. package/src/worktree.ts +9 -1
@@ -11,7 +11,7 @@
11
11
  */
12
12
  import type { Detector, Finding, RuleMeta } from "../types.js";
13
13
  import { CSHARP_EXTENSIONS, eachMatch, findingFromRule, hasExtension } from "../detect-utils.js";
14
- import { CWE_BROKEN_CRYPTO } from "../cwe.js";
14
+ import { CWE_BROKEN_CRYPTO, CWE_CERT_VALIDATION, CWE_WEAK_STRENGTH } from "../cwe.js";
15
15
 
16
16
  const RE_CS_RSA =
17
17
  /\bRSA\.Create\s*\(|\bnew\s+RSACryptoServiceProvider\s*\(|\bnew\s+RSACng\s*\(|\bnew\s+RSAOpenSsl\s*\(/g;
@@ -19,6 +19,37 @@ const RE_CS_ECDSA = /\bECDsa\.Create\s*\(|\bnew\s+ECDsaCng\s*\(|\bnew\s+ECDsaOpe
19
19
  const RE_CS_ECDH =
20
20
  /\bECDiffieHellman\.Create\s*\(|\bnew\s+ECDiffieHellmanCng\s*\(|\bnew\s+ECDiffieHellmanOpenSsl\s*\(/g;
21
21
  const RE_CS_DSA = /\bDSA\.Create\s*\(|\bnew\s+DSACryptoServiceProvider\s*\(|\bnew\s+DSACng\s*\(/g;
22
+ // Insecure TLS configuration (.NET). Mirrors source.ts's tlsDetector split of a
23
+ // cert-verification-disabled rule (tls-reject-unauthorized) and a legacy-version
24
+ // rule (tls-legacy-version) for the equivalent C# idioms:
25
+ // - DangerousAcceptAnyServerCertificateValidator / a custom
26
+ // ServerCertificateCustomValidationCallback → accepts any cert (MITM).
27
+ // - SslProtocols.Ssl3 / .Tls / .Tls11 → deprecated SSL 3.0 / TLS 1.0 / 1.1.
28
+ // `SslProtocols.Tls` (no suffix) is the legacy TLS 1.0 constant; `Tls12`/`Tls13`
29
+ // are excluded by the trailing \b (the following digit is a word char).
30
+ const RE_CS_TLS_CERT_VALIDATION =
31
+ /\bDangerousAcceptAnyServerCertificateValidator\b|ServerCertificateCustomValidationCallback\s*=/g;
32
+ const RE_CS_TLS_LEGACY_VERSION = /\bSslProtocols\.(?:Tls|Tls11|Ssl3)\b/g;
33
+ // Identifier-form JWT/JOSE signature algorithms (audit F7). The quoted-string
34
+ // alg token ("RS256") is caught by the language-agnostic jwt-jose detector, but
35
+ // Microsoft.IdentityModel passes the alg as an IDENTIFIER, not a string literal:
36
+ // SecurityAlgorithms.RsaSha256 / SecurityAlgorithms.EcdsaSha256.
37
+ const RE_CS_JWT_ALG = /\bSecurityAlgorithms\.(?:Rsa|Ecdsa)Sha(?:256|384|512)\b/g;
38
+ // BouncyCastle (Org.BouncyCastle) modern-curve and finite-field DH primitives,
39
+ // which System.Security.Cryptography does not expose directly. Each regex is
40
+ // anchored to the distinctive BouncyCastle class names for one family so it
41
+ // can't misfire on unrelated identifiers:
42
+ // - Ed25519KeyPairGenerator / Ed25519Signer / Ed25519PrivateKeyParameters → EdDSA
43
+ // - X25519KeyPairGenerator / X25519Agreement / X25519PrivateKeyParameters → X25519
44
+ // - X448KeyPairGenerator / X448Agreement / X448PrivateKeyParameters → X448
45
+ // - DHParametersGenerator / DHBasicAgreement / DH(Basic)KeyPairGenerator / DHParameters → DH
46
+ // The trailing \b keeps each token whole (e.g. Ed25519KeyGenerationParameters,
47
+ // X25519PublicKeyParameters and DHKeyGenerationParameters are NOT matched).
48
+ const RE_CS_BC_EDDSA = /\bEd25519(?:KeyPairGenerator|Signer|PrivateKeyParameters)\b/g;
49
+ const RE_CS_BC_X25519 = /\bX25519(?:KeyPairGenerator|Agreement|PrivateKeyParameters)\b/g;
50
+ const RE_CS_BC_X448 = /\bX448(?:KeyPairGenerator|Agreement|PrivateKeyParameters)\b/g;
51
+ const RE_CS_BC_DH =
52
+ /\bDH(?:ParametersGenerator|BasicAgreement|BasicKeyPairGenerator|KeyPairGenerator|Parameters)\b/g;
22
53
 
23
54
  const RULE_CS_RSA: RuleMeta = {
24
55
  id: "csharp-rsa",
@@ -71,14 +102,123 @@ const RULE_CS_DSA: RuleMeta = {
71
102
  message: "Classical DSA (.NET) is deprecated and forgeable by a quantum attacker.",
72
103
  remediation: "Rotate off DSA and migrate to ML-DSA-65 (FIPS 204).",
73
104
  };
105
+ const RULE_CS_TLS_CERT: RuleMeta = {
106
+ id: "csharp-tls-cert-validation",
107
+ title: "C# TLS certificate verification disabled",
108
+ description:
109
+ "DangerousAcceptAnyServerCertificateValidator / ServerCertificateCustomValidationCallback override",
110
+ category: "tls",
111
+ severity: "high",
112
+ confidence: "high",
113
+ hndl: false,
114
+ cwe: CWE_CERT_VALIDATION,
115
+ message: "Accepting any server certificate disables TLS certificate verification (MITM risk).",
116
+ remediation:
117
+ "Remove the custom validator and verify certificates properly; prefer PQC-hybrid key exchange.",
118
+ };
119
+ const RULE_CS_TLS_LEGACY: RuleMeta = {
120
+ id: "csharp-tls-legacy-version",
121
+ title: "C# legacy TLS/SSL version pinned",
122
+ description: "SslProtocols pinned to Ssl3 / TLS 1.0 / TLS 1.1",
123
+ category: "tls",
124
+ severity: "medium",
125
+ confidence: "high",
126
+ hndl: false,
127
+ cwe: CWE_WEAK_STRENGTH,
128
+ message:
129
+ "SSL 3.0 / TLS 1.0 / TLS 1.1 are deprecated and insecure; require TLS 1.2+ (prefer 1.3).",
130
+ remediation: "Use SslProtocols.Tls13 (or Tls12) and prefer PQC-hybrid key exchange.",
131
+ };
132
+ const RULE_CS_JWT_ALG: RuleMeta = {
133
+ id: "csharp-jwt-alg",
134
+ title: "C# identifier-form JWT/JOSE algorithm",
135
+ description: "Microsoft.IdentityModel SecurityAlgorithms.RsaSha* / EcdsaSha*",
136
+ category: "signature",
137
+ severity: "high",
138
+ confidence: "high",
139
+ algorithm: "unknown",
140
+ hndl: false,
141
+ cwe: CWE_BROKEN_CRYPTO,
142
+ message:
143
+ "A classical JWT/JOSE signature algorithm (.NET, identifier form) is used, forgeable by a quantum attacker.",
144
+ remediation: "ML-DSA-65 (FIPS 204); track IETF PQC JOSE/COSE algorithms",
145
+ };
146
+ const RULE_CS_BC_EDDSA: RuleMeta = {
147
+ id: "csharp-bouncycastle-eddsa",
148
+ title: "C# Ed25519 signature (BouncyCastle)",
149
+ description:
150
+ "Org.BouncyCastle Ed25519KeyPairGenerator / Ed25519Signer / Ed25519PrivateKeyParameters",
151
+ category: "signature",
152
+ severity: "high",
153
+ confidence: "high",
154
+ algorithm: "EdDSA",
155
+ hndl: false,
156
+ cwe: CWE_BROKEN_CRYPTO,
157
+ message: "Classical Ed25519 signing (BouncyCastle) is forgeable by a quantum attacker.",
158
+ remediation: "ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205)",
159
+ };
160
+ const RULE_CS_BC_X25519: RuleMeta = {
161
+ id: "csharp-bouncycastle-x25519",
162
+ title: "C# X25519 key agreement (BouncyCastle)",
163
+ description:
164
+ "Org.BouncyCastle X25519KeyPairGenerator / X25519Agreement / X25519PrivateKeyParameters",
165
+ category: "key-exchange",
166
+ severity: "high",
167
+ confidence: "high",
168
+ algorithm: "X25519",
169
+ hndl: true,
170
+ cwe: CWE_BROKEN_CRYPTO,
171
+ message:
172
+ "X25519 Diffie-Hellman key agreement (BouncyCastle) is broken by Shor's algorithm (harvest-now-decrypt-later).",
173
+ };
174
+ const RULE_CS_BC_X448: RuleMeta = {
175
+ id: "csharp-bouncycastle-x448",
176
+ title: "C# X448 key agreement (BouncyCastle)",
177
+ description: "Org.BouncyCastle X448KeyPairGenerator / X448Agreement / X448PrivateKeyParameters",
178
+ category: "key-exchange",
179
+ severity: "high",
180
+ confidence: "high",
181
+ algorithm: "X448",
182
+ hndl: true,
183
+ cwe: CWE_BROKEN_CRYPTO,
184
+ message:
185
+ "X448 Diffie-Hellman key agreement (BouncyCastle) is broken by Shor's algorithm (harvest-now-decrypt-later).",
186
+ };
187
+ const RULE_CS_BC_DH: RuleMeta = {
188
+ id: "csharp-bouncycastle-dh",
189
+ title: "C# finite-field Diffie-Hellman (BouncyCastle)",
190
+ description:
191
+ "Org.BouncyCastle DHParametersGenerator / DHBasicAgreement / DHKeyPairGenerator / DHParameters",
192
+ category: "key-exchange",
193
+ severity: "high",
194
+ confidence: "high",
195
+ algorithm: "DH",
196
+ hndl: true,
197
+ cwe: CWE_BROKEN_CRYPTO,
198
+ message:
199
+ "Finite-field Diffie-Hellman (BouncyCastle) is broken by Shor's algorithm (harvest-now-decrypt-later).",
200
+ };
74
201
 
75
202
  /** Detects classical asymmetric crypto in C# (System.Security.Cryptography). */
76
203
  export const csharpDetector: Detector = {
77
204
  id: "csharp-crypto",
78
- description: "Classical asymmetric crypto in C#/.NET (System.Security.Cryptography)",
205
+ description:
206
+ "Classical asymmetric crypto (System.Security.Cryptography) and insecure TLS config in C#/.NET",
79
207
  scope: "source",
80
208
  language: "csharp",
81
- rules: [RULE_CS_RSA, RULE_CS_ECDSA, RULE_CS_ECDH, RULE_CS_DSA],
209
+ rules: [
210
+ RULE_CS_RSA,
211
+ RULE_CS_ECDSA,
212
+ RULE_CS_ECDH,
213
+ RULE_CS_DSA,
214
+ RULE_CS_TLS_CERT,
215
+ RULE_CS_TLS_LEGACY,
216
+ RULE_CS_JWT_ALG,
217
+ RULE_CS_BC_EDDSA,
218
+ RULE_CS_BC_X25519,
219
+ RULE_CS_BC_X448,
220
+ RULE_CS_BC_DH,
221
+ ],
82
222
  appliesTo: (f) => hasExtension(f, CSHARP_EXTENSIONS),
83
223
  detect({ file, content }): Finding[] {
84
224
  const findings: Finding[] = [];
@@ -93,6 +233,17 @@ export const csharpDetector: Detector = {
93
233
  add(RE_CS_ECDH, RULE_CS_ECDH);
94
234
  add(RE_CS_RSA, RULE_CS_RSA);
95
235
  add(RE_CS_DSA, RULE_CS_DSA);
236
+ // Insecure TLS configuration (disjoint from the crypto factories above).
237
+ add(RE_CS_TLS_CERT_VALIDATION, RULE_CS_TLS_CERT);
238
+ add(RE_CS_TLS_LEGACY_VERSION, RULE_CS_TLS_LEGACY);
239
+ // Identifier-form JWT/JOSE signature algorithms (Microsoft.IdentityModel).
240
+ add(RE_CS_JWT_ALG, RULE_CS_JWT_ALG);
241
+ // BouncyCastle (Org.BouncyCastle) curve / finite-field DH primitives that
242
+ // System.Security.Cryptography does not expose directly.
243
+ add(RE_CS_BC_EDDSA, RULE_CS_BC_EDDSA);
244
+ add(RE_CS_BC_X25519, RULE_CS_BC_X25519);
245
+ add(RE_CS_BC_X448, RULE_CS_BC_X448);
246
+ add(RE_CS_BC_DH, RULE_CS_BC_DH);
96
247
  return findings;
97
248
  },
98
249
  };
@@ -6,11 +6,13 @@
6
6
  * `ecdsa.SignASN1`, `ecdh.X25519`, …) are precise, low-false-positive signals.
7
7
  *
8
8
  * Covered:
9
- * - crypto/rsa — GenerateKey, EncryptOAEP/PKCS1v15, SignPKCS1v15/PSS
10
- * - crypto/ecdsa — GenerateKey, Sign/SignASN1
9
+ * - crypto/rsa — GenerateKey, EncryptOAEP/PKCS1v15, SignPKCS1v15/PSS, DecryptOAEP, VerifyPKCS1v15/PSS
10
+ * - crypto/ecdsa — GenerateKey, Sign/SignASN1, Verify/VerifyASN1
11
11
  * - crypto/ecdh — P256/P384/P521/X25519 curve construction (key agreement)
12
- * - crypto/ed25519 — GenerateKey, Sign
12
+ * - crypto/elliptic — GenerateKey / ScalarMult (classic pre-1.20 ECDH)
13
+ * - crypto/ed25519 — GenerateKey, Sign, Verify
13
14
  * - crypto/dsa — GenerateKey, GenerateParameters (deprecated)
15
+ * - crypto/tls — InsecureSkipVerify, legacy MinVersion (transport config hygiene)
14
16
  *
15
17
  * HNDL policy mirrors the other detectors: KEM / key agreement (RSA encryption,
16
18
  * ECDH) is harvest-now-decrypt-later exposed (hndl:true); signatures (RSA-sign,
@@ -21,7 +23,7 @@
21
23
  */
22
24
  import type { Detector, Finding, RuleMeta } from "../types.js";
23
25
  import { GO_EXTENSIONS, eachMatch, findingFromRule, hasExtension } from "../detect-utils.js";
24
- import { CWE_BROKEN_CRYPTO } from "../cwe.js";
26
+ import { CWE_BROKEN_CRYPTO, CWE_CERT_VALIDATION, CWE_WEAK_STRENGTH } from "../cwe.js";
25
27
 
26
28
  /* -------------------------------------------------------------------------- */
27
29
  /* Precompiled regexes (module scope) */
@@ -31,9 +33,37 @@ const RE_GO_RSA_KEYGEN = /\brsa\.GenerateKey\s*\(|\brsa\.GenerateMultiPrimeKey\s
31
33
  const RE_GO_RSA_ENCRYPT = /\brsa\.EncryptOAEP\s*\(|\brsa\.EncryptPKCS1v15\s*\(/g;
32
34
  const RE_GO_RSA_SIGN = /\brsa\.SignPKCS1v15\s*\(|\brsa\.SignPSS\s*\(/g;
33
35
  const RE_GO_ECDSA = /\becdsa\.GenerateKey\s*\(|\becdsa\.SignASN1\s*\(|\becdsa\.Sign\s*\(/g;
34
- const RE_GO_ECDH = /\becdh\.(?:P256|P384|P521|X25519)\s*\(/g;
36
+ const RE_GO_ECDH = /\becdh\.(?:P256|P384|P521)\s*\(/g;
37
+ // X25519 gets its own family (algorithm "X25519", lower severity) to match how
38
+ // every other pack classifies it — Go was the lone site reporting it as ECDH/high
39
+ // (audit F9). Still key-exchange + hndl:true.
40
+ const RE_GO_X25519 = /\becdh\.X25519\s*\(/g;
35
41
  const RE_GO_ED25519 = /\bed25519\.GenerateKey\s*\(|\bed25519\.Sign\s*\(/g;
36
42
  const RE_GO_DSA = /\bdsa\.GenerateKey\s*\(|\bdsa\.GenerateParameters\s*\(/g;
43
+ // Verify / decrypt call sites — the inverse operations the Sign/Encrypt/
44
+ // GenerateKey rules above miss today (audit F4/F6). Deliberately disjoint from
45
+ // those rules to avoid double-counting: DecryptOAEP≠EncryptOAEP, Verify*≠Sign*.
46
+ const RE_GO_RSA_DECRYPT = /\brsa\.DecryptOAEP\s*\(/g;
47
+ const RE_GO_RSA_VERIFY = /\brsa\.VerifyPKCS1v15\s*\(|\brsa\.VerifyPSS\s*\(/g;
48
+ const RE_GO_ECDSA_VERIFY = /\becdsa\.Verify(?:ASN1)?\s*\(/g;
49
+ const RE_GO_ED25519_VERIFY = /\bed25519\.Verify\s*\(/g;
50
+ // Classic pre-1.20 elliptic-curve key agreement (crypto/elliptic), superseded by
51
+ // crypto/ecdh but still widespread. GenerateKey + ScalarMult are the low-level
52
+ // ECDH building blocks the crypto/ecdh rule does not see. `.ScalarMult(` is an
53
+ // unqualified method call, so this rule carries medium confidence.
54
+ const RE_GO_ECDH_CLASSIC = /\belliptic\.GenerateKey\s*\(|\.ScalarMult\s*\(/g;
55
+ // Go TLS misconfiguration (crypto/tls). Mirrors the JS tlsDetector: disabled
56
+ // certificate verification and a legacy TLS/SSL version floor.
57
+ const RE_GO_TLS_SKIP_VERIFY = /InsecureSkipVerify:\s*true/g;
58
+ const RE_GO_TLS_LEGACY_VERSION = /MinVersion:\s*tls\.Version(?:TLS1[01]|SSL30)/g;
59
+ // Identifier-form golang-jwt signing methods (audit gap: the quoted "RS256" alg
60
+ // token is caught by the language-agnostic jwt-jose detector, but golang-jwt
61
+ // passes the alg as an EXPORTED IDENTIFIER — `jwt.SigningMethodRS256`,
62
+ // `jwt.SigningMethodES256`, `jwt.SigningMethodEdDSA` — which the string rule
63
+ // misses. RS*/PS* → RSA, ES* → ECDSA, EdDSA → EdDSA. The `\b`s keep it precise:
64
+ // HS* HMAC methods and longer look-alikes (`SigningMethodRS2560`) do not match.
65
+ const RE_GO_JWT_SIGNINGMETHOD =
66
+ /\bSigningMethod(RS|PS|ES)(?:256|384|512)\b|\bSigningMethodEdDSA\b/g;
37
67
 
38
68
  /* -------------------------------------------------------------------------- */
39
69
  /* Rule catalog */
@@ -93,7 +123,7 @@ const RULE_GO_ECDSA: RuleMeta = {
93
123
  const RULE_GO_ECDH: RuleMeta = {
94
124
  id: "go-ecdh",
95
125
  title: "Go ECDH key exchange",
96
- description: "crypto/ecdh P256/P384/P521/X25519 key agreement",
126
+ description: "crypto/ecdh P256/P384/P521 key agreement",
97
127
  category: "key-exchange",
98
128
  severity: "high",
99
129
  confidence: "high",
@@ -103,6 +133,19 @@ const RULE_GO_ECDH: RuleMeta = {
103
133
  message:
104
134
  "Elliptic-curve Diffie-Hellman (Go crypto/ecdh) is broken by Shor's algorithm (harvest-now-decrypt-later).",
105
135
  };
136
+ const RULE_GO_X25519: RuleMeta = {
137
+ id: "go-x25519",
138
+ title: "Go X25519 key exchange",
139
+ description: "crypto/ecdh X25519 key agreement",
140
+ category: "key-exchange",
141
+ severity: "medium",
142
+ confidence: "high",
143
+ algorithm: "X25519",
144
+ hndl: true,
145
+ cwe: CWE_BROKEN_CRYPTO,
146
+ message:
147
+ "X25519 (Go crypto/ecdh) is modern but still classical key agreement — harvest-now-decrypt-later.",
148
+ };
106
149
  const RULE_GO_ED25519: RuleMeta = {
107
150
  id: "go-ed25519",
108
151
  title: "Go Ed25519 signature",
@@ -128,6 +171,132 @@ const RULE_GO_DSA: RuleMeta = {
128
171
  message: "Classical DSA (Go) is deprecated and forgeable by a quantum attacker.",
129
172
  remediation: "Rotate off DSA and migrate to ML-DSA-65 (FIPS 204).",
130
173
  };
174
+ const RULE_GO_RSA_DECRYPT: RuleMeta = {
175
+ id: "go-rsa-decrypt",
176
+ title: "Go RSA public-key decryption",
177
+ description: "crypto/rsa DecryptOAEP",
178
+ category: "kem",
179
+ severity: "high",
180
+ confidence: "high",
181
+ algorithm: "RSA",
182
+ hndl: true,
183
+ cwe: CWE_BROKEN_CRYPTO,
184
+ message:
185
+ "RSA public-key decryption (Go) recovers data protected by a classical KEM — harvest-now-decrypt-later exposed.",
186
+ };
187
+ const RULE_GO_RSA_VERIFY: RuleMeta = {
188
+ id: "go-rsa-verify",
189
+ title: "Go RSA signature verification",
190
+ description: "crypto/rsa VerifyPKCS1v15 / VerifyPSS",
191
+ category: "signature",
192
+ severity: "high",
193
+ confidence: "high",
194
+ algorithm: "RSA",
195
+ hndl: false,
196
+ cwe: CWE_BROKEN_CRYPTO,
197
+ message: "Verifies classical RSA signatures (Go), which are forgeable by a quantum attacker.",
198
+ remediation: "ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205)",
199
+ };
200
+ const RULE_GO_ECDSA_VERIFY: RuleMeta = {
201
+ id: "go-ecdsa-verify",
202
+ title: "Go ECDSA signature verification",
203
+ description: "crypto/ecdsa Verify / VerifyASN1",
204
+ category: "signature",
205
+ severity: "high",
206
+ confidence: "high",
207
+ algorithm: "ECDSA",
208
+ hndl: false,
209
+ cwe: CWE_BROKEN_CRYPTO,
210
+ message: "Verifies classical ECDSA signatures (Go), which are forgeable by a quantum attacker.",
211
+ remediation: "ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205)",
212
+ };
213
+ const RULE_GO_ED25519_VERIFY: RuleMeta = {
214
+ id: "go-ed25519-verify",
215
+ title: "Go Ed25519 signature verification",
216
+ description: "crypto/ed25519 Verify",
217
+ category: "signature",
218
+ severity: "low",
219
+ confidence: "high",
220
+ algorithm: "EdDSA",
221
+ hndl: false,
222
+ cwe: CWE_BROKEN_CRYPTO,
223
+ message: "Verifies Ed25519 signatures (Go) — modern but still classical and quantum-forgeable.",
224
+ };
225
+ const RULE_GO_ECDH_CLASSIC: RuleMeta = {
226
+ id: "go-ecdh-classic",
227
+ title: "Go classic EC key agreement (crypto/elliptic)",
228
+ description: "crypto/elliptic GenerateKey / ScalarMult (pre-1.20 ECDH)",
229
+ category: "key-exchange",
230
+ severity: "high",
231
+ confidence: "medium",
232
+ algorithm: "ECDH",
233
+ hndl: true,
234
+ cwe: CWE_BROKEN_CRYPTO,
235
+ message:
236
+ "Low-level elliptic-curve key agreement (Go crypto/elliptic) is broken by Shor's algorithm (harvest-now-decrypt-later).",
237
+ };
238
+ const RULE_GO_TLS_SKIP_VERIFY: RuleMeta = {
239
+ id: "go-tls-insecure-skip-verify",
240
+ title: "Go TLS certificate verification disabled",
241
+ description: "crypto/tls Config InsecureSkipVerify: true",
242
+ category: "tls",
243
+ severity: "high",
244
+ confidence: "high",
245
+ hndl: false,
246
+ cwe: CWE_CERT_VALIDATION,
247
+ message: "InsecureSkipVerify:true disables TLS certificate verification (Go) — MITM risk.",
248
+ remediation: "Remove InsecureSkipVerify:true; verify certificates properly.",
249
+ };
250
+ const RULE_GO_TLS_LEGACY_VERSION: RuleMeta = {
251
+ id: "go-tls-legacy-version",
252
+ title: "Go legacy TLS version pinned",
253
+ description: "crypto/tls MinVersion pinned to TLS 1.0/1.1 or SSL 3.0",
254
+ category: "tls",
255
+ severity: "medium",
256
+ confidence: "high",
257
+ hndl: false,
258
+ cwe: CWE_WEAK_STRENGTH,
259
+ message:
260
+ "MinVersion pins a deprecated TLS/SSL floor (TLS 1.0/1.1 or SSL 3.0) in Go; require TLS 1.3.",
261
+ remediation: "Set MinVersion: tls.VersionTLS13 and prefer PQC-hybrid key exchange.",
262
+ };
263
+ const RULE_GO_JWT_SIGNINGMETHOD: RuleMeta = {
264
+ id: "go-jwt-signingmethod",
265
+ title: "Go identifier-form JWT signing method",
266
+ description: "golang-jwt SigningMethodRS/PS/ES* / SigningMethodEdDSA identifier",
267
+ category: "signature",
268
+ severity: "high",
269
+ confidence: "high",
270
+ algorithm: "unknown", // representative umbrella; refined per-match (RSA/ECDSA/EdDSA)
271
+ hndl: false,
272
+ cwe: CWE_BROKEN_CRYPTO,
273
+ message:
274
+ "A classical JWT signature algorithm (Go golang-jwt, identifier form) is used, forgeable by a quantum attacker.",
275
+ remediation: "ML-DSA-65 (FIPS 204); track IETF PQC JOSE/COSE algorithms",
276
+ };
277
+
278
+ // The x509 PEM/DER key + certificate layer: parsing/marshalling classical RSA,
279
+ // EC and PKIX key material and X.509 certificates. This is the "handles classical
280
+ // keys" surface the Sign/Verify/GenerateKey rules miss — a key-loading utility
281
+ // (`x509.ParsePKCS8PrivateKey`) touches quantum-vulnerable material without ever
282
+ // naming rsa/ecdsa. Family is ambiguous at the parse site, so `unknown`.
283
+ const RE_GO_X509_PARSE =
284
+ /\bx509\.(?:ParsePKCS1PrivateKey|ParsePKCS8PrivateKey|ParsePKIXPublicKey|ParseECPrivateKey|ParsePKCS1PublicKey|MarshalPKCS1PrivateKey|MarshalPKCS8PrivateKey|MarshalPKIXPublicKey|MarshalECPrivateKey|ParseCertificates?|ParseCertificateRequest|CreateCertificate|CreateCertificateRequest)\b/g;
285
+ const RULE_GO_X509_PARSE: RuleMeta = {
286
+ id: "go-x509-parse",
287
+ title: "Go x509 classical key/certificate handling",
288
+ description: "x509.Parse*/Marshal*/Create* for RSA/EC/PKIX keys and X.509 certificates",
289
+ category: "certificate",
290
+ severity: "medium",
291
+ confidence: "medium",
292
+ algorithm: "unknown",
293
+ hndl: false,
294
+ cwe: CWE_BROKEN_CRYPTO,
295
+ message:
296
+ "This code parses/marshals classical asymmetric key or X.509 certificate material (x509.*), a quantum forgery/harvest surface.",
297
+ remediation:
298
+ "Inventory the key/cert types handled here; plan PQC (ML-DSA) certificate + key migration.",
299
+ };
131
300
 
132
301
  /** Detects classical asymmetric crypto in Go source (crypto/* standard library). */
133
302
  export const goDetector: Detector = {
@@ -141,8 +310,18 @@ export const goDetector: Detector = {
141
310
  RULE_GO_RSA_SIGN,
142
311
  RULE_GO_ECDSA,
143
312
  RULE_GO_ECDH,
313
+ RULE_GO_X25519,
144
314
  RULE_GO_ED25519,
145
315
  RULE_GO_DSA,
316
+ RULE_GO_RSA_DECRYPT,
317
+ RULE_GO_RSA_VERIFY,
318
+ RULE_GO_ECDSA_VERIFY,
319
+ RULE_GO_ED25519_VERIFY,
320
+ RULE_GO_ECDH_CLASSIC,
321
+ RULE_GO_TLS_SKIP_VERIFY,
322
+ RULE_GO_TLS_LEGACY_VERSION,
323
+ RULE_GO_JWT_SIGNINGMETHOD,
324
+ RULE_GO_X509_PARSE,
146
325
  ],
147
326
  appliesTo: (f) => hasExtension(f, GO_EXTENSIONS),
148
327
  detect({ file, content }): Finding[] {
@@ -159,8 +338,32 @@ export const goDetector: Detector = {
159
338
  add(RE_GO_RSA_SIGN, RULE_GO_RSA_SIGN);
160
339
  add(RE_GO_ECDSA, RULE_GO_ECDSA);
161
340
  add(RE_GO_ECDH, RULE_GO_ECDH);
341
+ add(RE_GO_X25519, RULE_GO_X25519);
162
342
  add(RE_GO_ED25519, RULE_GO_ED25519);
163
343
  add(RE_GO_DSA, RULE_GO_DSA);
344
+ add(RE_GO_RSA_DECRYPT, RULE_GO_RSA_DECRYPT);
345
+ add(RE_GO_RSA_VERIFY, RULE_GO_RSA_VERIFY);
346
+ add(RE_GO_ECDSA_VERIFY, RULE_GO_ECDSA_VERIFY);
347
+ add(RE_GO_ED25519_VERIFY, RULE_GO_ED25519_VERIFY);
348
+ add(RE_GO_ECDH_CLASSIC, RULE_GO_ECDH_CLASSIC);
349
+ add(RE_GO_TLS_SKIP_VERIFY, RULE_GO_TLS_SKIP_VERIFY);
350
+ add(RE_GO_TLS_LEGACY_VERSION, RULE_GO_TLS_LEGACY_VERSION);
351
+ add(RE_GO_X509_PARSE, RULE_GO_X509_PARSE);
352
+
353
+ // Identifier-form golang-jwt signing methods (jwt.SigningMethodRS256, …).
354
+ // Refine the umbrella "unknown" algorithm per match: m[1] is the RS/PS/ES
355
+ // prefix (RS/PS → RSA, ES → ECDSA); when it is undefined the EdDSA branch
356
+ // matched, so the family is EdDSA.
357
+ eachMatch(RE_GO_JWT_SIGNINGMETHOD, content, (m) => {
358
+ const algorithm: Finding["algorithm"] = m[1] === "ES" ? "ECDSA" : m[1] ? "RSA" : "EdDSA";
359
+ findings.push(
360
+ findingFromRule(
361
+ RULE_GO_JWT_SIGNINGMETHOD,
362
+ { file, content, index: m.index, matchLength: m[0].length },
363
+ { algorithm },
364
+ ),
365
+ );
366
+ });
164
367
 
165
368
  return findings;
166
369
  },