Summary
An assetType: algorithm asset with no algorithmFamily is dropped from the CycloneDX output, and the drop is only visible as a counter. This silently removes BIP-340 Schnorr detections from every CBOM.
Why the field is absent rather than wrong
The CycloneDX 1.7 cryptography vocabulary (cryptography-defs.schema.json, algorithmFamily) defines no Schnorr member, and no other/unknown member either. So a rule detecting BIP-340 Schnorr has three options and two are worse than the gap:
- coerce a neighbouring family such as
ECDSA — publishes a false algorithm;
- invent a value — fails schema validation downstream;
- omit the field and carry the scheme in
algorithmName — which is what the Schnorr rules across several ecosystems already do.
What happens today
internal/converter/mapper_algorithm.go:118-122 treats a missing algorithmFamily as a hard mapping error for assetType: algorithm:
family, hasFamily := asset.Metadata["algorithmFamily"]
if !hasFamily || strings.TrimSpace(family) == "" {
return fmt.Errorf("missing required field 'algorithmFamily' (required for assetType='algorithm')")
}
internal/converter/converter.go:113-119 then logs Skipping aggregated asset - conversion failed and increments skippedCount. Nothing in the emitted document records that an asset was dropped.
Reproduction
Scan a consumer of the coincurve PyPI package that calls sign_schnorr, sign and PublicKeyXOnly.verify in one file, with rules whose Schnorr entries omit algorithmFamily:
| output |
crypto assets |
| interim / mining format |
5, including 2 × algorithmName: Schnorr-BIP340-secp256k1 |
cyclonedx |
3 — ECDSA-secp256k1, private-key, public-key; both Schnorr algorithm assets absent |
Assets with assetType: related-crypto-material are unaffected, since the validation applies only to algorithm.
Scope
Not specific to one library or ecosystem: the BIP-340 rules for the secp256k1 and k256 Rust crates omit the field for the same reason, so their Schnorr algorithm assets are dropped identically. Detections survive in the mining pipeline and in served reachability answers; it is the CBOM that loses them.
Options
- Treat a missing
algorithmFamily as non-fatal for assetType: algorithm and emit the component with algorithmName and algorithmPrimitive only — a partial component beats a dropped one, and primitive is already required and present.
- Keep the validation and surface the drop in the document or as a non-zero exit, so it cannot pass unnoticed.
- Raise the vocabulary gap upstream with CycloneDX and carry a local allowance until it lands.
Option 1 plus option 2 would make Schnorr coverage visible without publishing a false family.
Summary
An
assetType: algorithmasset with noalgorithmFamilyis dropped from the CycloneDX output, and the drop is only visible as a counter. This silently removes BIP-340 Schnorr detections from every CBOM.Why the field is absent rather than wrong
The CycloneDX 1.7 cryptography vocabulary (
cryptography-defs.schema.json,algorithmFamily) defines no Schnorr member, and noother/unknownmember either. So a rule detecting BIP-340 Schnorr has three options and two are worse than the gap:ECDSA— publishes a false algorithm;algorithmName— which is what the Schnorr rules across several ecosystems already do.What happens today
internal/converter/mapper_algorithm.go:118-122treats a missingalgorithmFamilyas a hard mapping error forassetType: algorithm:internal/converter/converter.go:113-119then logsSkipping aggregated asset - conversion failedand incrementsskippedCount. Nothing in the emitted document records that an asset was dropped.Reproduction
Scan a consumer of the
coincurvePyPI package that callssign_schnorr,signandPublicKeyXOnly.verifyin one file, with rules whose Schnorr entries omitalgorithmFamily:algorithmName: Schnorr-BIP340-secp256k1cyclonedxECDSA-secp256k1,private-key,public-key; both Schnorr algorithm assets absentAssets with
assetType: related-crypto-materialare unaffected, since the validation applies only toalgorithm.Scope
Not specific to one library or ecosystem: the BIP-340 rules for the
secp256k1andk256Rust crates omit the field for the same reason, so their Schnorr algorithm assets are dropped identically. Detections survive in the mining pipeline and in served reachability answers; it is the CBOM that loses them.Options
algorithmFamilyas non-fatal forassetType: algorithmand emit the component withalgorithmNameandalgorithmPrimitiveonly — a partial component beats a dropped one, andprimitiveis already required and present.Option 1 plus option 2 would make Schnorr coverage visible without publishing a false family.