Skip to content

Cross-Architecture CBOM Generation

Cross-architecture scanning allows you to generate a Cryptographic Bill of Materials (CBOM) for a filesystem that belongs to a different system than the one running the scanner. Common scenarios include:

  • Scanning a container image exported to your host filesystem
  • Analyzing a Yocto or Buildroot rootfs built for ARM on an x86 development machine
  • Examining a mounted disk image from another Linux system
  • Auditing an OpenWrt firmware extracted for analysis

In these cases, the target filesystem has different packages, libraries, and configurations than your host system. Standard scanning would incorrectly query your host's package manager and detect your host's running services, contaminating the results with irrelevant data.

Cross-architecture mode solves this by:

  1. Disabling host package manager queries - No dpkg, rpm, or pacman queries against your host
  2. Using file-based version detection - Extracts versions from binary metadata instead
  3. Focusing on the target filesystem - Only analyzes what's in the directories you specify

When to Use Cross-Architecture Mode

Scenario Use Cross-Arch? Why
Scanning your own system (/usr, /etc) No Host package manager provides accurate versions
Scanning a Docker/Podman container export Yes Container has its own packages, not your host's
Scanning a Yocto rootfs Yes Embedded image has different libraries
Scanning a mounted USB drive with Linux Yes External system, different packages
Scanning /home/user/myapp on your system No Application runs on your host

Rule of thumb: If the files you're scanning came from a different Linux installation than the one you're running on, use cross-architecture mode.


Cross-Architecture CLI Flags

--cross-arch

Purpose: Enable cross-architecture scanning mode.

What it does: - Skips the Package Scanner (no host package manager queries) - Enables file-based version detection (ELF metadata analysis) - Prevents host system contamination in results

Example:

./cbom-generator --cross-arch /mnt/container-rootfs

--crypto-registry FILE

Purpose: Load custom library definitions for the target environment.

What it does: - Defines which libraries are cryptographic (by filename patterns) - Specifies algorithm capabilities for each library - Adapts detection to the target distribution

When to use: - Alpine containers: registry/crypto-registry-alpine.yaml - Yocto images: registry/crypto-registry-yocto.yaml - Custom environments: Create your own registry

Example:

./cbom-generator \
    --cross-arch \
    --crypto-registry registry/crypto-registry-alpine.yaml \
    /tmp/alpine-rootfs

--rootfs-prefix PATH

Purpose: Strip a path prefix from output locations.

What it does: - Removes the mount point prefix from file paths in the CBOM - Makes paths appear as they would on the target system

Example:

Without --rootfs-prefix:

"location": "/mnt/yocto-rootfs/usr/lib/libssl.so.3"

With --rootfs-prefix /mnt/yocto-rootfs:

"location": "/usr/lib/libssl.so.3"

Usage:

./cbom-generator \
    --cross-arch \
    --rootfs-prefix /mnt/yocto-rootfs \
    /mnt/yocto-rootfs/usr /mnt/yocto-rootfs/etc

--yocto-manifest FILE

Purpose: Load exact package versions from a Yocto build manifest.

What it does: - Reads the .manifest file generated by Yocto builds - Provides exact version information for all packages - Highest accuracy tier for version detection

Where to find the manifest:

$YOCTO_BUILD/tmp/deploy/images/<MACHINE>/<IMAGE>-<MACHINE>.manifest

Example:

./cbom-generator \
    --cross-arch \
    --yocto-manifest /path/to/core-image-minimal-qemuarm64.manifest \
    /mnt/yocto-rootfs

--discover-services

Purpose: Enable plugin-based service detection.

What it does: - Loads YAML service plugins - Detects services by checking for binaries and config files - Extracts crypto configuration from detected services

Note: In cross-arch mode, service detection looks for service binaries and configs within your target directories, not running processes on your host.

--plugin-dir PATH

Purpose: Specify where to load service plugins from.

Recommended for cross-arch: - Embedded systems: plugins/embedded/ - Enterprise services: plugins/

Example:

./cbom-generator \
    --cross-arch \
    --discover-services \
    --plugin-dir plugins/embedded \
    /mnt/yocto-rootfs

How Version Detection Works

When you scan your own system, the Package Scanner queries your package manager for exact version information. In cross-architecture mode, this isn't possible, so the scanner uses a tiered fallback system:

Tier Method Accuracy When Used
1 Yocto Manifest Exact When --yocto-manifest provided
2 Package Manager Exact Native scanning only (disabled in cross-arch)
3 ELF VERNEED Minimum API version Cross-arch, when binaries have version tags
4 SONAME Parsing Major version only Fallback when VERNEED unavailable

ELF VERNEED Detection

Binaries linked against versioned libraries contain version requirement tags. The scanner extracts these to determine minimum library versions:

Library Version Tag Format Example
OpenSSL OPENSSL_X.Y.Z OPENSSL_3.0.0 → version 3.0.0
GnuTLS GNUTLS_X_Y_Z GNUTLS_3_6_0 → version 3.6.0
GLIBC GLIBC_X.Y GLIBC_2.34 → version 2.34

SONAME Parsing

When VERNEED tags aren't available, the scanner falls back to parsing the library's SONAME:

  • libssl.so.3 → major version 3
  • libcrypto.so.1.1 → version 1.1
  • libgnutls.so.30 → major version 30

What Changes in Cross-Architecture Mode

Component Normal Mode Cross-Arch Mode
Package Scanner Queries host dpkg/rpm/pacman Disabled
Service Scanner Detects host processes Looks for service binaries in target
Version Detection Package manager queries ELF metadata analysis
Library Detection ldd or readelf readelf only (cross-arch safe)
Path Output Absolute paths Can strip prefix with --rootfs-prefix

Practical Examples

Scanning a Docker Container

# Export container filesystem
docker create --name scan-target nginx:alpine
docker export scan-target | tar -xf - -C /tmp/container-fs
docker rm scan-target

# Scan with Alpine registry
./cbom-generator \
    --cross-arch \
    --crypto-registry registry/crypto-registry-alpine.yaml \
    --rootfs-prefix /tmp/container-fs \
    --format cyclonedx --cyclonedx-spec 1.7 \
    -o nginx-cbom.json \
    /tmp/container-fs

# Cleanup
rm -rf /tmp/container-fs

Scanning a Yocto Rootfs

YOCTO_BUILD=/path/to/poky/build
ROOTFS=$YOCTO_BUILD/tmp/work/qemuarm64-poky-linux/core-image-minimal/1.0/rootfs
MANIFEST=$YOCTO_BUILD/tmp/deploy/images/qemuarm64/core-image-minimal-qemuarm64.manifest

./cbom-generator \
    --cross-arch \
    --yocto-manifest $MANIFEST \
    --discover-services \
    --plugin-dir plugins/embedded \
    --rootfs-prefix $ROOTFS \
    --format cyclonedx --cyclonedx-spec 1.7 \
    -o yocto-cbom.json \
    $ROOTFS/usr/bin \
    $ROOTFS/usr/sbin \
    $ROOTFS/usr/lib \
    $ROOTFS/etc

Scanning a Mounted Disk Image

# Mount the image
sudo mount /dev/sdb1 /mnt/external-linux

# Scan
./cbom-generator \
    --cross-arch \
    --rootfs-prefix /mnt/external-linux \
    --format cyclonedx --cyclonedx-spec 1.7 \
    -o external-cbom.json \
    /mnt/external-linux/usr \
    /mnt/external-linux/etc

# Unmount
sudo umount /mnt/external-linux

Scanning OpenWrt Firmware

# Extract firmware (using binwalk or manufacturer tools)
binwalk -e firmware.bin
cd _firmware.bin.extracted/squashfs-root

# Scan
./cbom-generator \
    --cross-arch \
    --discover-services \
    --plugin-dir plugins/embedded \
    --rootfs-prefix $(pwd) \
    --format cyclonedx --cyclonedx-spec 1.7 \
    -o openwrt-cbom.json \
    .

Directories to Include

For comprehensive coverage, include these directories from your target filesystem:

Directory Contents
/usr/bin User executables
/usr/sbin System executables
/usr/lib Shared libraries
/etc Configuration files
/etc/ssl Certificates and keys
/opt Optional packages (if present)

Example:

./cbom-generator --cross-arch \
    $ROOTFS/usr/bin \
    $ROOTFS/usr/sbin \
    $ROOTFS/usr/lib \
    $ROOTFS/etc


Validating Results

Check for Host Contamination

If you see your host's distribution in the results, cross-arch mode may not be working correctly:

# Should return empty for cross-arch scans of non-Ubuntu images
cat cbom.json | jq '.components[] |
    select(.properties) |
    .properties[] |
    select(.value | test("ubuntu"; "i"))'

Verify Package Scanner Was Skipped

Look for this message in the output:

INFO: Package scanner: SKIPPED (cross-arch mode - host package manager disabled)

Check Version Resolution Tiers

cat cbom.json | jq '.components[] |
    select(.properties) |
    select(.properties[] | .name == "cbom:version:tier")'

Common Issues

Host Packages Appearing in Results

Cause: Missing --cross-arch flag.

Solution: Add --cross-arch to your command.

Few or No Components Found

Causes: - Incorrect path to rootfs - Missing crypto libraries in target - Wrong crypto registry for target distribution

Solutions: 1. Verify paths exist: ls -la $ROOTFS/usr/lib/libcrypto* 2. Use appropriate crypto registry for the target 3. Include /usr/lib in scan paths

"Cannot execute binary file" Errors

Cause: Using --use-ldd with cross-architecture binaries.

Solution: Remove --use-ldd flag. The default readelf method works on any architecture.

Paths in Output Include Mount Point

Cause: Missing --rootfs-prefix flag.

Solution: Add --rootfs-prefix /your/mount/point to strip the prefix.


Flag Summary

Flag Required? Purpose
--cross-arch Yes Enable cross-architecture mode
--crypto-registry FILE Recommended Match target distribution's libraries
--rootfs-prefix PATH Optional Clean up paths in output
--yocto-manifest FILE Optional Exact versions for Yocto builds
--discover-services Optional Enable service detection
--plugin-dir PATH With discover-services Load appropriate plugins

See Also