Code Scanning

Cryptography Bill of Materials (CBOM)

Generate a CycloneDX 1.6 Cryptography Bill of Materials — an inventory of the cryptographic assets in your code — with xgrep sbom --include cbom.

Cryptography Bill of Materials (CBOM)

xgrep sbom --include cbom .
xgrep sbom --include cbom -o cbom.json .

A Cryptography Bill of Materials (CBOM) is a machine-readable inventory of the cryptographic assets your code uses — algorithms, key material, and protocols — and the relationships between them. It answers a question a vulnerability scan does not: "what cryptography do we use, and where?" That inventory is the starting point for post-quantum-cryptography (PQC) migration and for cryptographic compliance and audit.

xgrep emits a CBOM in the CycloneDX 1.6 format, produced with the upstream CycloneDX Go library, so the output conforms to the official CycloneDX 1.6 schema and is consumable by the broader CycloneDX ecosystem (CBOMkit, CBOM viewers, PQC-migration tooling).

Inventory, not findings

A CBOM is fundamentally different from a vulnerability report. It is a complete inventory: strong, correctly-used cryptography (for example AES-256-GCM) is listed as an asset, not flagged as a problem. Each asset is enriched so you can tell the strong from the weak at a glance — see asset fields below.

Because of that, a CBOM is generated by the sbom command (it is a bill of materials, like the dependency SBOM), not by xgrep scan. Detection runs as its own rule category (cbom) that is off in a normal scan, so it never adds inventory noise to your findings — and your existing weak-crypto security rules (weak-cipher, weak-hash, insecure-TLS, …) keep reporting vulnerabilities in xgrep scan exactly as before.

Selecting crypto, alone or combined

--include chooses what a bill of materials contains:

  • xgrep sbom — a Software BoM: your third-party dependencies (the default).
  • xgrep sbom --include cbom — a Cryptography BoM: the cryptographic assets in your source, and only those. No software dependencies.
  • xgrep sbom --include sca,cbom — both, merged into one CycloneDX 1.6 document (add aibom to fold in the AI inventory as well).

A set containing cbom always emits CycloneDX 1.6 JSON. --ref (build the BOM for a commit/tag/branch) and --exclude-dir (prune directories) apply to every content kind, including the crypto scan. The dependency-only filters (--ecosystem, --direct-only, --include-dev) act on the sca content — so they require sca to be selected. See Combined bills of materials.

The older xgrep sbom --cbom flag still works as a deprecated alias for --include cbom, and is slated for removal in v0.3.0.

What gets detected

Detection is language- and library-aware. The table below lists the libraries covered and the detected API surface per library:

LanguageLibraryDetected API surface
JavaJCA (javax.crypto / java.security)Cipher, MessageDigest, Mac, Signature, KeyGenerator, KeyPairGenerator, SecretKeyFactory, SSLContext, CertificateFactory
JavaBouncyCastle (lightweight API)Engines & digests (AESEngine, SHA256Digest, …), HMac
KotlinJCAas Java JCA
ScalaJCAas Java JCA
Pythonstdlib hashlib / hmacmd5/sha1/sha256/sha512, hashlib.new, pbkdf2_hmac, hmac
Pythonpyca/cryptography (hazmat)hashes.*, ciphers.algorithms.*, HMAC, RSA/EC/Ed25519/DSA keygen, PBKDF2HMAC/Scrypt/HKDF, x509 certificates
Gocrypto/* (stdlib)aes, des, rc4, md5, sha1, sha256, sha512, hmac, rsa, ecdsa, ed25519, x509/tls certificates
Gogolang.org/x/cryptosha3, chacha20poly1305, pbkdf2, hkdf, bcrypt, scrypt, argon2, blake2b, ripemd160
C#System.Security.Cryptography (.NET)hash Create/HashData, Aes/AesGcm/AesCcm/TripleDES/DES/RC2, RSA/ECDsa/ECDiffieHellman/DSA, HMAC*, Rfc2898DeriveBytes (PBKDF2), X509Certificate2
JavaScript / TypeScriptNode.js cryptocreateHash, createHmac, createCipheriv, generateKeyPair[Sync], pbkdf2, scrypt, hkdf, createSign
JavaScript / TypeScriptCryptoJS, bcrypt, argon2CryptoJS.AES/SHA256/MD5/HmacSHA256, bcrypt.hash, argon2.hash
RubyOpenSSL, Digest, bcryptOpenSSL::Cipher/Digest/HMAC/PKey (RSA/EC/DSA)/PKCS5, Digest::*, BCrypt
PHPopenssl_*, hash, sodium, password_hashopenssl_encrypt/openssl_pkey_new, hash/hash_hmac/hash_pbkdf2, sodium_*, password_hash (bcrypt/Argon2)
RustRustCrypto, ring, rsasha2/sha1/md-5/sha3, aes-gcm/aes, chacha20poly1305, des, hmac, hkdf, pbkdf2, argon2, bcrypt, rsa, ed25519-dalek, p256 ECDSA, x25519; ring digest/HMAC
SwiftCryptoKit, CommonCryptoSHA256/384/512, Insecure.MD5/SHA1, AES.GCM, ChaChaPoly, HMAC, HKDF, Curve25519, P256/384/521; CC_MD5/CC_SHA256/CCHmac
Dartcrypto, PointyCastlesha256/sha512/sha1/md5/Hmac; PointyCastle engines/digests, PBKDF2/scrypt derivators
Elixir:crypto, Comeonin:crypto hash/mac/crypto_one_time/generate_key; Bcrypt/Argon2/Pbkdf2
Erlangcryptocrypto:hash/mac/crypto_one_time/generate_key

Detected assets span symmetric and asymmetric ciphers, hashes, MACs, signatures, key-agreement schemes, KDFs, TLS, and X.509 certificates — all four CycloneDX asset types (algorithm, protocol, related-crypto-material, certificate). Coverage of additional languages and libraries is expanding. Because a CBOM's value depends on completeness, treat the absence of an asset as "not yet detected," not "no crypto."

xgrep also resolves constant references: when an algorithm is passed as an upper-case constant (e.g. Cipher.getInstance(ALGO) where static final String ALGO = "AES/GCM/NoPadding"), the constant is resolved to its string literal within the same file so the real algorithm is inventoried. A reference that cannot be resolved to a literal is dropped rather than recorded as an unnamed asset.

Output

The document is a CycloneDX 1.6 BOM whose components are cryptographic-asset entries. A single detected call becomes a fully-specified asset:

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.6",
  "metadata": {
    "timestamp": "2026-07-01T00:00:00Z",
    "component": { "type": "application", "bom-ref": "root:my-project", "name": "my-project" },
    "tools": { "components": [{ "type": "application", "name": "xgrep" }] },
  },
  "components": [
    {
      "type": "cryptographic-asset",
      "bom-ref": "crypto/algorithm/aes-128-gcm@2.16.840.1.101.3.4.1.6",
      "name": "AES-128-GCM",
      "cryptoProperties": {
        "assetType": "algorithm",
        "oid": "2.16.840.1.101.3.4.1.6",
        "algorithmProperties": {
          "primitive": "ae",
          "mode": "gcm",
          "parameterSetIdentifier": "128",
          "cryptoFunctions": ["encrypt", "decrypt", "tag"],
          "classicalSecurityLevel": 128,
          "nistQuantumSecurityLevel": 1,
        },
      },
      "evidence": {
        "occurrences": [
          {
            "location": "src/Crypto.java",
            "line": 12,
            "additionalContext": "javax.crypto.Cipher#getInstance",
          },
        ],
      },
    },
  ],
  "dependencies": [
    {
      "ref": "root:my-project",
      "dependsOn": ["crypto/algorithm/aes-128-gcm@2.16.840.1.101.3.4.1.6"],
    },
  ],
}

Understanding an asset

  • assetTypealgorithm, related-crypto-material, protocol, or certificate.
  • primitive — the algorithm's role: block-cipher, stream-cipher, ae (authenticated encryption), hash, mac, signature, pke, key-agree, kdf, …
  • oid — the algorithm's object identifier, when known.
  • parameterSetIdentifier — key or digest size (e.g. 128, 256).
  • mode / padding — for ciphers (e.g. gcm, cbc; pkcs5, oaep).
  • classicalSecurityLevel — security strength in bits against classical attacks.
  • nistQuantumSecurityLevel — NIST post-quantum category 05. 0 means quantum-vulnerable — the field to scan for when planning PQC migration (RSA/ECDSA/DH are 0; broken primitives like MD5/SHA-1 are also 0).
  • evidence.occurrences — every source location (file, line) and the detected API that produced the asset.

The dependency graph

Assets are cross-linked in the CycloneDX dependencies graph. The scanned application depends on each detected asset, and composite algorithms are decomposed into their parts — for example HMAC-SHA256 dependsOn SHA-256, and SHA256withRSA dependsOn both SHA-256 and RSA. Identical assets seen at many call sites collapse to a single component that accumulates all occurrences.

Consuming the CBOM

Write the document to a file and hand it to any CycloneDX-aware tool:

xgrep sbom --include cbom -o cbom.json .

For example, load it into a CBOM viewer, diff it across releases to track crypto drift, or feed it to PQC-readiness tooling that flags every nistQuantumSecurityLevel: 0 asset.

On this page