@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/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
|
|
@@ -101,6 +102,7 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
101
102
|
reason: "JWTs commonly signed with RS256/ES256 (classical RSA/ECDSA).",
|
|
102
103
|
algorithms: ["RSA", "ECDSA"],
|
|
103
104
|
severity: "high",
|
|
105
|
+
hndl: false,
|
|
104
106
|
},
|
|
105
107
|
{
|
|
106
108
|
name: "jose",
|
|
@@ -115,6 +117,7 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
115
117
|
reason: "JSON Web Signatures using classical RS/ES algorithms.",
|
|
116
118
|
algorithms: ["RSA", "ECDSA"],
|
|
117
119
|
severity: "high",
|
|
120
|
+
hndl: false,
|
|
118
121
|
},
|
|
119
122
|
{
|
|
120
123
|
name: "eccrypto",
|
|
@@ -171,6 +174,7 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
171
174
|
reason: "PASETO public tokens signed with classical Ed25519 (v2/v4) or RSA.",
|
|
172
175
|
algorithms: ["EdDSA", "RSA"],
|
|
173
176
|
severity: "medium",
|
|
177
|
+
hndl: false,
|
|
174
178
|
},
|
|
175
179
|
{
|
|
176
180
|
name: "bcrypto",
|
|
@@ -241,6 +245,7 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
241
245
|
reason: "JSON Web Algorithms: RSA (RS/PS) and EC (ES) signatures.",
|
|
242
246
|
algorithms: ["RSA", "ECDSA"],
|
|
243
247
|
severity: "medium",
|
|
248
|
+
hndl: false,
|
|
244
249
|
},
|
|
245
250
|
{
|
|
246
251
|
name: "jwk-to-pem",
|
|
@@ -255,6 +260,7 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
255
260
|
reason: "JWT signing/verification with classical RS/PS/ES algorithms.",
|
|
256
261
|
algorithms: ["RSA", "ECDSA"],
|
|
257
262
|
severity: "medium",
|
|
263
|
+
hndl: false,
|
|
258
264
|
},
|
|
259
265
|
{
|
|
260
266
|
name: "ssh2",
|
|
@@ -283,6 +289,7 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
283
289
|
reason: "HTTP request signing with classical RSA/ECDSA keys.",
|
|
284
290
|
algorithms: ["RSA", "ECDSA"],
|
|
285
291
|
severity: "medium",
|
|
292
|
+
hndl: false,
|
|
286
293
|
},
|
|
287
294
|
{
|
|
288
295
|
name: "libsodium-wrappers",
|
|
@@ -307,6 +314,28 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
307
314
|
algorithms: ["RSA", "ECDSA", "DSA"],
|
|
308
315
|
severity: "high",
|
|
309
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
|
+
},
|
|
310
339
|
{
|
|
311
340
|
name: "pycryptodomex",
|
|
312
341
|
ecosystem: "pypi",
|
|
@@ -341,6 +370,7 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
341
370
|
reason: "JWT signing with classical RS*/ES* algorithms.",
|
|
342
371
|
algorithms: ["RSA", "ECDSA"],
|
|
343
372
|
severity: "medium",
|
|
373
|
+
hndl: false,
|
|
344
374
|
},
|
|
345
375
|
{
|
|
346
376
|
name: "python-jose",
|
|
@@ -415,6 +445,13 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
415
445
|
algorithms: ["ECDSA", "ECDH"],
|
|
416
446
|
severity: "high",
|
|
417
447
|
},
|
|
448
|
+
{
|
|
449
|
+
name: "secp256k1",
|
|
450
|
+
ecosystem: "cargo",
|
|
451
|
+
reason: "libsecp256k1 bindings (blockchain) — classical ECDSA + ECDH.",
|
|
452
|
+
algorithms: ["ECDSA", "ECDH"],
|
|
453
|
+
severity: "high",
|
|
454
|
+
},
|
|
418
455
|
{
|
|
419
456
|
name: "ed25519-dalek",
|
|
420
457
|
ecosystem: "cargo",
|
|
@@ -438,6 +475,43 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
438
475
|
algorithms: ["RSA", "ECDSA", "EdDSA", "ECDH"],
|
|
439
476
|
severity: "medium",
|
|
440
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
|
+
},
|
|
441
515
|
|
|
442
516
|
// --- Maven (Java) ---
|
|
443
517
|
{
|
|
@@ -467,6 +541,22 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
467
541
|
reason: "Auth0 JWT with classical RS*/ES* algorithms.",
|
|
468
542
|
algorithms: ["RSA", "ECDSA"],
|
|
469
543
|
severity: "medium",
|
|
544
|
+
hndl: false,
|
|
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,
|
|
470
560
|
},
|
|
471
561
|
|
|
472
562
|
// --- RubyGems ---
|
|
@@ -476,6 +566,15 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
476
566
|
reason: "Ruby JWT with classical RS*/ES* algorithms.",
|
|
477
567
|
algorithms: ["RSA", "ECDSA"],
|
|
478
568
|
severity: "medium",
|
|
569
|
+
hndl: false,
|
|
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",
|
|
479
578
|
},
|
|
480
579
|
{
|
|
481
580
|
name: "rbnacl",
|
|
@@ -491,13 +590,46 @@ export const vulnerableDependencies: VulnerableDependency[] = [
|
|
|
491
590
|
algorithms: ["EdDSA"],
|
|
492
591
|
severity: "low",
|
|
493
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
|
+
},
|
|
494
625
|
];
|
|
495
626
|
|
|
496
627
|
/**
|
|
497
628
|
* Normalise a package name for matching within its ecosystem. PyPI is
|
|
498
629
|
* case-insensitive and folds runs of `-_.` to a single `-` (PEP 503); cargo /
|
|
499
|
-
* maven / rubygems are effectively lower-case
|
|
500
|
-
*
|
|
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).
|
|
501
633
|
*/
|
|
502
634
|
function normalizeName(ecosystem: DependencyEcosystem, name: string): string {
|
|
503
635
|
const n = name.trim();
|
|
@@ -583,6 +715,8 @@ export function manifestEcosystem(file: string): DependencyEcosystem | null {
|
|
|
583
715
|
if (base === "go.mod") return "go";
|
|
584
716
|
if (base === "pom.xml" || base === "build.gradle" || base === "build.gradle.kts") return "maven";
|
|
585
717
|
if (base === "gemfile" || base.endsWith(".gemspec")) return "rubygems";
|
|
718
|
+
if (base === "packages.config" || base === "directory.packages.props" || base.endsWith(".csproj"))
|
|
719
|
+
return "nuget";
|
|
586
720
|
return null;
|
|
587
721
|
}
|
|
588
722
|
|
|
@@ -648,6 +782,20 @@ function candidateNames(ecosystem: DependencyEcosystem, content: string): string
|
|
|
648
782
|
}
|
|
649
783
|
break;
|
|
650
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
|
+
}
|
|
651
799
|
case "npm":
|
|
652
800
|
break; // npm uses the JSON path, not this extractor.
|
|
653
801
|
}
|
|
@@ -682,8 +830,10 @@ function dependencyFinding(
|
|
|
682
830
|
severity: dep.severity,
|
|
683
831
|
confidence: "high",
|
|
684
832
|
algorithm,
|
|
685
|
-
// Confidentiality libs are HNDL-exposed; signature-only ones are not.
|
|
686
|
-
|
|
833
|
+
// Confidentiality libs are HNDL-exposed; signature-only ones are not. An
|
|
834
|
+
// explicit `dep.hndl` wins (some packages list RSA/EC as a family but only
|
|
835
|
+
// ever sign — e.g. JWS/JWT libs — and signatures are not HNDL-exposed).
|
|
836
|
+
hndl: dep.hndl ?? dep.algorithms.some(isConfidentialityFamily),
|
|
687
837
|
cwe: CWE_BROKEN_CRYPTO,
|
|
688
838
|
message: `${dep.name} — ${dep.reason}`,
|
|
689
839
|
remediation: multiFamilyRemediation(dep.algorithms),
|
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
|
};
|