@quantakrypto/core 0.4.4 → 0.5.0
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/README.md +76 -27
- package/dist/cbom-merge.d.ts.map +1 -1
- package/dist/cbom-merge.js +30 -8
- package/dist/cbom-merge.js.map +1 -1
- package/dist/cbom.d.ts +5 -0
- package/dist/cbom.d.ts.map +1 -1
- package/dist/cbom.js +132 -37
- package/dist/cbom.js.map +1 -1
- package/dist/comments.d.ts +2 -23
- package/dist/comments.d.ts.map +1 -1
- package/dist/comments.js +24 -5
- package/dist/comments.js.map +1 -1
- package/dist/detect-utils.d.ts +55 -21
- package/dist/detect-utils.d.ts.map +1 -1
- package/dist/detect-utils.js +133 -7
- package/dist/detect-utils.js.map +1 -1
- package/dist/detectors/age.d.ts +16 -0
- package/dist/detectors/age.d.ts.map +1 -0
- package/dist/detectors/age.js +40 -0
- package/dist/detectors/age.js.map +1 -0
- package/dist/detectors/ansible.d.ts +13 -0
- package/dist/detectors/ansible.d.ts.map +1 -0
- package/dist/detectors/ansible.js +108 -0
- package/dist/detectors/ansible.js.map +1 -0
- package/dist/detectors/bicep.d.ts +20 -0
- package/dist/detectors/bicep.d.ts.map +1 -0
- package/dist/detectors/bicep.js +74 -0
- package/dist/detectors/bicep.js.map +1 -0
- package/dist/detectors/c.d.ts.map +1 -1
- package/dist/detectors/c.js +30 -3
- package/dist/detectors/c.js.map +1 -1
- package/dist/detectors/cicd.d.ts.map +1 -1
- package/dist/detectors/cicd.js +18 -5
- package/dist/detectors/cicd.js.map +1 -1
- package/dist/detectors/cloud-kms.d.ts +8 -5
- package/dist/detectors/cloud-kms.d.ts.map +1 -1
- package/dist/detectors/cloud-kms.js +62 -20
- package/dist/detectors/cloud-kms.js.map +1 -1
- package/dist/detectors/cloudformation.d.ts +8 -0
- package/dist/detectors/cloudformation.d.ts.map +1 -1
- package/dist/detectors/cloudformation.js +41 -10
- package/dist/detectors/cloudformation.js.map +1 -1
- package/dist/detectors/codesign.d.ts +50 -0
- package/dist/detectors/codesign.d.ts.map +1 -0
- package/dist/detectors/codesign.js +143 -0
- package/dist/detectors/codesign.js.map +1 -0
- package/dist/detectors/csharp.d.ts.map +1 -1
- package/dist/detectors/csharp.js +13 -3
- package/dist/detectors/csharp.js.map +1 -1
- package/dist/detectors/dart.d.ts +35 -0
- package/dist/detectors/dart.d.ts.map +1 -0
- package/dist/detectors/dart.js +177 -0
- package/dist/detectors/dart.js.map +1 -0
- package/dist/detectors/database.d.ts +5 -3
- package/dist/detectors/database.d.ts.map +1 -1
- package/dist/detectors/database.js +45 -8
- package/dist/detectors/database.js.map +1 -1
- package/dist/detectors/dkim.d.ts +54 -0
- package/dist/detectors/dkim.d.ts.map +1 -0
- package/dist/detectors/dkim.js +92 -0
- package/dist/detectors/dkim.js.map +1 -0
- package/dist/detectors/dnssec.d.ts.map +1 -1
- package/dist/detectors/dnssec.js +19 -10
- package/dist/detectors/dnssec.js.map +1 -1
- package/dist/detectors/elixir.d.ts.map +1 -1
- package/dist/detectors/elixir.js +34 -2
- package/dist/detectors/elixir.js.map +1 -1
- package/dist/detectors/java.d.ts.map +1 -1
- package/dist/detectors/java.js +33 -3
- package/dist/detectors/java.js.map +1 -1
- package/dist/detectors/jose.d.ts.map +1 -1
- package/dist/detectors/jose.js +13 -3
- package/dist/detectors/jose.js.map +1 -1
- package/dist/detectors/jwk.d.ts +7 -7
- package/dist/detectors/jwk.d.ts.map +1 -1
- package/dist/detectors/jwk.js +44 -8
- package/dist/detectors/jwk.js.map +1 -1
- package/dist/detectors/k8s.d.ts.map +1 -1
- package/dist/detectors/k8s.js +5 -2
- package/dist/detectors/k8s.js.map +1 -1
- package/dist/detectors/keystore.d.ts +19 -0
- package/dist/detectors/keystore.d.ts.map +1 -0
- package/dist/detectors/keystore.js +76 -0
- package/dist/detectors/keystore.js.map +1 -0
- package/dist/detectors/mesh.d.ts +7 -8
- package/dist/detectors/mesh.d.ts.map +1 -1
- package/dist/detectors/mesh.js +17 -35
- package/dist/detectors/mesh.js.map +1 -1
- package/dist/detectors/messaging.d.ts +2 -2
- package/dist/detectors/messaging.d.ts.map +1 -1
- package/dist/detectors/messaging.js +19 -12
- package/dist/detectors/messaging.js.map +1 -1
- package/dist/detectors/objc.d.ts +41 -0
- package/dist/detectors/objc.d.ts.map +1 -0
- package/dist/detectors/objc.js +146 -0
- package/dist/detectors/objc.js.map +1 -0
- package/dist/detectors/openpgp.d.ts +20 -0
- package/dist/detectors/openpgp.d.ts.map +1 -0
- package/dist/detectors/openpgp.js +151 -0
- package/dist/detectors/openpgp.js.map +1 -0
- package/dist/detectors/pem.d.ts.map +1 -1
- package/dist/detectors/pem.js +32 -0
- package/dist/detectors/pem.js.map +1 -1
- package/dist/detectors/php.d.ts +2 -1
- package/dist/detectors/php.d.ts.map +1 -1
- package/dist/detectors/php.js +7 -3
- package/dist/detectors/php.js.map +1 -1
- package/dist/detectors/pkcs11.d.ts +17 -0
- package/dist/detectors/pkcs11.d.ts.map +1 -0
- package/dist/detectors/pkcs11.js +87 -0
- package/dist/detectors/pkcs11.js.map +1 -0
- package/dist/detectors/proxy.d.ts +52 -0
- package/dist/detectors/proxy.d.ts.map +1 -0
- package/dist/detectors/proxy.js +157 -0
- package/dist/detectors/proxy.js.map +1 -0
- package/dist/detectors/pulumi.d.ts +19 -0
- package/dist/detectors/pulumi.d.ts.map +1 -0
- package/dist/detectors/pulumi.js +80 -0
- package/dist/detectors/pulumi.js.map +1 -0
- package/dist/detectors/rust.d.ts.map +1 -1
- package/dist/detectors/rust.js +5 -0
- package/dist/detectors/rust.js.map +1 -1
- package/dist/detectors/secrets.d.ts +4 -1
- package/dist/detectors/secrets.d.ts.map +1 -1
- package/dist/detectors/secrets.js +5 -21
- package/dist/detectors/secrets.js.map +1 -1
- package/dist/detectors/solidity.d.ts +50 -0
- package/dist/detectors/solidity.d.ts.map +1 -0
- package/dist/detectors/solidity.js +108 -0
- package/dist/detectors/solidity.js.map +1 -0
- package/dist/detectors/source.d.ts.map +1 -1
- package/dist/detectors/source.js +53 -6
- package/dist/detectors/source.js.map +1 -1
- package/dist/detectors/spire.d.ts +49 -0
- package/dist/detectors/spire.d.ts.map +1 -0
- package/dist/detectors/spire.js +77 -0
- package/dist/detectors/spire.js.map +1 -0
- package/dist/detectors/ssh-ca.d.ts +72 -0
- package/dist/detectors/ssh-ca.d.ts.map +1 -0
- package/dist/detectors/ssh-ca.js +119 -0
- package/dist/detectors/ssh-ca.js.map +1 -0
- package/dist/detectors/supply-chain.d.ts +17 -0
- package/dist/detectors/supply-chain.d.ts.map +1 -0
- package/dist/detectors/supply-chain.js +89 -0
- package/dist/detectors/supply-chain.js.map +1 -0
- package/dist/detectors/swift.d.ts +22 -0
- package/dist/detectors/swift.d.ts.map +1 -0
- package/dist/detectors/swift.js +120 -0
- package/dist/detectors/swift.js.map +1 -0
- package/dist/detectors/terraform.d.ts.map +1 -1
- package/dist/detectors/terraform.js +35 -8
- package/dist/detectors/terraform.js.map +1 -1
- package/dist/detectors/vault.d.ts +15 -0
- package/dist/detectors/vault.d.ts.map +1 -0
- package/dist/detectors/vault.js +97 -0
- package/dist/detectors/vault.js.map +1 -0
- package/dist/detectors/vpn.d.ts +8 -8
- package/dist/detectors/vpn.d.ts.map +1 -1
- package/dist/detectors/vpn.js +12 -38
- package/dist/detectors/vpn.js.map +1 -1
- package/dist/detectors/weak-hash.d.ts +71 -0
- package/dist/detectors/weak-hash.d.ts.map +1 -0
- package/dist/detectors/weak-hash.js +116 -0
- package/dist/detectors/weak-hash.js.map +1 -0
- package/dist/detectors/webauthn.d.ts +61 -0
- package/dist/detectors/webauthn.d.ts.map +1 -0
- package/dist/detectors/webauthn.js +109 -0
- package/dist/detectors/webauthn.js.map +1 -0
- package/dist/detectors/xmldsig.d.ts +23 -0
- package/dist/detectors/xmldsig.d.ts.map +1 -0
- package/dist/detectors/xmldsig.js +84 -0
- package/dist/detectors/xmldsig.js.map +1 -0
- package/dist/evidence.d.ts +74 -4
- package/dist/evidence.d.ts.map +1 -1
- package/dist/evidence.js +71 -0
- package/dist/evidence.js.map +1 -1
- package/dist/index.d.ts +14 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -11
- package/dist/index.js.map +1 -1
- package/dist/inventory.d.ts +0 -2
- package/dist/inventory.d.ts.map +1 -1
- package/dist/inventory.js +15 -6
- package/dist/inventory.js.map +1 -1
- package/dist/registry.d.ts +9 -4
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +51 -4
- package/dist/registry.js.map +1 -1
- package/dist/remediate-pipeline.d.ts +0 -3
- package/dist/remediate-pipeline.d.ts.map +1 -1
- package/dist/remediate-pipeline.js +1 -1
- package/dist/remediate-pipeline.js.map +1 -1
- package/dist/remediation.d.ts +10 -0
- package/dist/remediation.d.ts.map +1 -1
- package/dist/remediation.js +32 -0
- 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 -1
- package/dist/report.js.map +1 -1
- package/dist/scan-worker.js +5 -3
- package/dist/scan-worker.js.map +1 -1
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +35 -6
- package/dist/scan.js.map +1 -1
- package/dist/standards-profiles.d.ts +58 -0
- package/dist/standards-profiles.d.ts.map +1 -0
- package/dist/standards-profiles.js +100 -0
- package/dist/standards-profiles.js.map +1 -0
- package/dist/types.d.ts +6 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.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/vex.d.ts +39 -0
- package/dist/vex.d.ts.map +1 -0
- package/dist/vex.js +87 -0
- package/dist/vex.js.map +1 -0
- package/dist/walk.d.ts +8 -3
- package/dist/walk.d.ts.map +1 -1
- package/dist/walk.js +32 -1
- package/dist/walk.js.map +1 -1
- package/package.json +1 -1
- package/src/cbom-merge.ts +38 -8
- package/src/cbom.ts +153 -39
- package/src/comments.ts +25 -6
- package/src/detect-utils.ts +133 -11
- package/src/detectors/age.ts +60 -0
- package/src/detectors/ansible.ts +140 -0
- package/src/detectors/bicep.ts +107 -0
- package/src/detectors/c.ts +31 -3
- package/src/detectors/cicd.ts +18 -5
- package/src/detectors/cloud-kms.ts +79 -25
- package/src/detectors/cloudformation.ts +45 -10
- package/src/detectors/codesign.ts +214 -0
- package/src/detectors/csharp.ts +13 -3
- package/src/detectors/dart.ts +237 -0
- package/src/detectors/database.ts +64 -11
- package/src/detectors/dkim.ts +172 -0
- package/src/detectors/dnssec.ts +19 -10
- package/src/detectors/elixir.ts +33 -2
- package/src/detectors/java.ts +37 -3
- package/src/detectors/jose.ts +19 -3
- package/src/detectors/jwk.ts +59 -17
- package/src/detectors/k8s.ts +5 -2
- package/src/detectors/keystore.ts +109 -0
- package/src/detectors/mesh.ts +21 -45
- package/src/detectors/messaging.ts +22 -14
- package/src/detectors/objc.ts +209 -0
- package/src/detectors/openpgp.ts +194 -0
- package/src/detectors/pem.ts +30 -0
- package/src/detectors/php.ts +9 -4
- package/src/detectors/pkcs11.ts +113 -0
- package/src/detectors/proxy.ts +236 -0
- package/src/detectors/pulumi.ts +106 -0
- package/src/detectors/rust.ts +5 -0
- package/src/detectors/secrets.ts +15 -26
- package/src/detectors/solidity.ts +176 -0
- package/src/detectors/source.ts +48 -5
- package/src/detectors/spire.ts +143 -0
- package/src/detectors/ssh-ca.ts +215 -0
- package/src/detectors/supply-chain.ts +117 -0
- package/src/detectors/swift.ts +149 -0
- package/src/detectors/terraform.ts +42 -8
- package/src/detectors/vault.ts +120 -0
- package/src/detectors/vpn.ts +20 -48
- package/src/detectors/weak-hash.ts +217 -0
- package/src/detectors/webauthn.ts +205 -0
- package/src/detectors/xmldsig.ts +115 -0
- package/src/evidence.ts +127 -4
- package/src/index.ts +41 -13
- package/src/inventory.ts +15 -7
- package/src/registry.ts +51 -4
- package/src/remediate-pipeline.ts +1 -1
- package/src/remediation.ts +39 -0
- package/src/report.ts +36 -1
- package/src/scan-worker.ts +5 -3
- package/src/scan.ts +41 -6
- package/src/standards-profiles.ts +136 -0
- package/src/types.ts +9 -4
- package/src/version.ts +1 -1
- package/src/vex.ts +122 -0
- package/src/walk.ts +33 -2
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source detector for classical asymmetric cryptography in Swift (Apple platforms) —
|
|
3
|
+
* Apple CryptoKit and the older Security framework (`SecKey*`). Lexical, same strategy
|
|
4
|
+
* as the other language packs; the API names are distinctive enough to keep the
|
|
5
|
+
* false-positive risk low. Comment/string suppression is handled centrally
|
|
6
|
+
* (`.swift` is a C-style comment language).
|
|
7
|
+
*
|
|
8
|
+
* CryptoKit:
|
|
9
|
+
* - `P256|P384|P521.Signing.PrivateKey` → ECDSA signature (hndl:false)
|
|
10
|
+
* - `P256|P384|P521.KeyAgreement.PrivateKey` → ECDH key agreement (hndl:true)
|
|
11
|
+
* - `Curve25519.Signing.PrivateKey` → Ed25519 signature (hndl:false)
|
|
12
|
+
* - `Curve25519.KeyAgreement.PrivateKey` → X25519 key agreement (hndl:true)
|
|
13
|
+
* (`SecureEnclave.P256.…` forms are covered by the same P-curve regexes.)
|
|
14
|
+
*
|
|
15
|
+
* Security framework:
|
|
16
|
+
* - `SecKeyCreateRandomKey` with `kSecAttrKeyTypeRSA` → RSA
|
|
17
|
+
* - … with `kSecAttrKeyTypeEC` / `kSecAttrKeyTypeECSECPrimeRandom` → EC
|
|
18
|
+
*/
|
|
19
|
+
import type { Detector, Finding, RuleMeta } from "../types.js";
|
|
20
|
+
import { SWIFT_EXTENSIONS, eachMatch, findingFromRule, hasExtension } from "../detect-utils.js";
|
|
21
|
+
import { CWE_BROKEN_CRYPTO } from "../cwe.js";
|
|
22
|
+
|
|
23
|
+
// CryptoKit P-curve keys, split by usage (Signing vs KeyAgreement). `SecureEnclave.`
|
|
24
|
+
// may prefix the P-curve type, so it is allowed optionally.
|
|
25
|
+
const RE_SWIFT_P_SIGN = /\b(?:SecureEnclave\.)?P(?:256|384|521)\.Signing\.PrivateKey\b/g;
|
|
26
|
+
const RE_SWIFT_P_KEX = /\b(?:SecureEnclave\.)?P(?:256|384|521)\.KeyAgreement\.PrivateKey\b/g;
|
|
27
|
+
// CryptoKit Curve25519: Signing = Ed25519 (EdDSA); KeyAgreement = X25519.
|
|
28
|
+
const RE_SWIFT_ED25519 = /\bCurve25519\.Signing\.PrivateKey\b/g;
|
|
29
|
+
const RE_SWIFT_X25519 = /\bCurve25519\.KeyAgreement\.PrivateKey\b/g;
|
|
30
|
+
// Security framework key-type attributes (used with SecKeyCreateRandomKey).
|
|
31
|
+
const RE_SWIFT_SEC_RSA = /\bkSecAttrKeyTypeRSA\b/g;
|
|
32
|
+
const RE_SWIFT_SEC_EC = /\bkSecAttrKeyType(?:EC|ECSECPrimeRandom)\b/g;
|
|
33
|
+
|
|
34
|
+
const RULE_SWIFT_ECDSA: RuleMeta = {
|
|
35
|
+
id: "swift-ecdsa",
|
|
36
|
+
title: "Swift CryptoKit ECDSA signing key",
|
|
37
|
+
description: "CryptoKit P256/P384/P521 Signing.PrivateKey",
|
|
38
|
+
category: "signature",
|
|
39
|
+
severity: "high",
|
|
40
|
+
confidence: "high",
|
|
41
|
+
algorithm: "ECDSA",
|
|
42
|
+
hndl: false,
|
|
43
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
44
|
+
message: "CryptoKit P-curve ECDSA signing (Swift) is forgeable by a quantum attacker.",
|
|
45
|
+
remediation: "ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205).",
|
|
46
|
+
};
|
|
47
|
+
const RULE_SWIFT_ECDH: RuleMeta = {
|
|
48
|
+
id: "swift-ecdh",
|
|
49
|
+
title: "Swift CryptoKit ECDH key agreement",
|
|
50
|
+
description: "CryptoKit P256/P384/P521 KeyAgreement.PrivateKey",
|
|
51
|
+
category: "key-exchange",
|
|
52
|
+
severity: "high",
|
|
53
|
+
confidence: "high",
|
|
54
|
+
algorithm: "ECDH",
|
|
55
|
+
hndl: true,
|
|
56
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
57
|
+
message: "CryptoKit P-curve ECDH key agreement (Swift) is harvest-now-decrypt-later exposed.",
|
|
58
|
+
remediation: "Migrate key agreement to hybrid X25519MLKEM768 (ML-KEM-768).",
|
|
59
|
+
};
|
|
60
|
+
const RULE_SWIFT_ED25519: RuleMeta = {
|
|
61
|
+
id: "swift-ed25519",
|
|
62
|
+
title: "Swift CryptoKit Ed25519 signing key",
|
|
63
|
+
description: "CryptoKit Curve25519.Signing.PrivateKey (Ed25519)",
|
|
64
|
+
category: "signature",
|
|
65
|
+
// `low`, aligned with Ed25519 in every other source pack (go/rust/ruby/python/node)
|
|
66
|
+
// — the same primitive must not flip CI exit codes based on which language wrote it.
|
|
67
|
+
severity: "low",
|
|
68
|
+
confidence: "high",
|
|
69
|
+
algorithm: "EdDSA",
|
|
70
|
+
hndl: false,
|
|
71
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
72
|
+
message: "CryptoKit Ed25519 signing (Swift) is classical and forgeable by a quantum attacker.",
|
|
73
|
+
remediation: "ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205).",
|
|
74
|
+
};
|
|
75
|
+
const RULE_SWIFT_X25519: RuleMeta = {
|
|
76
|
+
id: "swift-x25519",
|
|
77
|
+
title: "Swift CryptoKit X25519 key agreement",
|
|
78
|
+
description: "CryptoKit Curve25519.KeyAgreement.PrivateKey (X25519)",
|
|
79
|
+
category: "key-exchange",
|
|
80
|
+
severity: "medium",
|
|
81
|
+
confidence: "high",
|
|
82
|
+
algorithm: "X25519",
|
|
83
|
+
hndl: true,
|
|
84
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
85
|
+
message:
|
|
86
|
+
"CryptoKit X25519 key agreement (Swift) is classical and harvest-now-decrypt-later exposed.",
|
|
87
|
+
remediation: "Migrate key agreement to hybrid X25519MLKEM768 (ML-KEM-768).",
|
|
88
|
+
};
|
|
89
|
+
const RULE_SWIFT_RSA: RuleMeta = {
|
|
90
|
+
id: "swift-rsa",
|
|
91
|
+
title: "Swift Security-framework RSA key",
|
|
92
|
+
description: "SecKeyCreateRandomKey with kSecAttrKeyTypeRSA",
|
|
93
|
+
category: "kem",
|
|
94
|
+
severity: "high",
|
|
95
|
+
confidence: "high",
|
|
96
|
+
algorithm: "RSA",
|
|
97
|
+
hndl: true,
|
|
98
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
99
|
+
message: "Security-framework RSA key (Swift) is classical and not quantum-safe.",
|
|
100
|
+
remediation: "Plan migration to PQC (ML-KEM-768 for encryption, ML-DSA-65 for signatures).",
|
|
101
|
+
};
|
|
102
|
+
const RULE_SWIFT_SEC_EC: RuleMeta = {
|
|
103
|
+
id: "swift-sec-ec",
|
|
104
|
+
title: "Swift Security-framework EC key",
|
|
105
|
+
description: "SecKeyCreateRandomKey with kSecAttrKeyTypeEC",
|
|
106
|
+
category: "key-exchange",
|
|
107
|
+
severity: "high",
|
|
108
|
+
confidence: "high",
|
|
109
|
+
algorithm: "ECDH",
|
|
110
|
+
hndl: true,
|
|
111
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
112
|
+
message:
|
|
113
|
+
"Security-framework EC key (Swift); EC keys feed ECDSA signatures and ECDH key agreement (the ECDH path is harvest-now-decrypt-later exposed).",
|
|
114
|
+
remediation:
|
|
115
|
+
"For key agreement: hybrid X25519MLKEM768 (ML-KEM-768). For signatures: ML-DSA-65 (FIPS 204).",
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
/** Detects classical asymmetric crypto in Swift (CryptoKit + Security framework). */
|
|
119
|
+
export const swiftDetector: Detector = {
|
|
120
|
+
id: "swift-crypto",
|
|
121
|
+
description: "Classical asymmetric crypto in Swift (CryptoKit, Security framework)",
|
|
122
|
+
scope: "source",
|
|
123
|
+
language: "swift",
|
|
124
|
+
rules: [
|
|
125
|
+
RULE_SWIFT_ECDSA,
|
|
126
|
+
RULE_SWIFT_ECDH,
|
|
127
|
+
RULE_SWIFT_ED25519,
|
|
128
|
+
RULE_SWIFT_X25519,
|
|
129
|
+
RULE_SWIFT_RSA,
|
|
130
|
+
RULE_SWIFT_SEC_EC,
|
|
131
|
+
],
|
|
132
|
+
appliesTo: (f) => hasExtension(f, SWIFT_EXTENSIONS),
|
|
133
|
+
detect({ file, content }): Finding[] {
|
|
134
|
+
const findings: Finding[] = [];
|
|
135
|
+
const add = (re: RegExp, rule: RuleMeta) =>
|
|
136
|
+
eachMatch(re, content, (m) =>
|
|
137
|
+
findings.push(
|
|
138
|
+
findingFromRule(rule, { file, content, index: m.index, matchLength: m[0].length }),
|
|
139
|
+
),
|
|
140
|
+
);
|
|
141
|
+
add(RE_SWIFT_P_SIGN, RULE_SWIFT_ECDSA);
|
|
142
|
+
add(RE_SWIFT_P_KEX, RULE_SWIFT_ECDH);
|
|
143
|
+
add(RE_SWIFT_ED25519, RULE_SWIFT_ED25519);
|
|
144
|
+
add(RE_SWIFT_X25519, RULE_SWIFT_X25519);
|
|
145
|
+
add(RE_SWIFT_SEC_RSA, RULE_SWIFT_RSA);
|
|
146
|
+
add(RE_SWIFT_SEC_EC, RULE_SWIFT_SEC_EC);
|
|
147
|
+
return findings;
|
|
148
|
+
},
|
|
149
|
+
};
|
|
@@ -16,7 +16,13 @@
|
|
|
16
16
|
* (hndl:true) since a provisioned EC key can feed ECDH.
|
|
17
17
|
*/
|
|
18
18
|
import type { Detector, Finding, RuleMeta } from "../types.js";
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
eachMatch,
|
|
21
|
+
findingFromRule,
|
|
22
|
+
hasExtension,
|
|
23
|
+
maskBlockComments,
|
|
24
|
+
maskCommentLines,
|
|
25
|
+
} from "../detect-utils.js";
|
|
20
26
|
import { CWE_BROKEN_CRYPTO } from "../cwe.js";
|
|
21
27
|
|
|
22
28
|
const TF_EXTENSIONS: readonly string[] = [".tf", ".tf.json"];
|
|
@@ -29,12 +35,21 @@ const TF_EXTENSIONS: readonly string[] = [".tf", ".tf.json"];
|
|
|
29
35
|
const RE_TF_RSA = /(?<![\w"-])"?algorithm"?\s*[:=]\s*"RSA(?:_[A-Z0-9_]+)?"/g;
|
|
30
36
|
// ECDSA / EC signing: tls_private_key `"ECDSA"` and Google KMS `"EC_SIGN_…"`.
|
|
31
37
|
const RE_TF_ECDSA = /(?<![\w"-])"?algorithm"?\s*[:=]\s*"(?:ECDSA|EC_SIGN_[A-Z0-9_]+)"/g;
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
// EdDSA signing: hashicorp/tls `tls_private_key` `algorithm = "ED25519"` (a supported,
|
|
39
|
+
// classical algorithm the RSA/ECDSA rules miss).
|
|
40
|
+
const RE_TF_ED25519 = /(?<![\w"-])"?algorithm"?\s*[:=]\s*"ED25519"/g;
|
|
41
|
+
// AWS KMS key specs: the legacy `customer_master_key_spec` and the modern `key_spec`
|
|
42
|
+
// alias (aws provider v4+). The `(?<![\w"-])` lookbehind rejects the `key_spec` suffix
|
|
43
|
+
// inside `customer_master_key_spec` (preceded by `_`), so no double-count.
|
|
44
|
+
const RE_TF_KMS_RSA = /(?<![\w"-])"?(?:customer_master_key_spec|key_spec)"?\s*[:=]\s*"RSA_\d+"/g;
|
|
45
|
+
const RE_TF_KMS_EC =
|
|
46
|
+
/(?<![\w"-])"?(?:customer_master_key_spec|key_spec)"?\s*[:=]\s*"ECC_[A-Z0-9_]+"/g;
|
|
47
|
+
// `key_type` key material: Azure Key Vault (`"RSA"` / `"EC"`, incl. `-HSM`) and
|
|
48
|
+
// HashiCorp Vault PKI, which uses the lowercase `"rsa"` / `"ec"` tokens — so the value
|
|
49
|
+
// is matched case-insensitively. The `"…"` bound keeps `"ec"` from matching `"ecc"`,
|
|
50
|
+
// and `customer_master_key_spec` (AWS) is a different attribute handled above.
|
|
51
|
+
const RE_TF_AZ_RSA = /(?<![\w"-])"?key_type"?\s*[:=]\s*"RSA(?:-HSM)?"/gi;
|
|
52
|
+
const RE_TF_AZ_EC = /(?<![\w"-])"?key_type"?\s*[:=]\s*"EC(?:-HSM)?"/gi;
|
|
38
53
|
|
|
39
54
|
const RULE_TF_RSA: RuleMeta = {
|
|
40
55
|
id: "tf-rsa-key",
|
|
@@ -62,6 +77,19 @@ const RULE_TF_ECDSA: RuleMeta = {
|
|
|
62
77
|
message: "Terraform provisions a classical ECDSA key, forgeable by a quantum attacker.",
|
|
63
78
|
remediation: "ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205).",
|
|
64
79
|
};
|
|
80
|
+
const RULE_TF_ED25519: RuleMeta = {
|
|
81
|
+
id: "tf-ed25519-key",
|
|
82
|
+
title: "Terraform Ed25519 key",
|
|
83
|
+
description: 'Terraform tls_private_key algorithm = "ED25519"',
|
|
84
|
+
category: "signature",
|
|
85
|
+
severity: "medium",
|
|
86
|
+
confidence: "high",
|
|
87
|
+
algorithm: "EdDSA",
|
|
88
|
+
hndl: false,
|
|
89
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
90
|
+
message: "Terraform provisions a classical Ed25519 key, forgeable by a quantum attacker.",
|
|
91
|
+
remediation: "ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205).",
|
|
92
|
+
};
|
|
65
93
|
const RULE_TF_KMS_RSA: RuleMeta = {
|
|
66
94
|
id: "tf-kms-rsa",
|
|
67
95
|
title: "Terraform AWS KMS RSA CMK",
|
|
@@ -129,6 +157,7 @@ export const terraformDetector: Detector = {
|
|
|
129
157
|
rules: [
|
|
130
158
|
RULE_TF_RSA,
|
|
131
159
|
RULE_TF_ECDSA,
|
|
160
|
+
RULE_TF_ED25519,
|
|
132
161
|
RULE_TF_KMS_RSA,
|
|
133
162
|
RULE_TF_KMS_EC,
|
|
134
163
|
RULE_TF_AZ_RSA,
|
|
@@ -137,14 +166,19 @@ export const terraformDetector: Detector = {
|
|
|
137
166
|
appliesTo: (f) => hasExtension(f, TF_EXTENSIONS),
|
|
138
167
|
detect({ file, content }): Finding[] {
|
|
139
168
|
const findings: Finding[] = [];
|
|
169
|
+
// A commented HCL argument (`# algorithm = "RSA"`, `//` lines, and `/* … */` block
|
|
170
|
+
// comments) is not an active resource argument. Mask block comments then line
|
|
171
|
+
// comments; offsets preserved.
|
|
172
|
+
const scan = maskCommentLines(maskBlockComments(content), ["#", "//"]);
|
|
140
173
|
const add = (re: RegExp, rule: RuleMeta) =>
|
|
141
|
-
eachMatch(re,
|
|
174
|
+
eachMatch(re, scan, (m) =>
|
|
142
175
|
findings.push(
|
|
143
176
|
findingFromRule(rule, { file, content, index: m.index, matchLength: m[0].length }),
|
|
144
177
|
),
|
|
145
178
|
);
|
|
146
179
|
add(RE_TF_RSA, RULE_TF_RSA);
|
|
147
180
|
add(RE_TF_ECDSA, RULE_TF_ECDSA);
|
|
181
|
+
add(RE_TF_ED25519, RULE_TF_ED25519);
|
|
148
182
|
add(RE_TF_KMS_RSA, RULE_TF_KMS_RSA);
|
|
149
183
|
add(RE_TF_KMS_EC, RULE_TF_KMS_EC);
|
|
150
184
|
add(RE_TF_AZ_RSA, RULE_TF_AZ_RSA);
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config detector: classical asymmetric keys in native HashiCorp Vault server
|
|
3
|
+
* config / policy (HCL). Terraform-provisioned Vault is caught by the terraform
|
|
4
|
+
* detector (`.tf`); this covers Vault's OWN `.hcl` config — the `transit` and
|
|
5
|
+
* `pki` secrets engines, whose keys sign and wrap real production data.
|
|
6
|
+
*
|
|
7
|
+
* Covered (gated to a `transit`/`pki` marker to avoid firing on unrelated HCL):
|
|
8
|
+
* - transit key `type = "rsa-2048|3072|4096"` (RSA — key wrapping / signing).
|
|
9
|
+
* - transit key `type = "ecdsa-p256|p384|p521"` / `"ed25519"` (classical signing).
|
|
10
|
+
* - pki role `key_type = "rsa" | "ec"`.
|
|
11
|
+
*/
|
|
12
|
+
import type { Detector, Finding, RuleMeta } from "../types.js";
|
|
13
|
+
import { eachMatch, findingFromRule, hasExtension, maskCommentLines } from "../detect-utils.js";
|
|
14
|
+
import { CWE_BROKEN_CRYPTO } from "../cwe.js";
|
|
15
|
+
|
|
16
|
+
const HCL_EXTENSIONS: readonly string[] = [".hcl"];
|
|
17
|
+
|
|
18
|
+
const RE_TRANSIT_RSA = /\btype\s*=\s*"rsa-\d+"/g;
|
|
19
|
+
const RE_TRANSIT_ECDSA = /\btype\s*=\s*"ecdsa-p\d+"/g;
|
|
20
|
+
const RE_TRANSIT_ED25519 = /\btype\s*=\s*"ed25519"/g;
|
|
21
|
+
const RE_PKI_RSA = /\bkey_type\s*=\s*"rsa"/g;
|
|
22
|
+
const RE_PKI_EC = /\bkey_type\s*=\s*"ec"/g;
|
|
23
|
+
|
|
24
|
+
const RULE_TRANSIT_RSA: RuleMeta = {
|
|
25
|
+
id: "vault-transit-rsa",
|
|
26
|
+
title: "Vault transit RSA key",
|
|
27
|
+
description: 'Vault transit secrets engine key type = "rsa-*"',
|
|
28
|
+
category: "kem",
|
|
29
|
+
severity: "high",
|
|
30
|
+
confidence: "high",
|
|
31
|
+
algorithm: "RSA",
|
|
32
|
+
hndl: true,
|
|
33
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
34
|
+
message:
|
|
35
|
+
"Vault transit provisions a classical RSA key (signing / key wrapping), not quantum-safe.",
|
|
36
|
+
remediation:
|
|
37
|
+
"Plan migration to PQC (ML-KEM-768 for wrapping, ML-DSA-65 for signing) as Vault adds support.",
|
|
38
|
+
};
|
|
39
|
+
const RULE_TRANSIT_ECDSA: RuleMeta = {
|
|
40
|
+
id: "vault-transit-ecdsa",
|
|
41
|
+
title: "Vault transit ECDSA key",
|
|
42
|
+
description: 'Vault transit secrets engine key type = "ecdsa-p*"',
|
|
43
|
+
category: "signature",
|
|
44
|
+
severity: "medium",
|
|
45
|
+
confidence: "high",
|
|
46
|
+
algorithm: "ECDSA",
|
|
47
|
+
hndl: false,
|
|
48
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
49
|
+
message:
|
|
50
|
+
"Vault transit provisions a classical ECDSA signing key, forgeable by a quantum attacker.",
|
|
51
|
+
remediation: "ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205).",
|
|
52
|
+
};
|
|
53
|
+
const RULE_TRANSIT_ED25519: RuleMeta = {
|
|
54
|
+
id: "vault-transit-ed25519",
|
|
55
|
+
title: "Vault transit Ed25519 key",
|
|
56
|
+
description: 'Vault transit secrets engine key type = "ed25519"',
|
|
57
|
+
category: "signature",
|
|
58
|
+
severity: "low",
|
|
59
|
+
confidence: "high",
|
|
60
|
+
algorithm: "EdDSA",
|
|
61
|
+
hndl: false,
|
|
62
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
63
|
+
message:
|
|
64
|
+
"Vault transit provisions a classical Ed25519 signing key, forgeable by a quantum attacker.",
|
|
65
|
+
remediation: "ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205).",
|
|
66
|
+
};
|
|
67
|
+
const RULE_PKI_RSA: RuleMeta = {
|
|
68
|
+
id: "vault-pki-rsa",
|
|
69
|
+
title: "Vault PKI RSA role",
|
|
70
|
+
description: 'Vault pki secrets engine role key_type = "rsa"',
|
|
71
|
+
category: "certificate",
|
|
72
|
+
severity: "medium",
|
|
73
|
+
confidence: "high",
|
|
74
|
+
algorithm: "RSA",
|
|
75
|
+
hndl: true,
|
|
76
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
77
|
+
message: "Vault PKI mints certificates with a classical RSA key, not quantum-safe.",
|
|
78
|
+
remediation: "Plan migration to PQC certificate keys (ML-DSA-65) as the CA chain adds support.",
|
|
79
|
+
};
|
|
80
|
+
const RULE_PKI_EC: RuleMeta = {
|
|
81
|
+
id: "vault-pki-ec",
|
|
82
|
+
title: "Vault PKI EC role",
|
|
83
|
+
description: 'Vault pki secrets engine role key_type = "ec"',
|
|
84
|
+
category: "certificate",
|
|
85
|
+
severity: "medium",
|
|
86
|
+
confidence: "high",
|
|
87
|
+
algorithm: "ECDSA",
|
|
88
|
+
hndl: false,
|
|
89
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
90
|
+
message: "Vault PKI mints certificates with a classical EC key, forgeable by a quantum attacker.",
|
|
91
|
+
remediation: "Plan migration to ML-DSA-65 (FIPS 204) certificate keys.",
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/** Detects classical asymmetric keys in native Vault HCL config. */
|
|
95
|
+
export const vaultDetector: Detector = {
|
|
96
|
+
id: "vault-crypto",
|
|
97
|
+
description: "Classical asymmetric keys in native HashiCorp Vault config (transit, pki)",
|
|
98
|
+
scope: "config",
|
|
99
|
+
language: "any",
|
|
100
|
+
rules: [RULE_TRANSIT_RSA, RULE_TRANSIT_ECDSA, RULE_TRANSIT_ED25519, RULE_PKI_RSA, RULE_PKI_EC],
|
|
101
|
+
appliesTo: (f) => hasExtension(f, HCL_EXTENSIONS),
|
|
102
|
+
detect({ file, content }): Finding[] {
|
|
103
|
+
// Gate: only inside a Vault transit / pki context.
|
|
104
|
+
if (!content.includes("transit") && !content.includes("pki")) return [];
|
|
105
|
+
const scan = maskCommentLines(content, ["#", "//"]);
|
|
106
|
+
const findings: Finding[] = [];
|
|
107
|
+
const add = (re: RegExp, rule: RuleMeta) =>
|
|
108
|
+
eachMatch(re, scan, (m) =>
|
|
109
|
+
findings.push(
|
|
110
|
+
findingFromRule(rule, { file, content, index: m.index, matchLength: m[0].length }),
|
|
111
|
+
),
|
|
112
|
+
);
|
|
113
|
+
add(RE_TRANSIT_RSA, RULE_TRANSIT_RSA);
|
|
114
|
+
add(RE_TRANSIT_ECDSA, RULE_TRANSIT_ECDSA);
|
|
115
|
+
add(RE_TRANSIT_ED25519, RULE_TRANSIT_ED25519);
|
|
116
|
+
add(RE_PKI_RSA, RULE_PKI_RSA);
|
|
117
|
+
add(RE_PKI_EC, RULE_PKI_EC);
|
|
118
|
+
return findings;
|
|
119
|
+
},
|
|
120
|
+
};
|
package/src/detectors/vpn.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Config detector: classical key exchange in network transport / VPN config —
|
|
3
|
-
* WireGuard
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* exists).
|
|
3
|
+
* WireGuard and IPsec (strongSwan). These are the tunnels carrying "communication
|
|
4
|
+
* between things"; their key exchange is classical and so harvest-now-decrypt-later
|
|
5
|
+
* exposed (a recorded tunnel is decryptable once a CRQC exists).
|
|
7
6
|
*
|
|
8
7
|
* Covered (each gated so it only fires inside the relevant config):
|
|
9
8
|
* - **WireGuard** — `[Interface]`/`[Peer]` sections with `PrivateKey`/`PublicKey`.
|
|
@@ -12,18 +11,20 @@
|
|
|
12
11
|
* tunnel-wrapping layer. The private key is treated as sensitive key material.
|
|
13
12
|
* - **IPsec / strongSwan** — IKE/ESP proposals naming classical DH groups
|
|
14
13
|
* (`modp*` = finite-field DH, `ecp*` = ECDH).
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
14
|
+
*
|
|
15
|
+
* `sshd_config` / `ssh_config` KexAlgorithms are intentionally NOT handled here —
|
|
16
|
+
* the language-agnostic SSH token detector in `source.ts` (`ssh-kex-classical`)
|
|
17
|
+
* already covers them; a rule here would double-count.
|
|
18
18
|
*/
|
|
19
19
|
import type { Detector, Finding, RuleMeta } from "../types.js";
|
|
20
|
-
import { eachMatch, findingFromRule } from "../detect-utils.js";
|
|
20
|
+
import { eachMatch, findingFromRule, hasExtension, maskCommentLines } from "../detect-utils.js";
|
|
21
21
|
import { CWE_BROKEN_CRYPTO } from "../cwe.js";
|
|
22
22
|
|
|
23
|
+
const CONF_EXTENSIONS: readonly string[] = [".conf"];
|
|
24
|
+
|
|
23
25
|
const RE_WG_KEY = /\b(?:PrivateKey|PublicKey)\s*=\s*[A-Za-z0-9+/]{42,}=/g;
|
|
24
26
|
const RE_IPSEC_MODP = /\bmodp\d+\b/gi;
|
|
25
27
|
const RE_IPSEC_ECP = /\becp\d+(?:bp)?\b/gi;
|
|
26
|
-
const RE_SSHD_KEX = /^[ \t]*KexAlgorithms[ \t]+([^\n]*)/gm;
|
|
27
28
|
|
|
28
29
|
const RULE_WG: RuleMeta = {
|
|
29
30
|
id: "net-wireguard-x25519",
|
|
@@ -70,61 +71,32 @@ const RULE_IPSEC_EC: RuleMeta = {
|
|
|
70
71
|
remediation:
|
|
71
72
|
"Add a PQC/hybrid IKE proposal (X25519MLKEM768 / ML-KEM) as your IPsec stack supports it.",
|
|
72
73
|
};
|
|
73
|
-
const RULE_SSHD_KEX: RuleMeta = {
|
|
74
|
-
id: "net-sshd-classical-kex",
|
|
75
|
-
title: "SSH server offers no PQC key exchange",
|
|
76
|
-
description:
|
|
77
|
-
"sshd_config KexAlgorithms lists only classical key exchange (no sntrup761/mlkem768)",
|
|
78
|
-
category: "key-exchange",
|
|
79
|
-
severity: "medium",
|
|
80
|
-
confidence: "high",
|
|
81
|
-
algorithm: "ECDH",
|
|
82
|
-
hndl: true,
|
|
83
|
-
cwe: CWE_BROKEN_CRYPTO,
|
|
84
|
-
message:
|
|
85
|
-
"SSH server's KexAlgorithms offers only classical key exchange (no sntrup761x25519 / mlkem768x25519); sessions are harvest-now-decrypt-later exposed.",
|
|
86
|
-
remediation: "Add a PQC hybrid KEX: sntrup761x25519-sha512@openssh.com or mlkem768x25519-sha256.",
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
/** True when a KexAlgorithms value already offers a post-quantum hybrid KEX. */
|
|
90
|
-
function offersPqKex(kexLine: string): boolean {
|
|
91
|
-
return /sntrup761x25519|mlkem768/.test(kexLine);
|
|
92
|
-
}
|
|
93
74
|
|
|
94
|
-
/** Detects classical key exchange in WireGuard / IPsec
|
|
75
|
+
/** Detects classical key exchange in WireGuard / IPsec network config. */
|
|
95
76
|
export const vpnDetector: Detector = {
|
|
96
77
|
id: "network-transport-crypto",
|
|
97
|
-
description: "Classical key exchange in network transport / VPN config (WireGuard, IPsec
|
|
78
|
+
description: "Classical key exchange in network transport / VPN config (WireGuard, IPsec)",
|
|
98
79
|
scope: "config",
|
|
99
80
|
language: "any",
|
|
100
|
-
rules: [RULE_WG, RULE_IPSEC_DH, RULE_IPSEC_EC
|
|
101
|
-
appliesTo: (f) =>
|
|
102
|
-
const lower = f.toLowerCase();
|
|
103
|
-
const base = lower.split("/").pop() ?? lower;
|
|
104
|
-
return lower.endsWith(".conf") || base === "sshd_config" || base === "ssh_config";
|
|
105
|
-
},
|
|
81
|
+
rules: [RULE_WG, RULE_IPSEC_DH, RULE_IPSEC_EC],
|
|
82
|
+
appliesTo: (f) => hasExtension(f, CONF_EXTENSIONS),
|
|
106
83
|
detect({ file, content }): Finding[] {
|
|
107
84
|
const findings: Finding[] = [];
|
|
108
85
|
const push = (rule: RuleMeta, index: number, length: number) =>
|
|
109
86
|
findings.push(findingFromRule(rule, { file, content, index, matchLength: length }));
|
|
87
|
+
// ipsec.conf / wg configs use `#` line comments. Match over comment-masked
|
|
88
|
+
// content (offsets preserved); gates stay on the original.
|
|
89
|
+
const scan = maskCommentLines(content, ["#"]);
|
|
110
90
|
|
|
111
91
|
// WireGuard: gated to a WireGuard config section.
|
|
112
92
|
if (content.includes("[Interface]") || content.includes("[Peer]")) {
|
|
113
|
-
eachMatch(RE_WG_KEY,
|
|
93
|
+
eachMatch(RE_WG_KEY, scan, (m) => push(RULE_WG, m.index, m[0].length));
|
|
114
94
|
}
|
|
115
95
|
|
|
116
96
|
// IPsec / strongSwan: gated to a proposal assignment.
|
|
117
97
|
if (/\b(?:ike|esp|proposals?|keyexchange)\s*=/i.test(content)) {
|
|
118
|
-
eachMatch(RE_IPSEC_MODP,
|
|
119
|
-
eachMatch(RE_IPSEC_ECP,
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// sshd_config / ssh_config: KexAlgorithms line with no PQC hybrid offered.
|
|
123
|
-
const base = file.toLowerCase().split("/").pop() ?? "";
|
|
124
|
-
if (base === "sshd_config" || base === "ssh_config") {
|
|
125
|
-
eachMatch(RE_SSHD_KEX, content, (m) => {
|
|
126
|
-
if (!offersPqKex(m[1])) push(RULE_SSHD_KEX, m.index, m[0].length);
|
|
127
|
-
});
|
|
98
|
+
eachMatch(RE_IPSEC_MODP, scan, (m) => push(RULE_IPSEC_DH, m.index, m[0].length));
|
|
99
|
+
eachMatch(RE_IPSEC_ECP, scan, (m) => push(RULE_IPSEC_EC, m.index, m[0].length));
|
|
128
100
|
}
|
|
129
101
|
return findings;
|
|
130
102
|
},
|