@quantakrypto/core 0.4.3 → 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 +9 -0
- package/dist/cbom-merge.d.ts.map +1 -0
- package/dist/cbom-merge.js +121 -0
- package/dist/cbom-merge.js.map +1 -0
- 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 +6 -26
- package/dist/comments.d.ts.map +1 -1
- package/dist/comments.js +77 -38
- 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 +59 -21
- package/dist/detect-utils.d.ts.map +1 -1
- package/dist/detect-utils.js +143 -8
- 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 +4 -2
- package/dist/detectors/c.d.ts.map +1 -1
- package/dist/detectors/c.js +222 -4
- 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 +129 -0
- package/dist/detectors/cicd.js.map +1 -0
- package/dist/detectors/cloud-kms.d.ts +24 -0
- package/dist/detectors/cloud-kms.d.ts.map +1 -0
- package/dist/detectors/cloud-kms.js +99 -0
- package/dist/detectors/cloud-kms.js.map +1 -0
- package/dist/detectors/cloudformation.d.ts +38 -0
- package/dist/detectors/cloudformation.d.ts.map +1 -0
- package/dist/detectors/cloudformation.js +201 -0
- package/dist/detectors/cloudformation.js.map +1 -0
- 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 +19 -0
- package/dist/detectors/database.d.ts.map +1 -0
- package/dist/detectors/database.js +97 -0
- package/dist/detectors/database.js.map +1 -0
- 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 +55 -0
- package/dist/detectors/dnssec.d.ts.map +1 -0
- package/dist/detectors/dnssec.js +116 -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 +227 -0
- package/dist/detectors/elixir.js.map +1 -0
- package/dist/detectors/java.d.ts.map +1 -1
- package/dist/detectors/java.js +34 -4
- 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 +72 -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 +131 -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 +88 -0
- package/dist/detectors/k8s.js.map +1 -0
- 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 +34 -0
- package/dist/detectors/mesh.d.ts.map +1 -0
- package/dist/detectors/mesh.js +91 -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 +79 -0
- package/dist/detectors/messaging.js.map +1 -0
- 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 +33 -1
- package/dist/detectors/pem.js.map +1 -1
- package/dist/detectors/php.d.ts +25 -0
- package/dist/detectors/php.d.ts.map +1 -0
- package/dist/detectors/php.js +171 -0
- package/dist/detectors/php.js.map +1 -0
- 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/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 +73 -0
- package/dist/detectors/rust.js.map +1 -1
- package/dist/detectors/secrets.d.ts +24 -0
- package/dist/detectors/secrets.d.ts.map +1 -0
- package/dist/detectors/secrets.js +63 -0
- package/dist/detectors/secrets.js.map +1 -0
- 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 +243 -53
- 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/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/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 +21 -0
- package/dist/detectors/terraform.d.ts.map +1 -0
- package/dist/detectors/terraform.js +150 -0
- package/dist/detectors/terraform.js.map +1 -0
- 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 +22 -0
- package/dist/detectors/vpn.d.ts.map +1 -0
- package/dist/detectors/vpn.js +73 -0
- package/dist/detectors/vpn.js.map +1 -0
- 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 +79 -4
- package/dist/evidence.d.ts.map +1 -1
- package/dist/evidence.js +76 -0
- package/dist/evidence.js.map +1 -1
- package/dist/index.d.ts +17 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -9
- 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/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 +9 -4
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +81 -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 +23 -2
- 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 +38 -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/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 +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 +146 -0
- package/src/cbom.ts +153 -39
- package/src/comments.ts +84 -39
- package/src/dependencies.ts +2 -1
- package/src/detect-utils.ts +146 -12
- 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 +240 -6
- package/src/detectors/cicd.ts +171 -0
- package/src/detectors/cloud-kms.ts +141 -0
- package/src/detectors/cloudformation.ts +250 -0
- 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 +141 -0
- package/src/detectors/dkim.ts +172 -0
- package/src/detectors/dnssec.ts +195 -0
- package/src/detectors/elixir.ts +268 -0
- package/src/detectors/java.ts +39 -4
- package/src/detectors/jose.ts +110 -0
- package/src/detectors/jwk.ts +170 -0
- package/src/detectors/k8s.ts +115 -0
- package/src/detectors/keystore.ts +109 -0
- package/src/detectors/mesh.ts +130 -0
- package/src/detectors/messaging.ts +106 -0
- package/src/detectors/objc.ts +209 -0
- package/src/detectors/openpgp.ts +194 -0
- package/src/detectors/pem.ts +31 -1
- package/src/detectors/php.ts +230 -0
- package/src/detectors/pkcs11.ts +113 -0
- package/src/detectors/proxy.ts +236 -0
- package/src/detectors/pulumi.ts +106 -0
- package/src/detectors/python.ts +71 -0
- package/src/detectors/rust.ts +76 -0
- package/src/detectors/secrets.ts +103 -0
- package/src/detectors/solidity.ts +176 -0
- package/src/detectors/source.ts +283 -73
- package/src/detectors/spire.ts +143 -0
- package/src/detectors/ssh-ca.ts +215 -0
- package/src/detectors/stateful-hbs.ts +9 -6
- package/src/detectors/supply-chain.ts +117 -0
- package/src/detectors/swift.ts +149 -0
- package/src/detectors/terraform.ts +188 -0
- package/src/detectors/vault.ts +120 -0
- package/src/detectors/vpn.ts +103 -0
- 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 +138 -4
- package/src/index.ts +50 -12
- package/src/inventory.ts +15 -7
- package/src/policy.ts +180 -0
- package/src/registry.ts +81 -4
- package/src/remediate-pipeline.ts +26 -3
- package/src/remediation.ts +39 -0
- package/src/report.ts +43 -1
- package/src/scan-worker.ts +5 -3
- package/src/scan.ts +41 -6
- package/src/standards-profiles.ts +136 -0
- package/src/standards.ts +186 -0
- package/src/types.ts +11 -4
- package/src/version.ts +1 -1
- package/src/vex.ts +122 -0
- package/src/walk.ts +33 -2
package/dist/evidence.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evidence.js","sourceRoot":"","sources":["../src/evidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAmCvC,mFAAmF;AACnF,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACzD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAgC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YACrE,GAAG,CAAC,CAAC,CAAC,GAAG,YAAY,CAAE,KAAiC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AASD;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAkB,EAClB,OAA+B,EAAE;IAEjC,MAAM,QAAQ,GAAsB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9D,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClD,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI;QACrB,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI;KACtB,CAAC,CAAC,CAAC;IAEJ,+EAA+E;IAC/E,wEAAwE;IACxE,+EAA+E;IAC/E,6EAA6E;IAC7E,MAAM,YAAY,GAAG;QACnB,UAAU,EAAE,wBAAwB;QACpC,WAAW,EAAE,CAAC;QACd,OAAO,EAAE;YACP,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,IAAI;YACnC,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI;YAC3B,WAAW,EAAE,MAAM,CAAC,IAAI;SACzB;QACD,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;QACzC,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,QAAQ;KACT,CAAC;IACF,MAAM,WAAW,GACf,SAAS;QACT,UAAU,CAAC,QAAQ,CAAC;aACjB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC;aAClD,MAAM,CAAC,KAAK,CAAC,CAAC;IAEnB,OAAO;QACL,GAAG,YAAY;QACf,OAAO,EAAE,EAAE,GAAG,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,UAAU,EAAE;QACpE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC;QACpB,WAAW,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;KAC5C,CAAC;AACvB,CAAC","sourcesContent":["/**\n * ISO/IEC 27001:2022 Annex A 8.24 evidence-chain export\n * (docs/compliance/iso27001-a8.24-evidence.md).\n *\n * Emits a self-describing readiness report bundling the scan result, crypto\n * inventory, and CycloneDX CBOM, plus an attestation carrying a DETERMINISTIC\n * content hash — the same scan over the same commit + config yields the same\n * hash (the volatile scan timestamp is deliberately excluded from the hashed\n * body). Signing + RFC-3161 timestamping are left to an EXTERNAL, vetted signer\n * (ADR-0004: this project performs no cryptography itself — it orchestrates a\n * signer, it does not implement one). SHA-256 here is an integrity hash (a Node\n * built-in), not an asymmetric primitive.\n *\n * Honesty boundary: this artifact is EVIDENCE for A.8.24, not the control. The\n * organization still owns the cryptography policy, key management, and the\n * conformance judgment. A clean scan is the absence of detected candidates, not\n * proof of quantum-safety (qScan is lexical). See docs/COMPLIANCE.md §3.\n */\nimport { createHash } from \"node:crypto\";\n\nimport type { ScanResult } from \"./types.js\";\nimport { toCbom } from \"./cbom.js\";\nimport { VERSION } from \"./version.js\";\n\n/** Stable per-finding record for the evidence body (deterministic per commit). */\nexport interface EvidenceFinding {\n ruleId: string;\n algorithm?: string;\n severity: string;\n hndl: boolean;\n file: string;\n line: number;\n}\n\nexport interface ReadinessReport {\n reportType: \"quantakrypto-readiness\";\n specVersion: 1;\n subject: {\n repository: string | null;\n commit: string | null;\n scannedRoot: string;\n scanTimeUtc: string;\n };\n tool: { name: \"qScan\"; version: string };\n inventory: ScanResult[\"inventory\"];\n findings: EvidenceFinding[];\n cbom: unknown;\n attestation: {\n /** sha256 over the canonicalized deterministic body (excludes scanTimeUtc). */\n contentHash: string;\n /** RFC-3161 / transparency-log token — filled by an external signer. */\n timestamp: null;\n /** Detached signature over `contentHash` — filled by an external signer. */\n signature: null;\n };\n}\n\n/** Canonical JSON: object keys sorted recursively, so the hash is reproducible. */\nfunction canonicalize(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalize);\n if (value && typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(value as Record<string, unknown>).sort()) {\n out[k] = canonicalize((value as Record<string, unknown>)[k]);\n }\n return out;\n }\n return value;\n}\n\nexport interface ReadinessReportOptions {\n /** Repository URL (e.g. from `GITHUB_REPOSITORY`); omitted → null. */\n repository?: string;\n /** Full commit SHA (e.g. from `GITHUB_SHA`); omitted → null. */\n commit?: string;\n}\n\n/**\n * Build the A.8.24 readiness report for a scan result. The attestation's\n * `contentHash` covers everything EXCEPT the scan timestamp and the attestation\n * block itself, so re-running the same scan on the same commit is verifiable.\n */\nexport function buildReadinessReport(\n result: ScanResult,\n opts: ReadinessReportOptions = {},\n): ReadinessReport {\n const findings: EvidenceFinding[] = result.findings.map((f) => ({\n ruleId: f.ruleId,\n ...(f.algorithm ? { algorithm: f.algorithm } : {}),\n severity: f.severity,\n hndl: f.hndl,\n file: f.location.file,\n line: f.location.line,\n }));\n\n // The CBOM is a deterministic *view* of the (hashed) findings + inventory, but\n // its CycloneDX envelope carries a volatile timestamp/serial — so it is\n // EXCLUDED from the hashed body (its integrity follows from its hashed inputs)\n // to keep the content hash reproducible across scan runs on the same commit.\n const hashableBody = {\n reportType: \"quantakrypto-readiness\",\n specVersion: 1,\n subject: {\n repository: opts.repository ?? null,\n commit: opts.commit ?? null,\n scannedRoot: result.root,\n },\n tool: { name: \"qScan\", version: VERSION },\n inventory: result.inventory,\n findings,\n };\n const contentHash =\n \"sha256:\" +\n createHash(\"sha256\")\n .update(JSON.stringify(canonicalize(hashableBody)))\n .digest(\"hex\");\n\n return {\n ...hashableBody,\n subject: { ...hashableBody.subject, scanTimeUtc: result.finishedAt },\n cbom: toCbom(result),\n attestation: { contentHash, timestamp: null, signature: null },\n } as ReadinessReport;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"evidence.js","sourceRoot":"","sources":["../src/evidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAiDjD,mFAAmF;AACnF,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACzD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAgC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YACrE,GAAG,CAAC,CAAC,CAAC,GAAG,YAAY,CAAE,KAAiC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAWD;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAkB,EAClB,OAA+B,EAAE;IAEjC,MAAM,QAAQ,GAAsB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9D,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClD,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI;QACrB,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI;KACtB,CAAC,CAAC,CAAC;IAEJ,+EAA+E;IAC/E,wEAAwE;IACxE,+EAA+E;IAC/E,6EAA6E;IAC7E,gFAAgF;IAChF,0EAA0E;IAC1E,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAEjG,MAAM,YAAY,GAAG;QACnB,UAAU,EAAE,wBAAwB;QACpC,WAAW,EAAE,CAAC;QACd,OAAO,EAAE;YACP,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,IAAI;YACnC,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI;YAC3B,WAAW,EAAE,MAAM,CAAC,IAAI;SACzB;QACD,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;QACzC,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,QAAQ;QACR,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5C,CAAC;IACF,MAAM,WAAW,GACf,SAAS;QACT,UAAU,CAAC,QAAQ,CAAC;aACjB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC;aAClD,MAAM,CAAC,KAAK,CAAC,CAAC;IAEnB,OAAO;QACL,GAAG,YAAY;QACf,OAAO,EAAE,EAAE,GAAG,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,UAAU,EAAE;QACpE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC;QACpB,WAAW,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;KAC5C,CAAC;AACvB,CAAC;AAcD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAuB;IAC3D,MAAM,YAAY,GAAG;QACnB,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,OAAO,EAAE;YACP,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU;YACrC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM;YAC7B,WAAW,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW;SACxC;QACD,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE;QAC9D,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACzE,CAAC;IACF,MAAM,YAAY,GAChB,SAAS;QACT,UAAU,CAAC,QAAQ,CAAC;aACjB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC;aAClD,MAAM,CAAC,KAAK,CAAC,CAAC;IACnB,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC;IACnD,IAAI,YAAY,KAAK,WAAW,EAAE,CAAC;QACjC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;IACpD,CAAC;IACD,OAAO;QACL,KAAK,EAAE,KAAK;QACZ,YAAY;QACZ,WAAW;QACX,MAAM,EAAE,wEAAwE;KACjF,CAAC;AACJ,CAAC;AAyBD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAuB,EACvB,IAAyB;IAEzB,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC;IAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC;IAC/F,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW;QAChC,CAAC,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC;QACtC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC;IACjC,OAAO;QACL,GAAG,MAAM;QACT,WAAW,EAAE;YACX,GAAG,MAAM,CAAC,WAAW;YACrB,SAAS;YACT,SAAS;YACT,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzD,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzE;KACF,CAAC;AACJ,CAAC","sourcesContent":["/**\n * ISO/IEC 27001:2022 Annex A 8.24 evidence-chain export\n * (docs/compliance/iso27001-a8.24-evidence.md).\n *\n * Emits a self-describing readiness report bundling the scan result, crypto\n * inventory, and CycloneDX CBOM, plus an attestation carrying a DETERMINISTIC\n * content hash — the same scan over the same commit + config yields the same\n * hash (the volatile scan timestamp is deliberately excluded from the hashed\n * body). Signing + RFC-3161 timestamping are left to an EXTERNAL, vetted signer\n * (ADR-0004: this project performs no cryptography itself — it orchestrates a\n * signer, it does not implement one). SHA-256 here is an integrity hash (a Node\n * built-in), not an asymmetric primitive.\n *\n * Honesty boundary: this artifact is EVIDENCE for A.8.24, not the control. The\n * organization still owns the cryptography policy, key management, and the\n * conformance judgment. A clean scan is the absence of detected candidates, not\n * proof of quantum-safety (qScan is lexical). See docs/COMPLIANCE.md §3.\n */\nimport { createHash } from \"node:crypto\";\n\nimport type { ScanResult } from \"./types.js\";\nimport { toCbom } from \"./cbom.js\";\nimport { VERSION } from \"./version.js\";\nimport { buildPolicyMapping } from \"./policy.js\";\nimport type { CryptoPolicy, PolicyMapping } from \"./policy.js\";\n\n/** Stable per-finding record for the evidence body (deterministic per commit). */\nexport interface EvidenceFinding {\n ruleId: string;\n algorithm?: string;\n severity: string;\n hndl: boolean;\n file: string;\n line: number;\n}\n\nexport interface ReadinessReport {\n reportType: \"quantakrypto-readiness\";\n specVersion: 1;\n subject: {\n repository: string | null;\n commit: string | null;\n scannedRoot: string;\n scanTimeUtc: string;\n };\n tool: { name: \"qScan\"; version: string };\n inventory: ScanResult[\"inventory\"];\n findings: EvidenceFinding[];\n /** §4 policy verdicts, present only when a crypto policy was supplied. */\n policyMapping?: PolicyMapping;\n cbom: unknown;\n attestation: {\n /** sha256 over the canonicalized deterministic body (excludes scanTimeUtc). */\n contentHash: string;\n /**\n * RFC-3161 / transparency-log token over `contentHash`, produced by an EXTERNAL\n * timestamper (opaque string, e.g. base64). `null` until {@link signReadinessReport}\n * runs one.\n */\n timestamp: string | null;\n /**\n * Detached signature over `contentHash`, produced by an EXTERNAL signer (opaque\n * string, e.g. base64/PEM). `null` until {@link signReadinessReport} runs one.\n */\n signature: string | null;\n /** Non-sensitive provenance label of the signer (e.g. \"openssl\", \"cosign\"). */\n signedWith?: string;\n /** Non-sensitive provenance label of the timestamper (e.g. \"openssl-ts\"). */\n timestampedWith?: string;\n };\n}\n\n/** Canonical JSON: object keys sorted recursively, so the hash is reproducible. */\nfunction canonicalize(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalize);\n if (value && typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(value as Record<string, unknown>).sort()) {\n out[k] = canonicalize((value as Record<string, unknown>)[k]);\n }\n return out;\n }\n return value;\n}\n\nexport interface ReadinessReportOptions {\n /** Repository URL (e.g. from `GITHUB_REPOSITORY`); omitted → null. */\n repository?: string;\n /** Full commit SHA (e.g. from `GITHUB_SHA`); omitted → null. */\n commit?: string;\n /** Optional org cryptography policy — adds the §4 `policyMapping` verdicts. */\n policy?: CryptoPolicy;\n}\n\n/**\n * Build the A.8.24 readiness report for a scan result. The attestation's\n * `contentHash` covers everything EXCEPT the scan timestamp and the attestation\n * block itself, so re-running the same scan on the same commit is verifiable.\n */\nexport function buildReadinessReport(\n result: ScanResult,\n opts: ReadinessReportOptions = {},\n): ReadinessReport {\n const findings: EvidenceFinding[] = result.findings.map((f) => ({\n ruleId: f.ruleId,\n ...(f.algorithm ? { algorithm: f.algorithm } : {}),\n severity: f.severity,\n hndl: f.hndl,\n file: f.location.file,\n line: f.location.line,\n }));\n\n // The CBOM is a deterministic *view* of the (hashed) findings + inventory, but\n // its CycloneDX envelope carries a volatile timestamp/serial — so it is\n // EXCLUDED from the hashed body (its integrity follows from its hashed inputs)\n // to keep the content hash reproducible across scan runs on the same commit.\n // §4: if the org supplied a crypto policy, attest the per-finding verdicts too.\n // Deterministic (same findings + policy → same mapping), so it is hashed.\n const policyMapping = opts.policy ? buildPolicyMapping(result.findings, opts.policy) : undefined;\n\n const hashableBody = {\n reportType: \"quantakrypto-readiness\",\n specVersion: 1,\n subject: {\n repository: opts.repository ?? null,\n commit: opts.commit ?? null,\n scannedRoot: result.root,\n },\n tool: { name: \"qScan\", version: VERSION },\n inventory: result.inventory,\n findings,\n ...(policyMapping ? { policyMapping } : {}),\n };\n const contentHash =\n \"sha256:\" +\n createHash(\"sha256\")\n .update(JSON.stringify(canonicalize(hashableBody)))\n .digest(\"hex\");\n\n return {\n ...hashableBody,\n subject: { ...hashableBody.subject, scanTimeUtc: result.finishedAt },\n cbom: toCbom(result),\n attestation: { contentHash, timestamp: null, signature: null },\n } as ReadinessReport;\n}\n\n/** The result of {@link verifyReadinessReport}. */\nexport interface VerifyReadinessResult {\n /** True iff the recomputed body hash equals the hash claimed in the attestation. */\n valid: boolean;\n /** The hash recomputed over the report's CURRENT body. */\n computedHash: string;\n /** The hash claimed in the report's attestation (`attestation.contentHash`). */\n claimedHash: string;\n /** A short human reason; present only when `valid` is false. */\n reason?: string;\n}\n\n/**\n * Recompute the deterministic content hash over a readiness report's body and\n * compare it to the hash the attestation claims. Detects tampering with ANY\n * hashed field — a finding, the inventory, a policy verdict, or subject/tool\n * metadata: editing it after the fact changes the recomputed hash, so `valid`\n * becomes false.\n *\n * By construction the scan timestamp, the CBOM envelope, and the attestation\n * block itself are EXCLUDED from the hash (see {@link buildReadinessReport}), so\n * touching those does not fail verification — their integrity follows from their\n * hashed inputs. The body is reconstructed from the report's OWN stored fields\n * (including `tool.version`), so a report built by an older qScan still verifies.\n *\n * This checks the INTEGRITY hash only. It does NOT validate the detached\n * signature or RFC-3161 timestamp: those are opaque tokens from an external\n * signer (ADR-0004) and are verified with that signer's own tooling.\n */\nexport function verifyReadinessReport(report: ReadinessReport): VerifyReadinessResult {\n const hashableBody = {\n reportType: report.reportType,\n specVersion: report.specVersion,\n subject: {\n repository: report.subject.repository,\n commit: report.subject.commit,\n scannedRoot: report.subject.scannedRoot,\n },\n tool: { name: report.tool.name, version: report.tool.version },\n inventory: report.inventory,\n findings: report.findings,\n ...(report.policyMapping ? { policyMapping: report.policyMapping } : {}),\n };\n const computedHash =\n \"sha256:\" +\n createHash(\"sha256\")\n .update(JSON.stringify(canonicalize(hashableBody)))\n .digest(\"hex\");\n const claimedHash = report.attestation.contentHash;\n if (computedHash === claimedHash) {\n return { valid: true, computedHash, claimedHash };\n }\n return {\n valid: false,\n computedHash,\n claimedHash,\n reason: \"content-hash mismatch: the report body was modified after it was built\",\n };\n}\n\n/**\n * An EXTERNAL signer/timestamper the tool orchestrates. Per ADR-0004 the tool\n * implements no cryptography: it hands the payload to an operator-provided signer\n * (an `openssl`/`cosign` invocation, an RFC-3161 TSA client, …) and records what\n * comes back. `label` is a short, non-sensitive provenance string (e.g. the signer\n * program name) — NOT the full command, which may contain a key path.\n */\nexport interface EvidenceSigner {\n label: string;\n /**\n * Produce a detached signature / timestamp token (opaque string) over `payload`.\n * May be async so a future signer can shell out OR call a KMS / RFC-3161 TSA over\n * the network without foreclosing that once this contract freezes at 1.0.\n */\n sign(payload: string): string | Promise<string>;\n}\n\n/** Options for {@link signReadinessReport}: a detached-signature and/or a timestamp signer. */\nexport interface SignEvidenceOptions {\n signer?: EvidenceSigner;\n timestamper?: EvidenceSigner;\n}\n\n/**\n * Fill a readiness report's attestation with a detached signature and/or RFC-3161\n * timestamp, produced by EXTERNAL signers over the report's `contentHash`. Pure\n * orchestration: it invokes the injected signers and records their opaque output\n * plus a provenance label — it performs no cryptography itself (ADR-0004). Returns a\n * NEW report; the hashed body is untouched (attestation is excluded from the hash),\n * so signing never changes `contentHash`.\n */\nexport async function signReadinessReport(\n report: ReadinessReport,\n opts: SignEvidenceOptions,\n): Promise<ReadinessReport> {\n const payload = report.attestation.contentHash;\n const signature = opts.signer ? await opts.signer.sign(payload) : report.attestation.signature;\n const timestamp = opts.timestamper\n ? await opts.timestamper.sign(payload)\n : report.attestation.timestamp;\n return {\n ...report,\n attestation: {\n ...report.attestation,\n signature,\n timestamp,\n ...(opts.signer ? { signedWith: opts.signer.label } : {}),\n ...(opts.timestamper ? { timestampedWith: opts.timestamper.label } : {}),\n },\n };\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -28,27 +28,35 @@ export { configToggleCodemod } from "./codemods/config-toggle.js";
|
|
|
28
28
|
export { remediateFindings } from "./remediate-pipeline.js";
|
|
29
29
|
export type { RemediateOptions, RemediationResult, VerifiedPatch, RejectedPatch, } from "./remediate-pipeline.js";
|
|
30
30
|
export { AbortError, BudgetExceededError } from "./errors.js";
|
|
31
|
-
export { scanParallel
|
|
32
|
-
export type { ScanChunk
|
|
33
|
-
export { DetectorRegistry, defaultRegistry
|
|
34
|
-
export type { RuleCatalogEntry } from "./registry.js";
|
|
31
|
+
export { scanParallel } from "./parallel.js";
|
|
32
|
+
export type { ScanChunk } from "./parallel.js";
|
|
33
|
+
export { DetectorRegistry, defaultRegistry } from "./registry.js";
|
|
35
34
|
export { fingerprintFinding, baselineFromFindings, applyBaseline, loadBaseline, saveBaseline, BASELINE_VERSION, } from "./baseline.js";
|
|
36
35
|
export type { Baseline } from "./baseline.js";
|
|
37
36
|
export { changedFiles } from "./changed.js";
|
|
38
37
|
export { loadConfig, ConfigError, CONFIG_FILENAME } from "./config.js";
|
|
39
38
|
export type { QuantakryptoFileConfig, LoadConfigResult } from "./config.js";
|
|
40
|
-
export { walkFiles, isBinaryPath,
|
|
39
|
+
export { walkFiles, isBinaryPath, looksMinified } from "./walk.js";
|
|
41
40
|
export { isAnalyzableSource, ANALYZABLE_SOURCE_EXTENSIONS, ANALYZABLE_LANGUAGES_LABEL, } from "./detect-utils.js";
|
|
42
41
|
export { buildInventory } from "./inventory.js";
|
|
43
42
|
export { vulnerableDependencies, DEP_VULNERABLE_RULE, isManifestFile } from "./dependencies.js";
|
|
44
43
|
export { SEVERITY_ORDER, severityRank, meetsThreshold, sarifLevel } from "./severity.js";
|
|
45
|
-
export { toSarif, toJson, formatSummary, formatTierGuidance } from "./report.js";
|
|
44
|
+
export { toSarif, toJson, formatSummary, formatTierGuidance, formatProfileGuidance, } from "./report.js";
|
|
46
45
|
export type { ReportOptions } from "./report.js";
|
|
47
46
|
export { toCbom } from "./cbom.js";
|
|
48
47
|
export type { CycloneDxBom, CbomComponent } from "./cbom.js";
|
|
49
|
-
export {
|
|
50
|
-
export
|
|
51
|
-
export {
|
|
48
|
+
export { mergeCboms } from "./cbom-merge.js";
|
|
49
|
+
export { toOpenVex } from "./vex.js";
|
|
50
|
+
export type { OpenVexDocument, OpenVexStatement, OpenVexOptions } from "./vex.js";
|
|
51
|
+
export { buildReadinessReport, signReadinessReport, verifyReadinessReport } from "./evidence.js";
|
|
52
|
+
export type { ReadinessReport, EvidenceFinding, ReadinessReportOptions, EvidenceSigner, SignEvidenceOptions, VerifyReadinessResult, } from "./evidence.js";
|
|
53
|
+
export { buildPolicyMapping, parseCryptoPolicy } from "./policy.js";
|
|
54
|
+
export type { CryptoPolicy, PolicyVerdict, PolicyMapping, PolicyFindingVerdict } from "./policy.js";
|
|
55
|
+
export { remediationFor, remediationForTier, remediationForProfile, TIER_PARAMS, STATEFUL_HBS_NOTE, PQC_TRANSITION_NOTE, statefulHbsApplies, } from "./remediation.js";
|
|
52
56
|
export type { SecurityTier } from "./remediation.js";
|
|
57
|
+
export { PQC_STANDARDS } from "./standards.js";
|
|
58
|
+
export type { PqcStandards, StandardsCitation, StandardsReviewStatus } from "./standards.js";
|
|
59
|
+
export { STANDARDS_PROFILES, DEFAULT_PROFILE_ID, standardsProfileIds, getStandardsProfile, defaultStandardsProfile, } from "./standards-profiles.js";
|
|
60
|
+
export type { StandardsProfile, HybridStance } from "./standards-profiles.js";
|
|
53
61
|
export { CWE_BROKEN_CRYPTO, CWE_WEAK_STRENGTH, CWE_CERT_VALIDATION, CWE_HARDCODED_KEY, CWE_RISKY_PRIMITIVE, } from "./cwe.js";
|
|
54
62
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,cAAc,YAAY,CAAC;AAG3B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG5C,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGzE,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC7D,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,YAAY,EACV,YAAY,EACZ,eAAe,EACf,aAAa,EACb,KAAK,EACL,WAAW,GACZ,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACvF,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACrE,YAAY,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,aAAa,GACd,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -24,10 +24,12 @@ export { configToggleCodemod } from "./codemods/config-toggle.js";
|
|
|
24
24
|
export { remediateFindings } from "./remediate-pipeline.js";
|
|
25
25
|
// Scan cancellation / work-budget errors.
|
|
26
26
|
export { AbortError, BudgetExceededError } from "./errors.js";
|
|
27
|
-
// Parallel scanning (worker_threads pool)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
// Parallel scanning (worker_threads pool). The chunk/merge helpers and their
|
|
28
|
+
// SizedFile/ChunkResult types are internal plumbing (not part of the public API).
|
|
29
|
+
export { scanParallel } from "./parallel.js";
|
|
30
|
+
// Detector registry (plugin point). `detectorScope` and the rule-catalog type are
|
|
31
|
+
// internal.
|
|
32
|
+
export { DetectorRegistry, defaultRegistry } from "./registry.js";
|
|
31
33
|
// Canonical baseline (shared by qScan + the Action).
|
|
32
34
|
export { fingerprintFinding, baselineFromFindings, applyBaseline, loadBaseline, saveBaseline, BASELINE_VERSION, } from "./baseline.js";
|
|
33
35
|
// Incremental scanning: changed-files helper (git-aware, tolerant).
|
|
@@ -35,7 +37,7 @@ export { changedFiles } from "./changed.js";
|
|
|
35
37
|
// Optional `quantakrypto.config.json` loader (P2-9; see docs/CONFIG.md).
|
|
36
38
|
export { loadConfig, ConfigError, CONFIG_FILENAME } from "./config.js";
|
|
37
39
|
// Filesystem walker (relative POSIX paths, default ignores, size/binary filters).
|
|
38
|
-
export { walkFiles, isBinaryPath,
|
|
40
|
+
export { walkFiles, isBinaryPath, looksMinified } from "./walk.js";
|
|
39
41
|
// Analyzable-language coverage (which source languages the scanner inspects).
|
|
40
42
|
export { isAnalyzableSource, ANALYZABLE_SOURCE_EXTENSIONS, ANALYZABLE_LANGUAGES_LABEL, } from "./detect-utils.js";
|
|
41
43
|
// Inventory + readiness score.
|
|
@@ -47,13 +49,23 @@ export { vulnerableDependencies, DEP_VULNERABLE_RULE, isManifestFile } from "./d
|
|
|
47
49
|
// Severity utilities (ordering, threshold, SARIF level) — shared across tools.
|
|
48
50
|
export { SEVERITY_ORDER, severityRank, meetsThreshold, sarifLevel } from "./severity.js";
|
|
49
51
|
// Reporters.
|
|
50
|
-
export { toSarif, toJson, formatSummary, formatTierGuidance } from "./report.js";
|
|
52
|
+
export { toSarif, toJson, formatSummary, formatTierGuidance, formatProfileGuidance, } from "./report.js";
|
|
51
53
|
// CycloneDX 1.6 cryptographic bill of materials (CBOM) export.
|
|
52
54
|
export { toCbom } from "./cbom.js";
|
|
55
|
+
// Merge multiple CBOMs (code + infra + live endpoints) into one combined BOM.
|
|
56
|
+
export { mergeCboms } from "./cbom-merge.js";
|
|
57
|
+
// OpenVEX 0.2.0 export — quantum-readiness posture as VEX statements.
|
|
58
|
+
export { toOpenVex } from "./vex.js";
|
|
53
59
|
// ISO/IEC 27001 A.8.24 evidence-chain readiness report.
|
|
54
|
-
export { buildReadinessReport } from "./evidence.js";
|
|
55
|
-
//
|
|
56
|
-
export {
|
|
60
|
+
export { buildReadinessReport, signReadinessReport, verifyReadinessReport } from "./evidence.js";
|
|
61
|
+
// Cryptography policy → per-finding verdicts (A.8.24 evidence §4).
|
|
62
|
+
export { buildPolicyMapping, parseCryptoPolicy } from "./policy.js";
|
|
63
|
+
// Remediation lookup (family + tier-aware + profile-aware) and stateful-HBS guidance.
|
|
64
|
+
export { remediationFor, remediationForTier, remediationForProfile, TIER_PARAMS, STATEFUL_HBS_NOTE, PQC_TRANSITION_NOTE, statefulHbsApplies, } from "./remediation.js";
|
|
65
|
+
// Post-quantum standards source of truth + review cadence.
|
|
66
|
+
export { PQC_STANDARDS } from "./standards.js";
|
|
67
|
+
// Selectable standards regime profiles (NIST / CNSA / BSI / ANSSI / NCSC).
|
|
68
|
+
export { STANDARDS_PROFILES, DEFAULT_PROFILE_ID, standardsProfileIds, getStandardsProfile, defaultStandardsProfile, } from "./standards-profiles.js";
|
|
57
69
|
// CWE identifier constants.
|
|
58
70
|
export { CWE_BROKEN_CRYPTO, CWE_WEAK_STRENGTH, CWE_CERT_VALIDATION, CWE_HARDCODED_KEY, CWE_RISKY_PRIMITIVE, } from "./cwe.js";
|
|
59
71
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,cAAc,YAAY,CAAC;AAE3B,qEAAqE;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAKvC,8CAA8C;AAC9C,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEzE,2EAA2E;AAC3E,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAW7D,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEvF,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAErE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAQ5D,0CAA0C;AAC1C,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE9D,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @quantakrypto/core — public API (LOCKED CONTRACT).\n *\n * The exported NAMES and SIGNATURES below are the stable contract that\n * @quantakrypto/qscan, @quantakrypto/mcp and the GitHub Action depend on — do not change\n * them without updating all consumers. The implementations live in focused\n * modules under src/ and are re-exported here; the public surface is identical\n * to the original stub file.\n */\nexport * from \"./types.js\";\n\n// Tool version, surfaced in reports. Keep in sync with package.json.\nexport { VERSION } from \"./version.js\";\n\n// Minimal SARIF 2.1.0 log shape, defined alongside the reporters.\nexport type { SarifLog } from \"./report.js\";\n\n// Core orchestration + built-in detector set.\nexport { scan, detectors, detectFile, compareFindings } from \"./scan.js\";\n\n// Snippet-level fix verification (shared by MCP verify_fix + remediation).\nexport { verifyFix, languageToExtension } from \"./verify.js\";\nexport type { VerifyResult } from \"./verify.js\";\n\n// Agent-plane shared types + the context redactor (offline; reused by MCP).\nexport type {\n ContextLevel,\n RedactedContext,\n TriageVerdict,\n Patch,\n FixProposal,\n} from \"./agent-types.js\";\nexport { buildContext, renderPreflight } from \"./redact.js\";\nexport { TRIAGE_RUBRIC, TRIAGE_VERDICT_SCHEMA, buildTriageRequest } from \"./triage.js\";\nexport type { TriageRequest } from \"./triage.js\";\nexport {\n REMEDIATE_RUBRIC,\n FIX_REQUEST_SCHEMA,\n buildRemediateRequest,\n} from \"./remediate-request.js\";\nexport type { RemediateRequest } from \"./remediate-request.js\";\nexport { checkPatchPolicy } from \"./patch-policy.js\";\nexport type { PolicyContext, PolicyDecision } from \"./patch-policy.js\";\nexport { withWorktree } from \"./worktree.js\";\nexport { codemodRegistry, codemodFor } from \"./codemods/registry.js\";\nexport type { Codemod } from \"./codemods/registry.js\";\nexport { configToggleCodemod } from \"./codemods/config-toggle.js\";\nexport { remediateFindings } from \"./remediate-pipeline.js\";\nexport type {\n RemediateOptions,\n RemediationResult,\n VerifiedPatch,\n RejectedPatch,\n} from \"./remediate-pipeline.js\";\n\n// Scan cancellation / work-budget errors.\nexport { AbortError, BudgetExceededError } from \"./errors.js\";\n\n// Parallel scanning (worker_threads pool). The chunk/merge helpers and their\n// SizedFile/ChunkResult types are internal plumbing (not part of the public API).\nexport { scanParallel } from \"./parallel.js\";\nexport type { ScanChunk } from \"./parallel.js\";\n\n// Detector registry (plugin point). `detectorScope` and the rule-catalog type are\n// internal.\nexport { DetectorRegistry, defaultRegistry } from \"./registry.js\";\n\n// Canonical baseline (shared by qScan + the Action).\nexport {\n fingerprintFinding,\n baselineFromFindings,\n applyBaseline,\n loadBaseline,\n saveBaseline,\n BASELINE_VERSION,\n} from \"./baseline.js\";\nexport type { Baseline } from \"./baseline.js\";\n\n// Incremental scanning: changed-files helper (git-aware, tolerant).\nexport { changedFiles } from \"./changed.js\";\n\n// Optional `quantakrypto.config.json` loader (P2-9; see docs/CONFIG.md).\nexport { loadConfig, ConfigError, CONFIG_FILENAME } from \"./config.js\";\nexport type { QuantakryptoFileConfig, LoadConfigResult } from \"./config.js\";\n\n// Filesystem walker (relative POSIX paths, default ignores, size/binary filters).\nexport { walkFiles, isBinaryPath, looksMinified } from \"./walk.js\";\n\n// Analyzable-language coverage (which source languages the scanner inspects).\nexport {\n isAnalyzableSource,\n ANALYZABLE_SOURCE_EXTENSIONS,\n ANALYZABLE_LANGUAGES_LABEL,\n} from \"./detect-utils.js\";\n\n// Inventory + readiness score.\nexport { buildInventory } from \"./inventory.js\";\n\n// Vulnerable-dependency database (the manifest scanner is used internally by scan()).\n// `DEP_VULNERABLE_RULE` is the generic catalog entry for dependency findings\n// (which don't come from a Detector, so aren't in the registry's rule catalog).\nexport { vulnerableDependencies, DEP_VULNERABLE_RULE, isManifestFile } from \"./dependencies.js\";\n\n// Severity utilities (ordering, threshold, SARIF level) — shared across tools.\nexport { SEVERITY_ORDER, severityRank, meetsThreshold, sarifLevel } from \"./severity.js\";\n\n// Reporters.\nexport {\n toSarif,\n toJson,\n formatSummary,\n formatTierGuidance,\n formatProfileGuidance,\n} from \"./report.js\";\nexport type { ReportOptions } from \"./report.js\";\n\n// CycloneDX 1.6 cryptographic bill of materials (CBOM) export.\nexport { toCbom } from \"./cbom.js\";\nexport type { CycloneDxBom, CbomComponent } from \"./cbom.js\";\n// Merge multiple CBOMs (code + infra + live endpoints) into one combined BOM.\nexport { mergeCboms } from \"./cbom-merge.js\";\n// OpenVEX 0.2.0 export — quantum-readiness posture as VEX statements.\nexport { toOpenVex } from \"./vex.js\";\nexport type { OpenVexDocument, OpenVexStatement, OpenVexOptions } from \"./vex.js\";\n// ISO/IEC 27001 A.8.24 evidence-chain readiness report.\nexport { buildReadinessReport, signReadinessReport, verifyReadinessReport } from \"./evidence.js\";\nexport type {\n ReadinessReport,\n EvidenceFinding,\n ReadinessReportOptions,\n EvidenceSigner,\n SignEvidenceOptions,\n VerifyReadinessResult,\n} from \"./evidence.js\";\n\n// Cryptography policy → per-finding verdicts (A.8.24 evidence §4).\nexport { buildPolicyMapping, parseCryptoPolicy } from \"./policy.js\";\nexport type { CryptoPolicy, PolicyVerdict, PolicyMapping, PolicyFindingVerdict } from \"./policy.js\";\n\n// Remediation lookup (family + tier-aware + profile-aware) and stateful-HBS guidance.\nexport {\n remediationFor,\n remediationForTier,\n remediationForProfile,\n TIER_PARAMS,\n STATEFUL_HBS_NOTE,\n PQC_TRANSITION_NOTE,\n statefulHbsApplies,\n} from \"./remediation.js\";\nexport type { SecurityTier } from \"./remediation.js\";\n\n// Post-quantum standards source of truth + review cadence.\nexport { PQC_STANDARDS } from \"./standards.js\";\nexport type { PqcStandards, StandardsCitation, StandardsReviewStatus } from \"./standards.js\";\n\n// Selectable standards regime profiles (NIST / CNSA / BSI / ANSSI / NCSC).\nexport {\n STANDARDS_PROFILES,\n DEFAULT_PROFILE_ID,\n standardsProfileIds,\n getStandardsProfile,\n defaultStandardsProfile,\n} from \"./standards-profiles.js\";\nexport type { StandardsProfile, HybridStance } from \"./standards-profiles.js\";\n\n// CWE identifier constants.\nexport {\n CWE_BROKEN_CRYPTO,\n CWE_WEAK_STRENGTH,\n CWE_CERT_VALIDATION,\n CWE_HARDCODED_KEY,\n CWE_RISKY_PRIMITIVE,\n} from \"./cwe.js\";\n"]}
|
package/dist/inventory.d.ts
CHANGED
|
@@ -4,8 +4,6 @@
|
|
|
4
4
|
* and a 0–100 readiness score.
|
|
5
5
|
*/
|
|
6
6
|
import type { CryptoInventory, Finding } from "./types.js";
|
|
7
|
-
/** True when a finding's file path is test / fixture / example / documentation. */
|
|
8
|
-
export declare function isTestOrFixturePath(file: string): boolean;
|
|
9
7
|
/**
|
|
10
8
|
* Compute a 0–100 readiness score. 100 means no classical asymmetric crypto was
|
|
11
9
|
* found. Findings accrue a severity-weighted penalty (with per-bucket diminishing
|
package/dist/inventory.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inventory.d.ts","sourceRoot":"","sources":["../src/inventory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAEV,eAAe,EACf,OAAO,EAGR,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"inventory.d.ts","sourceRoot":"","sources":["../src/inventory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAEV,eAAe,EACf,OAAO,EAGR,MAAM,YAAY,CAAC;AAuDpB;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CA4B1D;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,eAAe,CAgCnE"}
|
package/dist/inventory.js
CHANGED
|
@@ -30,7 +30,7 @@ const SCORE_SCALE = 100;
|
|
|
30
30
|
*/
|
|
31
31
|
const TEST_PATH_WEIGHT = 0.15;
|
|
32
32
|
/** True when a finding's file path is test / fixture / example / documentation. */
|
|
33
|
-
|
|
33
|
+
function isTestOrFixturePath(file) {
|
|
34
34
|
const f = file.toLowerCase().replace(/\\/g, "/");
|
|
35
35
|
if (/(?:^|\/)(?:tests?|__tests__|testdata|test-data|fixtures?|examples?|demos?|samples?|specs?|mocks?|docs?|benchmarks?|e2e)\//.test(f)) {
|
|
36
36
|
return true;
|
|
@@ -55,18 +55,27 @@ export function isTestOrFixturePath(file) {
|
|
|
55
55
|
export function readinessScore(findings) {
|
|
56
56
|
if (findings.length === 0)
|
|
57
57
|
return 100;
|
|
58
|
-
|
|
58
|
+
// Diminishing-returns occurrence counters, kept SEPARATE for full-weight vs
|
|
59
|
+
// test-path findings. Sharing one counter per severity let whichever finding came
|
|
60
|
+
// first in the (path-sorted) list claim the `1/√1` slot, so a directory rename — or
|
|
61
|
+
// a test finding sorting ahead of a real one — changed the score. Bucketing makes
|
|
62
|
+
// the penalty independent of file order and of test/real interleaving.
|
|
63
|
+
const zero = () => ({
|
|
59
64
|
critical: 0,
|
|
60
65
|
high: 0,
|
|
61
66
|
medium: 0,
|
|
62
67
|
low: 0,
|
|
63
68
|
info: 0,
|
|
64
|
-
};
|
|
69
|
+
});
|
|
70
|
+
const seenReal = zero();
|
|
71
|
+
const seenTest = zero();
|
|
65
72
|
let penalty = 0;
|
|
66
73
|
for (const f of findings) {
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
|
|
74
|
+
const isTest = isTestOrFixturePath(f.location.file);
|
|
75
|
+
const bucket = isTest ? seenTest : seenReal;
|
|
76
|
+
bucket[f.severity] += 1;
|
|
77
|
+
const weight = SEVERITY_WEIGHT[f.severity] * (isTest ? TEST_PATH_WEIGHT : 1);
|
|
78
|
+
penalty += penaltyFor(weight, bucket[f.severity]);
|
|
70
79
|
}
|
|
71
80
|
return Math.max(0, Math.min(100, Math.round(100 * Math.exp(-penalty / SCORE_SCALE))));
|
|
72
81
|
}
|
package/dist/inventory.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inventory.js","sourceRoot":"","sources":["../src/inventory.ts"],"names":[],"mappings":"AAaA,4EAA4E;AAC5E,MAAM,UAAU,GAAe,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAE7E,uFAAuF;AACvF,MAAM,eAAe,GAA6B;IAChD,QAAQ,EAAE,EAAE;IACZ,IAAI,EAAE,EAAE;IACR,MAAM,EAAE,CAAC;IACT,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,CAAC;CACR,CAAC;AAEF;;;;;GAKG;AACH,SAAS,UAAU,CAAC,MAAc,EAAE,UAAkB;IACpD,OAAO,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACxC,CAAC;AAED,wEAAwE;AACxE,MAAM,WAAW,GAAG,GAAG,CAAC;AAExB;;;;;;;;GAQG;AACH,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAE9B,mFAAmF;AACnF,
|
|
1
|
+
{"version":3,"file":"inventory.js","sourceRoot":"","sources":["../src/inventory.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Aggregates findings into a {@link CryptoInventory}: per-algorithm,\n * per-category and per-severity counts, the harvest-now-decrypt-later count,\n * and a 0–100 readiness score.\n */\nimport type {\n AlgorithmFamily,\n CryptoInventory,\n Finding,\n FindingCategory,\n Severity,\n} from \"./types.js\";\n\n/** All severities, most → least severe (used to seed the counts record). */\nconst SEVERITIES: Severity[] = [\"critical\", \"high\", \"medium\", \"low\", \"info\"];\n\n/** Base penalty applied to the readiness score for the first finding of a severity. */\nconst SEVERITY_WEIGHT: Record<Severity, number> = {\n critical: 30,\n high: 18,\n medium: 8,\n low: 3,\n info: 1,\n};\n\n/**\n * Apply diminishing returns to repeated findings of the same severity: the Nth\n * finding contributes `weight / sqrt(N)`. This keeps a single critical hit very\n * impactful while a codebase with hundreds of medium findings doesn't underflow\n * past zero on the first few — the score still saturates toward 0 sensibly.\n */\nfunction penaltyFor(weight: number, occurrence: number): number {\n return weight / Math.sqrt(occurrence);\n}\n\n/** Decay constant for the readiness score (larger = more forgiving). */\nconst SCORE_SCALE = 100;\n\n/**\n * Fraction of the normal penalty a finding in test/fixture/example/doc code\n * contributes to the readiness score. Such findings are almost always test\n * vectors, sample keys, or the library's own algorithm enumerations — accurate\n * detections, but not the deployed crypto whose migration the score is meant to\n * track. Real-repo runs showed 60–77% of findings live in these paths, which\n * dragged the score of no-real-crypto codebases down unfairly. They still appear\n * in the inventory counts in full; only their *score* weight is reduced.\n */\nconst TEST_PATH_WEIGHT = 0.15;\n\n/** True when a finding's file path is test / fixture / example / documentation. */\nfunction isTestOrFixturePath(file: string): boolean {\n const f = file.toLowerCase().replace(/\\\\/g, \"/\");\n if (\n /(?:^|\\/)(?:tests?|__tests__|testdata|test-data|fixtures?|examples?|demos?|samples?|specs?|mocks?|docs?|benchmarks?|e2e)\\//.test(\n f,\n )\n ) {\n return true;\n }\n const base = f.slice(f.lastIndexOf(\"/\") + 1);\n if (/(?:^|[_.-])(?:test|spec)\\.[a-z0-9]+$/.test(base)) return true; // test.go, foo_test.go, foo.test.ts\n if (/^test_[^/]+\\.py$/.test(base)) return true; // python test_foo.py\n if (/^changelog/.test(base) || /\\.(?:md|markdown|rst|adoc|asciidoc)$/.test(base)) return true;\n return false;\n}\n\n/**\n * Compute a 0–100 readiness score. 100 means no classical asymmetric crypto was\n * found. Findings accrue a severity-weighted penalty (with per-bucket diminishing\n * returns), then the score is `100 * e^(-penalty/scale)`. Exponential decay keeps\n * the score responsive across the whole range — fixing findings always raises it,\n * and a large legacy repo lands low without pinning flat at 0 (which made progress\n * invisible under the old linear model). Tuned so one low ~97, one critical ~74.\n */\nexport function readinessScore(findings: Finding[]): number {\n if (findings.length === 0) return 100;\n\n // Diminishing-returns occurrence counters, kept SEPARATE for full-weight vs\n // test-path findings. Sharing one counter per severity let whichever finding came\n // first in the (path-sorted) list claim the `1/√1` slot, so a directory rename — or\n // a test finding sorting ahead of a real one — changed the score. Bucketing makes\n // the penalty independent of file order and of test/real interleaving.\n const zero = (): Record<Severity, number> => ({\n critical: 0,\n high: 0,\n medium: 0,\n low: 0,\n info: 0,\n });\n const seenReal = zero();\n const seenTest = zero();\n\n let penalty = 0;\n for (const f of findings) {\n const isTest = isTestOrFixturePath(f.location.file);\n const bucket = isTest ? seenTest : seenReal;\n bucket[f.severity] += 1;\n const weight = SEVERITY_WEIGHT[f.severity] * (isTest ? TEST_PATH_WEIGHT : 1);\n penalty += penaltyFor(weight, bucket[f.severity]);\n }\n\n return Math.max(0, Math.min(100, Math.round(100 * Math.exp(-penalty / SCORE_SCALE))));\n}\n\n/** Build the full inventory (counts + HNDL + score) from a set of findings. */\nexport function buildInventory(findings: Finding[]): CryptoInventory {\n const byAlgorithm: Partial<Record<AlgorithmFamily, number>> = {};\n const byCategory: Partial<Record<FindingCategory, number>> = {};\n const bySeverity: Record<Severity, number> = {\n critical: 0,\n high: 0,\n medium: 0,\n low: 0,\n info: 0,\n };\n let hndlCount = 0;\n\n for (const f of findings) {\n if (f.algorithm) {\n byAlgorithm[f.algorithm] = (byAlgorithm[f.algorithm] ?? 0) + 1;\n }\n byCategory[f.category] = (byCategory[f.category] ?? 0) + 1;\n bySeverity[f.severity] += 1;\n if (f.hndl) hndlCount += 1;\n }\n\n // Ensure all severities are present (seeded above to 0). SEVERITIES is the\n // canonical ordering and guards against missing keys if the type changes.\n void SEVERITIES;\n\n return {\n byAlgorithm,\n byCategory,\n bySeverity,\n hndlCount,\n readinessScore: readinessScore(findings),\n };\n}\n"]}
|
package/dist/policy.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Machine-readable cryptography policy → per-finding verdicts for the ISO/IEC
|
|
3
|
+
* 27001 A.8.24 evidence report (docs/compliance/iso27001-a8.24-evidence.md §4).
|
|
4
|
+
*
|
|
5
|
+
* An organization supplies a policy listing which classical algorithm families it
|
|
6
|
+
* prohibits, permits, or is actively transitioning off. `buildPolicyMapping` then
|
|
7
|
+
* flags each qScan finding as `conformant` / `violation` / `transition-pending`
|
|
8
|
+
* against that policy — turning the neutral inventory into audit-ready evidence
|
|
9
|
+
* that the org *assesses* its cryptography against a defined policy.
|
|
10
|
+
*
|
|
11
|
+
* Honesty boundary: without a policy the report stays neutral inventory and the
|
|
12
|
+
* ORG owns the conformance judgment (COMPLIANCE.md §3). The policy is a permit-
|
|
13
|
+
* list: a classical family not named anywhere defaults to a violation (unmanaged
|
|
14
|
+
* crypto is a policy gap), overridable via `defaultVerdict`.
|
|
15
|
+
*/
|
|
16
|
+
import type { AlgorithmFamily, Finding } from "./types.js";
|
|
17
|
+
/** The three verdicts a finding can carry against a policy. */
|
|
18
|
+
export type PolicyVerdict = "conformant" | "violation" | "transition-pending";
|
|
19
|
+
/** An organization-supplied cryptography policy (from a JSON file). */
|
|
20
|
+
export interface CryptoPolicy {
|
|
21
|
+
/** Human name / version of the policy, recorded in the evidence report. */
|
|
22
|
+
name?: string;
|
|
23
|
+
/** Families the org explicitly accepts (e.g. short-lived signatures) → conformant. */
|
|
24
|
+
permitted?: AlgorithmFamily[];
|
|
25
|
+
/** Families the org prohibits outright → violation. */
|
|
26
|
+
prohibited?: AlgorithmFamily[];
|
|
27
|
+
/** Families being actively migrated, allowed within the window → transition-pending. */
|
|
28
|
+
inTransition?: AlgorithmFamily[];
|
|
29
|
+
/** Optional migration deadline (ISO date / year), recorded for context. */
|
|
30
|
+
transitionDeadline?: string;
|
|
31
|
+
/** Verdict for a family named in none of the lists. Default: `"violation"`. */
|
|
32
|
+
defaultVerdict?: PolicyVerdict;
|
|
33
|
+
}
|
|
34
|
+
/** One finding's verdict against the policy. */
|
|
35
|
+
export interface PolicyFindingVerdict {
|
|
36
|
+
ruleId: string;
|
|
37
|
+
algorithm: AlgorithmFamily | "unknown";
|
|
38
|
+
file: string;
|
|
39
|
+
line: number;
|
|
40
|
+
verdict: PolicyVerdict;
|
|
41
|
+
reason: string;
|
|
42
|
+
}
|
|
43
|
+
/** The `policyMapping` block added to the evidence report. */
|
|
44
|
+
export interface PolicyMapping {
|
|
45
|
+
policyName: string | null;
|
|
46
|
+
transitionDeadline: string | null;
|
|
47
|
+
summary: Record<PolicyVerdict, number>;
|
|
48
|
+
findings: PolicyFindingVerdict[];
|
|
49
|
+
}
|
|
50
|
+
/** Resolve one algorithm family's verdict + a human reason against a policy. */
|
|
51
|
+
export declare function verdictForAlgorithm(algorithm: AlgorithmFamily | undefined, policy: CryptoPolicy): {
|
|
52
|
+
verdict: PolicyVerdict;
|
|
53
|
+
reason: string;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Map every finding to a policy verdict, with per-verdict counts. Deterministic:
|
|
57
|
+
* the same findings + policy always yield the same mapping (safe to hash in the
|
|
58
|
+
* A.8.24 evidence attestation).
|
|
59
|
+
*/
|
|
60
|
+
export declare function buildPolicyMapping(findings: readonly Finding[], policy: CryptoPolicy): PolicyMapping;
|
|
61
|
+
/**
|
|
62
|
+
* Validate + normalize a parsed policy object (from an operator's JSON file).
|
|
63
|
+
* Throws a `TypeError` with a clear message on anything malformed — a bad policy
|
|
64
|
+
* file must fail loudly, never silently degrade the evidence verdict.
|
|
65
|
+
*/
|
|
66
|
+
export declare function parseCryptoPolicy(raw: unknown): CryptoPolicy;
|
|
67
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE3D,+DAA+D;AAC/D,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,WAAW,GAAG,oBAAoB,CAAC;AAgB9E,uEAAuE;AACvE,MAAM,WAAW,YAAY;IAC3B,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sFAAsF;IACtF,SAAS,CAAC,EAAE,eAAe,EAAE,CAAC;IAC9B,uDAAuD;IACvD,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,wFAAwF;IACxF,YAAY,CAAC,EAAE,eAAe,EAAE,CAAC;IACjC,2EAA2E;IAC3E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,+EAA+E;IAC/E,cAAc,CAAC,EAAE,aAAa,CAAC;CAChC;AAED,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,eAAe,GAAG,SAAS,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,8DAA8D;AAC9D,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,OAAO,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IACvC,QAAQ,EAAE,oBAAoB,EAAE,CAAC;CAClC;AAED,gFAAgF;AAChF,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,eAAe,GAAG,SAAS,EACtC,MAAM,EAAE,YAAY,GACnB;IAAE,OAAO,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAmB5C;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,MAAM,EAAE,YAAY,GACnB,aAAa,CAwBf;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,CA+C5D"}
|
package/dist/policy.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/** The complete set of algorithm families a policy may reference. */
|
|
2
|
+
const ALGORITHM_FAMILIES = [
|
|
3
|
+
"RSA",
|
|
4
|
+
"ECDH",
|
|
5
|
+
"ECDSA",
|
|
6
|
+
"EdDSA",
|
|
7
|
+
"DH",
|
|
8
|
+
"DSA",
|
|
9
|
+
"X25519",
|
|
10
|
+
"X448",
|
|
11
|
+
"ECIES",
|
|
12
|
+
"unknown",
|
|
13
|
+
];
|
|
14
|
+
/** Resolve one algorithm family's verdict + a human reason against a policy. */
|
|
15
|
+
export function verdictForAlgorithm(algorithm, policy) {
|
|
16
|
+
const algo = algorithm ?? "unknown";
|
|
17
|
+
if (policy.prohibited?.includes(algo)) {
|
|
18
|
+
return { verdict: "violation", reason: `${algo} is prohibited by the policy.` };
|
|
19
|
+
}
|
|
20
|
+
if (policy.inTransition?.includes(algo)) {
|
|
21
|
+
return {
|
|
22
|
+
verdict: "transition-pending",
|
|
23
|
+
reason: `${algo} is being migrated (in the policy's transition set).`,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
if (policy.permitted?.includes(algo)) {
|
|
27
|
+
return { verdict: "conformant", reason: `${algo} is permitted by the policy.` };
|
|
28
|
+
}
|
|
29
|
+
const fallback = policy.defaultVerdict ?? "violation";
|
|
30
|
+
return {
|
|
31
|
+
verdict: fallback,
|
|
32
|
+
reason: `${algo} is not named in the policy (default verdict: ${fallback}).`,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Map every finding to a policy verdict, with per-verdict counts. Deterministic:
|
|
37
|
+
* the same findings + policy always yield the same mapping (safe to hash in the
|
|
38
|
+
* A.8.24 evidence attestation).
|
|
39
|
+
*/
|
|
40
|
+
export function buildPolicyMapping(findings, policy) {
|
|
41
|
+
const summary = {
|
|
42
|
+
conformant: 0,
|
|
43
|
+
violation: 0,
|
|
44
|
+
"transition-pending": 0,
|
|
45
|
+
};
|
|
46
|
+
const mapped = findings.map((f) => {
|
|
47
|
+
const { verdict, reason } = verdictForAlgorithm(f.algorithm, policy);
|
|
48
|
+
summary[verdict]++;
|
|
49
|
+
return {
|
|
50
|
+
ruleId: f.ruleId,
|
|
51
|
+
algorithm: f.algorithm ?? "unknown",
|
|
52
|
+
file: f.location.file,
|
|
53
|
+
line: f.location.line,
|
|
54
|
+
verdict,
|
|
55
|
+
reason,
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
return {
|
|
59
|
+
policyName: policy.name ?? null,
|
|
60
|
+
transitionDeadline: policy.transitionDeadline ?? null,
|
|
61
|
+
summary,
|
|
62
|
+
findings: mapped,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Validate + normalize a parsed policy object (from an operator's JSON file).
|
|
67
|
+
* Throws a `TypeError` with a clear message on anything malformed — a bad policy
|
|
68
|
+
* file must fail loudly, never silently degrade the evidence verdict.
|
|
69
|
+
*/
|
|
70
|
+
export function parseCryptoPolicy(raw) {
|
|
71
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
72
|
+
throw new TypeError("crypto policy must be a JSON object");
|
|
73
|
+
}
|
|
74
|
+
const obj = raw;
|
|
75
|
+
const validFamilies = new Set(ALGORITHM_FAMILIES);
|
|
76
|
+
const list = (key) => {
|
|
77
|
+
const v = obj[key];
|
|
78
|
+
if (v === undefined)
|
|
79
|
+
return undefined;
|
|
80
|
+
if (!Array.isArray(v))
|
|
81
|
+
throw new TypeError(`policy "${key}" must be an array of algorithm families`);
|
|
82
|
+
for (const item of v) {
|
|
83
|
+
if (typeof item !== "string" || !validFamilies.has(item)) {
|
|
84
|
+
throw new TypeError(`policy "${key}" has an unknown algorithm family ${JSON.stringify(item)}; expected one of ${ALGORITHM_FAMILIES.join(", ")}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return v;
|
|
88
|
+
};
|
|
89
|
+
const verdicts = new Set(["conformant", "violation", "transition-pending"]);
|
|
90
|
+
let defaultVerdict;
|
|
91
|
+
if (obj.defaultVerdict !== undefined) {
|
|
92
|
+
if (typeof obj.defaultVerdict !== "string" ||
|
|
93
|
+
!verdicts.has(obj.defaultVerdict)) {
|
|
94
|
+
throw new TypeError(`policy "defaultVerdict" must be one of ${[...verdicts].join(", ")}`);
|
|
95
|
+
}
|
|
96
|
+
defaultVerdict = obj.defaultVerdict;
|
|
97
|
+
}
|
|
98
|
+
if (obj.name !== undefined && typeof obj.name !== "string") {
|
|
99
|
+
throw new TypeError('policy "name" must be a string');
|
|
100
|
+
}
|
|
101
|
+
if (obj.transitionDeadline !== undefined && typeof obj.transitionDeadline !== "string") {
|
|
102
|
+
throw new TypeError('policy "transitionDeadline" must be a string');
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
...(obj.name !== undefined ? { name: obj.name } : {}),
|
|
106
|
+
...(list("permitted") ? { permitted: list("permitted") } : {}),
|
|
107
|
+
...(list("prohibited") ? { prohibited: list("prohibited") } : {}),
|
|
108
|
+
...(list("inTransition") ? { inTransition: list("inTransition") } : {}),
|
|
109
|
+
...(obj.transitionDeadline !== undefined
|
|
110
|
+
? { transitionDeadline: obj.transitionDeadline }
|
|
111
|
+
: {}),
|
|
112
|
+
...(defaultVerdict !== undefined ? { defaultVerdict } : {}),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAoBA,qEAAqE;AACrE,MAAM,kBAAkB,GAA+B;IACrD,KAAK;IACL,MAAM;IACN,OAAO;IACP,OAAO;IACP,IAAI;IACJ,KAAK;IACL,QAAQ;IACR,MAAM;IACN,OAAO;IACP,SAAS;CACV,CAAC;AAoCF,gFAAgF;AAChF,MAAM,UAAU,mBAAmB,CACjC,SAAsC,EACtC,MAAoB;IAEpB,MAAM,IAAI,GAAG,SAAS,IAAI,SAAS,CAAC;IACpC,IAAI,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI,+BAA+B,EAAE,CAAC;IAClF,CAAC;IACD,IAAI,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,OAAO;YACL,OAAO,EAAE,oBAAoB;YAC7B,MAAM,EAAE,GAAG,IAAI,sDAAsD;SACtE,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,8BAA8B,EAAE,CAAC;IAClF,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,cAAc,IAAI,WAAW,CAAC;IACtD,OAAO;QACL,OAAO,EAAE,QAAQ;QACjB,MAAM,EAAE,GAAG,IAAI,iDAAiD,QAAQ,IAAI;KAC7E,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,QAA4B,EAC5B,MAAoB;IAEpB,MAAM,OAAO,GAAkC;QAC7C,UAAU,EAAE,CAAC;QACb,SAAS,EAAE,CAAC;QACZ,oBAAoB,EAAE,CAAC;KACxB,CAAC;IACF,MAAM,MAAM,GAA2B,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACxD,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,mBAAmB,CAAC,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACrE,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnB,OAAO;YACL,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,SAAS,EAAE,CAAC,CAAC,SAAS,IAAI,SAAS;YACnC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI;YACrB,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI;YACrB,OAAO;YACP,MAAM;SACP,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,OAAO;QACL,UAAU,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI;QAC/B,kBAAkB,EAAE,MAAM,CAAC,kBAAkB,IAAI,IAAI;QACrD,OAAO;QACP,QAAQ,EAAE,MAAM;KACjB,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,SAAS,CAAC,qCAAqC,CAAC,CAAC;IAC7D,CAAC;IACD,MAAM,GAAG,GAAG,GAA8B,CAAC;IAC3C,MAAM,aAAa,GAAG,IAAI,GAAG,CAAS,kBAAkB,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,CAAC,GAAW,EAAiC,EAAE;QAC1D,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QACtC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YACnB,MAAM,IAAI,SAAS,CAAC,WAAW,GAAG,0CAA0C,CAAC,CAAC;QAChF,KAAK,MAAM,IAAI,IAAI,CAAC,EAAE,CAAC;YACrB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzD,MAAM,IAAI,SAAS,CACjB,WAAW,GAAG,qCAAqC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,qBAAqB,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC5H,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO,CAAsB,CAAC;IAChC,CAAC,CAAC;IACF,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAgB,CAAC,YAAY,EAAE,WAAW,EAAE,oBAAoB,CAAC,CAAC,CAAC;IAC3F,IAAI,cAAyC,CAAC;IAC9C,IAAI,GAAG,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;QACrC,IACE,OAAO,GAAG,CAAC,cAAc,KAAK,QAAQ;YACtC,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,cAA+B,CAAC,EAClD,CAAC;YACD,MAAM,IAAI,SAAS,CAAC,0CAA0C,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5F,CAAC;QACD,cAAc,GAAG,GAAG,CAAC,cAA+B,CAAC;IACvD,CAAC;IACD,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC3D,MAAM,IAAI,SAAS,CAAC,gCAAgC,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,GAAG,CAAC,kBAAkB,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,kBAAkB,KAAK,QAAQ,EAAE,CAAC;QACvF,MAAM,IAAI,SAAS,CAAC,8CAA8C,CAAC,CAAC;IACtE,CAAC;IACD,OAAO;QACL,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,GAAG,CAAC,GAAG,CAAC,kBAAkB,KAAK,SAAS;YACtC,CAAC,CAAC,EAAE,kBAAkB,EAAE,GAAG,CAAC,kBAA4B,EAAE;YAC1D,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5D,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Machine-readable cryptography policy → per-finding verdicts for the ISO/IEC\n * 27001 A.8.24 evidence report (docs/compliance/iso27001-a8.24-evidence.md §4).\n *\n * An organization supplies a policy listing which classical algorithm families it\n * prohibits, permits, or is actively transitioning off. `buildPolicyMapping` then\n * flags each qScan finding as `conformant` / `violation` / `transition-pending`\n * against that policy — turning the neutral inventory into audit-ready evidence\n * that the org *assesses* its cryptography against a defined policy.\n *\n * Honesty boundary: without a policy the report stays neutral inventory and the\n * ORG owns the conformance judgment (COMPLIANCE.md §3). The policy is a permit-\n * list: a classical family not named anywhere defaults to a violation (unmanaged\n * crypto is a policy gap), overridable via `defaultVerdict`.\n */\nimport type { AlgorithmFamily, Finding } from \"./types.js\";\n\n/** The three verdicts a finding can carry against a policy. */\nexport type PolicyVerdict = \"conformant\" | \"violation\" | \"transition-pending\";\n\n/** The complete set of algorithm families a policy may reference. */\nconst ALGORITHM_FAMILIES: readonly AlgorithmFamily[] = [\n \"RSA\",\n \"ECDH\",\n \"ECDSA\",\n \"EdDSA\",\n \"DH\",\n \"DSA\",\n \"X25519\",\n \"X448\",\n \"ECIES\",\n \"unknown\",\n];\n\n/** An organization-supplied cryptography policy (from a JSON file). */\nexport interface CryptoPolicy {\n /** Human name / version of the policy, recorded in the evidence report. */\n name?: string;\n /** Families the org explicitly accepts (e.g. short-lived signatures) → conformant. */\n permitted?: AlgorithmFamily[];\n /** Families the org prohibits outright → violation. */\n prohibited?: AlgorithmFamily[];\n /** Families being actively migrated, allowed within the window → transition-pending. */\n inTransition?: AlgorithmFamily[];\n /** Optional migration deadline (ISO date / year), recorded for context. */\n transitionDeadline?: string;\n /** Verdict for a family named in none of the lists. Default: `\"violation\"`. */\n defaultVerdict?: PolicyVerdict;\n}\n\n/** One finding's verdict against the policy. */\nexport interface PolicyFindingVerdict {\n ruleId: string;\n algorithm: AlgorithmFamily | \"unknown\";\n file: string;\n line: number;\n verdict: PolicyVerdict;\n reason: string;\n}\n\n/** The `policyMapping` block added to the evidence report. */\nexport interface PolicyMapping {\n policyName: string | null;\n transitionDeadline: string | null;\n summary: Record<PolicyVerdict, number>;\n findings: PolicyFindingVerdict[];\n}\n\n/** Resolve one algorithm family's verdict + a human reason against a policy. */\nexport function verdictForAlgorithm(\n algorithm: AlgorithmFamily | undefined,\n policy: CryptoPolicy,\n): { verdict: PolicyVerdict; reason: string } {\n const algo = algorithm ?? \"unknown\";\n if (policy.prohibited?.includes(algo)) {\n return { verdict: \"violation\", reason: `${algo} is prohibited by the policy.` };\n }\n if (policy.inTransition?.includes(algo)) {\n return {\n verdict: \"transition-pending\",\n reason: `${algo} is being migrated (in the policy's transition set).`,\n };\n }\n if (policy.permitted?.includes(algo)) {\n return { verdict: \"conformant\", reason: `${algo} is permitted by the policy.` };\n }\n const fallback = policy.defaultVerdict ?? \"violation\";\n return {\n verdict: fallback,\n reason: `${algo} is not named in the policy (default verdict: ${fallback}).`,\n };\n}\n\n/**\n * Map every finding to a policy verdict, with per-verdict counts. Deterministic:\n * the same findings + policy always yield the same mapping (safe to hash in the\n * A.8.24 evidence attestation).\n */\nexport function buildPolicyMapping(\n findings: readonly Finding[],\n policy: CryptoPolicy,\n): PolicyMapping {\n const summary: Record<PolicyVerdict, number> = {\n conformant: 0,\n violation: 0,\n \"transition-pending\": 0,\n };\n const mapped: PolicyFindingVerdict[] = findings.map((f) => {\n const { verdict, reason } = verdictForAlgorithm(f.algorithm, policy);\n summary[verdict]++;\n return {\n ruleId: f.ruleId,\n algorithm: f.algorithm ?? \"unknown\",\n file: f.location.file,\n line: f.location.line,\n verdict,\n reason,\n };\n });\n return {\n policyName: policy.name ?? null,\n transitionDeadline: policy.transitionDeadline ?? null,\n summary,\n findings: mapped,\n };\n}\n\n/**\n * Validate + normalize a parsed policy object (from an operator's JSON file).\n * Throws a `TypeError` with a clear message on anything malformed — a bad policy\n * file must fail loudly, never silently degrade the evidence verdict.\n */\nexport function parseCryptoPolicy(raw: unknown): CryptoPolicy {\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new TypeError(\"crypto policy must be a JSON object\");\n }\n const obj = raw as Record<string, unknown>;\n const validFamilies = new Set<string>(ALGORITHM_FAMILIES);\n const list = (key: string): AlgorithmFamily[] | undefined => {\n const v = obj[key];\n if (v === undefined) return undefined;\n if (!Array.isArray(v))\n throw new TypeError(`policy \"${key}\" must be an array of algorithm families`);\n for (const item of v) {\n if (typeof item !== \"string\" || !validFamilies.has(item)) {\n throw new TypeError(\n `policy \"${key}\" has an unknown algorithm family ${JSON.stringify(item)}; expected one of ${ALGORITHM_FAMILIES.join(\", \")}`,\n );\n }\n }\n return v as AlgorithmFamily[];\n };\n const verdicts = new Set<PolicyVerdict>([\"conformant\", \"violation\", \"transition-pending\"]);\n let defaultVerdict: PolicyVerdict | undefined;\n if (obj.defaultVerdict !== undefined) {\n if (\n typeof obj.defaultVerdict !== \"string\" ||\n !verdicts.has(obj.defaultVerdict as PolicyVerdict)\n ) {\n throw new TypeError(`policy \"defaultVerdict\" must be one of ${[...verdicts].join(\", \")}`);\n }\n defaultVerdict = obj.defaultVerdict as PolicyVerdict;\n }\n if (obj.name !== undefined && typeof obj.name !== \"string\") {\n throw new TypeError('policy \"name\" must be a string');\n }\n if (obj.transitionDeadline !== undefined && typeof obj.transitionDeadline !== \"string\") {\n throw new TypeError('policy \"transitionDeadline\" must be a string');\n }\n return {\n ...(obj.name !== undefined ? { name: obj.name as string } : {}),\n ...(list(\"permitted\") ? { permitted: list(\"permitted\") } : {}),\n ...(list(\"prohibited\") ? { prohibited: list(\"prohibited\") } : {}),\n ...(list(\"inTransition\") ? { inTransition: list(\"inTransition\") } : {}),\n ...(obj.transitionDeadline !== undefined\n ? { transitionDeadline: obj.transitionDeadline as string }\n : {}),\n ...(defaultVerdict !== undefined ? { defaultVerdict } : {}),\n };\n}\n"]}
|
package/dist/registry.d.ts
CHANGED
|
@@ -49,10 +49,15 @@ export declare class DetectorRegistry {
|
|
|
49
49
|
clone(): DetectorRegistry;
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
52
|
-
* The built-in detectors, in run order: the JS/TS source + config
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
52
|
+
* The built-in detectors, in run order: the JS/TS source + language-agnostic config
|
|
53
|
+
* detectors, the per-language source packs (Python, Go, Java/Kotlin/Scala, C#, Rust,
|
|
54
|
+
* Ruby, PHP, Elixir, C/C++, Swift, Objective-C, Dart, Solidity/Move/Cairo), the
|
|
55
|
+
* infrastructure/config detectors (Terraform, Bicep, Pulumi, CloudFormation, cloud-KMS,
|
|
56
|
+
* k8s, mesh, DNSSEC, Vault, database/TDE, messaging, VPN, Ansible, supply-chain, CI/CD,
|
|
57
|
+
* secrets, age, keystore, OpenPGP, JWK, XML-DSig/SAML, PKCS#11/HSM, DKIM, SSH-CA,
|
|
58
|
+
* SPIFFE/SPIRE, reverse-proxy/gRPC TLS, WebAuthn/FIDO2, code-signing, weak-hash-in-
|
|
59
|
+
* signature), and the stateful-HBS (SP 800-208) detector. The manifest (dependency)
|
|
60
|
+
* scanner is handled separately by `scan()`.
|
|
56
61
|
*
|
|
57
62
|
* This is the single source of truth for the default detector set: both
|
|
58
63
|
* {@link defaultRegistry} and the public `detectors` export (re-exported from
|
package/dist/registry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAgDpE,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,CAAC,EAAE,QAAQ,GAAG,aAAa,CAExD;AAED,+FAA+F;AAC/F,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA+B;IACpD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IAEtC,4EAA4E;gBAChE,OAAO,GAAE,SAAS,QAAQ,EAAO;IAI7C,kFAAkF;IAClF,QAAQ,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI;IAS3B,wDAAwD;IACxD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAIrC,qDAAqD;IACrD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIxB,uDAAuD;IACvD,GAAG,IAAI,QAAQ,EAAE;IAIjB;;;;;;OAMG;IACH,WAAW,IAAI,QAAQ,EAAE;IAezB,gFAAgF;IAChF,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IASrD,uEAAuE;IACvE,KAAK,IAAI,gBAAgB;CAG1B;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAQ,EA+CtC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,kBAAyC,CAAC"}
|