@quantakrypto/core 0.4.2 → 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.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 +138 -2
- 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 +117 -7
- 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.map +1 -1
- package/dist/patch-policy.js.map +1 -1
- package/dist/redact.d.ts.map +1 -1
- package/dist/redact.js +39 -0
- 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 +17 -5
- 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 +8 -1
- 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 +1 -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.js.map +1 -1
- package/package.json +1 -1
- package/src/comments.ts +140 -1
- package/src/dependencies.ts +143 -4
- 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 +149 -6
- 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/redact.ts +41 -0
- package/src/registry.ts +4 -2
- package/src/remediate-pipeline.ts +55 -0
- package/src/remediation.ts +23 -8
- package/src/report.ts +41 -2
- package/src/scan.ts +13 -1
- package/src/types.ts +1 -1
- package/src/version.ts +1 -1
package/src/comments.ts
CHANGED
|
@@ -109,6 +109,54 @@ export function commentSpans(content: string, style: CommentStyle): Array<[numbe
|
|
|
109
109
|
return spans;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Compute Python triple-quoted string spans (`"""…"""` / `'''…'''`). These are
|
|
114
|
+
* docstrings / prose in practice, so a crypto *name* mentioned inside one
|
|
115
|
+
* (`:param key_type: eg "ssh-ed25519"`) should not fire a token finding — but a
|
|
116
|
+
* PEM key pasted into one is still real material, so {@link stripCommentFindings}
|
|
117
|
+
* exempts `pem-*` rules. Comments and normal strings are skipped so a `"""`
|
|
118
|
+
* delimiter inside them is not mis-detected.
|
|
119
|
+
*/
|
|
120
|
+
export function pythonDocstringSpans(content: string): Array<[number, number]> {
|
|
121
|
+
const spans: Array<[number, number]> = [];
|
|
122
|
+
const n = content.length;
|
|
123
|
+
let i = 0;
|
|
124
|
+
while (i < n) {
|
|
125
|
+
const c = content[i];
|
|
126
|
+
if (c === "#") {
|
|
127
|
+
i++;
|
|
128
|
+
while (i < n && content[i] !== "\n") i++;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if ((c === '"' || c === "'") && content[i + 1] === c && content[i + 2] === c) {
|
|
132
|
+
const start = i;
|
|
133
|
+
i += 3;
|
|
134
|
+
while (i < n && !(content[i] === c && content[i + 1] === c && content[i + 2] === c)) i++;
|
|
135
|
+
i = Math.min(n, i + 3);
|
|
136
|
+
spans.push([start, i]);
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (c === '"' || c === "'") {
|
|
140
|
+
const q = c;
|
|
141
|
+
i++;
|
|
142
|
+
while (i < n) {
|
|
143
|
+
if (content[i] === "\\") {
|
|
144
|
+
i += 2;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (content[i] === q) {
|
|
148
|
+
i++;
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
i++;
|
|
152
|
+
}
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
i++;
|
|
156
|
+
}
|
|
157
|
+
return spans;
|
|
158
|
+
}
|
|
159
|
+
|
|
112
160
|
/** True if `offset` falls inside one of the (sorted, non-overlapping) spans. */
|
|
113
161
|
export function offsetInSpans(spans: ReadonlyArray<[number, number]>, offset: number): boolean {
|
|
114
162
|
let lo = 0;
|
|
@@ -163,7 +211,9 @@ export function stripCommentFindings(
|
|
|
163
211
|
const style = commentStyleForFile(file);
|
|
164
212
|
if (!style) return findings;
|
|
165
213
|
const spans = commentSpans(content, style);
|
|
166
|
-
|
|
214
|
+
// Python docstrings suppress prose *token* rules but keep real PEM material.
|
|
215
|
+
const docSpans = style === "hash" ? pythonDocstringSpans(content) : [];
|
|
216
|
+
if (spans.length === 0 && docSpans.length === 0) return findings;
|
|
167
217
|
|
|
168
218
|
// 1-based line → start offset, to turn a finding's (line, column) back into an
|
|
169
219
|
// absolute offset (column is 1-based: offset = lineStart + column - 1).
|
|
@@ -173,6 +223,95 @@ export function stripCommentFindings(
|
|
|
173
223
|
}
|
|
174
224
|
|
|
175
225
|
return findings.filter((f) => {
|
|
226
|
+
const start = lineStarts[f.location.line - 1] ?? 0;
|
|
227
|
+
const offset = start + ((f.location.column ?? 1) - 1);
|
|
228
|
+
if (offsetInSpans(spans, offset)) return false;
|
|
229
|
+
if (docSpans.length > 0 && !f.ruleId.startsWith("pem-") && offsetInSpans(docSpans, offset)) {
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
return true;
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Compute the string-literal spans (`[start, end)`) of `content`, skipping over
|
|
238
|
+
* comments so a quote inside a comment is not treated as a string. Used to
|
|
239
|
+
* suppress findings from IDENTIFIER-only rules (e.g. a Go `SigningMethodRS256`
|
|
240
|
+
* mentioned inside an error-message string) — the mirror of {@link commentSpans}.
|
|
241
|
+
*/
|
|
242
|
+
export function stringSpans(content: string, style: CommentStyle): Array<[number, number]> {
|
|
243
|
+
const spans: Array<[number, number]> = [];
|
|
244
|
+
const n = content.length;
|
|
245
|
+
let i = 0;
|
|
246
|
+
while (i < n) {
|
|
247
|
+
const c = content[i];
|
|
248
|
+
if (style === "c" && c === "/" && content[i + 1] === "/") {
|
|
249
|
+
i += 2;
|
|
250
|
+
while (i < n && content[i] !== "\n") i++;
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
if (style === "c" && c === "/" && content[i + 1] === "*") {
|
|
254
|
+
i += 2;
|
|
255
|
+
while (i < n && !(content[i] === "*" && content[i + 1] === "/")) i++;
|
|
256
|
+
i = Math.min(n, i + 2);
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
if (style === "hash" && c === "#") {
|
|
260
|
+
i++;
|
|
261
|
+
while (i < n && content[i] !== "\n") i++;
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
265
|
+
const quote = c;
|
|
266
|
+
const start = i;
|
|
267
|
+
i++;
|
|
268
|
+
while (i < n) {
|
|
269
|
+
if (content[i] === "\\") {
|
|
270
|
+
i += 2;
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
if (content[i] === quote) {
|
|
274
|
+
i++;
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
i++;
|
|
278
|
+
}
|
|
279
|
+
spans.push([start, i]);
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
i++;
|
|
283
|
+
}
|
|
284
|
+
return spans;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Drop findings of "code-only" rules (`ruleIds`) whose match starts inside a
|
|
289
|
+
* string literal. Some rules — an identifier-form JWT signing method, a Go
|
|
290
|
+
* `SigningMethodRS256` — are only meaningful as code; when the same token appears
|
|
291
|
+
* inside a string (a test's `t.Error("SigningMethodPS256 …")`) it is prose, not a
|
|
292
|
+
* usage. Rules that legitimately match inside strings (quoted `"RS256"` alg
|
|
293
|
+
* tokens, cipher-suite strings, ssh-key tokens) are NOT in `ruleIds` and pass
|
|
294
|
+
* through untouched.
|
|
295
|
+
*/
|
|
296
|
+
export function stripStringLiteralFindings(
|
|
297
|
+
findings: Finding[],
|
|
298
|
+
content: string,
|
|
299
|
+
file: string,
|
|
300
|
+
ruleIds: ReadonlySet<string>,
|
|
301
|
+
): Finding[] {
|
|
302
|
+
if (findings.length === 0 || !findings.some((f) => ruleIds.has(f.ruleId))) return findings;
|
|
303
|
+
const style = commentStyleForFile(file);
|
|
304
|
+
if (!style) return findings;
|
|
305
|
+
const spans = stringSpans(content, style);
|
|
306
|
+
if (spans.length === 0) return findings;
|
|
307
|
+
|
|
308
|
+
const lineStarts: number[] = [0];
|
|
309
|
+
for (let i = 0; i < content.length; i++) {
|
|
310
|
+
if (content[i] === "\n") lineStarts.push(i + 1);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return findings.filter((f) => {
|
|
314
|
+
if (!ruleIds.has(f.ruleId)) return true;
|
|
176
315
|
const start = lineStarts[f.location.line - 1] ?? 0;
|
|
177
316
|
const offset = start + ((f.location.column ?? 1) - 1);
|
|
178
317
|
return !offsetInSpans(spans, offset);
|
package/src/dependencies.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Curated database of packages that primarily expose classical asymmetric
|
|
3
3
|
* cryptography (and are therefore quantum-vulnerable), across multiple
|
|
4
|
-
* ecosystems (npm, PyPI, crates.io, Go modules, Maven, RubyGems), plus a
|
|
4
|
+
* ecosystems (npm, PyPI, crates.io, Go modules, Maven, RubyGems, NuGet), plus a
|
|
5
5
|
* manifest scanner that flags any of them found in the corresponding manifest
|
|
6
|
-
* (package.json, requirements.txt, Cargo.toml, go.mod, pom.xml, Gemfile,
|
|
6
|
+
* (package.json, requirements.txt, Cargo.toml, go.mod, pom.xml, Gemfile,
|
|
7
|
+
* packages.config / *.csproj, …).
|
|
7
8
|
*
|
|
8
9
|
* The list is intentionally focused on libraries whose *purpose* is classical
|
|
9
10
|
* public-key crypto. General-purpose packages that merely call the language's
|
|
@@ -313,6 +314,28 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
313
314
|
algorithms: ["RSA", "ECDSA", "DSA"],
|
|
314
315
|
severity: "high",
|
|
315
316
|
},
|
|
317
|
+
{
|
|
318
|
+
name: "pycrypto",
|
|
319
|
+
ecosystem: "pypi",
|
|
320
|
+
reason: "Abandoned/unmaintained crypto library — classical RSA/DSA/ElGamal.",
|
|
321
|
+
algorithms: ["RSA", "DSA"],
|
|
322
|
+
severity: "high",
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
name: "jwcrypto",
|
|
326
|
+
ecosystem: "pypi",
|
|
327
|
+
reason: "JWK / JWS / JWE with classical RS*/ES* and ECDH-ES key agreement.",
|
|
328
|
+
algorithms: ["RSA", "ECDSA", "ECDH"],
|
|
329
|
+
severity: "medium",
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
name: "authlib",
|
|
333
|
+
ecosystem: "pypi",
|
|
334
|
+
reason: "OAuth / OIDC / JOSE stack using classical RS*/ES* JWT signing.",
|
|
335
|
+
algorithms: ["RSA", "ECDSA"],
|
|
336
|
+
severity: "medium",
|
|
337
|
+
hndl: false,
|
|
338
|
+
},
|
|
316
339
|
{
|
|
317
340
|
name: "pycryptodomex",
|
|
318
341
|
ecosystem: "pypi",
|
|
@@ -422,6 +445,13 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
422
445
|
algorithms: ["ECDSA", "ECDH"],
|
|
423
446
|
severity: "high",
|
|
424
447
|
},
|
|
448
|
+
{
|
|
449
|
+
name: "secp256k1",
|
|
450
|
+
ecosystem: "cargo",
|
|
451
|
+
reason: "libsecp256k1 bindings (blockchain) — classical ECDSA + ECDH.",
|
|
452
|
+
algorithms: ["ECDSA", "ECDH"],
|
|
453
|
+
severity: "high",
|
|
454
|
+
},
|
|
425
455
|
{
|
|
426
456
|
name: "ed25519-dalek",
|
|
427
457
|
ecosystem: "cargo",
|
|
@@ -445,6 +475,43 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
445
475
|
algorithms: ["RSA", "ECDSA", "EdDSA", "ECDH"],
|
|
446
476
|
severity: "medium",
|
|
447
477
|
},
|
|
478
|
+
{
|
|
479
|
+
name: "github.com/golang-jwt/jwt/v5",
|
|
480
|
+
ecosystem: "go",
|
|
481
|
+
reason: "golang-jwt — classical RS*/PS*/ES* JWT algorithms.",
|
|
482
|
+
algorithms: ["RSA", "ECDSA"],
|
|
483
|
+
severity: "medium",
|
|
484
|
+
hndl: false,
|
|
485
|
+
},
|
|
486
|
+
{
|
|
487
|
+
name: "github.com/golang-jwt/jwt/v4",
|
|
488
|
+
ecosystem: "go",
|
|
489
|
+
reason: "golang-jwt (v4) — classical RS*/PS*/ES* JWT algorithms.",
|
|
490
|
+
algorithms: ["RSA", "ECDSA"],
|
|
491
|
+
severity: "medium",
|
|
492
|
+
hndl: false,
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
name: "github.com/go-jose/go-jose/v4",
|
|
496
|
+
ecosystem: "go",
|
|
497
|
+
reason: "go-jose — classical JOSE (RSA/ECDSA signatures, ECDH-ES key agreement).",
|
|
498
|
+
algorithms: ["RSA", "ECDSA", "ECDH"],
|
|
499
|
+
severity: "medium",
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
name: "github.com/cloudflare/circl",
|
|
503
|
+
ecosystem: "go",
|
|
504
|
+
reason: "Cloudflare CIRCL — classical ECDH/EdDSA curves (X25519, X448, Ed25519, P-256).",
|
|
505
|
+
algorithms: ["ECDH", "EdDSA"],
|
|
506
|
+
severity: "medium",
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
name: "github.com/decred/dcrd/dcrec/secp256k1/v4",
|
|
510
|
+
ecosystem: "go",
|
|
511
|
+
reason: "decred secp256k1 — classical ECDSA/ECDH on the secp256k1 curve (blockchain keys).",
|
|
512
|
+
algorithms: ["ECDSA", "ECDH"],
|
|
513
|
+
severity: "medium",
|
|
514
|
+
},
|
|
448
515
|
|
|
449
516
|
// --- Maven (Java) ---
|
|
450
517
|
{
|
|
@@ -476,6 +543,21 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
476
543
|
severity: "medium",
|
|
477
544
|
hndl: false,
|
|
478
545
|
},
|
|
546
|
+
{
|
|
547
|
+
name: "nimbus-jose-jwt",
|
|
548
|
+
ecosystem: "maven",
|
|
549
|
+
reason: "Nimbus JOSE+JWT — classical RS*/PS*/ES* JWS and RSA/ECDH-ES JWE.",
|
|
550
|
+
algorithms: ["RSA", "ECDSA", "ECDH"],
|
|
551
|
+
severity: "medium",
|
|
552
|
+
},
|
|
553
|
+
{
|
|
554
|
+
name: "jjwt-api",
|
|
555
|
+
ecosystem: "maven",
|
|
556
|
+
reason: "JJWT (io.jsonwebtoken) — classical RS*/ES* JWT signing.",
|
|
557
|
+
algorithms: ["RSA", "ECDSA"],
|
|
558
|
+
severity: "medium",
|
|
559
|
+
hndl: false,
|
|
560
|
+
},
|
|
479
561
|
|
|
480
562
|
// --- RubyGems ---
|
|
481
563
|
{
|
|
@@ -486,6 +568,14 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
486
568
|
severity: "medium",
|
|
487
569
|
hndl: false,
|
|
488
570
|
},
|
|
571
|
+
{
|
|
572
|
+
name: "net-ssh",
|
|
573
|
+
ecosystem: "rubygems",
|
|
574
|
+
reason:
|
|
575
|
+
"Ruby SSH client — classical host/user keys (RSA/ECDSA/Ed25519) and ECDH/DH key exchange.",
|
|
576
|
+
algorithms: ["RSA", "ECDSA", "ECDH"],
|
|
577
|
+
severity: "medium",
|
|
578
|
+
},
|
|
489
579
|
{
|
|
490
580
|
name: "rbnacl",
|
|
491
581
|
ecosystem: "rubygems",
|
|
@@ -500,13 +590,46 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
500
590
|
algorithms: ["EdDSA"],
|
|
501
591
|
severity: "low",
|
|
502
592
|
},
|
|
593
|
+
|
|
594
|
+
// --- NuGet (.NET) ---
|
|
595
|
+
{
|
|
596
|
+
name: "BouncyCastle.Cryptography",
|
|
597
|
+
ecosystem: "nuget",
|
|
598
|
+
reason: "BouncyCastle for .NET — full classical RSA/ECDSA/ECDH/DSA suite.",
|
|
599
|
+
algorithms: ["RSA", "ECDSA", "ECDH", "DSA"],
|
|
600
|
+
severity: "high",
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
name: "Portable.BouncyCastle",
|
|
604
|
+
ecosystem: "nuget",
|
|
605
|
+
reason: "Portable BouncyCastle for .NET — classical RSA/ECDSA/ECDH/DSA.",
|
|
606
|
+
algorithms: ["RSA", "ECDSA", "ECDH", "DSA"],
|
|
607
|
+
severity: "high",
|
|
608
|
+
},
|
|
609
|
+
{
|
|
610
|
+
name: "System.IdentityModel.Tokens.Jwt",
|
|
611
|
+
ecosystem: "nuget",
|
|
612
|
+
reason: "Microsoft JWT handler — classical RS*/ES* (RSA/ECDSA) signatures.",
|
|
613
|
+
algorithms: ["RSA", "ECDSA"],
|
|
614
|
+
severity: "medium",
|
|
615
|
+
hndl: false,
|
|
616
|
+
},
|
|
617
|
+
{
|
|
618
|
+
name: "Microsoft.IdentityModel.Tokens",
|
|
619
|
+
ecosystem: "nuget",
|
|
620
|
+
reason: "Microsoft IdentityModel token crypto — classical RSA/ECDSA keys.",
|
|
621
|
+
algorithms: ["RSA", "ECDSA"],
|
|
622
|
+
severity: "medium",
|
|
623
|
+
hndl: false,
|
|
624
|
+
},
|
|
503
625
|
];
|
|
504
626
|
|
|
505
627
|
/**
|
|
506
628
|
* Normalise a package name for matching within its ecosystem. PyPI is
|
|
507
629
|
* case-insensitive and folds runs of `-_.` to a single `-` (PEP 503); cargo /
|
|
508
|
-
* maven / rubygems are effectively lower-case
|
|
509
|
-
*
|
|
630
|
+
* maven / rubygems / nuget are effectively lower-case (NuGet ids are matched
|
|
631
|
+
* case-insensitively); npm and go module paths are matched verbatim (npm scopes
|
|
632
|
+
* and go paths are case-sensitive).
|
|
510
633
|
*/
|
|
511
634
|
function normalizeName(ecosystem: DependencyEcosystem, name: string): string {
|
|
512
635
|
const n = name.trim();
|
|
@@ -592,6 +715,8 @@ export function manifestEcosystem(file: string): DependencyEcosystem | null {
|
|
|
592
715
|
if (base === "go.mod") return "go";
|
|
593
716
|
if (base === "pom.xml" || base === "build.gradle" || base === "build.gradle.kts") return "maven";
|
|
594
717
|
if (base === "gemfile" || base.endsWith(".gemspec")) return "rubygems";
|
|
718
|
+
if (base === "packages.config" || base === "directory.packages.props" || base.endsWith(".csproj"))
|
|
719
|
+
return "nuget";
|
|
595
720
|
return null;
|
|
596
721
|
}
|
|
597
722
|
|
|
@@ -657,6 +782,20 @@ function candidateNames(ecosystem: DependencyEcosystem, content: string): string
|
|
|
657
782
|
}
|
|
658
783
|
break;
|
|
659
784
|
}
|
|
785
|
+
case "nuget": {
|
|
786
|
+
// NuGet manifests are XML. `.csproj` / `Directory.Packages.props` declare
|
|
787
|
+
// `<PackageReference Include="Name" … />`; `packages.config` uses
|
|
788
|
+
// `<package id="Name" … />`. Pull the Include= / id= attribute value from
|
|
789
|
+
// each. The `[^>]` guard keeps every match inside a single tag, so the
|
|
790
|
+
// scan is linear (no nested quantifiers → no catastrophic backtracking).
|
|
791
|
+
for (const m of content.matchAll(/<PackageReference\b[^>]*\bInclude\s*=\s*"([^"]+)"/gi)) {
|
|
792
|
+
names.push(m[1]);
|
|
793
|
+
}
|
|
794
|
+
for (const m of content.matchAll(/<package\b[^>]*\bid\s*=\s*"([^"]+)"/gi)) {
|
|
795
|
+
names.push(m[1]);
|
|
796
|
+
}
|
|
797
|
+
break;
|
|
798
|
+
}
|
|
660
799
|
case "npm":
|
|
661
800
|
break; // npm uses the JSON path, not this extractor.
|
|
662
801
|
}
|
package/src/detect-utils.ts
CHANGED
|
@@ -237,14 +237,43 @@ export const RUBY_EXTENSIONS: readonly string[] = [".rb"];
|
|
|
237
237
|
/** C / C++ source extensions handled by the OpenSSL detector. */
|
|
238
238
|
export const C_EXTENSIONS: readonly string[] = [".c", ".h", ".cc", ".cpp", ".cxx", ".hpp", ".hh"];
|
|
239
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Prose/documentation extensions. The language-agnostic *token* detectors (SSH
|
|
242
|
+
* public keys, TLS cipher suites, certificate signature algorithms) must not run
|
|
243
|
+
* on these: a changelog or README that mentions `ssh-rsa` or `ECDHE-RSA` in a
|
|
244
|
+
* sentence is prose, not crypto config. (PEM/`-----BEGIN` material stays in scope
|
|
245
|
+
* everywhere, so a key pasted into docs is still caught.)
|
|
246
|
+
*/
|
|
247
|
+
export const DOC_EXTENSIONS: readonly string[] = [
|
|
248
|
+
".md",
|
|
249
|
+
".markdown",
|
|
250
|
+
".mdown",
|
|
251
|
+
".mkd",
|
|
252
|
+
".rst",
|
|
253
|
+
".adoc",
|
|
254
|
+
".asciidoc",
|
|
255
|
+
".textile",
|
|
256
|
+
".org",
|
|
257
|
+
".rdoc",
|
|
258
|
+
".pod",
|
|
259
|
+
];
|
|
260
|
+
|
|
240
261
|
/**
|
|
241
262
|
* File-literal surfaces where a JWT/JOSE algorithm string (`"RS256"`, `"ES256"`)
|
|
242
263
|
* is the same evidence regardless of language. Used to un-gate the JWT detector
|
|
243
|
-
* from JS-only.
|
|
244
|
-
*
|
|
245
|
-
*
|
|
264
|
+
* from JS-only. Covers the languages whose JWT libraries pass the alg as a quoted
|
|
265
|
+
* token — JS/TS, Python, Go (`jwt.GetSigningMethod("RS256")`) and Ruby
|
|
266
|
+
* (`JWT.encode(payload, key, 'RS256')`) — so the regex stays precise (`HS*` HMAC
|
|
267
|
+
* tokens are excluded by `RE_JWT_ALG`). Java/C# pass the alg as an *identifier*
|
|
268
|
+
* (`SignatureAlgorithm.RS256`), which needs its own pattern — a later pass.
|
|
269
|
+
* YAML/JSON config carry unquoted tokens and higher FP risk, so they wait too.
|
|
246
270
|
*/
|
|
247
|
-
export const JWT_HOST_EXTENSIONS: readonly string[] = [
|
|
271
|
+
export const JWT_HOST_EXTENSIONS: readonly string[] = [
|
|
272
|
+
...JS_TS_EXTENSIONS,
|
|
273
|
+
...PYTHON_EXTENSIONS,
|
|
274
|
+
...GO_EXTENSIONS,
|
|
275
|
+
...RUBY_EXTENSIONS,
|
|
276
|
+
];
|
|
248
277
|
|
|
249
278
|
/**
|
|
250
279
|
* Extensions the scanner can actually analyze for inline crypto usage today
|
package/src/detectors/c.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import type { Detector, Finding, RuleMeta } from "../types.js";
|
|
18
18
|
import { C_EXTENSIONS, eachMatch, findingFromRule, hasExtension } from "../detect-utils.js";
|
|
19
|
-
import { CWE_BROKEN_CRYPTO } from "../cwe.js";
|
|
19
|
+
import { CWE_BROKEN_CRYPTO, CWE_CERT_VALIDATION, CWE_WEAK_STRENGTH } from "../cwe.js";
|
|
20
20
|
|
|
21
21
|
const RE_C_RSA = /\bRSA_generate_key(?:_ex)?\s*\(|\bEVP_RSA_gen\s*\(/g;
|
|
22
22
|
const RE_C_EC = /\bEC_KEY_generate_key\s*\(|\bEC_KEY_new_by_curve_name\s*\(/g;
|
|
@@ -24,6 +24,30 @@ const RE_C_ECDSA = /\bECDSA_do_sign\s*\(|\bECDSA_sign\s*\(/g;
|
|
|
24
24
|
const RE_C_ECDH = /\bECDH_compute_key\s*\(/g;
|
|
25
25
|
const RE_C_DSA = /\bDSA_generate_key\s*\(|\bDSA_generate_parameters(?:_ex)?\s*\(/g;
|
|
26
26
|
const RE_C_DH = /\bDH_generate_key\s*\(|\bDH_generate_parameters(?:_ex)?\s*\(/g;
|
|
27
|
+
// Modern OpenSSL 3.x EVP API (the legacy *_generate_key forms above are
|
|
28
|
+
// deprecated) + libsodium — the biggest C false-negative surface (audit F1).
|
|
29
|
+
const RE_C_EVP_KEYGEN = /\bEVP_PKEY_(?:Q_)?keygen\s*\(|\bEVP_PKEY_paramgen\s*\(/g;
|
|
30
|
+
const RE_C_EVP_DERIVE = /\bEVP_PKEY_derive\s*\(/g;
|
|
31
|
+
const RE_C_EVP_CRYPT = /\bEVP_PKEY_(?:encrypt|decrypt)\s*\(/g;
|
|
32
|
+
const RE_C_EVP_SIGN = /\bEVP_DigestSign(?:Init)?\s*\(|\bEVP_DigestVerify(?:Init)?\s*\(/g;
|
|
33
|
+
// X25519: crypto_box / crypto_kx key pairs (incl. the fully-qualified
|
|
34
|
+
// curve25519xsalsa20poly1305 form) plus the low-level crypto_scalarmult
|
|
35
|
+
// primitive — all classical Curve25519 key agreement (audit recall gap).
|
|
36
|
+
const RE_C_SODIUM_BOX =
|
|
37
|
+
/\bcrypto_box_(?:curve25519xsalsa20poly1305_)?(?:seed_)?keypair\s*\(|\bcrypto_kx_keypair\s*\(|\bcrypto_scalarmult_(?:curve25519|base)\s*\(/g;
|
|
38
|
+
// EdDSA: crypto_sign key pairs, including the explicit _ed25519 forms and the
|
|
39
|
+
// deterministic seed_keypair variants (audit recall gap: _ed25519_keypair).
|
|
40
|
+
const RE_C_SODIUM_SIGN = /\bcrypto_sign_(?:ed25519_)?(?:seed_)?keypair\s*\(/g;
|
|
41
|
+
// Legacy verify / decrypt counterparts to the *_sign / *_encrypt rules above
|
|
42
|
+
// (audit F4-c): the classic OpenSSL RSA/ECDSA verification and RSA raw
|
|
43
|
+
// decryption call forms that the modern EVP + legacy keygen rules don't cover.
|
|
44
|
+
const RE_C_ECDSA_VERIFY = /\bECDSA_verify\s*\(/g;
|
|
45
|
+
const RE_C_RSA_VERIFY = /\bRSA_verify\s*\(/g;
|
|
46
|
+
const RE_C_RSA_CRYPT = /\bRSA_public_encrypt\s*\(|\bRSA_private_decrypt\s*\(/g;
|
|
47
|
+
// C/OpenSSL legacy TLS configuration (mirrors source.ts tlsDetector): forcing a
|
|
48
|
+
// deprecated protocol version or disabling certificate verification.
|
|
49
|
+
const RE_C_TLS_VERSION = /\bTLSv1_method\b|\bSSLv3_method\b/g;
|
|
50
|
+
const RE_C_TLS_VERIFY_NONE = /\bSSL_VERIFY_NONE\b/g;
|
|
27
51
|
|
|
28
52
|
const RULE_C_RSA: RuleMeta = {
|
|
29
53
|
id: "c-rsa-keygen",
|
|
@@ -104,6 +128,153 @@ const RULE_C_DH: RuleMeta = {
|
|
|
104
128
|
message:
|
|
105
129
|
"Finite-field Diffie-Hellman (C/OpenSSL) is broken by Shor's algorithm (harvest-now-decrypt-later).",
|
|
106
130
|
};
|
|
131
|
+
const RULE_C_EVP_KEYGEN: RuleMeta = {
|
|
132
|
+
id: "c-evp-keygen",
|
|
133
|
+
title: "C/OpenSSL EVP key generation",
|
|
134
|
+
description: "OpenSSL 3.x EVP_PKEY_keygen / EVP_PKEY_Q_keygen / paramgen",
|
|
135
|
+
category: "key-exchange",
|
|
136
|
+
severity: "high",
|
|
137
|
+
confidence: "high",
|
|
138
|
+
algorithm: "unknown",
|
|
139
|
+
hndl: true,
|
|
140
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
141
|
+
message:
|
|
142
|
+
"Generates an asymmetric key via the OpenSSL 3.x EVP API (the key type — RSA/EC/DH/X25519 — is set on the CTX). Treated conservatively as key-exchange-capable (harvest-now-decrypt-later).",
|
|
143
|
+
remediation:
|
|
144
|
+
"For key agreement: hybrid X25519MLKEM768 (ML-KEM-768). For signatures: ML-DSA-65 (FIPS 204).",
|
|
145
|
+
};
|
|
146
|
+
const RULE_C_EVP_DERIVE: RuleMeta = {
|
|
147
|
+
id: "c-evp-derive",
|
|
148
|
+
title: "C/OpenSSL EVP key agreement",
|
|
149
|
+
description: "OpenSSL 3.x EVP_PKEY_derive (ECDH / DH shared secret)",
|
|
150
|
+
category: "key-exchange",
|
|
151
|
+
severity: "high",
|
|
152
|
+
confidence: "high",
|
|
153
|
+
algorithm: "ECDH",
|
|
154
|
+
hndl: true,
|
|
155
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
156
|
+
message:
|
|
157
|
+
"Derives an (EC)DH shared secret via the OpenSSL EVP API — broken by Shor's algorithm (harvest-now-decrypt-later).",
|
|
158
|
+
};
|
|
159
|
+
const RULE_C_EVP_CRYPT: RuleMeta = {
|
|
160
|
+
id: "c-evp-pkey-crypt",
|
|
161
|
+
title: "C/OpenSSL EVP public-key encryption",
|
|
162
|
+
description: "OpenSSL 3.x EVP_PKEY_encrypt / EVP_PKEY_decrypt (RSA)",
|
|
163
|
+
category: "kem",
|
|
164
|
+
severity: "high",
|
|
165
|
+
confidence: "high",
|
|
166
|
+
algorithm: "RSA",
|
|
167
|
+
hndl: true,
|
|
168
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
169
|
+
message:
|
|
170
|
+
"RSA public-key encryption/decryption via the OpenSSL EVP API is harvest-now-decrypt-later exposed.",
|
|
171
|
+
};
|
|
172
|
+
const RULE_C_EVP_SIGN: RuleMeta = {
|
|
173
|
+
id: "c-evp-sign",
|
|
174
|
+
title: "C/OpenSSL EVP signing",
|
|
175
|
+
description: "OpenSSL 3.x EVP_DigestSign* / EVP_DigestVerify*",
|
|
176
|
+
category: "signature",
|
|
177
|
+
severity: "high",
|
|
178
|
+
confidence: "high",
|
|
179
|
+
algorithm: "unknown",
|
|
180
|
+
hndl: false,
|
|
181
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
182
|
+
message:
|
|
183
|
+
"Classical signature via the OpenSSL EVP API (RSA/ECDSA/EdDSA) is forgeable by a quantum attacker.",
|
|
184
|
+
remediation: "ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205)",
|
|
185
|
+
};
|
|
186
|
+
const RULE_C_SODIUM_BOX: RuleMeta = {
|
|
187
|
+
id: "c-libsodium-box",
|
|
188
|
+
title: "libsodium X25519 key pair",
|
|
189
|
+
description:
|
|
190
|
+
"libsodium crypto_box / crypto_kx keypair + crypto_scalarmult (X25519 key agreement)",
|
|
191
|
+
category: "key-exchange",
|
|
192
|
+
severity: "medium",
|
|
193
|
+
confidence: "high",
|
|
194
|
+
algorithm: "X25519",
|
|
195
|
+
hndl: true,
|
|
196
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
197
|
+
message:
|
|
198
|
+
"libsodium crypto_box uses X25519 key agreement — modern but classical, and harvest-now-decrypt-later exposed.",
|
|
199
|
+
};
|
|
200
|
+
const RULE_C_SODIUM_SIGN: RuleMeta = {
|
|
201
|
+
id: "c-libsodium-sign",
|
|
202
|
+
title: "libsodium Ed25519 key pair",
|
|
203
|
+
description: "libsodium crypto_sign(_ed25519)(_seed)_keypair (Ed25519 signatures)",
|
|
204
|
+
category: "signature",
|
|
205
|
+
severity: "low",
|
|
206
|
+
confidence: "high",
|
|
207
|
+
algorithm: "EdDSA",
|
|
208
|
+
hndl: false,
|
|
209
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
210
|
+
message:
|
|
211
|
+
"libsodium crypto_sign uses Ed25519 signatures — classical and forgeable by a quantum attacker.",
|
|
212
|
+
};
|
|
213
|
+
const RULE_C_ECDSA_VERIFY: RuleMeta = {
|
|
214
|
+
id: "c-ecdsa-verify",
|
|
215
|
+
title: "C/OpenSSL ECDSA signature verification",
|
|
216
|
+
description: "OpenSSL ECDSA_verify",
|
|
217
|
+
category: "signature",
|
|
218
|
+
severity: "high",
|
|
219
|
+
confidence: "high",
|
|
220
|
+
algorithm: "ECDSA",
|
|
221
|
+
hndl: false,
|
|
222
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
223
|
+
message:
|
|
224
|
+
"Classical ECDSA verification (C/OpenSSL) trusts signatures forgeable by a quantum attacker.",
|
|
225
|
+
remediation: "ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205)",
|
|
226
|
+
};
|
|
227
|
+
const RULE_C_RSA_VERIFY: RuleMeta = {
|
|
228
|
+
id: "c-rsa-verify",
|
|
229
|
+
title: "C/OpenSSL RSA signature verification",
|
|
230
|
+
description: "OpenSSL RSA_verify",
|
|
231
|
+
category: "signature",
|
|
232
|
+
severity: "high",
|
|
233
|
+
confidence: "high",
|
|
234
|
+
algorithm: "RSA",
|
|
235
|
+
hndl: false,
|
|
236
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
237
|
+
message:
|
|
238
|
+
"Classical RSA signature verification (C/OpenSSL) trusts signatures forgeable by a quantum attacker.",
|
|
239
|
+
remediation: "ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205)",
|
|
240
|
+
};
|
|
241
|
+
const RULE_C_RSA_CRYPT: RuleMeta = {
|
|
242
|
+
id: "c-rsa-crypt",
|
|
243
|
+
title: "C/OpenSSL RSA public-key encryption",
|
|
244
|
+
description: "OpenSSL RSA_public_encrypt / RSA_private_decrypt",
|
|
245
|
+
category: "kem",
|
|
246
|
+
severity: "high",
|
|
247
|
+
confidence: "high",
|
|
248
|
+
algorithm: "RSA",
|
|
249
|
+
hndl: true,
|
|
250
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
251
|
+
message:
|
|
252
|
+
"Legacy RSA public-key encryption/decryption (C/OpenSSL) is harvest-now-decrypt-later exposed.",
|
|
253
|
+
};
|
|
254
|
+
const RULE_C_TLS_VERSION: RuleMeta = {
|
|
255
|
+
id: "c-tls-legacy-version",
|
|
256
|
+
title: "Legacy TLS/SSL version pinned (C/OpenSSL)",
|
|
257
|
+
description: "OpenSSL TLSv1_method / SSLv3_method",
|
|
258
|
+
category: "tls",
|
|
259
|
+
severity: "medium",
|
|
260
|
+
confidence: "high",
|
|
261
|
+
hndl: false,
|
|
262
|
+
cwe: CWE_WEAK_STRENGTH,
|
|
263
|
+
message: "TLS 1.0 / SSLv3 are deprecated and insecure; require TLS 1.3.",
|
|
264
|
+
remediation: "Use TLS_method() with a minimum of TLS 1.3 and prefer PQC-hybrid key exchange.",
|
|
265
|
+
};
|
|
266
|
+
const RULE_C_TLS_VERIFY_NONE: RuleMeta = {
|
|
267
|
+
id: "c-tls-verify-none",
|
|
268
|
+
title: "TLS certificate verification disabled (C/OpenSSL)",
|
|
269
|
+
description: "OpenSSL SSL_VERIFY_NONE",
|
|
270
|
+
category: "tls",
|
|
271
|
+
severity: "high",
|
|
272
|
+
confidence: "high",
|
|
273
|
+
hndl: false,
|
|
274
|
+
cwe: CWE_CERT_VALIDATION,
|
|
275
|
+
message: "SSL_VERIFY_NONE disables TLS certificate verification (MITM risk).",
|
|
276
|
+
remediation: "Use SSL_VERIFY_PEER and verify certificates properly.",
|
|
277
|
+
};
|
|
107
278
|
|
|
108
279
|
/** Detects classical asymmetric crypto in C/C++ (OpenSSL). */
|
|
109
280
|
export const cDetector: Detector = {
|
|
@@ -111,7 +282,25 @@ export const cDetector: Detector = {
|
|
|
111
282
|
description: "Classical asymmetric crypto in C/C++ (OpenSSL)",
|
|
112
283
|
scope: "source",
|
|
113
284
|
language: "c",
|
|
114
|
-
rules: [
|
|
285
|
+
rules: [
|
|
286
|
+
RULE_C_RSA,
|
|
287
|
+
RULE_C_EC,
|
|
288
|
+
RULE_C_ECDSA,
|
|
289
|
+
RULE_C_ECDH,
|
|
290
|
+
RULE_C_DSA,
|
|
291
|
+
RULE_C_DH,
|
|
292
|
+
RULE_C_EVP_KEYGEN,
|
|
293
|
+
RULE_C_EVP_DERIVE,
|
|
294
|
+
RULE_C_EVP_CRYPT,
|
|
295
|
+
RULE_C_EVP_SIGN,
|
|
296
|
+
RULE_C_SODIUM_BOX,
|
|
297
|
+
RULE_C_SODIUM_SIGN,
|
|
298
|
+
RULE_C_ECDSA_VERIFY,
|
|
299
|
+
RULE_C_RSA_VERIFY,
|
|
300
|
+
RULE_C_RSA_CRYPT,
|
|
301
|
+
RULE_C_TLS_VERSION,
|
|
302
|
+
RULE_C_TLS_VERIFY_NONE,
|
|
303
|
+
],
|
|
115
304
|
appliesTo: (f) => hasExtension(f, C_EXTENSIONS),
|
|
116
305
|
detect({ file, content }): Finding[] {
|
|
117
306
|
const findings: Finding[] = [];
|
|
@@ -127,6 +316,17 @@ export const cDetector: Detector = {
|
|
|
127
316
|
add(RE_C_ECDH, RULE_C_ECDH);
|
|
128
317
|
add(RE_C_DSA, RULE_C_DSA);
|
|
129
318
|
add(RE_C_DH, RULE_C_DH);
|
|
319
|
+
add(RE_C_EVP_KEYGEN, RULE_C_EVP_KEYGEN);
|
|
320
|
+
add(RE_C_EVP_DERIVE, RULE_C_EVP_DERIVE);
|
|
321
|
+
add(RE_C_EVP_CRYPT, RULE_C_EVP_CRYPT);
|
|
322
|
+
add(RE_C_EVP_SIGN, RULE_C_EVP_SIGN);
|
|
323
|
+
add(RE_C_SODIUM_BOX, RULE_C_SODIUM_BOX);
|
|
324
|
+
add(RE_C_SODIUM_SIGN, RULE_C_SODIUM_SIGN);
|
|
325
|
+
add(RE_C_ECDSA_VERIFY, RULE_C_ECDSA_VERIFY);
|
|
326
|
+
add(RE_C_RSA_VERIFY, RULE_C_RSA_VERIFY);
|
|
327
|
+
add(RE_C_RSA_CRYPT, RULE_C_RSA_CRYPT);
|
|
328
|
+
add(RE_C_TLS_VERSION, RULE_C_TLS_VERSION);
|
|
329
|
+
add(RE_C_TLS_VERIFY_NONE, RULE_C_TLS_VERIFY_NONE);
|
|
130
330
|
return findings;
|
|
131
331
|
},
|
|
132
332
|
};
|