@quantakrypto/core 0.4.3 → 0.4.4
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/dist/cbom-merge.d.ts +9 -0
- package/dist/cbom-merge.d.ts.map +1 -0
- package/dist/cbom-merge.js +99 -0
- package/dist/cbom-merge.js.map +1 -0
- package/dist/comments.d.ts +4 -3
- package/dist/comments.d.ts.map +1 -1
- package/dist/comments.js +53 -33
- package/dist/comments.js.map +1 -1
- package/dist/dependencies.d.ts.map +1 -1
- package/dist/dependencies.js +1 -1
- package/dist/dependencies.js.map +1 -1
- package/dist/detect-utils.d.ts +5 -1
- package/dist/detect-utils.d.ts.map +1 -1
- package/dist/detect-utils.js +11 -2
- package/dist/detect-utils.js.map +1 -1
- package/dist/detectors/c.d.ts +4 -2
- package/dist/detectors/c.d.ts.map +1 -1
- package/dist/detectors/c.js +192 -1
- package/dist/detectors/c.js.map +1 -1
- package/dist/detectors/cicd.d.ts +27 -0
- package/dist/detectors/cicd.d.ts.map +1 -0
- package/dist/detectors/cicd.js +116 -0
- package/dist/detectors/cicd.js.map +1 -0
- package/dist/detectors/cloud-kms.d.ts +21 -0
- package/dist/detectors/cloud-kms.d.ts.map +1 -0
- package/dist/detectors/cloud-kms.js +57 -0
- package/dist/detectors/cloud-kms.js.map +1 -0
- package/dist/detectors/cloudformation.d.ts +30 -0
- package/dist/detectors/cloudformation.d.ts.map +1 -0
- package/dist/detectors/cloudformation.js +170 -0
- package/dist/detectors/cloudformation.js.map +1 -0
- package/dist/detectors/database.d.ts +17 -0
- package/dist/detectors/database.d.ts.map +1 -0
- package/dist/detectors/database.js +60 -0
- package/dist/detectors/database.js.map +1 -0
- package/dist/detectors/dnssec.d.ts +55 -0
- package/dist/detectors/dnssec.d.ts.map +1 -0
- package/dist/detectors/dnssec.js +107 -0
- package/dist/detectors/dnssec.js.map +1 -0
- package/dist/detectors/elixir.d.ts +20 -0
- package/dist/detectors/elixir.d.ts.map +1 -0
- package/dist/detectors/elixir.js +195 -0
- package/dist/detectors/elixir.js.map +1 -0
- package/dist/detectors/java.d.ts.map +1 -1
- package/dist/detectors/java.js +1 -1
- package/dist/detectors/java.js.map +1 -1
- package/dist/detectors/jose.d.ts +20 -0
- package/dist/detectors/jose.d.ts.map +1 -0
- package/dist/detectors/jose.js +62 -0
- package/dist/detectors/jose.js.map +1 -0
- package/dist/detectors/jwk.d.ts +25 -0
- package/dist/detectors/jwk.d.ts.map +1 -0
- package/dist/detectors/jwk.js +95 -0
- package/dist/detectors/jwk.js.map +1 -0
- package/dist/detectors/k8s.d.ts +17 -0
- package/dist/detectors/k8s.d.ts.map +1 -0
- package/dist/detectors/k8s.js +85 -0
- package/dist/detectors/k8s.js.map +1 -0
- package/dist/detectors/mesh.d.ts +35 -0
- package/dist/detectors/mesh.d.ts.map +1 -0
- package/dist/detectors/mesh.js +109 -0
- package/dist/detectors/mesh.js.map +1 -0
- package/dist/detectors/messaging.d.ts +16 -0
- package/dist/detectors/messaging.d.ts.map +1 -0
- package/dist/detectors/messaging.js +72 -0
- package/dist/detectors/messaging.js.map +1 -0
- package/dist/detectors/pem.js +1 -1
- package/dist/detectors/pem.js.map +1 -1
- package/dist/detectors/php.d.ts +24 -0
- package/dist/detectors/php.d.ts.map +1 -0
- package/dist/detectors/php.js +167 -0
- package/dist/detectors/php.js.map +1 -0
- package/dist/detectors/python.d.ts.map +1 -1
- package/dist/detectors/python.js +70 -0
- package/dist/detectors/python.js.map +1 -1
- package/dist/detectors/rust.d.ts.map +1 -1
- package/dist/detectors/rust.js +68 -0
- package/dist/detectors/rust.js.map +1 -1
- package/dist/detectors/secrets.d.ts +21 -0
- package/dist/detectors/secrets.d.ts.map +1 -0
- package/dist/detectors/secrets.js +79 -0
- package/dist/detectors/secrets.js.map +1 -0
- package/dist/detectors/source.d.ts.map +1 -1
- package/dist/detectors/source.js +190 -47
- package/dist/detectors/source.js.map +1 -1
- package/dist/detectors/stateful-hbs.d.ts.map +1 -1
- package/dist/detectors/stateful-hbs.js +9 -6
- package/dist/detectors/stateful-hbs.js.map +1 -1
- package/dist/detectors/terraform.d.ts +21 -0
- package/dist/detectors/terraform.d.ts.map +1 -0
- package/dist/detectors/terraform.js +123 -0
- package/dist/detectors/terraform.js.map +1 -0
- package/dist/detectors/vpn.d.ts +22 -0
- package/dist/detectors/vpn.d.ts.map +1 -0
- package/dist/detectors/vpn.js +99 -0
- package/dist/detectors/vpn.js.map +1 -0
- package/dist/evidence.d.ts +5 -0
- package/dist/evidence.d.ts.map +1 -1
- package/dist/evidence.js +5 -0
- package/dist/evidence.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/policy.d.ts +67 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +115 -0
- package/dist/policy.js.map +1 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +30 -0
- package/dist/registry.js.map +1 -1
- package/dist/remediate-pipeline.d.ts.map +1 -1
- package/dist/remediate-pipeline.js +22 -1
- package/dist/remediate-pipeline.js.map +1 -1
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +7 -0
- package/dist/report.js.map +1 -1
- package/dist/standards.d.ts +96 -0
- package/dist/standards.d.ts.map +1 -0
- package/dist/standards.js +107 -0
- package/dist/standards.js.map +1 -0
- package/dist/types.d.ts +1 -1
- 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/package.json +1 -1
- package/src/cbom-merge.ts +116 -0
- package/src/comments.ts +59 -33
- package/src/dependencies.ts +2 -1
- package/src/detect-utils.ts +14 -2
- package/src/detectors/c.ts +209 -3
- package/src/detectors/cicd.ts +158 -0
- package/src/detectors/cloud-kms.ts +87 -0
- package/src/detectors/cloudformation.ts +215 -0
- package/src/detectors/database.ts +88 -0
- package/src/detectors/dnssec.ts +186 -0
- package/src/detectors/elixir.ts +237 -0
- package/src/detectors/java.ts +2 -1
- package/src/detectors/jose.ts +94 -0
- package/src/detectors/jwk.ts +128 -0
- package/src/detectors/k8s.ts +112 -0
- package/src/detectors/mesh.ts +154 -0
- package/src/detectors/messaging.ts +98 -0
- package/src/detectors/pem.ts +1 -1
- package/src/detectors/php.ts +225 -0
- package/src/detectors/python.ts +71 -0
- package/src/detectors/rust.ts +71 -0
- package/src/detectors/secrets.ts +114 -0
- package/src/detectors/source.ts +235 -68
- package/src/detectors/stateful-hbs.ts +9 -6
- package/src/detectors/terraform.ts +154 -0
- package/src/detectors/vpn.ts +131 -0
- package/src/evidence.ts +11 -0
- package/src/index.ts +10 -0
- package/src/policy.ts +180 -0
- package/src/registry.ts +30 -0
- package/src/remediate-pipeline.ts +25 -2
- package/src/report.ts +7 -0
- package/src/standards.ts +186 -0
- package/src/types.ts +2 -0
- package/src/version.ts +1 -1
package/src/detectors/c.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Source-code detector for classical asymmetric cryptography in C / C++ using
|
|
3
|
-
* OpenSSL (the dominant crypto library for the ecosystem)
|
|
4
|
-
*
|
|
3
|
+
* OpenSSL (the dominant crypto library for the ecosystem), libsodium, and — for
|
|
4
|
+
* the embedded / firmware / IoT niche — Mbed TLS (`mbedtls_*`) and wolfSSL /
|
|
5
|
+
* wolfCrypt (`wc_*`). Lexical, same strategy as the other packs; every library's
|
|
6
|
+
* function names are distinctive enough to keep the false-positive risk low.
|
|
5
7
|
*
|
|
6
8
|
* NOTE: scanning OpenSSL's OWN source/headers will naturally light up (the
|
|
7
9
|
* library declares these symbols) — that is inherent to lexical scanning of a
|
|
@@ -48,6 +50,24 @@ const RE_C_RSA_CRYPT = /\bRSA_public_encrypt\s*\(|\bRSA_private_decrypt\s*\(/g;
|
|
|
48
50
|
// deprecated protocol version or disabling certificate verification.
|
|
49
51
|
const RE_C_TLS_VERSION = /\bTLSv1_method\b|\bSSLv3_method\b/g;
|
|
50
52
|
const RE_C_TLS_VERIFY_NONE = /\bSSL_VERIFY_NONE\b/g;
|
|
53
|
+
// Embedded C crypto libraries (the "embedded" niche): Mbed TLS and wolfSSL /
|
|
54
|
+
// wolfCrypt. Both use highly-distinctive `mbedtls_*` / `wc_*` prefixes, so the
|
|
55
|
+
// false-positive risk is low. These dominate firmware / IoT / RTOS builds where
|
|
56
|
+
// OpenSSL is too heavy — a codebase surface qScan previously missed entirely.
|
|
57
|
+
const RE_C_MBEDTLS_RSA = /\bmbedtls_rsa_gen_key\s*\(/g;
|
|
58
|
+
const RE_C_MBEDTLS_EC = /\bmbedtls_ecp_gen_key(?:pair)?\s*\(/g;
|
|
59
|
+
const RE_C_MBEDTLS_ECDSA =
|
|
60
|
+
/\bmbedtls_ecdsa_(?:sign|write_signature|read_signature|verify)\w*\s*\(/g;
|
|
61
|
+
const RE_C_MBEDTLS_ECDH = /\bmbedtls_ecdh_(?:compute_shared|calc_secret)\s*\(/g;
|
|
62
|
+
const RE_C_MBEDTLS_DH = /\bmbedtls_dhm_(?:make_public|make_params|calc_secret)\s*\(/g;
|
|
63
|
+
const RE_C_WOLF_RSA =
|
|
64
|
+
/\bwc_MakeRsaKey\s*\(|\bwc_RsaPublicEncrypt\s*\(|\bwc_RsaPrivateDecrypt\s*\(/g;
|
|
65
|
+
const RE_C_WOLF_ECC = /\bwc_ecc_make_key(?:_ex)?\s*\(/g;
|
|
66
|
+
const RE_C_WOLF_ECDSA = /\bwc_ecc_sign_hash\s*\(|\bwc_ecc_verify_hash\s*\(/g;
|
|
67
|
+
const RE_C_WOLF_ECDH = /\bwc_ecc_shared_secret\s*\(/g;
|
|
68
|
+
const RE_C_WOLF_DH = /\bwc_DhGenerateKeyPair\s*\(|\bwc_DhAgree\s*\(/g;
|
|
69
|
+
const RE_C_WOLF_CURVE25519 = /\bwc_curve25519_(?:make_key|shared_secret)\s*\(/g;
|
|
70
|
+
const RE_C_WOLF_ED25519 = /\bwc_ed25519_(?:make_key|sign_msg|verify_msg)\s*\(/g;
|
|
51
71
|
|
|
52
72
|
const RULE_C_RSA: RuleMeta = {
|
|
53
73
|
id: "c-rsa-keygen",
|
|
@@ -275,11 +295,173 @@ const RULE_C_TLS_VERIFY_NONE: RuleMeta = {
|
|
|
275
295
|
message: "SSL_VERIFY_NONE disables TLS certificate verification (MITM risk).",
|
|
276
296
|
remediation: "Use SSL_VERIFY_PEER and verify certificates properly.",
|
|
277
297
|
};
|
|
298
|
+
// --- Mbed TLS (embedded) ---
|
|
299
|
+
const RULE_C_MBEDTLS_RSA: RuleMeta = {
|
|
300
|
+
id: "c-mbedtls-rsa-keygen",
|
|
301
|
+
title: "Mbed TLS RSA key generation",
|
|
302
|
+
description: "Mbed TLS mbedtls_rsa_gen_key",
|
|
303
|
+
category: "kem",
|
|
304
|
+
severity: "high",
|
|
305
|
+
confidence: "high",
|
|
306
|
+
algorithm: "RSA",
|
|
307
|
+
hndl: true,
|
|
308
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
309
|
+
message: "Generates a classical RSA key pair (Mbed TLS, embedded), which is not quantum-safe.",
|
|
310
|
+
};
|
|
311
|
+
const RULE_C_MBEDTLS_EC: RuleMeta = {
|
|
312
|
+
id: "c-mbedtls-ec-keygen",
|
|
313
|
+
title: "Mbed TLS EC key generation",
|
|
314
|
+
description: "Mbed TLS mbedtls_ecp_gen_key / mbedtls_ecp_gen_keypair",
|
|
315
|
+
category: "key-exchange",
|
|
316
|
+
severity: "high",
|
|
317
|
+
confidence: "high",
|
|
318
|
+
algorithm: "ECDH",
|
|
319
|
+
hndl: true,
|
|
320
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
321
|
+
message:
|
|
322
|
+
"Generates a classical EC key pair (Mbed TLS, embedded). EC keys feed BOTH ECDSA signatures and ECDH key agreement; the ECDH path is harvest-now-decrypt-later exposed.",
|
|
323
|
+
remediation:
|
|
324
|
+
"For key agreement: hybrid X25519MLKEM768 (ML-KEM-768). For signatures: ML-DSA-65 (FIPS 204).",
|
|
325
|
+
};
|
|
326
|
+
const RULE_C_MBEDTLS_ECDSA: RuleMeta = {
|
|
327
|
+
id: "c-mbedtls-ecdsa",
|
|
328
|
+
title: "Mbed TLS ECDSA signature",
|
|
329
|
+
description: "Mbed TLS mbedtls_ecdsa_sign / write_signature / read_signature / verify",
|
|
330
|
+
category: "signature",
|
|
331
|
+
severity: "high",
|
|
332
|
+
confidence: "high",
|
|
333
|
+
algorithm: "ECDSA",
|
|
334
|
+
hndl: false,
|
|
335
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
336
|
+
message: "Classical ECDSA (Mbed TLS, embedded) is forgeable by a quantum attacker.",
|
|
337
|
+
remediation: "ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205)",
|
|
338
|
+
};
|
|
339
|
+
const RULE_C_MBEDTLS_ECDH: RuleMeta = {
|
|
340
|
+
id: "c-mbedtls-ecdh",
|
|
341
|
+
title: "Mbed TLS ECDH key agreement",
|
|
342
|
+
description: "Mbed TLS mbedtls_ecdh_compute_shared / mbedtls_ecdh_calc_secret",
|
|
343
|
+
category: "key-exchange",
|
|
344
|
+
severity: "high",
|
|
345
|
+
confidence: "high",
|
|
346
|
+
algorithm: "ECDH",
|
|
347
|
+
hndl: true,
|
|
348
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
349
|
+
message:
|
|
350
|
+
"Elliptic-curve Diffie-Hellman (Mbed TLS, embedded) is broken by Shor's algorithm (harvest-now-decrypt-later).",
|
|
351
|
+
};
|
|
352
|
+
const RULE_C_MBEDTLS_DH: RuleMeta = {
|
|
353
|
+
id: "c-mbedtls-dh",
|
|
354
|
+
title: "Mbed TLS Diffie-Hellman key exchange",
|
|
355
|
+
description: "Mbed TLS mbedtls_dhm_make_public / make_params / calc_secret",
|
|
356
|
+
category: "key-exchange",
|
|
357
|
+
severity: "high",
|
|
358
|
+
confidence: "high",
|
|
359
|
+
algorithm: "DH",
|
|
360
|
+
hndl: true,
|
|
361
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
362
|
+
message:
|
|
363
|
+
"Finite-field Diffie-Hellman (Mbed TLS, embedded) is broken by Shor's algorithm (harvest-now-decrypt-later).",
|
|
364
|
+
};
|
|
365
|
+
// --- wolfSSL / wolfCrypt (embedded) ---
|
|
366
|
+
const RULE_C_WOLF_RSA: RuleMeta = {
|
|
367
|
+
id: "c-wolfssl-rsa",
|
|
368
|
+
title: "wolfSSL RSA key/usage",
|
|
369
|
+
description: "wolfCrypt wc_MakeRsaKey / wc_RsaPublicEncrypt / wc_RsaPrivateDecrypt",
|
|
370
|
+
category: "kem",
|
|
371
|
+
severity: "high",
|
|
372
|
+
confidence: "high",
|
|
373
|
+
algorithm: "RSA",
|
|
374
|
+
hndl: true,
|
|
375
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
376
|
+
message:
|
|
377
|
+
"Classical RSA key generation / encryption (wolfSSL, embedded) is harvest-now-decrypt-later exposed.",
|
|
378
|
+
};
|
|
379
|
+
const RULE_C_WOLF_ECC: RuleMeta = {
|
|
380
|
+
id: "c-wolfssl-ecc-keygen",
|
|
381
|
+
title: "wolfSSL EC key generation",
|
|
382
|
+
description: "wolfCrypt wc_ecc_make_key / wc_ecc_make_key_ex",
|
|
383
|
+
category: "key-exchange",
|
|
384
|
+
severity: "high",
|
|
385
|
+
confidence: "high",
|
|
386
|
+
algorithm: "ECDH",
|
|
387
|
+
hndl: true,
|
|
388
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
389
|
+
message:
|
|
390
|
+
"Generates a classical EC key pair (wolfSSL, embedded). EC keys feed BOTH ECDSA signatures and ECDH key agreement; the ECDH path is harvest-now-decrypt-later exposed.",
|
|
391
|
+
remediation:
|
|
392
|
+
"For key agreement: hybrid X25519MLKEM768 (ML-KEM-768). For signatures: ML-DSA-65 (FIPS 204).",
|
|
393
|
+
};
|
|
394
|
+
const RULE_C_WOLF_ECDSA: RuleMeta = {
|
|
395
|
+
id: "c-wolfssl-ecdsa",
|
|
396
|
+
title: "wolfSSL ECDSA signature",
|
|
397
|
+
description: "wolfCrypt wc_ecc_sign_hash / wc_ecc_verify_hash",
|
|
398
|
+
category: "signature",
|
|
399
|
+
severity: "high",
|
|
400
|
+
confidence: "high",
|
|
401
|
+
algorithm: "ECDSA",
|
|
402
|
+
hndl: false,
|
|
403
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
404
|
+
message: "Classical ECDSA (wolfSSL, embedded) is forgeable by a quantum attacker.",
|
|
405
|
+
remediation: "ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205)",
|
|
406
|
+
};
|
|
407
|
+
const RULE_C_WOLF_ECDH: RuleMeta = {
|
|
408
|
+
id: "c-wolfssl-ecdh",
|
|
409
|
+
title: "wolfSSL ECDH key agreement",
|
|
410
|
+
description: "wolfCrypt wc_ecc_shared_secret",
|
|
411
|
+
category: "key-exchange",
|
|
412
|
+
severity: "high",
|
|
413
|
+
confidence: "high",
|
|
414
|
+
algorithm: "ECDH",
|
|
415
|
+
hndl: true,
|
|
416
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
417
|
+
message:
|
|
418
|
+
"Elliptic-curve Diffie-Hellman (wolfSSL, embedded) is broken by Shor's algorithm (harvest-now-decrypt-later).",
|
|
419
|
+
};
|
|
420
|
+
const RULE_C_WOLF_DH: RuleMeta = {
|
|
421
|
+
id: "c-wolfssl-dh",
|
|
422
|
+
title: "wolfSSL Diffie-Hellman key exchange",
|
|
423
|
+
description: "wolfCrypt wc_DhGenerateKeyPair / wc_DhAgree",
|
|
424
|
+
category: "key-exchange",
|
|
425
|
+
severity: "high",
|
|
426
|
+
confidence: "high",
|
|
427
|
+
algorithm: "DH",
|
|
428
|
+
hndl: true,
|
|
429
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
430
|
+
message:
|
|
431
|
+
"Finite-field Diffie-Hellman (wolfSSL, embedded) is broken by Shor's algorithm (harvest-now-decrypt-later).",
|
|
432
|
+
};
|
|
433
|
+
const RULE_C_WOLF_CURVE25519: RuleMeta = {
|
|
434
|
+
id: "c-wolfssl-curve25519",
|
|
435
|
+
title: "wolfSSL X25519 key agreement",
|
|
436
|
+
description: "wolfCrypt wc_curve25519_make_key / wc_curve25519_shared_secret",
|
|
437
|
+
category: "key-exchange",
|
|
438
|
+
severity: "medium",
|
|
439
|
+
confidence: "high",
|
|
440
|
+
algorithm: "X25519",
|
|
441
|
+
hndl: true,
|
|
442
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
443
|
+
message:
|
|
444
|
+
"X25519 key agreement (wolfSSL, embedded) is modern but classical, and harvest-now-decrypt-later exposed.",
|
|
445
|
+
};
|
|
446
|
+
const RULE_C_WOLF_ED25519: RuleMeta = {
|
|
447
|
+
id: "c-wolfssl-ed25519",
|
|
448
|
+
title: "wolfSSL Ed25519 signature",
|
|
449
|
+
description: "wolfCrypt wc_ed25519_make_key / wc_ed25519_sign_msg / wc_ed25519_verify_msg",
|
|
450
|
+
category: "signature",
|
|
451
|
+
severity: "low",
|
|
452
|
+
confidence: "high",
|
|
453
|
+
algorithm: "EdDSA",
|
|
454
|
+
hndl: false,
|
|
455
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
456
|
+
message:
|
|
457
|
+
"Ed25519 signatures (wolfSSL, embedded) are classical and forgeable by a quantum attacker.",
|
|
458
|
+
remediation: "ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205)",
|
|
459
|
+
};
|
|
278
460
|
|
|
279
461
|
/** Detects classical asymmetric crypto in C/C++ (OpenSSL). */
|
|
280
462
|
export const cDetector: Detector = {
|
|
281
463
|
id: "c-crypto",
|
|
282
|
-
description: "Classical asymmetric crypto in C/C++ (OpenSSL)",
|
|
464
|
+
description: "Classical asymmetric crypto in C/C++ (OpenSSL, libsodium, Mbed TLS, wolfSSL)",
|
|
283
465
|
scope: "source",
|
|
284
466
|
language: "c",
|
|
285
467
|
rules: [
|
|
@@ -300,6 +482,18 @@ export const cDetector: Detector = {
|
|
|
300
482
|
RULE_C_RSA_CRYPT,
|
|
301
483
|
RULE_C_TLS_VERSION,
|
|
302
484
|
RULE_C_TLS_VERIFY_NONE,
|
|
485
|
+
RULE_C_MBEDTLS_RSA,
|
|
486
|
+
RULE_C_MBEDTLS_EC,
|
|
487
|
+
RULE_C_MBEDTLS_ECDSA,
|
|
488
|
+
RULE_C_MBEDTLS_ECDH,
|
|
489
|
+
RULE_C_MBEDTLS_DH,
|
|
490
|
+
RULE_C_WOLF_RSA,
|
|
491
|
+
RULE_C_WOLF_ECC,
|
|
492
|
+
RULE_C_WOLF_ECDSA,
|
|
493
|
+
RULE_C_WOLF_ECDH,
|
|
494
|
+
RULE_C_WOLF_DH,
|
|
495
|
+
RULE_C_WOLF_CURVE25519,
|
|
496
|
+
RULE_C_WOLF_ED25519,
|
|
303
497
|
],
|
|
304
498
|
appliesTo: (f) => hasExtension(f, C_EXTENSIONS),
|
|
305
499
|
detect({ file, content }): Finding[] {
|
|
@@ -327,6 +521,18 @@ export const cDetector: Detector = {
|
|
|
327
521
|
add(RE_C_RSA_CRYPT, RULE_C_RSA_CRYPT);
|
|
328
522
|
add(RE_C_TLS_VERSION, RULE_C_TLS_VERSION);
|
|
329
523
|
add(RE_C_TLS_VERIFY_NONE, RULE_C_TLS_VERIFY_NONE);
|
|
524
|
+
add(RE_C_MBEDTLS_RSA, RULE_C_MBEDTLS_RSA);
|
|
525
|
+
add(RE_C_MBEDTLS_EC, RULE_C_MBEDTLS_EC);
|
|
526
|
+
add(RE_C_MBEDTLS_ECDSA, RULE_C_MBEDTLS_ECDSA);
|
|
527
|
+
add(RE_C_MBEDTLS_ECDH, RULE_C_MBEDTLS_ECDH);
|
|
528
|
+
add(RE_C_MBEDTLS_DH, RULE_C_MBEDTLS_DH);
|
|
529
|
+
add(RE_C_WOLF_RSA, RULE_C_WOLF_RSA);
|
|
530
|
+
add(RE_C_WOLF_ECC, RULE_C_WOLF_ECC);
|
|
531
|
+
add(RE_C_WOLF_ECDSA, RULE_C_WOLF_ECDSA);
|
|
532
|
+
add(RE_C_WOLF_ECDH, RULE_C_WOLF_ECDH);
|
|
533
|
+
add(RE_C_WOLF_DH, RULE_C_WOLF_DH);
|
|
534
|
+
add(RE_C_WOLF_CURVE25519, RULE_C_WOLF_CURVE25519);
|
|
535
|
+
add(RE_C_WOLF_ED25519, RULE_C_WOLF_ED25519);
|
|
330
536
|
return findings;
|
|
331
537
|
},
|
|
332
538
|
};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config detector: classical signing of build artifacts and code in CI/CD
|
|
3
|
+
* pipelines (GitHub Actions, GitLab CI, Jenkins, Azure Pipelines, CircleCI).
|
|
4
|
+
*
|
|
5
|
+
* Artifact and code signatures are the signature-side analogue of "harvest now,
|
|
6
|
+
* decrypt later": a release signed today with a classical key is *forgeable* once
|
|
7
|
+
* a CRQC exists, and long-lived artifacts (container images, released binaries,
|
|
8
|
+
* SBOM attestations) keep verifying against that classical public key for years.
|
|
9
|
+
* So these are flagged `hndl:false` (a signature is not confidentiality — nothing
|
|
10
|
+
* to harvest) but remain real quantum-migration debt.
|
|
11
|
+
*
|
|
12
|
+
* Covered command invocations (distinctive enough inside a CI file that the
|
|
13
|
+
* false-positive risk is low):
|
|
14
|
+
* - `cosign sign|attest|generate-key-pair` → sigstore/cosign uses ECDSA P-256
|
|
15
|
+
* (both key-based and keyless/Fulcio).
|
|
16
|
+
* - `gpg --detach-sign|--clearsign|--sign` → GnuPG, classically RSA.
|
|
17
|
+
* - `jarsigner` → Java JAR signing (RSA/DSA/EC).
|
|
18
|
+
* - `codesign --sign|-s` → Apple code signing (RSA).
|
|
19
|
+
* - `minisign` → Ed25519 signatures.
|
|
20
|
+
*
|
|
21
|
+
* Gated to CI/CD pipeline files so `gpg`/`cosign` mentioned in a shell script or
|
|
22
|
+
* doc does not fire; the surface here is specifically the release pipeline.
|
|
23
|
+
*/
|
|
24
|
+
import type { Detector, Finding, RuleMeta } from "../types.js";
|
|
25
|
+
import { eachMatch, findingFromRule } from "../detect-utils.js";
|
|
26
|
+
import { CWE_BROKEN_CRYPTO } from "../cwe.js";
|
|
27
|
+
|
|
28
|
+
/** True for the CI/CD pipeline definition files this detector inspects. */
|
|
29
|
+
function isCiPipelineFile(filePath: string): boolean {
|
|
30
|
+
const lower = filePath.toLowerCase();
|
|
31
|
+
const base = lower.split("/").pop() ?? lower;
|
|
32
|
+
return (
|
|
33
|
+
(lower.includes(".github/workflows/") && (lower.endsWith(".yml") || lower.endsWith(".yaml"))) ||
|
|
34
|
+
base === ".gitlab-ci.yml" ||
|
|
35
|
+
lower.endsWith(".gitlab-ci.yml") ||
|
|
36
|
+
base === "jenkinsfile" ||
|
|
37
|
+
lower.endsWith(".jenkinsfile") ||
|
|
38
|
+
base === "azure-pipelines.yml" ||
|
|
39
|
+
base === "azure-pipelines.yaml" ||
|
|
40
|
+
(lower.includes(".circleci/") && (lower.endsWith(".yml") || lower.endsWith(".yaml")))
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface CiRule {
|
|
45
|
+
re: RegExp;
|
|
46
|
+
meta: RuleMeta;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const CI_RULES: CiRule[] = [
|
|
50
|
+
{
|
|
51
|
+
re: /\bcosign\s+(?:sign|attest|sign-blob|generate-key-pair)\b/g,
|
|
52
|
+
meta: {
|
|
53
|
+
id: "ci-cosign-ecdsa",
|
|
54
|
+
title: "cosign artifact signing (ECDSA)",
|
|
55
|
+
description: "sigstore/cosign signing in a CI pipeline",
|
|
56
|
+
category: "signature",
|
|
57
|
+
severity: "medium",
|
|
58
|
+
confidence: "high",
|
|
59
|
+
algorithm: "ECDSA",
|
|
60
|
+
hndl: false,
|
|
61
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
62
|
+
message:
|
|
63
|
+
"CI pipeline signs artifacts with cosign (ECDSA P-256, key-based or keyless/Fulcio); classical signatures are forgeable once a CRQC exists.",
|
|
64
|
+
remediation:
|
|
65
|
+
"Track sigstore's post-quantum signing roadmap (ML-DSA); plan hybrid signing for long-lived release artifacts.",
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
re: /\bgpg\b[^\n]*?\s--(?:detach-sign|clearsign|sign)\b/g,
|
|
70
|
+
meta: {
|
|
71
|
+
id: "ci-gpg-sign",
|
|
72
|
+
title: "GPG signing (RSA)",
|
|
73
|
+
description: "GnuPG detached/clear signing in a CI pipeline",
|
|
74
|
+
category: "signature",
|
|
75
|
+
severity: "medium",
|
|
76
|
+
confidence: "high",
|
|
77
|
+
algorithm: "RSA",
|
|
78
|
+
hndl: false,
|
|
79
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
80
|
+
message:
|
|
81
|
+
"CI pipeline signs with GPG, classically an RSA signing key; forgeable once a CRQC exists.",
|
|
82
|
+
remediation: "Plan migration to ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205) signatures.",
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
re: /\bjarsigner\b/g,
|
|
87
|
+
meta: {
|
|
88
|
+
id: "ci-jarsigner",
|
|
89
|
+
title: "Java jarsigner (classical)",
|
|
90
|
+
description: "JDK jarsigner code signing in a CI pipeline",
|
|
91
|
+
category: "signature",
|
|
92
|
+
severity: "medium",
|
|
93
|
+
confidence: "high",
|
|
94
|
+
algorithm: "RSA",
|
|
95
|
+
hndl: false,
|
|
96
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
97
|
+
message:
|
|
98
|
+
"CI pipeline signs JARs with jarsigner (classical RSA/DSA/EC signing key); forgeable once a CRQC exists.",
|
|
99
|
+
remediation:
|
|
100
|
+
"Plan migration to a PQC signature scheme (ML-DSA-65 / SLH-DSA) as the JDK adds support.",
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
re: /\bcodesign\s+(?:-s\b|--sign\b)/g,
|
|
105
|
+
meta: {
|
|
106
|
+
id: "ci-codesign",
|
|
107
|
+
title: "Apple codesign (RSA)",
|
|
108
|
+
description: "Apple codesign in a CI pipeline",
|
|
109
|
+
category: "signature",
|
|
110
|
+
severity: "medium",
|
|
111
|
+
confidence: "high",
|
|
112
|
+
algorithm: "RSA",
|
|
113
|
+
hndl: false,
|
|
114
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
115
|
+
message:
|
|
116
|
+
"CI pipeline signs with Apple codesign (classical RSA signing identity); forgeable once a CRQC exists.",
|
|
117
|
+
remediation: "Classical only today; track Apple's PQC signing support and plan migration.",
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
re: /\bminisign\b/g,
|
|
122
|
+
meta: {
|
|
123
|
+
id: "ci-minisign",
|
|
124
|
+
title: "minisign (Ed25519)",
|
|
125
|
+
description: "minisign signing in a CI pipeline",
|
|
126
|
+
category: "signature",
|
|
127
|
+
severity: "low",
|
|
128
|
+
confidence: "high",
|
|
129
|
+
algorithm: "EdDSA",
|
|
130
|
+
hndl: false,
|
|
131
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
132
|
+
message:
|
|
133
|
+
"CI pipeline signs with minisign (Ed25519); modern but classical and forgeable once a CRQC exists.",
|
|
134
|
+
remediation: "Plan migration to ML-DSA-65 (FIPS 204) or SLH-DSA (FIPS 205).",
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
];
|
|
138
|
+
|
|
139
|
+
/** Detects classical artifact / code signing in CI/CD pipeline definitions. */
|
|
140
|
+
export const cicdDetector: Detector = {
|
|
141
|
+
id: "cicd-signing",
|
|
142
|
+
description: "Classical artifact / code signing in CI/CD pipelines",
|
|
143
|
+
scope: "config",
|
|
144
|
+
language: "any",
|
|
145
|
+
rules: CI_RULES.map((r) => r.meta),
|
|
146
|
+
appliesTo: isCiPipelineFile,
|
|
147
|
+
detect({ file, content }): Finding[] {
|
|
148
|
+
const findings: Finding[] = [];
|
|
149
|
+
for (const rule of CI_RULES) {
|
|
150
|
+
eachMatch(rule.re, content, (m) => {
|
|
151
|
+
findings.push(
|
|
152
|
+
findingFromRule(rule.meta, { file, content, index: m.index, matchLength: m[0].length }),
|
|
153
|
+
);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return findings;
|
|
157
|
+
},
|
|
158
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud-KMS SDK detector: classical asymmetric keys minted at RUNTIME through a
|
|
3
|
+
* cloud KMS SDK call — the application-code counterpart to the Terraform detector
|
|
4
|
+
* (which covers the infrastructure-as-code path). AWS KMS `CreateKey` /
|
|
5
|
+
* `GenerateDataKeyPair` select the key type with a `KeySpec` / `KeyPairSpec`
|
|
6
|
+
* (legacy `CustomerMasterKeySpec`) field whose value is `RSA_*` or `ECC_*`.
|
|
7
|
+
*
|
|
8
|
+
* These PascalCase field names + `RSA_2048` / `ECC_NIST_P256` values are specific
|
|
9
|
+
* to the AWS KMS API across every SDK language (JS/TS, Python/boto3, Java, Go,
|
|
10
|
+
* the CLI, JSON policies), so a single lexical rule catches them all with a very
|
|
11
|
+
* low false-positive rate. Terraform uses the snake_case `customer_master_key_spec`
|
|
12
|
+
* instead, so this never double-counts with the IaC detector.
|
|
13
|
+
*
|
|
14
|
+
* HNDL: an RSA KMS key (encryption/KEM) and an EC KMS key (which AWS KMS can use
|
|
15
|
+
* for ECDH key agreement as well as ECDSA signing) are both harvest-now-decrypt-
|
|
16
|
+
* later exposed → hndl:true.
|
|
17
|
+
*/
|
|
18
|
+
import type { Detector, Finding, RuleMeta } from "../types.js";
|
|
19
|
+
import { eachMatch, findingFromRule } from "../detect-utils.js";
|
|
20
|
+
import { CWE_BROKEN_CRYPTO } from "../cwe.js";
|
|
21
|
+
|
|
22
|
+
// The AWS KMS key-spec fields (CreateKey / GenerateDataKeyPair / legacy CMK). The
|
|
23
|
+
// optional `"?` after the field name accepts both the JS/HCL form (`KeySpec:`) and
|
|
24
|
+
// the JSON form where the key is quoted (`"KeySpec":`).
|
|
25
|
+
const SPEC_KEYS = "KeySpec|KeyPairSpec|CustomerMasterKeySpec";
|
|
26
|
+
const RE_KMS_RSA = new RegExp(`\\b(?:${SPEC_KEYS})"?\\s*[:=]\\s*['"]RSA_\\d+['"]`, "g");
|
|
27
|
+
const RE_KMS_EC = new RegExp(`\\b(?:${SPEC_KEYS})"?\\s*[:=]\\s*['"]ECC_[A-Z0-9_]+['"]`, "g");
|
|
28
|
+
|
|
29
|
+
const RULE_KMS_RSA: RuleMeta = {
|
|
30
|
+
id: "cloud-kms-rsa",
|
|
31
|
+
title: "AWS KMS RSA key",
|
|
32
|
+
description: "AWS KMS CreateKey / GenerateDataKeyPair with an RSA_* key spec",
|
|
33
|
+
category: "kem",
|
|
34
|
+
severity: "high",
|
|
35
|
+
confidence: "high",
|
|
36
|
+
algorithm: "RSA",
|
|
37
|
+
hndl: true,
|
|
38
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
39
|
+
message:
|
|
40
|
+
"Mints a classical RSA key via the AWS KMS SDK (harvest-now-decrypt-later exposed for encryption).",
|
|
41
|
+
remediation: "Plan migration to PQC as cloud KMS adds ML-KEM / ML-DSA key specs.",
|
|
42
|
+
};
|
|
43
|
+
const RULE_KMS_EC: RuleMeta = {
|
|
44
|
+
id: "cloud-kms-ec",
|
|
45
|
+
title: "AWS KMS EC key",
|
|
46
|
+
description: "AWS KMS CreateKey / GenerateDataKeyPair with an ECC_* key spec",
|
|
47
|
+
category: "key-exchange",
|
|
48
|
+
severity: "high",
|
|
49
|
+
confidence: "high",
|
|
50
|
+
algorithm: "ECDH",
|
|
51
|
+
hndl: true,
|
|
52
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
53
|
+
message:
|
|
54
|
+
"Mints a classical EC key via the AWS KMS SDK; EC keys feed ECDSA signatures and ECDH key agreement (the ECDH path is harvest-now-decrypt-later exposed).",
|
|
55
|
+
remediation:
|
|
56
|
+
"For key agreement: hybrid X25519MLKEM768 (ML-KEM-768). For signatures: ML-DSA-65 (FIPS 204).",
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/** Detects classical asymmetric keys provisioned via a cloud KMS SDK call. */
|
|
60
|
+
export const cloudKmsDetector: Detector = {
|
|
61
|
+
id: "cloud-kms",
|
|
62
|
+
description: "Classical asymmetric keys minted via a cloud KMS SDK (AWS KMS)",
|
|
63
|
+
scope: "config",
|
|
64
|
+
language: "any",
|
|
65
|
+
rules: [RULE_KMS_RSA, RULE_KMS_EC],
|
|
66
|
+
appliesTo: () => true,
|
|
67
|
+
detect({ file, content }): Finding[] {
|
|
68
|
+
// Fast reject: only proceed if a KMS key-spec field name is present.
|
|
69
|
+
if (
|
|
70
|
+
!content.includes("KeySpec") &&
|
|
71
|
+
!content.includes("KeyPairSpec") &&
|
|
72
|
+
!content.includes("CustomerMasterKeySpec")
|
|
73
|
+
) {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
const findings: Finding[] = [];
|
|
77
|
+
const add = (re: RegExp, rule: RuleMeta): void =>
|
|
78
|
+
eachMatch(re, content, (m) =>
|
|
79
|
+
findings.push(
|
|
80
|
+
findingFromRule(rule, { file, content, index: m.index, matchLength: m[0].length }),
|
|
81
|
+
),
|
|
82
|
+
);
|
|
83
|
+
add(RE_KMS_RSA, RULE_KMS_RSA);
|
|
84
|
+
add(RE_KMS_EC, RULE_KMS_EC);
|
|
85
|
+
return findings;
|
|
86
|
+
},
|
|
87
|
+
};
|