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:
- Disabling host package manager queries - No dpkg, rpm, or pacman queries against your host
- Using file-based version detection - Extracts versions from binary metadata instead
- 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 version3libcrypto.so.1.1→ version1.1libgnutls.so.30→ major version30
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¶
- Container Scanning - Docker and Podman workflows
- Scanner Behavior - How each scanner works