@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.
- package/LICENSE +201 -0
- package/README.md +38 -10
- package/dist/agent-types.js.map +1 -1
- package/dist/baseline.js.map +1 -1
- package/dist/cache.js.map +1 -1
- package/dist/cbom.d.ts.map +1 -1
- package/dist/cbom.js +13 -4
- package/dist/cbom.js.map +1 -1
- package/dist/changed.js.map +1 -1
- package/dist/codemods/config-toggle.js.map +1 -1
- package/dist/codemods/registry.js.map +1 -1
- package/dist/comments.d.ts +26 -0
- package/dist/comments.d.ts.map +1 -1
- package/dist/comments.js +141 -1
- package/dist/comments.js.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/cwe.js.map +1 -1
- package/dist/dependencies.d.ts +3 -2
- package/dist/dependencies.d.ts.map +1 -1
- package/dist/dependencies.js +151 -4
- package/dist/dependencies.js.map +1 -1
- package/dist/detect-utils.d.ts +14 -3
- package/dist/detect-utils.d.ts.map +1 -1
- package/dist/detect-utils.js +32 -4
- package/dist/detect-utils.js.map +1 -1
- package/dist/detectors/c.d.ts.map +1 -1
- package/dist/detectors/c.js +190 -2
- package/dist/detectors/c.js.map +1 -1
- package/dist/detectors/csharp.d.ts.map +1 -1
- package/dist/detectors/csharp.js +141 -3
- package/dist/detectors/csharp.js.map +1 -1
- package/dist/detectors/go.d.ts +5 -3
- package/dist/detectors/go.d.ts.map +1 -1
- package/dist/detectors/go.js +187 -3
- package/dist/detectors/go.js.map +1 -1
- package/dist/detectors/java.d.ts.map +1 -1
- package/dist/detectors/java.js +168 -3
- package/dist/detectors/java.js.map +1 -1
- package/dist/detectors/pem.d.ts.map +1 -1
- package/dist/detectors/pem.js +49 -1
- package/dist/detectors/pem.js.map +1 -1
- package/dist/detectors/python.d.ts.map +1 -1
- package/dist/detectors/python.js +74 -3
- package/dist/detectors/python.js.map +1 -1
- package/dist/detectors/ruby.d.ts +9 -5
- package/dist/detectors/ruby.d.ts.map +1 -1
- package/dist/detectors/ruby.js +122 -2
- package/dist/detectors/ruby.js.map +1 -1
- package/dist/detectors/rust.d.ts +8 -3
- package/dist/detectors/rust.d.ts.map +1 -1
- package/dist/detectors/rust.js +185 -3
- package/dist/detectors/rust.js.map +1 -1
- package/dist/detectors/source.d.ts.map +1 -1
- package/dist/detectors/source.js +131 -13
- package/dist/detectors/source.js.map +1 -1
- package/dist/detectors/stateful-hbs.d.ts +22 -0
- package/dist/detectors/stateful-hbs.d.ts.map +1 -0
- package/dist/detectors/stateful-hbs.js +139 -0
- package/dist/detectors/stateful-hbs.js.map +1 -0
- package/dist/errors.js.map +1 -1
- package/dist/evidence.d.ts +48 -0
- package/dist/evidence.d.ts.map +1 -0
- package/dist/evidence.js +76 -0
- package/dist/evidence.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/inventory.d.ts +2 -0
- package/dist/inventory.d.ts.map +1 -1
- package/dist/inventory.js +27 -1
- package/dist/inventory.js.map +1 -1
- package/dist/parallel.js +15 -0
- package/dist/parallel.js.map +1 -1
- package/dist/patch-policy.js.map +1 -1
- package/dist/redact.d.ts.map +1 -1
- package/dist/redact.js +122 -7
- package/dist/redact.js.map +1 -1
- package/dist/registry.d.ts +2 -2
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +4 -2
- package/dist/registry.js.map +1 -1
- package/dist/remediate-pipeline.d.ts +3 -0
- package/dist/remediate-pipeline.d.ts.map +1 -1
- package/dist/remediate-pipeline.js +50 -0
- package/dist/remediate-pipeline.js.map +1 -1
- package/dist/remediate-request.js.map +1 -1
- package/dist/remediation.d.ts +9 -3
- package/dist/remediation.d.ts.map +1 -1
- package/dist/remediation.js +33 -6
- package/dist/remediation.js.map +1 -1
- package/dist/report.d.ts +9 -0
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +31 -0
- package/dist/report.js.map +1 -1
- package/dist/scan-worker.js.map +1 -1
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +16 -2
- package/dist/scan.js.map +1 -1
- package/dist/severity.js.map +1 -1
- package/dist/triage.js.map +1 -1
- package/dist/types.d.ts +8 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/verify.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/walk.js.map +1 -1
- package/dist/worktree.d.ts.map +1 -1
- package/dist/worktree.js +10 -1
- package/dist/worktree.js.map +1 -1
- package/package.json +1 -1
- package/src/cbom.ts +13 -4
- package/src/comments.ts +140 -1
- package/src/dependencies.ts +156 -6
- package/src/detect-utils.ts +33 -4
- package/src/detectors/c.ts +202 -2
- package/src/detectors/csharp.ts +154 -3
- package/src/detectors/go.ts +209 -6
- package/src/detectors/java.ts +189 -3
- package/src/detectors/pem.ts +53 -1
- package/src/detectors/python.ts +82 -3
- package/src/detectors/ruby.ts +138 -7
- package/src/detectors/rust.ts +211 -7
- package/src/detectors/source.ts +163 -12
- package/src/detectors/stateful-hbs.ts +177 -0
- package/src/evidence.ts +124 -0
- package/src/index.ts +5 -1
- package/src/inventory.ts +31 -1
- package/src/parallel.ts +15 -0
- package/src/redact.ts +125 -8
- package/src/registry.ts +4 -2
- package/src/remediate-pipeline.ts +55 -0
- package/src/remediation.ts +41 -9
- package/src/report.ts +41 -2
- package/src/scan.ts +21 -2
- package/src/types.ts +8 -1
- package/src/version.ts +1 -1
- package/src/worktree.ts +9 -1
package/src/detectors/csharp.ts
CHANGED
|
@@ -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:
|
|
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: [
|
|
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
|
};
|
package/src/detectors/go.ts
CHANGED
|
@@ -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/
|
|
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
|
|
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
|
|
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
|
},
|